public MLineString UnionM(MLineString l) { if (!this.monotone || !l.monotone) { throw new ApplicationException("MGeometryException.OPERATION_REQUIRES_MONOTONE"); } ICoordinate[] linecoar = l.Coordinates; if (l.GetMeasureDirection() == MGeometryType.Decreasing) { CoordinateArrays.Reverse(linecoar); } ICoordinate[] thiscoar = this.Coordinates; if (this.GetMeasureDirection() == MGeometryType.Decreasing) { CoordinateArrays.Reverse(thiscoar); } // either the last coordinate in thiscoar Equals the first in linecoar; // or the last in linecoar Equals the first in thiscoar; MCoordinate lasttco = (MCoordinate)thiscoar[thiscoar.Length - 1]; MCoordinate firsttco = (MCoordinate)thiscoar[0]; MCoordinate lastlco = (MCoordinate)linecoar[linecoar.Length - 1]; MCoordinate firstlco = (MCoordinate)linecoar[0]; MCoordinate[] newcoar = new MCoordinate[thiscoar.Length + linecoar.Length - 1]; if (lasttco.Equals2D(firstlco) && DoubleComparator.Equals(lasttco.M, firstlco.M)) { Array.Copy(thiscoar, 0, newcoar, 0, thiscoar.Length); Array.Copy(linecoar, 1, newcoar, thiscoar.Length, linecoar.Length - 1); } else if (lastlco.Equals2D(firsttco) && DoubleComparator.Equals(lastlco.M, firsttco.M)) { Array.Copy(linecoar, 0, newcoar, 0, linecoar.Length); Array.Copy(thiscoar, 1, newcoar, linecoar.Length, thiscoar.Length - 1); } else { throw new ApplicationException("MGeometryException.UNIONM_ON_DISJOINT_MLINESTRINGS"); } ICoordinateSequence mcs = this.Factory.CoordinateSequenceFactory.Create(newcoar); MLineString returnmlinestring = new MLineString(mcs, this.Factory); Debug.Assert(returnmlinestring.IsMonotone(false), "new UnionM-ed MLineString is not monotone"); return(returnmlinestring); }
/** * Assigns the first coordinate in the CoordinateSequence to the * <code>beginMeasure</code> and the last coordinate in the * CoordinateSequence to the <code>endMeasure</code>. Measure values for * intermediate coordinates are then interpolated proportionally based on * their 2d offset of the overall 2d length of the LineString. * <p> * If the beginMeasure and endMeasure values are equal it is assumed that * all intermediate coordinates shall be the same value. * * @param beginMeasure * Measure value for first coordinate * @param endMeasure * Measure value for last coordinate */ public void Interpolate(double beginMeasure, double endMeasure) { if (this.IsEmpty) { return; } // interpolate with first vertex = beginMeasure; last vertex = // endMeasure ICoordinate[] coordinates = this.Coordinates; double length = this.Length; double mLength = endMeasure - beginMeasure; double d = 0; bool continuous = DoubleComparator.Equals(beginMeasure, endMeasure); double m = beginMeasure; MCoordinate prevCoord = MCoordinate.ConvertCoordinate(coordinates[0]); prevCoord.M = m; MCoordinate curCoord; for (int i = 1; i < coordinates.Length; i++) { curCoord = MCoordinate.ConvertCoordinate(coordinates[i]); if (continuous) { curCoord.M = beginMeasure; } else { d += curCoord.Distance(prevCoord); m = beginMeasure + (d / length) * mLength; curCoord.M = m; prevCoord = curCoord; } } this.GeometryChanged(); Debug.Assert(this.IsMonotone(false), "interpolate function should always leave IMGeometry monotone"); }
/* * (non-Javadoc) * * @see org.hibernatespatial.mgeom.IMGeometry#GetCoordinatesBetween(double,double) */ public ICoordinateSequence[] GetCoordinatesBetween(double fromM, double toM) { if (!this.IsMonotone(false)) { throw new ApplicationException("MGeometryException.OPERATION_REQUIRES_MONOTONE"); } if (this.IsEmpty || !this.IsMonotone(false)) { return(new MCoordinateSequence[0]); } else { double[] mval = this.GetMeasures(); // determin upper and lower boundaries for the MLineString Measures double lb = Math.Min(mval[0], mval[mval.Length - 1]); double up = Math.Max(mval[0], mval[mval.Length - 1]); // set fromM and toM to maximal/minimal values when they exceed // lowerbound-upperbound fromM = Math.Max(lb, Math.Min(fromM, up)); toM = Math.Max(lb, Math.Min(toM, up)); // if at this point the fromM and toM are equal, then return an // empty MCoordinateSequence if (DoubleComparator.Equals(fromM, toM)) { return(new MCoordinateSequence[0]); } MCoordinate[] mcoords = (MCoordinate[])this.Coordinates; // ensure that we traverse the coordinate array in ascending M-order if (GetMeasureDirection() == MGeometryType.Decreasing) { CoordinateArrays.Reverse(mcoords); } double minM = Math.Min(fromM, toM); double maxM = Math.Max(fromM, toM); List <MCoordinate> mcolist = new List <MCoordinate>(); for (int i = 0; i < mcoords.Length; i++) { if (mcolist.Count == 0 && mcoords[i].M >= minM) { MCoordinate mco2 = mcoords[i]; if (DoubleComparator.Equals(mcoords[i].M, minM)) { mcolist.Add(mco2); } else { MCoordinate mco1 = mcoords[i - 1]; double r = (minM - mco1.M) / (mco2.M - mco1.M); Debug.Assert(DoubleComparator.Equals(mco1.M + r * (mco2.M - mco1.M), minM), "Error on assumption on r"); MCoordinate mc = new MCoordinate( mco1.X + r * (mco2.X - mco1.X), mco1.Y + r * (mco2.Y - mco1.Y), mco1.Z + r * (mco2.Z - mco1.Z), minM); mcolist.Add(mc); } } else if (mcoords[i].M >= minM && mcoords[i].M <= maxM) { mcolist.Add(mcoords[i]); if (DoubleComparator.Equals(mcoords[i].M, maxM)) { break; } } else if (mcoords[i].M > maxM) { // mcoords[i] > Math.max(fromM, toM Debug.Assert(i > 0, "mistaken assumption"); MCoordinate mco2 = mcoords[i]; MCoordinate mco1 = mcoords[i - 1]; double r = (maxM - mco1.M) / (mco2.M - mco1.M); MCoordinate mc = new MCoordinate( mco1.X + r * (mco2.X - mco1.X), mco1.Y + r * (mco2.Y - mco1.Y), mco1.Z + r * (mco2.Z - mco1.Z), maxM ); mcolist.Add(mc); break; } } // copy over, but only to the length of numPnts MCoordinate[] h = new MCoordinate[mcolist.Count]; for (int i = 0; i < mcolist.Count; i++) { h[i] = (MCoordinate)mcolist[i]; } if (!DoubleComparator.Equals(minM, fromM)) { CoordinateArrays.Reverse(h); } MCoordinateSequence mc2 = new MCoordinateSequence(h); return(new MCoordinateSequence[] { mc2 }); } }