public static void AddPaths([NotNull] IList <Linestring> linestringsToAdd, [NotNull] IPolyline toResult) { Func <Pnt3D, WKSPointZ> createPoint; if (GeometryUtils.IsZAware(toResult)) { createPoint = p => WKSPointZUtils.CreatePoint(p.X, p.Y, p.Z); } else { createPoint = p => WKSPointZUtils.CreatePoint(p.X, p.Y, double.NaN); } IPath pathTemplate = GeometryFactory.CreateEmptyPath(toResult); foreach (Linestring resultLinestring in linestringsToAdd) { var pathPoints = new WKSPointZ[resultLinestring.SegmentCount + 1]; var i = 0; foreach (Line3D line3D in resultLinestring) { pathPoints[i++] = createPoint(line3D.StartPoint); } Pnt3D last = resultLinestring[resultLinestring.SegmentCount - 1].EndPoint; pathPoints[i] = createPoint(last); IPath path = GeometryFactory.Clone(pathTemplate); GeometryUtils.AddWKSPointZs((IPointCollection4)path, pathPoints); ((IGeometryCollection)toResult).AddGeometry(path); } }
/// <summary> /// Determines whether the two geometries have the same set of vertices. /// Duplicate vertices are ignored. /// </summary> /// <returns></returns> public bool HaveSameVertices(bool ignoreDuplicateVertices = true) { WKSPointZ[] baseCoords = GeometryUtils.GetWKSPointZs(_baseGeometry, true); WKSPointZ[] compareCoords = GeometryUtils.GetWKSPointZs(_compareGeometry, true); return(WKSPointZUtils.HaveSameVertices(baseCoords, compareCoords, _xyTolerance, _zTolerance, ignoreDuplicateVertices)); }
/// <summary> /// Advances the vertex index of coordsToAdvance starting at currentIndex until /// the point at the index matches coordinateToMatch. All intermediate points are /// added to changedCoords. /// </summary> /// <param name="coordsToAdvance">The list of coordinates (sorted) to go through /// until a coordinate matches <paramref name="coordinateToMatch"/>.</param> /// <param name="index">The index to start at which shall be incremented unit the coordinates match.</param> /// <param name="coordinateToMatch">The target coordinate.</param> /// <param name="comparer">The comparer.</param> /// <param name="changedCoords">The list of coordinates that do not match.</param> /// <param name="addChangesToResult">Whether the changed points should be added to changedCoords</param> /// <param name="reportDuplicateVertices">Whether duplicate vertices in the coordsToAdvance should be reported or not.</param> /// <returns>Whether a match was found or not.</returns> private bool AdvanceIndexUntilMatch( [NotNull] WKSPointZ[] coordsToAdvance, ref int index, WKSPointZ coordinateToMatch, [NotNull] IComparer <WKSPointZ> comparer, [NotNull] ICollection <WKSPointZ> changedCoords, bool addChangesToResult, bool reportDuplicateVertices) { WKSPointZ currentCoord = coordsToAdvance[index]; while (comparer.Compare(coordinateToMatch, currentCoord) >= 0 && index < coordsToAdvance.Length) { // check if within the tolerance - performance could be improved if comparer could directly handle // the tolerance. bool useTolerance = Math.Abs(_xyTolerance) > double.Epsilon || (!double.IsNaN(_zTolerance) && Math.Abs(_zTolerance) > double.Epsilon); if (useTolerance && GeometryUtils.IsSamePoint(currentCoord, coordinateToMatch, _xyTolerance, _zTolerance)) { return(true); } if (addChangesToResult) { // except if it's a duplicate that should not be reported bool sameAsPrevious = WKSPointZUtils.ArePointsEqual( coordsToAdvance, index, index - 1, _xyTolerance, _zTolerance); if (!sameAsPrevious || reportDuplicateVertices) { changedCoords.Add(currentCoord); } } ++index; if (index < coordsToAdvance.Length) { currentCoord = coordsToAdvance[index]; } } return(false); }
private IList <WKSPointZ> GetPointDifference(bool symmetric) { var result = new List <WKSPointZ>(); if (!GeometryUtils.IsSamePoint((IPoint)_baseGeometry, (IPoint)_compareGeometry, _xyTolerance, _zTolerance)) { result.Add(WKSPointZUtils.CreatePoint((IPoint)_baseGeometry)); if (symmetric) { result.Add(WKSPointZUtils.CreatePoint((IPoint)_compareGeometry)); } } return(result); }
public static void AddPoints(IEnumerable <Pnt3D> points, IMultipoint toResult) { Func <Pnt3D, WKSPointZ> createPoint; if (GeometryUtils.IsZAware(toResult)) { createPoint = p => WKSPointZUtils.CreatePoint(p.X, p.Y, p.Z); } else { createPoint = p => WKSPointZUtils.CreatePoint(p.X, p.Y, double.NaN); } WKSPointZ[] wksPointZs = points.Select(p => createPoint(p)).ToArray(); GeometryUtils.AddWKSPointZs((IPointCollection4)toResult, wksPointZs); }
private static WKSPointZ[] GetWksPoints(IEnumerable <Pnt3D> pnts, int pointCount) { WKSPointZ[] wksPointArray = GetWksPointArray(pointCount); var count = 0; foreach (Pnt3D pnt3D in pnts) { if (count == pointCount) { break; } wksPointArray[count++] = WKSPointZUtils.CreatePoint(pnt3D.X, pnt3D.Y, pnt3D.Z); } return(wksPointArray); }
/// <summary> /// Adds the remaining points starting from baseIndexStart for baseCoords and from /// compareIndexStart for compareCoords. /// </summary> /// <param name="baseCoords"></param> /// <param name="compareCoords"></param> /// <param name="baseIndexStart"></param> /// <param name="compareIndexStart"></param> /// <param name="result"></param> /// <param name="reportDuplicateVertices"></param> /// <param name="baseInsertsOnly"></param> private void AddRemainingPoints( WKSPointZ[] baseCoords, WKSPointZ[] compareCoords, int baseIndexStart, int compareIndexStart, List <WKSPointZ> result, bool reportDuplicateVertices, bool baseInsertsOnly) { // add all remaining points from baseCoords for (int i = baseIndexStart; i < baseCoords.Length; i++) { bool sameAsPrevious = WKSPointZUtils.ArePointsEqual( baseCoords, i, i - 1, _xyTolerance, _zTolerance); if (sameAsPrevious && !reportDuplicateVertices) { continue; } result.Add(baseCoords[i]); } if (!baseInsertsOnly) { // add all remaining points from baseCoords for (int i = compareIndexStart; i < compareCoords.Length; i++) { bool sameAsPrevious = WKSPointZUtils.ArePointsEqual(compareCoords, i, i - 1, _xyTolerance, _zTolerance); if (sameAsPrevious && !reportDuplicateVertices) { continue; } result.Add(compareCoords[i]); } } }
private static bool TryGetPlaneVectors(WKSPointZ normal, WKSPointZ vector, out WKSPointZ planeVector1, out WKSPointZ planeVector2) { planeVector1 = WKSPointZUtils.GetVectorProduct(normal, vector); const double e = 0.1; if (GetLength2(planeVector1) < e) { planeVector2 = new WKSPointZ(); return(false); } planeVector1 = WKSPointZUtils.GetNormed(planeVector1); planeVector2 = WKSPointZUtils.GetVectorProduct(normal, planeVector1); return(GetLength2(planeVector2) >= e); }
public void GetPlaneVectors(out WKSPointZ planeVector1, out WKSPointZ planeVector2) { WKSPointZ normal = GetNormalVector(); if (TryGetPlaneVectors(normal, WKSPointZUtils.CreatePoint(1, 0, 0), out planeVector1, out planeVector2)) { return; } if (TryGetPlaneVectors(normal, WKSPointZUtils.CreatePoint(0, 1, 0), out planeVector1, out planeVector2)) { return; } if (TryGetPlaneVectors(normal, WKSPointZUtils.CreatePoint(0, 0, 1), out planeVector1, out planeVector2)) { return; } throw new InvalidOperationException("unable to create plane vectors"); }
public WKSPointZ GetPlaneVector() { WKSPointZ normal = GetNormalVector(); WKSPointZ planeVector; if (TryGetNormal(normal, WKSPointZUtils.CreatePoint(1, 0, 0), out planeVector)) { } else if (TryGetNormal(normal, WKSPointZUtils.CreatePoint(0, 1, 0), out planeVector)) { } else if (TryGetNormal(normal, WKSPointZUtils.CreatePoint(0, 0, 1), out planeVector)) { } else { throw new InvalidOperationException("unable to create plane vector"); } WKSPointZ normedPlaneVector = WKSPointZUtils.GetNormed(planeVector); return(normedPlaneVector); }
private IList <WKSPointZ> GetChangedVertices( WKSPointZ[] baseCoords, WKSPointZ[] compareCoords, bool reportDuplicateVertices, bool baseInsertsOnly) { Assert.ArgumentNotNull(baseCoords, nameof(baseCoords)); Assert.ArgumentNotNull(compareCoords, nameof(compareCoords)); var comparer = new WKSPointZComparer(_xyTolerance, _zTolerance, 0, 0, 0); Array.Sort(baseCoords, comparer); Array.Sort(compareCoords, comparer); var result = new List <WKSPointZ>(); var i1 = 0; var i2 = 0; while (i1 < baseCoords.Length && i2 < compareCoords.Length) { WKSPointZ a = baseCoords[i1]; WKSPointZ b = compareCoords[i2]; bool inSync = GeometryUtils.IsSamePoint(a, b, _xyTolerance, _zTolerance); if (!inSync) { // a is greater than b, advance b until in sync with a bool matchAdvanceCompareCoords = AdvanceIndexUntilMatch( compareCoords, ref i2, a, comparer, result, !baseInsertsOnly, reportDuplicateVertices); // b is greater than a, advance a until in sync with b bool matchAdvanceBaseCoords = AdvanceIndexUntilMatch( baseCoords, ref i1, b, comparer, result, true, reportDuplicateVertices); if (matchAdvanceCompareCoords || matchAdvanceBaseCoords) { inSync = true; } } // Advance to next set of coordinates only if in sync to make sure no difference points are missed if (inSync) { ++i1; ++i2; } // Skip identical points in sequence otherwise From/To points in rotated ring get reported as changes // NOTE: SameCoords tolerates index out of bounds! while (WKSPointZUtils.ArePointsEqual(baseCoords, i1, i1 - 1, _xyTolerance, _zTolerance)) { bool compareCoordsHasDuplicateToo = inSync && WKSPointZUtils.ArePointsEqual(compareCoords, i2, i2 - 1, _xyTolerance, _zTolerance); if (compareCoordsHasDuplicateToo) { // in sync and both have a duplicate at the same location -> unchanged, do not report // but increment both indexes ++i2; } else { // not in sync or compare geometry has no duplicate -> changed, report on request if (reportDuplicateVertices) { result.Add(baseCoords[i1]); } } // eventually landing at the next non-identical point: ++i1; } // process remaining duplicates at current location (or at original location if not in sync) while (WKSPointZUtils.ArePointsEqual(compareCoords, i2, i2 - 1, _xyTolerance, _zTolerance)) { if (reportDuplicateVertices && !baseInsertsOnly) { result.Add(compareCoords[i2]); } ++i2; } } AddRemainingPoints(baseCoords, compareCoords, i1, i2, result, reportDuplicateVertices, baseInsertsOnly); return(result); }
private static bool TryGetNormal(WKSPointZ v0, WKSPointZ v1, out WKSPointZ normal) { normal = WKSPointZUtils.GetVectorProduct(v0, v1); return(GetLength2(normal) > 0.1); }