/// <summary> /// Calculates LCS matrix of the plane of region according to points /// </summary> /// <param name="region">region of the plane</param> /// <returns>Matrix44 of LCS</returns> public static IMatrix44 GetMatrixPlane(IRegion3D region) { if (region == null) { return(null); } ISegment3D firstSeg = region.Outline[0]; Vector3D firstVec = Subtract(firstSeg.StartPoint, firstSeg.EndPoint); IPoint3D pointInPlane = null; // loop for 1 not 0 for (int i = 1; i < region.Outline.Count; i++) { ISegment3D nextSeg = region.Outline[i]; Vector3D nextVec = Subtract(nextSeg.StartPoint, nextSeg.EndPoint); if (!IsCollinear(firstVec, nextVec, MathConstants.ZeroWeak)) { pointInPlane = nextSeg.EndPoint; break; } } if (pointInPlane != null) { return(GetLCSMatrix(firstSeg.StartPoint, firstSeg.EndPoint, pointInPlane, Plane.XY)); } return(new Matrix44()); }
/// <summary> /// creates a polyline from another polyline /// </summary> /// <param name="source">Source polyline</param> public PolyLine3D(IPolyLine3D source) { if (source != null) { Name = (source as ElementBase).Name; segments = new List <ISegment3D>(); if (source.Segments != null) { IPoint3D point = null; foreach (ISegment3D segment in source.Segments) { ISegment3D seg = segment.CloneSegment(); if (point != null) { seg.StartPoint = point; } point = seg.EndPoint; Add(seg); } if (source.IsClosed && segments.Count > 0) { segments[segments.Count - 1].EndPoint = segments[0].StartPoint; } } } }
/// <summary> /// Removes a specific segment from the polyline, adaptes shorter segment /// </summary> /// <param name="segment">The object to remove from the polyline.</param> /// <returns>Index of the removed segment</returns> public int RemoveAdaptShorter(ISegment3D segment) { UnsubscribeEventsFromSegment(segment); int indexOfDelSegment = segments.IndexOf(segment); RemoveAtAdaptShorter(indexOfDelSegment); return(indexOfDelSegment); }
public static ISegment2D ConvertTo2D(ISegment3D segment3D, IMatrix44 lcs) { var segmentCopy = segment3D.CloneSegment(); GeomOperation.TransformToLCS(lcs, segmentCopy); var segment2D = ConvertTo2D(segmentCopy); return(segment2D); }
/// <summary> /// Gets direction of the begin and end point of the segment (normalized) /// </summary> /// <param name="src">Segment</param> /// <returns>Direction</returns> public static WM.Vector3D GetDirection(this ISegment3D src) { var temp = new WM.Vector3D(src.EndPoint.X - src.StartPoint.X, src.EndPoint.Y - src.StartPoint.Y, src.EndPoint.Z - src.StartPoint.Z); temp.Normalize(); return(temp); }
/// <summary> /// Create a segment as a copy of another /// </summary> /// <param name="source">Source segment</param> public Segment3D(ISegment3D source) { if (source != null) { startPoint = new Point3D(source.StartPoint.X, source.StartPoint.Y, source.StartPoint.Z); endPoint = new Point3D(source.EndPoint.X, source.EndPoint.Y, source.EndPoint.Z); (source as Segment3D).LocalCoordinateSystem.CopyTo(ref localCoordinateSystem); SubscribePointEvents(); } }
/// <summary> /// Unsubscribe Events From given segment /// </summary> /// <param name="segment"></param> protected void UnsubscribeEventsFromSegment(ISegment3D segment) { //ElementBase elementSegment = segment as ElementBase; //if (elementSegment == null) //{ // return; //} ////elementSegment.ObjectChanged -= new ObjectChangedEventHandler(OnGeometryChanged); ////elementSegment.ObjectLinked -= new ObjectLinkedEventHandler(OnObjectLinked); //PropertyChangedEventManager.RemoveListener(elementSegment, this); }
/// <summary> /// Convert the points of polyline based on baseGeometry /// </summary> /// <param name="matrix">LCS matrix of baseGeometry</param> /// <param name="baseGeometry">Based on this region, the given polyline is modifed</param> /// <param name="polyline">Input polyline object</param> /// <param name="modifyInput">If true, given polyline object is modified. Otherwise prepare new polyline object</param> /// <returns>Polyline object which is based on baseGeometry</returns> public static IPolyLine3D GetPolylineOnRegion(IMatrix44 matrix, IRegion3D baseGeometry, IPolyLine3D polyline, bool modifyInput = true) { if (baseGeometry == null || polyline == null) { return(null); } if (matrix == null) { matrix = GetMatrixPlane(baseGeometry); } if (!modifyInput) { polyline = new PolyLine3D(polyline); } bool isIndependent = true; if (polyline.IsClosed) { isIndependent = false; } ISegment3D firstSegment = null; IPoint3D lastEndPoint = null; foreach (ISegment3D segment in polyline.Segments) { GetSegmentOnRegion(matrix, baseGeometry, segment, isIndependent); if (lastEndPoint != null) { segment.StartPoint = lastEndPoint; } if (firstSegment == null) { firstSegment = segment; } lastEndPoint = segment.EndPoint; isIndependent = false; } if (firstSegment != null && lastEndPoint != null) { firstSegment.StartPoint = lastEndPoint; } return(polyline); }
/// <summary> /// Inserts <paramref name="segmentToInsert"/> after <paramref name="baseSegment"/>. /// If <paramref name="baseSegment"/> in not in the polyline exception is thrown. /// </summary> /// <param name="baseSegment"></param> /// <param name="segmentToInsert"></param> public void InsertSegmentAfterSegment(ISegment3D baseSegment, ISegment3D segmentToInsert) { int baseSegmentIndex = segments.IndexOf(baseSegment); if (baseSegmentIndex == -1) { throw new ArgumentException("PolyLine3D InsertAfter : Segment not found"); } baseSegment.EndPoint = segmentToInsert.StartPoint; segments.Insert(baseSegmentIndex + 1, segmentToInsert); SubscribeEventsFromSegment(segmentToInsert); }
private static ISegment2D ConvertTo2D(ISegment3D segment3D) { if (segment3D.SegmentType == SegmentType.Line) { LineSegment2D lineSegment2D = new LineSegment2D(new Point(segment3D.EndPoint.X, segment3D.EndPoint.Y)); return(lineSegment2D); } else if (segment3D.SegmentType == SegmentType.CircularArc) { CircularArcSegment2D arcSegment2D = new CircularArcSegment2D(new Point(segment3D.EndPoint.X, segment3D.EndPoint.Y), new Point((segment3D as IArcSegment3D).IntermedPoint.X, (segment3D as IArcSegment3D).IntermedPoint.Y)); return(arcSegment2D); } return(null); }
/// <summary> /// Create a new region as union of two input regions /// </summary> /// <param name="a">region a</param> /// <param name="b">region b</param> /// <param name="result">returns result region = a + b</param> /// <returns>false if the operation failed</returns> public static bool MergeRegions(IRegion3D a, IRegion3D b, out IRegion3D result) { List <Tuple <ISegment3D, ISegment3D, bool> > foundPairs = new List <Tuple <ISegment3D, ISegment3D, bool> >(); var res = new Region3D(a); //simple solution - regiony se dotýkají, nepřekrývají foreach (var segA in res.Outline.Segments) { foreach (var segB in b.Outline.Segments) { // default used tolerance is too big MathConstants.ZeroGeneral = 1E-10 // tolerance to find the same segments is set to 1E-4m = 0.0001m = 0.1mm, maximum sensitivity to find same points on segment is 1E-6 (tested) if (IsEqualWithTolerance(segA, segB, MathConstants.ZeroWeak)) { foundPairs.Add(new Tuple <ISegment3D, ISegment3D, bool>(segA, segB, false)); break; } else if (IsEqualWithTolerance(segA, Reverse(segB), MathConstants.ZeroWeak)) { foundPairs.Add(new Tuple <ISegment3D, ISegment3D, bool>(segA, segB, true)); break; } } } if (foundPairs.Any()) { Tuple <ISegment3D, ISegment3D, bool> first = foundPairs[0]; IPolyLine3D polylineB = new PolyLine3D(b.Outline); var segmentB = first.Item2; if (!first.Item3) { polylineB = Reverse(polylineB); } foreach (var seg in polylineB.Segments) { if (IsEqual(segmentB, seg) || IsEqual(segmentB, Reverse(seg))) { segmentB = seg; } } var polyline = new PolyLine3D(); int segInx = GetIndexOfSegment(polylineB, segmentB); for (int i = segInx + 1; i < polylineB.Segments.Count(); i++) { polyline.Add(polylineB[i].CloneSegment()); } for (int i = 0; i < segInx; i++) { polyline.Add(polylineB[i].CloneSegment()); } int resSegInx = GetIndexOfSegment(res.Outline, first.Item1); var prevSeg = GetPreviousSegment(res.Outline, resSegInx); ISegment3D baseSeg = prevSeg; foreach (var seg in polyline.Segments) { res.Outline.InsertSegmentAfterSegment(baseSeg, seg); baseSeg = seg; } int baseSegInx = GetIndexOfSegment(res.Outline, baseSeg); var nextSeg = GetNextSegment(res.Outline, baseSegInx); res.Outline.Remove(nextSeg); foreach (var opening in b.Openings) { res.AddOpening(opening); } result = res; return(true); } result = null; return(false); }
/// <summary> /// Calculate inner partial polyline by intersecting region and polyline /// </summary> /// <param name="region">IRegion3D</param> /// <param name="innerPolyline">Polyline3D used to calculate inner partial polyline</param> /// <param name="innerPolylineList">List of inner partial polyline prepared from the given polygon and polyline</param> /// <returns>IntersectionResults</returns> public static IntersectionResults Intersect(IRegion3D region, IPolyLine3D innerPolyline, ICollection <IPolyLine3D> innerPolylineList) { if (region == null || innerPolyline == null || innerPolylineList == null) { return(IntersectionResults.Undefined); } IPolyLine3D outerPolyline = region.Outline; List <IPoint3D> listOfIntersectionPoint = new List <IPoint3D>(); Intersect(outerPolyline, innerPolyline, listOfIntersectionPoint); foreach (IPolyLine3D opening in region.Openings) { Intersect(opening, innerPolyline, listOfIntersectionPoint); } if (listOfIntersectionPoint.Count < 1) { IPoint3D point = GetPointOnPolyLine(innerPolyline, 0.5); return(IsPointOn(region, point)); } SortedSet <double> relativePositionSet = new SortedSet <double>(); relativePositionSet.Add(0); relativePositionSet.Add(1); foreach (IPoint3D point in listOfIntersectionPoint) { double relativePosition = 0; if (GetRelativePosition(innerPolyline, point, ref relativePosition)) { if (!relativePositionSet.Contains(relativePosition)) { relativePositionSet.Add(relativePosition); } } } IList <ISegment3D> splittedSegments = SplitPolyline(innerPolyline, relativePositionSet); if (splittedSegments == null) { return(IntersectionResults.Undefined); } IntersectionResults interSectionResult = IntersectionResults.Undefined; foreach (ISegment3D segment in splittedSegments) { IPoint3D point = new Point3D(); if (GetPointOnSegment(segment, 0.5, ref point)) { IntersectionResults result = IsPointOn(region, point); interSectionResult |= result; if (result == IntersectionResults.Inside || result == IntersectionResults.OnBorderCurve) { IPolyLine3D polyline = new PolyLine3D(); if (innerPolylineList.Count < 1) { polyline.Add(segment); } else { IPolyLine3D existingPolyline = innerPolylineList.Last(); if (existingPolyline.Count < 1) { polyline.Add(segment); } else { if (existingPolyline.Count > 1) { ISegment3D lastSegment = existingPolyline.Segments.Last(); if (lastSegment.EndPoint.Equals(segment.StartPoint)) { polyline = existingPolyline; } } polyline.Add(segment); } } if (!innerPolylineList.Contains(polyline)) { innerPolylineList.Add(polyline); } } } } if (innerPolylineList.Count < 1) { return(IntersectionResults.OnBorderNode | IntersectionResults.Outside); } return(interSectionResult); }
/// <summary> /// Convert the points of segment based on baseGeometry /// </summary> /// <param name="matrix">LCS matrix of baseGeometry</param> /// <param name="baseGeometry">Based on this region, the given segment is modifed</param> /// <param name="segment">Input segment object</param> /// <param name="isIndependent">Segment is independent</param> /// <param name="modifyInput">If true, given segment object is modified. Otherwise prepare new segment object</param> /// <returns>Segment object which is based on baseGeometry</returns> public static ISegment3D GetSegmentOnRegion(IMatrix44 matrix, IRegion3D baseGeometry, ISegment3D segment, bool isIndependent = true, bool modifyInput = true) { if (baseGeometry == null || segment == null) { return(null); } if (matrix == null) { matrix = GetMatrixPlane(baseGeometry); } if (!modifyInput) { segment = segment.CloneSegment(); } ILineSegment3D line = segment as ILineSegment3D; if (line != null) { if (isIndependent) { line.StartPoint = GetPointOnRegion(matrix, baseGeometry, line.StartPoint); } line.EndPoint = GetPointOnRegion(matrix, baseGeometry, line.EndPoint); return(line); } IArcSegment3D arc = segment as IArcSegment3D; if (arc != null) { if (isIndependent) { arc.StartPoint = GetPointOnRegion(matrix, baseGeometry, arc.StartPoint); } arc.IntermedPoint = GetPointOnRegion(matrix, baseGeometry, arc.IntermedPoint); arc.EndPoint = GetPointOnRegion(matrix, baseGeometry, arc.EndPoint); return(arc); } throw new NotSupportedException(); }
/// <summary> /// Insert a segment to the collection at the specified index /// </summary> /// <param name="index">The zero based index at which item should be inserted</param> /// <param name="item">The segment to insert into the collection</param> public void Insert(int index, ISegment3D item) { segments.Insert(index, item); SubscribeEventsFromSegment(item); }
/// <summary> /// Add a segment to polyline /// </summary> /// <param name="segment">New segment to be added</param> public void Add(ISegment3D segment) { segments.Add(segment); SubscribeEventsFromSegment(segment); }
/// <summary> /// Get StraightLine which connects start and end point of the <paramref name=""/> /// </summary> /// <param name="seg"></param> /// <returns>StraightLine</returns> public static StraightLine GetStraightLine(this ISegment3D seg) { return(new StraightLine(seg.StartPoint, seg.EndPoint)); }