public static IPolyLine2D Convert(this Polyline source) { var target = new PolyLine2D(source.Segments.Count); foreach (var s in source.Segments) { ISegment2D segment = null; switch (s.Type) { case SegmentType.StartPoint: target.StartPoint = new Point(s.Parameters[0], s.Parameters[1]); continue; case SegmentType.Line: segment = new LineSegment2D(new Point(s.Parameters[0], s.Parameters[1])); break; case SegmentType.CircArc3Points: segment = new CircularArcSegment2D(new Point(s.Parameters[0], s.Parameters[1]), new Point(s.Parameters[2], s.Parameters[3])); break; } target.Segments.Add(segment); } return(target); }
/// <summary> /// Divide <c>ParabolicArcSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Region2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { var segment = source as ParabolicArcSegment2D; // The angle in degrees double totalAngle = segment.GetAngle(ref start); if (angle < Math.Abs(totalAngle) || this.numberOfTiles > 1) { int numberOfTiles = Math.Max((int)Math.Ceiling(Math.Abs(totalAngle) / angle), this.numberOfTiles); double deltaAngle = totalAngle / numberOfTiles; var mat = new Matrix(); mat.Rotate(deltaAngle); var t = segment.GetTangentOnSegment(ref start, 0); for (int i = 1; i < numberOfTiles; ++i) { t = mat.Transform(t); if (segment.CoordinatesFromTangent(ref start, t, out Point p)) { target.Add(p); } } } target.Add(segment.EndPoint); }
private static Segment Convert(this ISegment2D segment, ref Point start, Point?origin = null) { var line = segment as LineSegment2D; if (line != null) { if (origin.HasValue) { return(Segment.LineSegment(line.EndX - origin.Value.X, line.EndY - origin.Value.Y)); } else { return(Segment.LineSegment(line.EndX, line.EndY)); } } var circArc = segment as CircularArcSegment2D; if (circArc != null) { double[] p; if (origin.HasValue) { p = new double[] { circArc.EndX - origin.Value.X, circArc.EndY - origin.Value.Y, circArc.Point.X - origin.Value.X, circArc.Point.Y - origin.Value.Y, } } ; else { p = new double[] { circArc.EndX, circArc.EndY, circArc.Point.X, circArc.Point.Y, } }; return(new Segment { Type = SegmentType.CircArc3Points, Parameters = p, }); } throw new NotImplementedException(); }
/// <summary> /// Divide <c>LineSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Polygon2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { double length = source.GetLength(ref start); if (numberOfTiles > 1 || length > lengthOfTile) { int tiles = Math.Max(numberOfTiles, (int)Math.Ceiling(length / lengthOfTile)); LineSegment2D segment = source as LineSegment2D; Vector u = Point.Subtract(segment.EndPoint, start) / tiles; Point pt = start; for (int i = 1; i < tiles; ++i) { pt = Point.Add(pt, u); target.Add(pt); } } target.Add(source.EndPoint); }
/// <summary> /// Divide <c>CircularArcSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Region2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { CircularArcSegment2D segment = source as CircularArcSegment2D; // The angle in degrees double totalAngle = Math.Abs(segment.GetAngle(ref start)); if (angle < totalAngle || this.numberOfTiles > 1) { int numberOfTiles = Math.Max((int)Math.Ceiling(totalAngle / angle), this.numberOfTiles); double deltaAngle = totalAngle / numberOfTiles * segment.IsCounterClockwise(ref start); Matrix mat = new Matrix(); Point centre = segment.GetCentre(ref start); for (int i = 1; i < numberOfTiles; ++i) { mat.RotateAt(deltaAngle, centre.X, centre.Y); target.Add(mat.Transform(start)); } } target.Add(segment.EndPoint); }
private static void CreateCenterlineSegment(Point plateSideBegPt, ISegment2D plateSide, Point oppositeSideBegPt, ISegment2D oppositeSide, out Point clBegPt, out Point clEndPt) { clBegPt = new Point((plateSideBegPt.X + oppositeSide.EndPoint.X) * 0.5, (plateSideBegPt.Y + oppositeSide.EndPoint.Y) * 0.5); clEndPt = new Point((plateSide.EndPoint.X + oppositeSideBegPt.X) * 0.5, (plateSide.EndPoint.Y + oppositeSideBegPt.Y) * 0.5); }
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); }
public static bool TryGetCenterlineOfOpenCFSection(IPolyLine2D outline, double thickness, out IList <IPolyLine2D> centerlines, double tolerance = 0.0001, bool isClosed = true) { int edgeSegmentsCount = 0; centerlines = new List <IPolyLine2D>(); List <Tuple <int, int, Point, Point> > segLst = new List <Tuple <int, int, Point, Point> >(); Point begPt = outline.StartPoint; for (int i = 0, sz = outline.Segments.Count; i < sz; i++) { ISegment2D seg = outline.Segments[i]; IList <ISegment2D> candidates = FindSecondSideOfPlate(begPt, seg, outline, thickness, tolerance); if (!candidates.Any()) { edgeSegmentsCount++; } foreach (ISegment2D candidate in candidates) { int ix = outline.Segments.IndexOf(candidate); Point candidateBegPt = (ix == 0) ? outline.StartPoint : outline.Segments[ix - 1].EndPoint; CreateCenterlineSegment(begPt, seg, candidateBegPt, candidate, out Point clBegPt, out Point clEndPt); segLst.Add(new Tuple <int, int, Point, Point>(i, ix, clBegPt, clEndPt)); } begPt = seg.EndPoint; } if (edgeSegmentsCount != 2) { return(false); } //iterations List <Tuple <Point, Point> > centerlineSegments = new List <Tuple <Point, Point> >(); while (segLst.Any()) { List <Tuple <int, int, Point, Point> > resolved = new List <Tuple <int, int, Point, Point> >(); for (int i = 0, sz = segLst.Count; i < sz; i++) { bool pair = false; Tuple <int, int, Point, Point> seg = segLst[i]; if (resolved.Contains(seg) && isClosed) { continue; } if (i < sz - 1) { if (i > 0) { if (segLst[i - 1].Item1 == seg.Item1) { pair = true; } } if (segLst[i + 1].Item1 == seg.Item1) { pair = true; } } if (!pair) { centerlineSegments.Add(new Tuple <Point, Point>(seg.Item3, seg.Item4)); resolved.Add(seg); Tuple <int, int, Point, Point> secondPart = segLst.FirstOrDefault((item) => item.Item1 == seg.Item2 && item.Item2 == seg.Item1); if (secondPart != null) { resolved.Add(secondPart); int secIx = segLst.IndexOf(secondPart); Tuple <int, int, Point, Point> prev = (secIx == 0) ? null : segLst[secIx - 1]; Tuple <int, int, Point, Point> next = (secIx == segLst.Count - 1) ? null : segLst[secIx + 1]; Tuple <int, int, Point, Point> pairMember = null; if (prev != null) { if (prev.Item1 == secondPart.Item1) { pairMember = prev; } } if (next != null) { if (next.Item1 == secondPart.Item1) { pairMember = next; } } if (pairMember != null) { resolved.Add(pairMember); Tuple <int, int, Point, Point> part3 = segLst.FirstOrDefault((item) => item.Item1 == pairMember.Item2 && item.Item2 == pairMember.Item1); if (part3 != null) { resolved.Add(part3); } } } } } var toBeRemoved = resolved.Distinct(); foreach (Tuple <int, int, Point, Point> remItem in toBeRemoved) { segLst.Remove(remItem); } } if (!centerlineSegments.Any()) { return(false); } List <Tuple <Point, Point> > centerlineOrder = new List <Tuple <Point, Point> >(); centerlineOrder.Add(centerlineSegments.First()); centerlineSegments.Remove(centerlineSegments.First()); bool escape = false; while (centerlineSegments.Any() && !escape) { List <Tuple <Point, Point> > toBeRemoved = new List <Tuple <Point, Point> >(); Tuple <Point, Point> forwardDir = centerlineOrder.Last(); Tuple <Point, Point> backwardDir = centerlineOrder.First(); foreach (Tuple <Point, Point> seg in centerlineSegments) { if (seg.Item1.IsEqualWithTolerance(forwardDir.Item2)) { forwardDir = seg; toBeRemoved.Add(seg); centerlineOrder.Add(seg); } else if (seg.Item2.IsEqualWithTolerance(forwardDir.Item2)) { forwardDir = new Tuple <Point, Point>(seg.Item2, seg.Item1); toBeRemoved.Add(seg); centerlineOrder.Add(forwardDir); } else if (seg.Item2.IsEqualWithTolerance(backwardDir.Item1)) { backwardDir = seg; toBeRemoved.Add(seg); centerlineOrder.Insert(0, seg); } else if (seg.Item1.IsEqualWithTolerance(backwardDir.Item1)) { backwardDir = new Tuple <Point, Point>(seg.Item2, seg.Item1); toBeRemoved.Add(seg); centerlineOrder.Insert(0, backwardDir); } } foreach (Tuple <Point, Point> remItem in toBeRemoved) { centerlineSegments.Remove(remItem); } if (!toBeRemoved.Any()) { Debug.Fail("Nespojitá střednice!! V algoritmu je chyba."); escape = true; } } IPolyLine2D centerline = new PolyLine2D(centerlineOrder.Count); for (int i = 0, sz = centerlineOrder.Count; i < sz; i++) { Tuple <Point, Point> segPts = centerlineOrder[i]; if (i == 0) { centerline.StartPoint = segPts.Item1; } centerline.Segments.Add(new LineSegment2D(segPts.Item2)); } centerlines.Add(centerline); return(true); }