/** * @param float $r1 * @param float $r2 * @param float $alpha * @param float $angle * * @return Path */ function getGroupPath($r1, $r2, $alpha, $angle) { $radians = ArcUtils::getArcRadians($alpha, $angle); $scale = ArcUtils::getScale($radians); list($sX, $sY) = ArcUtils::getPolarPoint($r2, $radians[0]); list($curX, $curY) = ArcUtils::getPolarPoint($r1, $radians[0]); $path = new Path($sX, $sY); if ($r1 !== $r2) { $path->lineTo($curX, $curY); } $pos = 1; while ($pos < count($radians)) { list($nextX, $nextY) = ArcUtils::getPolarPoint($r1, $radians[$pos++]); list($c1X, $c1Y) = ArcUtils::getBezierControl($curX, $curY, -$scale); list($c2X, $c2Y) = ArcUtils::getBezierControl($nextX, $nextY, $scale); $path->curveTo($c1X, $c1Y, $c2X, $c2Y, $nextX, $nextY); $curX = $nextX; $curY = $nextY; } list($eX, $eY) = ArcUtils::getPolarPoint($r2, end($radians)); if ($r1 !== $r2) { $path->lineTo($eX, $eY); } return $path; }
/** * @param Path $path */ private function initTable(Path $path) { $curX = 0.0; $curY = 0.0; foreach ($path->getElements() as $path) { $destX = $path->getDestX(); $destY = $path->getDestY(); if ($path instanceof LineTo || $path instanceof Close) { if ($curX === $destX && $curY === $destY) { // skip empty lines continue; } $this->addSection(new LinearSection($curX, $curY, $destX, $destY)); } elseif ($path instanceof CurveTo) { $c1x = $path->getControl1X(); $c1y = $path->getControl1Y(); $c2x = $path->getControl2X(); $c2y = $path->getControl2Y(); if ($curX === $destX && $curY === $destY && $curX === $c1x && $curY === $c1y && $curX === $c2x && $curY === $c2y) { // skip empty curve continue; } $this->addSection(new CurvedSection($curX, $curY, $c1x, $c1y, $c2x, $c2y, $destX, $destY)); } $curX = $destX; $curY = $destY; } }
/** */ public function testVisibility() { $path = new Path(1, 2); $this->assertFalse($path->isVisible()); $path = new Path(1, 2); $path->close(); $this->assertFalse($path->isVisible()); $path = new Path(1, 2); $path->lineTo(2, 3); $this->assertTrue($path->isVisible()); $path = new Path(1, 2); $path->curveTo(2, 3, 3, 4, 4, 5); $this->assertTrue($path->isVisible()); }
/** * @return Path */ private function getPartialRingPath() { $outer = $this->getOuterRadius(); $inner = $this->getInnerRadius(); $cx = $this->getX(); $cy = $this->getY(); if ($this->angle === 0.0) { $radian = ArcUtils::toRadian($this->getAlpha()); list($outerX, $outerY) = ArcUtils::getPolarPoint($outer, $radian); list($innerX, $innerY) = ArcUtils::getPolarPoint($inner, $radian); return (new Path($outerX + $cx, $outerY + $cy))->lineTo($innerX + $cx, $innerY + $cy)->close(); } $radians = ArcUtils::getArcRadians($this->getAlpha(), $this->getAngle()); $scale = ArcUtils::getScale($radians); $pos = 0; // outer arc list($curX, $curY) = ArcUtils::getPolarPoint($outer, $radians[$pos++]); $path = new Path($curX + $cx, $curY + $cy); while ($pos < count($radians)) { list($nextX, $nextY) = ArcUtils::getPolarPoint($outer, $radians[$pos++]); list($c1X, $c1Y) = ArcUtils::getBezierControl($curX, $curY, -$scale); list($c2X, $c2Y) = ArcUtils::getBezierControl($nextX, $nextY, $scale); $path->curveTo($c1X + $cx, $c1Y + $cy, $c2X + $cx, $c2Y + $cy, $nextX + $cx, $nextY + $cy); $curX = $nextX; $curY = $nextY; } // inner arc list($curX, $curY) = ArcUtils::getPolarPoint($inner, $radians[--$pos]); if ($this->angle === 360.0) { // full ring $path->close()->moveTo($curX + $cx, $curY + $cy); } else { $path->lineTo($curX + $cx, $curY + $cy); } while ($pos > 0) { list($nextX, $nextY) = ArcUtils::getPolarPoint($inner, $radians[--$pos]); list($c1X, $c1Y) = ArcUtils::getBezierControl($curX, $curY, $scale); list($c2X, $c2Y) = ArcUtils::getBezierControl($nextX, $nextY, -$scale); $path->curveTo($c1X + $cx, $c1Y + $cy, $c2X + $cx, $c2Y + $cy, $nextX + $cx, $nextY + $cy); $curX = $nextX; $curY = $nextY; } // close path $path->close(); return $path; }
/** * @param ZendPage $page * @param Path $path * @param int $fillType * * @return ZendPage * @throws \Exception */ private function drawRawPath(ZendPage $page, Path $path, $fillType) { $content = ''; foreach ($path->getElements() as $element) { if ($element instanceof MoveTo) { $xObj = new ZendNumericObject($element->getDestX()); $yObj = new ZendNumericObject($element->getDestY()); $content .= $xObj->toString() . ' ' . $yObj->toString() . ' ' . " m\n"; } elseif ($element instanceof LineTo) { $xObj = new ZendNumericObject($element->getDestX()); $yObj = new ZendNumericObject($element->getDestY()); $content .= $xObj->toString() . ' ' . $yObj->toString() . ' ' . " l\n"; } elseif ($element instanceof CurveTo) { $x1Obj = new ZendNumericObject($element->getControl1X()); $y1Obj = new ZendNumericObject($element->getControl1Y()); $x2Obj = new ZendNumericObject($element->getControl2X()); $y2Obj = new ZendNumericObject($element->getControl2Y()); $x3Obj = new ZendNumericObject($element->getDestX()); $y3Obj = new ZendNumericObject($element->getDestY()); $content .= $x1Obj->toString() . ' ' . $y1Obj->toString() . ' ' . $x2Obj->toString() . ' ' . $y2Obj->toString() . ' ' . $x3Obj->toString() . ' ' . $y3Obj->toString() . ' ' . " c\n"; } elseif ($element instanceof Close) { $content .= "h\n"; } else { throw new InvalidArgumentException('unsupported path element: ' . get_class($element)); } } switch ($fillType) { case ZendPage::SHAPE_DRAW_FILL_AND_STROKE: $content .= " B*\n"; break; case ZendPage::SHAPE_DRAW_FILL: $content .= " f*\n"; break; case ZendPage::SHAPE_DRAW_STROKE: $content .= " S\n"; break; } return $page->rawWrite($content, 'PDF'); }
$path->curveTo($radius * sin(9.0 / 5.0 * pi()) / 2, $radius * cos(9.0 / 5.0 * pi()) / 2, $radius * sin(1.0 / 5.0 * pi()) / 2, $radius * cos(1.0 / 5.0 * pi()) / 2, $radius * sin(2.0 / 5.0 * pi()), $radius * cos(2.0 / 5.0 * pi())); $path->curveTo($radius * sin(3.0 / 5.0 * pi()) / 2, $radius * cos(3.0 / 5.0 * pi()) / 2, $radius * sin(5.0 / 5.0 * pi()) / 2, $radius * cos(5.0 / 5.0 * pi()) / 2, $radius * sin(6.0 / 5.0 * pi()), $radius * cos(6.0 / 5.0 * pi())); $path->curveTo($radius * sin(7.0 / 5.0 * pi()) / 2, $radius * cos(7.0 / 5.0 * pi()) / 2, $radius * sin(9.0 / 5.0 * pi()) / 2, $radius * cos(9.0 / 5.0 * pi()) / 2, $radius * sin(0.0 / 5.0 * pi()), $radius * cos(0.0 / 5.0 * pi())); $path->close(); $graphic->addPath($path)->setFillColor('black', 0.3); $radius = 80; $path = new Path($radius * sin(1.0 / 5.0 * pi()), $radius * cos(1.0 / 5.0 * pi())); $path->lineTo($radius * sin(5.0 / 5.0 * pi()), $radius * cos(5.0 / 5.0 * pi())); $path->lineTo($radius * sin(9.0 / 5.0 * pi()), $radius * cos(9.0 / 5.0 * pi())); $path->lineTo($radius * sin(3.0 / 5.0 * pi()), $radius * cos(3.0 / 5.0 * pi())); $path->lineTo($radius * sin(7.0 / 5.0 * pi()), $radius * cos(7.0 / 5.0 * pi())); $path->lineTo($radius * sin(1.0 / 5.0 * pi()), $radius * cos(1.0 / 5.0 * pi())); $path->close(); $graphic->addPath($path)->setFillColor('black')->setStrokeColor('blue', 0.6)->setOpacity(0.6); $radius = 20; $path = new Path($radius * sin(0.0 / 3.0 * pi()), $radius * cos(0.0 / 3.0 * pi())); $path->lineTo($radius * sin(2.0 / 3.0 * pi()), $radius * cos(2.0 / 3.0 * pi())); $path->lineTo($radius * sin(4.0 / 3.0 * pi()), $radius * cos(4.0 / 3.0 * pi())); $path->close(); $path->moveTo($radius * sin(1.0 / 3.0 * pi()), $radius * cos(1.0 / 3.0 * pi())); $path->lineTo($radius * sin(5.0 / 3.0 * pi()), $radius * cos(5.0 / 3.0 * pi())); $path->lineTo($radius * sin(3.0 / 3.0 * pi()), $radius * cos(3.0 / 3.0 * pi())); $path->close(); $graphic->addPath($path)->setFillColor('gray')->setStrokeColor('black', 0.6)->setOpacity(0.6); $graphic->addCircle(0, 0, 80)->setStrokeColor('green'); // just supported in svg-writer, yet $text = $graphic->addPathText('Round and Round and Round and Round ...', $p1); $text->setFont(12); $text->align(FontStyle::HORIZONTAL_ALIGN_MIDDLE, FontStyle::VERTICAL_ALIGN_BOTTOM); $text->setStrokeColor('red'); $text->setStrokeWidth(0.2);
/** * @param SimpleXMLElement $svg * @param Path $path * @param $yBase * * @return SimpleXMLElement * @throws \Exception */ private function addPath(SimpleXMLElement $svg, Path $path, $yBase) { $d = ''; foreach ($path->getElements() as $element) { if ($element instanceof MoveTo) { $d .= 'M ' . $element->getDestX() . ',' . ($yBase - $element->getDestY()) . ' '; } elseif ($element instanceof LineTo) { $d .= 'L ' . $element->getDestX() . ',' . ($yBase - $element->getDestY()) . ' '; } elseif ($element instanceof CurveTo) { $d .= 'C ' . $element->getControl1X() . ',' . ($yBase - $element->getControl1Y()) . ' ' . $element->getControl2X() . ',' . ($yBase - $element->getControl2Y()) . ' ' . $element->getDestX() . ',' . ($yBase - $element->getDestY()) . ' '; } elseif ($element instanceof Close) { $d .= "Z "; } else { throw new InvalidArgumentException('unsupported path element: ' . get_class($element)); } } $child = $svg->addChild("path"); $child->addAttribute("d", $d); return $child; }
h<?php use VectorGraphics\Model\Graphic; use VectorGraphics\Model\Path; $graphic = new Graphic(); $graphic->setViewportCorners(-50, -50, 50, 50); $graphic->addRectangle(-49, -49, 98, 98)->setStrokeWidth(2); $graphic->addCircle(0, 0, 45)->setFillColor('red', 0.5); $radius = 40; $path = new Path($radius * sin(0.0 / 5.0 * pi()), $radius * cos(0.0 / 5.0 * pi())); $path->lineTo($radius * sin(4.0 / 5.0 * pi()), $radius * cos(4.0 / 5.0 * pi())); $path->lineTo($radius * sin(8.0 / 5.0 * pi()), $radius * cos(8.0 / 5.0 * pi())); $path->lineTo($radius * sin(2.0 / 5.0 * pi()), $radius * cos(2.0 / 5.0 * pi())); $path->lineTo($radius * sin(6.0 / 5.0 * pi()), $radius * cos(6.0 / 5.0 * pi())); $path->close(); $graphic->addPath($path); return $graphic;