protected static IPolyLine2D CreatePolyline(List <IntPoint> cpolyline, bool containsCircArc, double maxCircArcAngle, bool tryRecoverCircArc = true) { IPolyLine2D polyline; if (containsCircArc && tryRecoverCircArc) { polyline = GeomTools2D.CreatePolyline(CreatePolygon(cpolyline), maxCircArcAngle); } else { var count = cpolyline.Count; polyline = new PolyLine2D(count); if (count > 0) { polyline.StartPoint = new IdaComPoint2D(cpolyline[0].X / ClipperScale, cpolyline[0].Y / ClipperScale); var segments = polyline.Segments; for (int i = 1; i < count; ++i) { segments.Add(new LineSegment2D(new Point(cpolyline[i].X / ClipperScale, cpolyline[i].Y / ClipperScale))); } } } polyline.Close(); return(polyline); }
/// <summary> /// Creates a circular arc segment defined by tangents and radius. /// </summary> /// <param name="p1">The first point of tangent</param> /// <param name="p2">The intersection of tangents (the vertex).</param> /// <param name="p3">The other point of second tangent.</param> /// <param name="radius">The radius of curcular arc.</param> /// <param name="validateRounding">Indicates, whether validate rounding, that is inside given points p1, p2 and p3. /// If true and rounding is outside given point, then ArgumentException is thrown.</param> /// <param name="startPoint">The start point of circular arc segment.</param> /// <returns>A new circular arc segment.</returns> public static CircularArcSegment2D CreateByTangents(Point p1, Point p2, Point p3, double radius, bool validateRounding, out Point startPoint) { var v1 = p2 - p1; var ptl = GeomTools2D.PointToLine(ref p3, ref p1, ref v1); if (ptl == PointRelatedToLine.OnLine) { throw new NotSupportedException(); } var v2 = p3 - p2; var n1 = v1.Perpendicular(); var n2 = v2.Perpendicular(); n1.Normalize(); n2.Normalize(); n1 *= radius; n2 *= radius; if (ptl == PointRelatedToLine.LeftSide) { n1 *= -1; n2 *= -1; } var p11 = p1 + n1; var p22 = p2 + n2; var centre = GeomTools2D.LineIntersection(p11, v1, p22, v2); var c1 = centre - n1; var c3 = centre - n2; var n12 = n1 + n2; n12.Normalize(); n12 *= radius; var c2 = centre - n12; if (validateRounding) { var vv1 = c1 - p1; var test = v1 * vv1; if (test < 0) { throw new ArgumentException(); } var vv2 = c3 - p3; test = v2 * vv2; if (test > 0) { throw new ArgumentException(); } } startPoint = c1; return(new CircularArcSegment2D(c3, c2)); }
private static bool TrySortSegments(IPolyLine2D pattern, IPolyLine2D polyline, double offset) { if (pattern.Segments.Count == polyline.Segments.Count && pattern.Segments.Count > 0) { Point patStart = pattern.StartPoint; var patSegment = pattern.Segments[0]; var patU = patSegment.EndPoint - patStart; patU.Normalize(); Point start = polyline.StartPoint; for (var i = 0; i < polyline.Segments.Count; ++i) { var segment = polyline.Segments[i]; var u = segment.EndPoint - start; var t = Vector.CrossProduct(patU, u); if (t.IsZero(1e-4)) { // jsou rovnobezne, zkusime vzdalenost t = GeomTools2D.LineToPointDistance(ref patStart, ref patU, ref start); if (t.IsEqual(System.Math.Abs(offset), 0.001)) { // mam segment odpovidajici prvnimu ve vzorove geometrii u.Normalize(); if (!u.X.IsEqual(patU.X, 0.1) || !u.Y.IsEqual(patU.Y, 0.1)) { // jsou opracne orientovane start = segment.EndPoint; GeomTools2D.ReversePolyline(ref polyline); } if (i == 0) { return(true); } var circ = polyline.Segments.AsCircular(); var rotated = circ.Skip(i).Take(polyline.Segments.Count).ToList(); polyline.Segments.Clear(); (polyline.Segments as List <ISegment2D>).AddRange(rotated); polyline.StartPoint = start; return(true); } } start = segment.EndPoint; } } return(false); }
public static void SortSegments(IPolyLine2D polyline, IPolyLine2D pattern) { var patternStart = (Point)pattern.StartPoint; var patternCount = pattern.Segments.Count; int patternInx = -1, inx = -1; for (var i = 0; i < patternCount; ++i) { var patternSegment = pattern.Segments[i]; var start = (Point)polyline.StartPoint; var count = polyline.Segments.Count; for (var j = 0; j < count; ++j) { var segment = polyline.Segments[j]; if (start.IsEqualWithTolerance(patternStart, 1e-6) && segment.EndPoint.IsEqualWithTolerance(patternSegment.EndPoint, 1e-6) && segment.GetType() == patternSegment.GetType()) { patternInx = i; inx = j; break; } start = segment.EndPoint; } if (inx >= 0) { break; } patternStart = patternSegment.EndPoint; } if (patternInx != inx) { GeomTools2D.RotateSegments(polyline, inx - patternInx); } }
private static IList <ISegment2D> FindSecondSideOfPlate(Point plateSideBegPt, ISegment2D plateSide, IPolyLine2D outline, double distance, double tolerance = 0.0001) { Vector vec2 = new Vector(plateSideBegPt.X - plateSide.EndPoint.X, plateSideBegPt.Y - plateSide.EndPoint.Y); List <ISegment2D> foundCandidates = new List <ISegment2D>(); Point begPt = outline.StartPoint; foreach (ISegment2D seg in outline.Segments) { if (seg != plateSide) { Vector vec1 = new Vector(begPt.X - seg.EndPoint.X, begPt.Y - seg.EndPoint.Y); double angle = Math.Abs(GeomTools2D.AngleBetweenVectors(vec1, vec2)); if (angle.IsEqual(0.0, 0.035) || angle.IsEqual(Math.PI, 0.035)) { if (GeomTools2D.Distance(plateSideBegPt, plateSide.EndPoint, seg.EndPoint).IsEqual(distance, tolerance)) { Vector vector = new Vector(1.0, 0.0); Vector vector2 = new Vector(plateSide.EndPoint.X - plateSideBegPt.X, plateSide.EndPoint.Y - plateSideBegPt.Y); double angle2 = Vector.AngleBetween(vector, vector2); //GeomTools2D.AngleBetweenVectors(vector, vector2); Matrix mx = Matrix.Identity; mx.Rotate(-angle2); Point a1 = mx.Transform(plateSideBegPt); Point a2 = mx.Transform(plateSide.EndPoint); Point b1 = mx.Transform(begPt); Point b2 = mx.Transform(seg.EndPoint); bool test = false; if (b1.X.IsEqual(a1.X) || b1.X.IsEqual(a2.X) || b2.X.IsEqual(a1.X) || b2.X.IsEqual(a2.X)) { test = true; } else { if (Math.Sign(b1.X - a1.X) != Math.Sign(b1.X - a2.X)) { test = true; } if (Math.Sign(b2.X - a1.X) != Math.Sign(b2.X - a2.X)) { test = true; } if (Math.Sign(a1.X - b1.X) != Math.Sign(a1.X - b2.X)) { test = true; } if (Math.Sign(a2.X - b1.X) != Math.Sign(a2.X - b2.X)) { test = true; } } if (test) { foundCandidates.Add(seg); } } } } begPt = seg.EndPoint; } return(foundCandidates); }