protected static List <IntPoint> CreatePolygon(IPolyLine2D polyline, PolyLine2DDiscretizator discretizator, bool counterClockwise) { IPolygon2D polygon = new Polygon2D(); discretizator.Discretize(polyline, ref polygon, null); return(CreatePolygon(polygon, counterClockwise)); }
public static IPolyLine3D TrimmedRegion(Matrix44 lcs, IPolyLine3D trimmedRegion, IPolyLine3D trimRegion, out bool done) { done = false; List <IPoint3D> listOfIntersectionPoint = new List <IPoint3D>(); Intersect(trimmedRegion, trimRegion, listOfIntersectionPoint); if (listOfIntersectionPoint.Count > 0) { done = true; IPolyLine3D trimmedRegionCopy = new PolyLine3D(trimmedRegion); IPolyLine3D trimRegionCopy = new PolyLine3D(trimRegion); IPolyLine2D trimmedPolyLine2D = ConvertTo2D(lcs, trimmedRegionCopy); IPolyLine2D trimPolyLine2D = ConvertTo2D(lcs, trimRegionCopy); Region2D trimmedRegion2D = new Region2D(trimmedPolyLine2D); Region2D trimRegion2D = new Region2D(trimPolyLine2D); // odecte od "trimmedRegion2D" "trimRegion2D". var clipper = new ClipperController(trimmedRegion2D, trimRegion2D); IRegion2D[] regions = clipper.Difference().ToArray(); if (regions.Length > 0) { IPolyLine3D adaptedRegion = ConvertTo3D(regions[0].Outline); TransformToGCS(lcs, adaptedRegion); return(adaptedRegion); } } return(trimmedRegion); }
public static IPolyLine3D ConvertTo3D(IPolyLine2D polyline, IMatrix44 lcs) { var geom = GeomOperation.ConvertTo3D(polyline); GeomOperation.TransformToGCS(lcs, geom); return(geom); }
/// <summary> /// Creates region and sets its outline and openings /// </summary> /// <param name="outline">Outline of the region</param> /// <param name="openings">Openings in the region</param> public Region2D(IPolyLine2D outline, IList <IPolyLine2D> openings) { this.isEditing = false; Outline = outline; Openings = openings; ArcDiscrAngle = Math.PI / 12; // 15 degrees }
/// <summary> /// Creates region and sets its outline by passed polyline /// </summary> /// <param name="outline">outline of the region</param> public Region2D(IPolyLine2D outline) { this.isEditing = false; Outline = outline; Openings = new ObservableList <IPolyLine2D>(); ArcDiscrAngle = Math.PI / 12; // 15 degrees }
public static Polyline Convert(this IPolyLine2D source, Point?origin = null) { var segments = new List <Segment>(source.Segments.Count + 1); Point start = source.StartPoint; if (origin.HasValue) { start = new Point(start.X - origin.Value.X, start.Y - origin.Value.Y); } segments.Add(Segment.StartPoint(start.X, start.Y)); foreach (var s in source.Segments) { segments.Add(s.Convert(ref start, origin)); start = s.EndPoint; if (origin.HasValue) { start = new Point(start.X - origin.Value.X, start.Y - origin.Value.Y); } } var target = new Polyline { Segments = segments, }; return(target); }
internal static IPolygon2D ToPolygon2D(IPolyLine2D polyline, int numberOfArcTiles = 2) { var discr = new PolyLine2DDiscretizator { Angle = 180, NumberOfArcTiles = numberOfArcTiles, LengthOfTile = double.PositiveInfinity, }; IPolygon2D polygon = new Polygon2D(); discr.Discretize(polyline, ref polygon, null); return(polygon); }
public void Add(IPolyLine2D polyline, PolyType type) { if (!this.containsCircArc) { this.containsCircArc |= polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null; } var p = CreatePolygon(polyline, this.Discretizator, false); this.clipper.AddPath(p, type, polyline.IsClosed); }
public static Rect2D Boundary(this IPolyLine2D source) { Point start = source.StartPoint; var ret = new Rect2D(start, new Size()); foreach (var s in source.Segments) { var sg = s.Convert(ref start); ret.Union(sg.GetBoundary(start)); start = s.EndPoint; } return(ret); }
/// <summary> /// adds opening in opening list, create new Id for new opening /// </summary> /// <param name="opening">new opening</param> public void AddOpening(IPolyLine2D opening) { var lastId = 0; if (Openings.Count > 0) { var opLast = Openings.MaxByOrDefault(o => o.Id); lastId = opLast != null ? opLast.Id : 0; } opening.Id = lastId + 1; Openings.Add(opening); }
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); }
internal static Polygon3D ToPolygon3D(IPolyLine2D outline, IMatrix44 lcs) { /// pozor - konvertuje pouze koncove body - tzn. zadne obloucky var count = outline.Segments.Count; var polygon = new Polygon3D(count + 1); var point = outline.StartPoint; var point3D = lcs.TransformToGCS(new WM.Point3D(0, point.X, point.Y)); polygon.Add(point3D); for (var i = 0; i < count; ++i) { point = outline.Segments[i].EndPoint; point3D = lcs.TransformToGCS(new WM.Point3D(0, point.X, point.Y)); polygon.Add(point3D); } return(polygon); }
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); } }
public static IEnumerable <IPolyLine2D> BuildOffset(IPolyLine2D polyline, double delta, JoinType joinType, EndType endType, double mitterLimit, bool sort = false, double maxDiscretizationAngle = 5) { PolyLine2DDiscretizator discretizator = new PolyLine2DDiscretizator { NumberOfTiles = 1, LengthOfTile = double.MaxValue, Angle = maxDiscretizationAngle }; var p = CreatePolygon(polyline, discretizator, true); bool containsCircArc = joinType == JoinType.jtRound || endType == EndType.etOpenRound; if (!containsCircArc) { containsCircArc = polyline.Segments.FirstOrDefault(s => s is CircularArcSegment2D) != null; } var co = new ClipperOffset(mitterLimit); co.AddPath(p, joinType, endType); var solution = new List <List <IntPoint> >(); co.Execute(ref solution, delta * ClipperScale); if (sort && polyline.IsClosed && !containsCircArc && joinType == JoinType.jtMiter && (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) && solution.Count == 1) { // try to sort offset path according to source path var newPolyline = CreatePolyline(solution[0], containsCircArc, maxDiscretizationAngle + 1); TrySortSegments(polyline, newPolyline, delta); yield return(newPolyline); } else { foreach (var polygon in solution) { yield return(CreatePolyline(polygon, containsCircArc, maxDiscretizationAngle + 1)); } } }
/// <summary> /// Discretize of <c>PolyLine2D</c> to <c>Polygon2D</c>. /// </summary> /// <param name="source">The <c>PolyLine2D</c> to discretization.</param> /// <param name="target">The <c>Polygon2D</c> as destination.</param> /// <param name="targetInxs">The <c>IList</c> as destination.</param> public void Discretize(IPolyLine2D source, ref IPolygon2D target, IList <int> targetInxs) { if (source == null) { return; } Point start = source.StartPoint; target.Add(start); int i = 0; int lastInx = 0; foreach (var segment in source.Segments) { SelectSegment2DDiscretizator(segment.GetType()).Discretize(start, segment, target); start = segment.EndPoint; if (targetInxs != null) { for (int j = lastInx; j < target.Count; j++) { targetInxs.Add(i); } lastInx = target.Count; } i++; } if (targetInxs != null) { if (source.IsClosed && (targetInxs.Count > 0)) { targetInxs[0] = targetInxs[targetInxs.Count - 1]; } } }
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); }