// This is where the real work is done. public void AddLine(double x, double y, double?z, double?m) { // If we've already found a point, then we're done. We just need to keep ignoring these // pesky calls. if (_foundPoint != null) { return; } // Make a point for our current position. var thisPoint = CheckShapePointAndGet(m, Ext.GetPoint(x, y, z, m, _srid)); // is the found point between this point and the last, or past this point? if (m != null && _measure.IsWithinRange(_lastPoint.M.Value, m.Value)) { // now we need to do the hard work and find the point in between these two _foundPoint = Functions.LRS.Geometry.InterpolateBetweenGeom(_lastPoint, thisPoint, _measure); if (_lastPoint.IsWithinTolerance(_foundPoint, _tolerance)) { _foundPoint = _lastPoint; IsShapePoint = true; } else if (thisPoint.IsWithinTolerance(_foundPoint, _tolerance)) { _foundPoint = thisPoint; IsShapePoint = true; } } else { // it's past this point---just step along the line _lastPoint = thisPoint; } }
/// <summary> /// Utility Method for removing the consecutive duplicate vertices /// </summary> /// <param name="geometry"></param> /// <param name="tolerance"></param> /// <returns></returns> public static SqlGeometry RemoveDuplicateVertices(SqlGeometry geometry, double tolerance = Constants.Tolerance) { if (!geometry.STIsValid()) { Ext.ThrowIfInvalidGeometry(); } return(geometry.Reduce(tolerance)); }
// Start the figure. Note that since we only operate on LineStrings, this should only be executed // once. public void BeginFigure(double x, double y, double?z, double?m) { if (_foundPoint != null) { return; } // Memorize the point. _lastPoint = CheckShapePointAndGet(m, Ext.GetPoint(x, y, z, m, _srid)); }
// This is where the real work is done. public void AddLine(double x, double y, double?z, double?m) { // To unify code for ascending and descending measures - clipPointMeasure double?clipPointMeasure = GetClipPointMeasure(m); double newX, newY; // If current measure is between start measure and end measure, // we should add segment to the result linestring if (m.IsWithinRange(_clipStartMeasure, _clipEndMeasure)) { // if the geometry is started, just add the point to line if (_started) { _target.AddLine(x, y, z, m); } // Else we need to begin the geom figure first else { var isShapePoint = false; // if clip point is shape point measure then add the point without computation if (m.EqualsTo(clipPointMeasure)) { _target.BeginFigure(x, y, null, m); isShapePoint = true; } else { ComputePointCoordinates(clipPointMeasure, m, x, y, out newX, out newY); // if computed point is within tolerance of last point then begin figure with last point if (Ext.IsWithinTolerance(_previousX, _previousY, newX, newY, _tolerance)) { _target.BeginFigure(_previousX, _previousY, null, _retainClipMeasure ? _clipStartMeasure : _previousM); } // check with current point against new computed point else if (Ext.IsWithinTolerance(x, y, newX, newY, _tolerance)) { _target.BeginFigure(x, y, null, m); isShapePoint = true; } // else begin figure with clipped point else { _target.BeginFigure(newX, newY, null, clipPointMeasure); } } _started = true; if (_clipStartMeasure.EqualsTo(_clipEndMeasure) || isShapePoint) { UpdateLastPoint(x, y, m); return; } _target.AddLine(x, y, z, m); } } // We may still need to add last segment, // if current point is the first one after we passed range of interest else { if (!_started) { var isShapePoint = false; if (clipPointMeasure.IsWithinRange(m, _previousM)) { ComputePointCoordinates(clipPointMeasure, m, x, y, out newX, out newY); // if computed point is within tolerance of last point then begin figure with last point if (Ext.IsWithinTolerance(_previousX, _previousY, newX, newY, _tolerance)) { _target.BeginFigure(_previousX, _previousY, null, _retainClipMeasure ? clipPointMeasure : _previousM); } // check with current point against new computed point else if (Ext.IsWithinTolerance(x, y, newX, newY, _tolerance)) { _target.BeginFigure(x, y, null, _retainClipMeasure ? clipPointMeasure : m); isShapePoint = true; } // else begin figure with clipped point else { _target.BeginFigure(newX, newY, null, clipPointMeasure); } _started = true; if (_clipStartMeasure.EqualsTo(_clipEndMeasure) || isShapePoint) { UpdateLastPoint(x, y, m); return; } } } if (_started && !_finished) { // re calculate clip point measure as it can be changed from above condition. clipPointMeasure = GetClipPointMeasure(m); if (clipPointMeasure.IsWithinRange(m, _previousM)) { ComputePointCoordinates(clipPointMeasure, m, x, y, out newX, out newY); var isWithinLastPoint = Ext.IsWithinTolerance(_previousX, _previousY, newX, newY, _tolerance); var isWithinCurrentPoint = Ext.IsWithinTolerance(x, y, newX, newY, _tolerance); // if computed point is within tolerance of last point then skip if (!isWithinLastPoint) { // if within current point then add current point if (isWithinCurrentPoint) { _target.AddLine(x, y, null, _retainClipMeasure ? clipPointMeasure : m); } // else add computed point else { _target.AddLine(newX, newY, null, clipPointMeasure); } } _finished = true; } } } // re-assign the current co-ordinates to match for next iteration. UpdateLastPoint(x, y, m); }
public static SqlGeometry ExtractGeometry(SqlGeometry sqlGeometry, int elementIndex, int ringIndex = 0) { if (sqlGeometry.IsNullOrEmpty()) { return(sqlGeometry); } // GEOMETRYCOLLECTION if (sqlGeometry.IsGeometryCollection()) { if (elementIndex == 0 || elementIndex > sqlGeometry.STNumGeometries()) { Ext.ThrowInvalidElementIndex(); } // reset geometry and element index and pass through sqlGeometry = sqlGeometry.STGeometryN(elementIndex); elementIndex = 1; // if the resultant is MULTILINE; reset the ring index and assign it to element index if (sqlGeometry.IsMultiLineString()) { elementIndex = ringIndex; ringIndex = 0; } } // Handle for Curve Polygon with Compound Curve if (sqlGeometry.IsCurvePolygon()) { if (elementIndex != 1) { Ext.ThrowInvalidElementIndex(); } if (ringIndex == 0) { return(sqlGeometry); } // re-assign sub component; if it is a COMPOUND CURVE var subComponent = ringIndex == 1 ? sqlGeometry.STExteriorRing() : sqlGeometry.STInteriorRingN(ringIndex - 1); // subtracting exterior ring count if (subComponent.IsCompoundCurve()) { sqlGeometry = subComponent; elementIndex = 1; ringIndex = 1; } } var isSimpleType = sqlGeometry.IsPoint() || sqlGeometry.IsLineString() || sqlGeometry.IsCircularString(); // if simple type then return input geometry when index is 1 or 0 if (isSimpleType) { if (elementIndex != 1) { Ext.ThrowInvalidElementIndex(); } if (ringIndex > 1) { Ext.ThrowInvalidSubElementIndex(); } if (isSimpleType && ringIndex <= 1) { return(sqlGeometry); } } // MULTIPOINT if (sqlGeometry.IsMultiPoint()) { if (elementIndex != 1) { Ext.ThrowInvalidElementIndex(); } if (ringIndex == 0) { return(sqlGeometry); } var obtainedGeom = sqlGeometry.STGeometryN(ringIndex); if (obtainedGeom == null || obtainedGeom.IsNull) { Ext.ThrowInvalidSubElementIndex(); } return(obtainedGeom); } // MULTILINESTRING if (sqlGeometry.IsMultiLineString()) { if (elementIndex > sqlGeometry.STNumGeometries()) { Ext.ThrowInvalidElementIndex(); } if (ringIndex > 1) { Ext.ThrowInvalidSubElementIndex(); } return(sqlGeometry.STGeometryN(elementIndex)); } // COMPOUND CURVE if (sqlGeometry.IsCompoundCurve()) { if (elementIndex != 1) { Ext.ThrowInvalidElementIndex(); } if (ringIndex > 1) { Ext.ThrowInvalidSubElementIndex(); } return(sqlGeometry); } // POLYGON and CURVEPOLYGON if (sqlGeometry.IsPolygon() || sqlGeometry.IsCurvePolygon()) { if (elementIndex != 1) { Ext.ThrowInvalidElementIndex(); } // if sub element index is zero then return the input geometry if (ringIndex == 0) { return(sqlGeometry); } if (ringIndex > sqlGeometry.STNumInteriorRing() + 1) { Ext.ThrowInvalidSubElementIndex(); } return(GetPolygon(sqlGeometry, ringIndex)); } // MULTIPOLYGON if (sqlGeometry.IsMultiPolygon()) { if (elementIndex == 0 || elementIndex > sqlGeometry.STNumGeometries()) { Ext.ThrowInvalidElementIndex(); } sqlGeometry = sqlGeometry.STGeometryN(elementIndex); // if sub element index is zero then return the input geometry if (ringIndex == 0) { return(sqlGeometry); } if (ringIndex > sqlGeometry.STNumInteriorRing() + 1) { Ext.ThrowInvalidSubElementIndex(); } return(GetPolygon(sqlGeometry, ringIndex)); } return(sqlGeometry); }