/// <summary> /// Determine Point On Region /// </summary> /// <param name="region">Region</param> /// <param name="pointOnRegion">Point to be checked</param> /// <param name="toleranceLevel">Tolerance Level</param> /// <returns>Intersection Results</returns> public static IntersectionResults IsPointOn(IRegion3D region, IPoint3D pointOnRegion, double toleranceLevel = MathConstants.ZeroWeak) { IntersectionResults regionResult = IsPointOn(region.Outline, pointOnRegion, toleranceLevel); if (regionResult != IntersectionResults.Inside) { return(regionResult); } foreach (IPolyLine3D opening in region.Openings) { IntersectionResults openingResult = IsPointOn(opening, pointOnRegion, toleranceLevel); if (openingResult == IntersectionResults.Inside) { return(IntersectionResults.OnInSideOpening); } else if (openingResult == IntersectionResults.Outside) { continue; } else { return(openingResult); } } return(regionResult); }
/// <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()); }
public static double GetRadiusOfSmallestArcSegment(IRegion3D region) { var radius = GetRadiusOfSmallestArcSegment(region.Outline); if (region.Openings.Any()) { if (radius.IsZero(1e-6)) { radius = double.PositiveInfinity; } foreach (IPolyLine3D opening in region.Openings) { var l = GetRadiusOfSmallestArcSegment(opening); if (!l.IsZero(1e-6)) { radius = Math.Min(radius, l); } } if (double.IsPositiveInfinity(radius)) { return(0); } } return(radius); }
/// <summary> /// Calculate the points of region for a given interval /// </summary> /// <param name="region">Geometry Region</param> /// <param name="interval">Interval</param> /// <param name="listOfPoint">List of region points</param> public static void PointsAtInterval(IRegion3D region, double interval, List <IPoint3D> listOfPoint) { if (listOfPoint == null || region == null) { return; } if (region.Outline.Count == 0) { return; } if (interval.IsLesserOrEqual(0) || interval.IsGreaterOrEqual(1)) { return; } PointsAtInterval(region.Outline, interval, listOfPoint); foreach (IPolyLine3D polyline in region.Openings) { List <IPoint3D> openingPoints = new List <IPoint3D>(); PointsAtInterval(polyline, interval, openingPoints); listOfPoint.AddRange(openingPoints); } }
/// <summary> /// Convert Region Points to Point List /// </summary> /// <param name="region">Geometry Region</param> /// <param name="listOfPoint">List of Region point</param> public static void ConvertRegionToPointList(IRegion3D region, List <IPoint3D> listOfPoint) { if (listOfPoint == null || region == null) { return; } if (region.Outline.Count == 0) { return; } List <IPoint3D> outlinePoints = new List <IPoint3D>(); ConvertPolylineToPointList(region.Outline, outlinePoints, false); if (outlinePoints.Count > 0) { outlinePoints.RemoveAt(outlinePoints.Count - 1); listOfPoint.AddRange(outlinePoints); } foreach (IPolyLine3D polyline in region.Openings) { List <IPoint3D> openingPoints = new List <IPoint3D>(); ConvertPolylineToPointList(polyline, openingPoints, false); if (openingPoints.Count > 0) { openingPoints.RemoveAt(openingPoints.Count - 1); listOfPoint.AddRange(openingPoints); } } }
public static double GetLengthOfSmallestArcSegment(IRegion3D region) { double length = GetLengthOfSmallestArcSegment(region.Outline); if (region.Openings.Any()) { if (length.IsZero(1e-6)) { length = double.PositiveInfinity; } foreach (IPolyLine3D opening in region.Openings) { var l = GetLengthOfSmallestArcSegment(opening); if (!l.IsZero(1e-6)) { length = Math.Min(length, l); } } if (double.IsPositiveInfinity(length)) { return(0); } } return(length); }
/// <summary> /// Creates Matrix44 from Region3D data /// </summary> /// <param name="region">Region3D</param> /// <returns>Matrix44</returns> public static Matrix44 MatrixRegion(IRegion3D region) { Region3D reg = region as Region3D; IPoint3D origin = region.Outline[0].StartPoint; return(new Matrix44(origin, reg.LCS.VecX, reg.LCS.VecY, reg.LCS.VecZ)); }
/// <summary> /// Check the given polyline is valid /// </summary> /// <param name="region">The region to be validated</param> /// <returns>True if the polyline is valid</returns> public static bool IsValid(IRegion3D region) { if (region.Outline.IsClosed == false) { return(false); } if (IsValid(region.Outline) == false) { return(false); } foreach (IPolyLine3D opening in region.Openings) { if (opening.IsClosed == false) { return(false); } if (IsValid(opening) == false) { return(false); } } return(true); }
/// <summary> /// Transform a given region to LCS using the matrix /// </summary> /// <param name="matrix">Matrix which is used to transform</param> /// <param name="region">Region which is to be transformed</param> public static void TransformToLCS(IMatrix44 matrix, IRegion3D region) { TransformToLCS(matrix, region.Outline); foreach (IPolyLine3D opening in region.Openings) { TransformToLCS(matrix, opening); } }
/// <summary> /// Point On Region /// </summary> /// <param name="region">Region</param> /// <param name="offsetX">Local Offset X</param> /// <param name="offsetY">Local Offset Y</param> public PointOnRegion(IRegion3D region, double offsetX, double offsetY) { Name = "PointOnRegion"; this.region = region; OffsetX = offsetX; OffsetY = offsetY; UpdatePointOnRegion(); SubscribeEventsFromRegion(); }
/// <summary> /// Move region according to given vector /// </summary> /// <param name="region">Region to be moved</param> /// <param name="displacement">Displacement vector</param> public static void Move(IRegion3D region, Vector3D displacement) { Move(region.Outline, displacement); foreach (IPolyLine3D opening in region.Openings) { Move(opening, displacement); } }
/// <summary> /// Calculate the Length of smallest segment of given region /// </summary> /// <param name="region">IRegion3D</param> /// <returns>Length of smallest segment of given region</returns> public static double GetLengthOfSmallestSegment(IRegion3D region) { double length = GetLengthOfSmallestSegment(region.Outline); foreach (IPolyLine3D opening in region.Openings) { length = Math.Min(length, GetLengthOfSmallestSegment(opening)); } return(length); }
/// <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> /// Prepare new region by divide the arc segments into several linear segments /// </summary> /// <param name="region">IRegion3D</param> /// <param name="distance">Maximum distance of a line segment which is created from curved segments</param> /// <returns>New PolyLine3D</returns> public static IRegion3D GetLinearSegments(IRegion3D region, double distance) { IRegion3D newRegion = new Region3D { Outline = GetLinearSegments(region.Outline, distance) }; foreach (IPolyLine3D opening in region.Openings) { newRegion.AddOpening(GetLinearSegments(opening, distance)); } return(newRegion); }
/// <summary> /// Convert Region3D to Region2D /// </summary> /// <param name="region3D">3D Region</param> /// <returns>2D Region</returns> public static IRegion2D ConvertTo2D(IRegion3D region3D) { IRegion2D region2D = new Region2D { Outline = ConvertTo2D(region3D.Outline) }; foreach (IPolyLine3D polyline in region3D.Openings) { region2D.Openings.Add(ConvertTo2D(polyline)); } return(region2D); }
/// <summary> /// Calculate relative position of point on polyline. /// </summary> /// <param name="region">region</param> /// <param name="point">Point</param> /// <param name="relativeX">Relative Position along local X axis</param> /// <param name="relativeY">Relative Position along local Y axis</param> /// <param name="toleranceLevel">Tolerance Level</param> /// <returns>True if point exist in polyline</returns> public static bool GetRelativePosition(IRegion3D region, IPoint3D point, ref double relativeX, ref double relativeY, double toleranceLevel = MathConstants.ZeroWeak) { IMatrix44 matrix = GeomOperation.GetMatrixPlane(region); IPoint3D pointInLCS = matrix.TransformToLCS(point); if (pointInLCS.Z.IsZero() == false) { return(false); } relativeX = pointInLCS.X; relativeY = pointInLCS.Y; return(true); }
/// <summary> /// Prepare new region by divide the arc segments into several linear segments /// </summary> /// <param name="region">IRegion3D</param> /// <param name="numberOfParts">Number of linear parts</param> /// <returns>New PolyLine3D</returns> public static IRegion3D GetLinearSegments(IRegion3D region, int numberOfParts) { IRegion3D newRegion = new Region3D { Outline = GetLinearSegments(region.Outline, numberOfParts) }; foreach (IPolyLine3D opening in region.Openings) { newRegion.AddOpening(GetLinearSegments(opening, numberOfParts)); } return(newRegion); }
/// <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> /// Calculate points at a given position for each segment /// </summary> /// <param name="region">Geometry Region</param> /// <param name="relativePosition">Relative position of each segment</param> /// <param name="listOfPoint">List of points</param> public static void PointsAtPosition(IRegion3D region, double relativePosition, ICollection <IPoint3D> listOfPoint) { if (listOfPoint == null || region == null) { return; } if (region.Outline.Count == 0) { return; } PointsAtPosition(region.Outline, relativePosition, listOfPoint); foreach (IPolyLine3D polyline in region.Openings) { PointsAtPosition(polyline, relativePosition, listOfPoint); } }
public static IRegion2D ConvertTo2D(IRegion3D region3D, IMatrix44 lcs) { var regionCopy = new Region3D(region3D); GeomOperation.TransformToLCS(lcs, regionCopy); var outline2D = ConvertTo2D(regionCopy.Outline); var region2D = new Region2D(outline2D); if (regionCopy.OpeningsCount > 0) { foreach (var opening3D in regionCopy.Openings) { region2D.Openings.Add(ConvertTo2D(opening3D)); } } return(region2D); }
/// <summary> /// Get all segments of from the region (including idges of the openings) /// </summary> /// <param name="region"></param> /// <returns></returns> public static IEnumerable <ISegment3D> GetAllSegments(this IRegion3D region) { foreach (var s in region.Outline.Segments) { yield return(s); } if (region.Openings != null && region.Openings.Any()) { foreach (var o in region.Openings) { foreach (var s in o.Segments) { yield return(s); } } } }
/// <summary> /// Prepare a region without reflex angles /// If any segment exists with reflex angle, divide it into two /// </summary> /// <param name="region">Region</param> /// <returns>New region without reflex angle</returns> public static IRegion3D SplitSegmentWithReflexAngle(IRegion3D region) { if (region == null) { return(null); } IRegion3D newRegion = new Region3D { Outline = SplitSegmentWithReflexAngle(region.Outline) }; foreach (IPolyLine3D opening in region.Openings) { newRegion.AddOpening(SplitSegmentWithReflexAngle(opening)); } return(newRegion); }
/// <summary> /// Validates the arc segment in region. /// </summary> /// <param name="region">IRegion3D</param> /// <returns>Validated Region3D</returns> public static IRegion3D GetValidRegion(IRegion3D region) { if (region == null) { return(null); } IRegion3D newRegion = new Region3D { Outline = GetValidPolyLine(region.Outline) }; foreach (IPolyLine3D opening in region.Openings) { newRegion.AddOpening(GetValidPolyLine(opening)); } return(newRegion); }
/// <summary> /// Creates a region from another one /// </summary> /// <param name="source">Source region</param> public Region3D(IRegion3D source) { if (source != null) { Name = (source as ElementBase).Name; Outline = new PolyLine3D(source.Outline); if (source.Openings != null) { openings = new List <IPolyLine3D>(); foreach (IPolyLine3D opening in source.Openings) { AddOpening(new PolyLine3D(opening)); } } if (source.LCS != null) { this.LCS = new CoordSystemByVector(source.LCS); } } }
/// <summary> /// Convert the points of region based on baseGeometry /// </summary> /// <param name="baseGeometry">Based on this region, the given region is modifed</param> /// <param name="region">Input region object</param> /// <param name="modifyInput">If true, given region object is modified. Otherwise prepare new region object</param> /// <returns>Region object which is based on baseGeometry</returns> public static IRegion3D GetRegionOnRegion(IRegion3D baseGeometry, IRegion3D region, bool modifyInput = true) { if (baseGeometry == null || region == null) { return(null); } if (!modifyInput) { region = new Region3D(region); } IMatrix44 matrix = GetMatrixPlane(baseGeometry); GetPolylineOnRegion(matrix, baseGeometry, region.Outline); foreach (IPolyLine3D opening in region.Openings) { GetPolylineOnRegion(matrix, baseGeometry, opening); } return(region); }
/// <summary> /// Prepaer a point on region from given region and point. /// </summary> /// <param name="matrix">LCS matrix of baseGeometry</param> /// <param name="baseGeometry">IRegion3D</param> /// <param name="point">IPoint3D</param> /// <returns>New IPointOnRegion object</returns> public static IPointOnRegion GetPointOnRegion(IMatrix44 matrix, IRegion3D baseGeometry, IPoint3D point) { if (baseGeometry == null || point == null) { return(null); } if (matrix == null) { matrix = GetMatrixPlane(baseGeometry); } IPoint3D pointInLCS = matrix.TransformToLCS(point); if (pointInLCS.Z.IsZero() == false) { throw new NotSupportedException("Screen point and selected region are not in same plane"); } IPointOnRegion pointOnRegion = new PointOnRegion(baseGeometry, pointInLCS.X, pointInLCS.Y); return(pointOnRegion); }
/// <summary> /// Default constructor /// </summary> public PointOnRegion() { Name = "PointOnRegion"; region = new Region3D(); SubscribeEventsFromRegion(); }
/// <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); }