Quantcast

Constructing a specific offset point or line.

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Constructing a specific offset point or line.

Jeff Adams-4
My apologies if this has already been discussed, but I couldn't find a way to search the archive.

I need to construct, at a minimum, a single point offset to one side (right or left) of an input line, given a % distance along the line (I.E. 25% from the start point, 10 feet offset to the left).

It would also work for my purposes to construct an entire matching line offset to the right or left, which might be a more generically useful thing to do.

Is there a way to do this using JTS (well, technically I'm using NTS)?  The closest thing I could find was the OffsetCurveBuilder, but that produces points offset around all sides.  I can hack up the source code to just do what I want, but it seems like this is something that might/should be possible using the normal interfaces?

Thanks,
Jeff

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Constructing a specific offset point or line.

Martin Davis
Constructing an offset point from a line is straightforward.   Use
LengthIndexedLine.extractPoint(index, offset) - for your example, this
would look like:  extractPoint(0.25, 10)

Currently there's no way to compute an offset linestring.  This would be
a nice feature to have, alright.  There's some complexity involved in
implementing it for the general case, which is one reason I haven't
tackled this yet.

Jeff Adams wrote:

> My apologies if this has already been discussed, but I couldn't find a
> way to search the archive.
>
> I need to construct, at a minimum, a single point offset to one side
> (right or left) of an input line, given a % distance along the line
> (I.E. 25% from the start point, 10 feet offset to the left).
>
> It would also work for my purposes to construct an entire matching
> line offset to the right or left, which might be a more generically
> useful thing to do.
>
> Is there a way to do this using JTS (well, technically I'm using
> NTS)?  The closest thing I could find was the OffsetCurveBuilder, but
> that produces points offset around all sides.  I can hack up the
> source code to just do what I want, but it seems like this is
> something that might/should be possible using the normal interfaces?
>
> Thanks,
> Jeff
> ------------------------------------------------------------------------
>
> _______________________________________________
> jts-devel mailing list
> [hidden email]
> http://lists.refractions.net/mailman/listinfo/jts-devel
>  

--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Constructing a specific offset point or line.

Jeff Adams-4
Thanks for help on the point.

Is generating the offset line is more complicated than what the OffsetCurveBuilder is already doing?  It seems like if you copy the source for OffsetCurveBuilder and modified it like so:

  public LineString getLineCurve(LineString input, double distance, bool doLeftSide)
  {
    Coordinate[] inputPts = input.GetCoordinates();
    // a zero or negative width buffer of a line/point is empty
    if (distance <= 0.0) return lineList;

    init(distance);
    computeLineBufferCurve(inputPts, doLeftSide);
    Coordinate[] lineCoord = getCoordinates();
    return new LineString(lineCoord)
  }

  private void computeLineBufferCurve(Coordinate[] inputPts, bool doLeftSide)
  {
    int n = inputPts.length - 1;
   
    if (doLeftSide) {
        // compute points for left side of line
        initSideSegments(inputPts[0], inputPts[1], Position.LEFT);
        for (int i = 2; i <= n; i++) {
          addNextSegment(inputPts[i], true);
        }
    } else {
        // compute points for right side of line
        initSideSegments(inputPts[n], inputPts[n - 1], Position.LEFT);
        for (int i = n - 2; i >= 0; i--) {
          addNextSegment(inputPts[i], true);
        }
    }
    addLastSegment();
   
    closePts();
  }

Isn't that awfully close to what I want to do?


On Thu, Aug 7, 2008 at 1:53 PM, Martin Davis <[hidden email]> wrote:
Constructing an offset point from a line is straightforward.   Use LengthIndexedLine.extractPoint(index, offset) - for your example, this would look like:  extractPoint(0.25, 10)

Currently there's no way to compute an offset linestring.  This would be a nice feature to have, alright.  There's some complexity involved in implementing it for the general case, which is one reason I haven't tackled this yet.

Jeff Adams wrote:
My apologies if this has already been discussed, but I couldn't find a way to search the archive.

I need to construct, at a minimum, a single point offset to one side (right or left) of an input line, given a % distance along the line (I.E. 25% from the start point, 10 feet offset to the left).

It would also work for my purposes to construct an entire matching line offset to the right or left, which might be a more generically useful thing to do.

Is there a way to do this using JTS (well, technically I'm using NTS)?  The closest thing I could find was the OffsetCurveBuilder, but that produces points offset around all sides.  I can hack up the source code to just do what I want, but it seems like this is something that might/should be possible using the normal interfaces?

Thanks,
Jeff
------------------------------------------------------------------------

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
 

--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel


_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Constructing a specific offset point or line.

Martin Davis
Have you tested with fairly wiggly lines?  The OffsetCurveLineBuilder
does not produce a single smooth line - where there are concave angles
it introduces "closing arcs", which are probably not what you want.



Jeff Adams wrote:

> Thanks for help on the point.
>
> Is generating the offset line is more complicated than what the
> OffsetCurveBuilder is already doing?  It seems like if you copy the
> source for OffsetCurveBuilder and modified it like so:
>
>   public LineString getLineCurve(LineString input, double distance,
> bool doLeftSide)
>   {
>     Coordinate[] inputPts = input.GetCoordinates();
>     // a zero or negative width buffer of a line/point is empty
>     if (distance <= 0.0) return lineList;
>
>     init(distance);
>     computeLineBufferCurve(inputPts, doLeftSide);
>     Coordinate[] lineCoord = getCoordinates();
>     return new LineString(lineCoord)
>   }
>
>   private void computeLineBufferCurve(Coordinate[] inputPts, bool
> doLeftSide)
>   {
>     int n = inputPts.length - 1;
>    
>     if (doLeftSide) {
>         // compute points for left side of line
>         initSideSegments(inputPts[0], inputPts[1], Position.LEFT);
>         for (int i = 2; i <= n; i++) {
>           addNextSegment(inputPts[i], true);
>         }
>     } else {
>         // compute points for right side of line
>         initSideSegments(inputPts[n], inputPts[n - 1], Position.LEFT);
>         for (int i = n - 2; i >= 0; i--) {
>           addNextSegment(inputPts[i], true);
>         }
>     }
>     addLastSegment();
>    
>     closePts();
>   }
>
> Isn't that awfully close to what I want to do?
>
>
> On Thu, Aug 7, 2008 at 1:53 PM, Martin Davis <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Constructing an offset point from a line is straightforward.   Use
>     LengthIndexedLine.extractPoint(index, offset) - for your example,
>     this would look like:  extractPoint(0.25, 10)
>
>     Currently there's no way to compute an offset linestring.  This
>     would be a nice feature to have, alright.  There's some complexity
>     involved in implementing it for the general case, which is one
>     reason I haven't tackled this yet.
>
>     Jeff Adams wrote:
>
>         My apologies if this has already been discussed, but I
>         couldn't find a way to search the archive.
>
>         I need to construct, at a minimum, a single point offset to
>         one side (right or left) of an input line, given a % distance
>         along the line (I.E. 25% from the start point, 10 feet offset
>         to the left).
>
>         It would also work for my purposes to construct an entire
>         matching line offset to the right or left, which might be a
>         more generically useful thing to do.
>
>         Is there a way to do this using JTS (well, technically I'm
>         using NTS)?  The closest thing I could find was the
>         OffsetCurveBuilder, but that produces points offset around all
>         sides.  I can hack up the source code to just do what I want,
>         but it seems like this is something that might/should be
>         possible using the normal interfaces?
>
>         Thanks,
>         Jeff
>         ------------------------------------------------------------------------
>
>         _______________________________________________
>         jts-devel mailing list
>         [hidden email]
>         <mailto:[hidden email]>
>         http://lists.refractions.net/mailman/listinfo/jts-devel
>          
>
>
>     --
>     Martin Davis
>     Senior Technical Architect
>     Refractions Research, Inc.
>     (250) 383-3022
>
>     _______________________________________________
>     jts-devel mailing list
>     [hidden email]
>     <mailto:[hidden email]>
>     http://lists.refractions.net/mailman/listinfo/jts-devel
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> jts-devel mailing list
> [hidden email]
> http://lists.refractions.net/mailman/listinfo/jts-devel
>  

--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Constructing a specific offset point or line.

Jeff Adams-4
So I haven't commented on this in a while but I figured I'd let you know how it turned out.  You're right, OffsetCurveLineBuilder doesn't seem to do what I want.  So I wrote something to do it by hand instead.

I'm sure it isn't perfect and doesn't handle all cases, but it's what I came up with.  It's really just a "move" not an "offset", in that it doesn't alter the shape of the line at all (depending what you have in mind, a perfect 180 degree curve "offset" to the inside should be a smaller 180 degree curve centered about the same point, whereas my code will move the curve without changing its size, so its center would be moved).  However this works well enough for my purpose.

Anyway, I hope this is useful for someone (and I hope I didn't just duplicate some already-developed function :-o).

Oh and technically this is code using NTS not JTS, (this is c#), but you can port it to java by changing "bool" to "boolean" and a couple other feats of great technical prowess.

        /// <summary>
        /// Moves a line the given distance to either the "left" or
        /// "right" of the line.  The "average" angle of the line is calculated
        /// and that is what is used to determine "left" and "right".
        /// </summary>
        /// <param name="input">The line to shift.</param>
        /// <param name="toTheRight">If true, move to the right.
        ///                          If false, move to the left.</param>
        /// <param name="distance">How far to shift the line.</param>
        /// <returns>A new line, identical to the input except all points in it are
        ///          moved to the left or right.</returns>
        public static ILineString ShiftLine(ILineString input, bool toTheRight,
            double distance)
        {
            if (input.NumPoints < 2)
            {
                throw new ArgumentException("Cannot shift a line with less than two points: " + input);
            }
            double totalWeightedLineAngleRadians = 0.0;
            double totalDistance = 0.0;
            // Iterate over all segments of the line, getting the angle for
            // each and weighting it by how long the segment is.
            for (int i = 1; i < input.NumPoints; i++)
            {
                IPoint point0 = input.GetPointN(i - 1);
                IPoint point1 = input.GetPointN(i);
                // Calculate the angle of this segment of the line.
                double angleRadians = Math.Atan2(point1.Y - point0.Y, point1.X - point0.X);
                double segmentDistance = point0.Distance(point1);
                // Now "weight" the angle by the distance.
                totalWeightedLineAngleRadians += angleRadians * segmentDistance;
                totalDistance += segmentDistance;
            }
            // Now divide total angle by distance to get an "average" angle.
            double avgAngle = totalWeightedLineAngleRadians / totalDistance;
            // Now turn to the right or left.
            if (toTheRight)
            {
                avgAngle -= Math.PI / 2;
            }
            else
            {
                avgAngle += Math.PI / 2;
            }
            // Now convert back to an x/y offset.
            double yOffset = Math.Sin(avgAngle) * distance;
            double xOffset = Math.Cos(avgAngle) * distance;
            ICoordinate[] shiftedCoords = new ICoordinate[input.NumPoints];
            for (int i = 0; i < shiftedCoords.Length; i++)
            {
                IPoint p = input.GetPointN(i);
                shiftedCoords[i] = new Coordinate(p.X + xOffset, p.Y + yOffset);
            }
            return new LineString(shiftedCoords);
        }

        /// <exclude/>
        [Test] public void TestSimpleLineShift()
        {
            double sqrt3 = Math.Sqrt(3);
            ICoordinate[] ls1Coords = new ICoordinate[2];
            ls1Coords[0] = new Coordinate(0, 0);
            ls1Coords[1] = new Coordinate(sqrt3, 1);
            ILineString ls1 = new LineString(ls1Coords);
            ILineString ls2 = StaticHelperClass.ShiftLine(ls1, true, 2/sqrt3);
            AssertDoublesEqual(1/sqrt3, ls2.StartPoint.X, "Wrong start x.");
            AssertDoublesEqual(-1.0, ls2.StartPoint.Y, "Wrong start y.");
            AssertDoublesEqual(sqrt3 + 1/sqrt3, ls2.EndPoint.X, "Wrong end x.");
            AssertDoublesEqual(0.0, ls2.EndPoint.Y, "Wrong end y.");
        }

        /// <exclude/>
        [Test] public void TestBentLineShift()
        {
            ICoordinate[] ls1Coords = new ICoordinate[3];
            ls1Coords[0] = new Coordinate(0, 0);
            ls1Coords[1] = new Coordinate(1, 0);
            ls1Coords[2] = new Coordinate(1, 1);
            ILineString ls1 = new LineString(ls1Coords);
            ILineString ls2 = StaticHelperClass.ShiftLine(ls1, false, Math.Sqrt(2));
            AssertDoublesEqual(-1.0, ls2.GetPointN(0).X, "Wrong 0th x.");
            AssertDoublesEqual(1.0, ls2.GetPointN(0).Y, "Wrong 0th y.");
            AssertDoublesEqual(0.0, ls2.GetPointN(1).X, "Wrong 1st x.");
            AssertDoublesEqual(1.0, ls2.GetPointN(1).Y, "Wrong 1st y.");
            AssertDoublesEqual(0.0, ls2.GetPointN(2).X, "Wrong 2nd x.");
            AssertDoublesEqual(2.0, ls2.GetPointN(2).Y, "Wrong 2nd y.");
        }
        private void AssertDoublesEqual(double double1, double double2, string desc)
        {
            double precisionLimit = 0.00000001;
            Assert.Greater(double2, double1 - precisionLimit, desc);
            Assert.Less(double2, double1 + precisionLimit, desc);
        }



On Thu, Aug 7, 2008 at 5:13 PM, Martin Davis <[hidden email]> wrote:
Have you tested with fairly wiggly lines?  The OffsetCurveLineBuilder does not produce a single smooth line - where there are concave angles it introduces "closing arcs", which are probably not what you want.



Jeff Adams wrote:
Thanks for help on the point.

Is generating the offset line is more complicated than what the OffsetCurveBuilder is already doing?  It seems like if you copy the source for OffsetCurveBuilder and modified it like so:

 public LineString getLineCurve(LineString input, double distance, bool doLeftSide)
 {
   Coordinate[] inputPts = input.GetCoordinates();
   // a zero or negative width buffer of a line/point is empty
   if (distance <= 0.0) return lineList;

   init(distance);
   computeLineBufferCurve(inputPts, doLeftSide);
   Coordinate[] lineCoord = getCoordinates();
   return new LineString(lineCoord)
 }

 private void computeLineBufferCurve(Coordinate[] inputPts, bool doLeftSide)
 {
   int n = inputPts.length - 1;
     if (doLeftSide) {
       // compute points for left side of line
       initSideSegments(inputPts[0], inputPts[1], Position.LEFT);
       for (int i = 2; i <= n; i++) {
         addNextSegment(inputPts[i], true);
       }
   } else {
       // compute points for right side of line
       initSideSegments(inputPts[n], inputPts[n - 1], Position.LEFT);
       for (int i = n - 2; i >= 0; i--) {
         addNextSegment(inputPts[i], true);
       }
   }
   addLastSegment();
     closePts();
 }

Isn't that awfully close to what I want to do?


On Thu, Aug 7, 2008 at 1:53 PM, Martin Davis <[hidden email] <mailto:[hidden email]>> wrote:

   Constructing an offset point from a line is straightforward.   Use
   LengthIndexedLine.extractPoint(index, offset) - for your example,
   this would look like:  extractPoint(0.25, 10)

   Currently there's no way to compute an offset linestring.  This
   would be a nice feature to have, alright.  There's some complexity
   involved in implementing it for the general case, which is one
   reason I haven't tackled this yet.

   Jeff Adams wrote:

       My apologies if this has already been discussed, but I
       couldn't find a way to search the archive.

       I need to construct, at a minimum, a single point offset to
       one side (right or left) of an input line, given a % distance
       along the line (I.E. 25% from the start point, 10 feet offset
       to the left).

       It would also work for my purposes to construct an entire
       matching line offset to the right or left, which might be a
       more generically useful thing to do.

       Is there a way to do this using JTS (well, technically I'm
       using NTS)?  The closest thing I could find was the
       OffsetCurveBuilder, but that produces points offset around all
       sides.  I can hack up the source code to just do what I want,
       but it seems like this is something that might/should be
       possible using the normal interfaces?

       Thanks,
       Jeff
       ------------------------------------------------------------------------

       _______________________________________________
       jts-devel mailing list
       [hidden email]
       <mailto:[hidden email]>

       http://lists.refractions.net/mailman/listinfo/jts-devel
       

   --    Martin Davis
   Senior Technical Architect
   Refractions Research, Inc.
   (250) 383-3022

   _______________________________________________
   jts-devel mailing list
   [hidden email]
   <mailto:[hidden email]>

   http://lists.refractions.net/mailman/listinfo/jts-devel


------------------------------------------------------------------------

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
 

--
Martin Davis
Senior Technical Architect
Refractions Research, Inc.
(250) 383-3022

_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel


_______________________________________________
jts-devel mailing list
[hidden email]
http://lists.refractions.net/mailman/listinfo/jts-devel
Loading...