private Affine(AffinePlan[] creationPlans) { //----------------------- //start with identity matrix _elems = AffineMat.Iden;//copy isIdenHint = true; if (creationPlans == null) { return; } //----------------------- int j = creationPlans.Length; for (int i = 0; i < j; ++i) { AffinePlan plan = creationPlans[i]; switch (plan.cmd) { case AffineMatrixCommand.None: break; case AffineMatrixCommand.Rotate: isIdenHint = false; _elems.Rotate(plan.x); break; case AffineMatrixCommand.Scale: isIdenHint = false; _elems.Scale(plan.x, plan.y); break; case AffineMatrixCommand.Translate: isIdenHint = false; _elems.Translate(plan.x, plan.y); break; case AffineMatrixCommand.Skew: isIdenHint = false; _elems.Skew(plan.x, plan.y); break; case AffineMatrixCommand.Invert: isIdenHint = false; _elems.Invert(); break; default: throw new NotSupportedException(); } } }
private Affine(Affine copyFrom, AffinePlan creationPlan) { _elems = copyFrom._elems; //----------------------- switch (creationPlan.cmd) { default: { throw new NotSupportedException(); } case AffineMatrixCommand.None: _isIdenHint = copyFrom._isIdenHint; break; case AffineMatrixCommand.Rotate: _isIdenHint = false; _elems.Rotate(creationPlan.x); break; case AffineMatrixCommand.Scale: _isIdenHint = false; _elems.Scale(creationPlan.x, creationPlan.y); break; case AffineMatrixCommand.Skew: _isIdenHint = false; _elems.Skew(creationPlan.x, creationPlan.y); break; case AffineMatrixCommand.Translate: _isIdenHint = false; _elems.Translate(creationPlan.x, creationPlan.y); break; case AffineMatrixCommand.Invert: _isIdenHint = false; _elems.Invert(); break; } }
void BuildAff(ref AffinePlan plan) { switch (plan.cmd) { case AffineMatrixCommand.None: break; case AffineMatrixCommand.Rotate: _isIdenHint = false; _elems.Rotate(plan.x); break; case AffineMatrixCommand.Scale: _isIdenHint = false; _elems.Scale(plan.x, plan.y); break; case AffineMatrixCommand.Translate: _isIdenHint = false; _elems.Translate(plan.x, plan.y); break; case AffineMatrixCommand.Skew: _isIdenHint = false; _elems.Skew(plan.x, plan.y); break; case AffineMatrixCommand.Invert: _isIdenHint = false; _elems.Invert(); break; default: throw new NotSupportedException(); } }
//--------------------------------------------------------------------- public void DrawArc( float fromX, float fromY, float endX, float endY, float xaxisRotationAngleDec, float rx, float ry, SvgArcSize arcSize, SvgArcSweep arcSweep) { //------------------ //SVG Elliptical arc ... //from Apache Batik //----------------- CenterFormArc centerFormArc = new CenterFormArc(); ComputeArc2(fromX, fromY, rx, ry, AggMath.deg2rad(xaxisRotationAngleDec), arcSize == SvgArcSize.Large, arcSweep == SvgArcSweep.Negative, endX, endY, ref centerFormArc); // using (VectorToolBox.Borrow(out Arc arcTool)) using (VxsTemp.Borrow(out var v1, out var v2, out var v3)) { arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry, centerFormArc.radStartAngle, (centerFormArc.radStartAngle + centerFormArc.radSweepDiff)); bool stopLoop = false; foreach (VertexData vertexData in arcTool.GetVertexIter()) { switch (vertexData.command) { case VertexCmd.NoMore: stopLoop = true; break; default: v1.AddVertex(vertexData.x, vertexData.y, vertexData.command); //yield return vertexData; break; } //------------------------------ if (stopLoop) { break; } } double scaleRatio = 1; if (centerFormArc.scaleUp) { int vxs_count = v1.Count; double px0, py0, px_last, py_last; v1.GetVertex(0, out px0, out py0); v1.GetVertex(vxs_count - 1, out px_last, out py_last); double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0)); double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY)); if (distance1 < distance2) { scaleRatio = distance2 / distance1; } else { } } if (xaxisRotationAngleDec != 0) { //also rotate if (centerFormArc.scaleUp) { //var mat = Affine.NewMatix( // new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), // new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio), // new AffinePlan(AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), // new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); //mat1.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.Scale(scaleRatio); mat.RotateDeg(xaxisRotationAngleDec); mat.Translate(centerFormArc.cx, centerFormArc.cy); VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } else { //not scale //var mat = Affine.NewMatix( // AffinePlan.Translate(-centerFormArc.cx, -centerFormArc.cy), // AffinePlan.RotateDeg(xaxisRotationAngleDec), // AffinePlan.Translate(centerFormArc.cx, centerFormArc.cy)); //mat.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.RotateDeg(xaxisRotationAngleDec); mat.Translate(centerFormArc.cx, centerFormArc.cy); VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } } else { //no rotate if (centerFormArc.scaleUp) { //var mat = Affine.NewMatix( // new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), // new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio), // new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); //mat.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.RotateDeg(scaleRatio); mat.Translate(centerFormArc.cx, centerFormArc.cy); // VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } } //_stroke.Width = this.StrokeWidth; //_stroke.MakeVxs(v1, v3); //_pcx.DrawGfxPath(_pcx.StrokeColor, _pathRenderVxBuilder.CreatePathRenderVx(v3)); } }
//-------------------------------------------------------------------- public void init(double x0, double y0, double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x2, double y2) { m_radii_ok = true; if (rx < 0.0) { rx = -rx; } if (ry < 0.0) { ry = -rx; } // Calculate the middle point between // the current and the final points //------------------------ double dx2 = (x0 - x2) / 2.0; double dy2 = (y0 - y2) / 2.0; double cos_a = Math.Cos(angle); double sin_a = Math.Sin(angle); // Calculate (x1, y1) //------------------------ double x1 = cos_a * dx2 + sin_a * dy2; double y1 = -sin_a * dx2 + cos_a * dy2; // Ensure radii are large enough //------------------------ double prx = rx * rx; double pry = ry * ry; double px1 = x1 * x1; double py1 = y1 * y1; // Check that radii are large enough //------------------------ double radii_check = px1 / prx + py1 / pry; if (radii_check > 1.0) { rx = Math.Sqrt(radii_check) * rx; ry = Math.Sqrt(radii_check) * ry; prx = rx * rx; pry = ry * ry; if (radii_check > 10.0) { m_radii_ok = false; } } // Calculate (cx1, cy1) //------------------------ double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0; double sq = (prx * pry - prx * py1 - pry * px1) / (prx * py1 + pry * px1); double coef = sign * Math.Sqrt((sq < 0) ? 0 : sq); double cx1 = coef * ((rx * y1) / ry); double cy1 = coef * -((ry * x1) / rx); // // Calculate (cx, cy) from (cx1, cy1) //------------------------ double sx2 = (x0 + x2) / 2.0; double sy2 = (y0 + y2) / 2.0; double cx = sx2 + (cos_a * cx1 - sin_a * cy1); double cy = sy2 + (sin_a * cx1 + cos_a * cy1); // Calculate the start_angle (angle1) and the sweep_angle (dangle) //------------------------ double ux = (x1 - cx1) / rx; double uy = (y1 - cy1) / ry; double vx = (-x1 - cx1) / rx; double vy = (-y1 - cy1) / ry; double p, n; // Calculate the angle start //------------------------ n = Math.Sqrt(ux * ux + uy * uy); p = ux; // (1 * ux) + (0 * uy) sign = (uy < 0) ? -1.0 : 1.0; double v = p / n; if (v < -1.0) { v = -1.0; } if (v > 1.0) { v = 1.0; } double start_angle = sign * Math.Acos(v); // Calculate the sweep angle //------------------------ n = Math.Sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); p = ux * vx + uy * vy; sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; v = p / n; if (v < -1.0) { v = -1.0; } if (v > 1.0) { v = 1.0; } double sweep_angle = sign * Math.Acos(v); if (!sweep_flag && sweep_angle > 0) { sweep_angle -= Math.PI * 2.0; } else if (sweep_flag && sweep_angle < 0) { sweep_angle += Math.PI * 2.0; } // We can now build and transform the resulting arc //------------------------ m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle); AffineMat mtx = AffineMat.Iden(); mtx.Rotate(angle); mtx.Translate(cx, cy); //Affine mtx = Affine.New( // AffinePlan.Rotate(angle), // AffinePlan.Translate(cx, cy) // ); for (int i = 2; i < m_arc.m_num_vertices - 2; i += 2) { mtx.Transform(ref m_arc.m_vertices[i], ref m_arc.m_vertices[i + 1]); } // We must make sure that the starting and ending points // exactly coincide with the initial (x0,y0) and (x2,y2) m_arc.m_vertices[0] = x0; m_arc.m_vertices[1] = y0; if (m_arc.m_num_vertices > 2) { m_arc.m_vertices[m_arc.m_num_vertices - 2] = x2; m_arc.m_vertices[m_arc.m_num_vertices - 1] = y2; } }