GEOS  3.13.0dev
LineSegment.h
1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2009 2011 Sandro Santilli <strk@kbt.io>
7  * Copyright (C) 2005-2006 Refractions Research Inc.
8  * Copyright (C) 2001-2002 Vivid Solutions Inc.
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU Lesser General Public Licence as published
12  * by the Free Software Foundation.
13  * See the COPYING file for more information.
14  *
15  **********************************************************************
16  *
17  * Last port: geom/LineSegment.java r18 (JTS-1.11)
18  *
19  **********************************************************************/
20 
21 #pragma once
22 
23 #include <geos/export.h>
24 #include <geos/geom/Coordinate.h> // for composition
25 #include <geos/geom/LineSegment.h>
26 #include <geos/algorithm/Distance.h>
27 #include <geos/algorithm/Orientation.h>
28 
29 #include <array>
30 #include <iostream> // for ostream
31 #include <functional> // for std::hash
32 #include <memory> // for unique_ptr
33 #include <cassert>
34 #include <unordered_set>
35 
36 // Forward declarations
37 namespace geos {
38 namespace geom {
39 class CoordinateSequence;
40 class GeometryFactory;
41 class LineString;
42 }
43 }
44 
45 namespace geos {
46 namespace geom { // geos::geom
47 
61 class GEOS_DLL LineSegment {
62 public:
63 
64 
65  Coordinate p0;
67 
68  LineSegment(const Coordinate& c0, const Coordinate& c1)
69  : p0(c0)
70  , p1(c1)
71  {};
72 
73  LineSegment(double x0, double y0, double x1, double y1)
74  : p0(x0, y0)
75  , p1(x1, y1)
76  {};
77 
78  LineSegment() {};
79 
80 
81  void setCoordinates(const Coordinate& c0, const Coordinate& c1)
82  {
83  p0 = c0;
84  p1 = c1;
85  };
86 
87  void setCoordinates(const LineSegment& ls)
88  {
89  setCoordinates(ls.p0, ls.p1);
90  };
91 
92  // obsoleted, use operator[] instead
93  //const Coordinate& getCoordinate(std::size_t i) const;
94 
95  const Coordinate& operator[](std::size_t i) const
96  {
97  if(i == 0) {
98  return p0;
99  }
100  assert(i == 1);
101  return p1;
102  };
103 
104  Coordinate& operator[](std::size_t i)
105  {
106  if(i == 0) {
107  return p0;
108  }
109  assert(i == 1);
110  return p1;
111  };
112 
114  double minX() const
115  {
116  return std::min(p0.x, p1.x);
117  };
118 
120  double maxX() const
121  {
122  return std::max(p0.x, p1.x);
123  };
124 
126  double minY() const
127  {
128  return std::min(p0.y, p1.y);
129  };
130 
132  double maxY() const
133  {
134  return std::max(p0.y, p1.y);
135  };
136 
138  double getLength() const
139  {
140  return p0.distance(p1);
141  };
142 
147  bool isHorizontal() const
148  {
149  return p0.y == p1.y;
150  };
151 
156  bool isVertical() const
157  {
158  return p0.x == p1.x;
159  };
160 
182  int orientationIndex(const LineSegment& seg) const;
183 
184  // TODO deprecate this
185  int orientationIndex(const LineSegment* seg) const
186  {
187  assert(seg);
188  return orientationIndex(*seg);
189  };
190 
202  int orientationIndex(const CoordinateXY& p) const
203  {
204  return algorithm::Orientation::index(p0, p1, p);
205  }
206 
223  int orientationIndex(const Coordinate& p) const
224  {
225  return algorithm::Orientation::index(p0, p1, p);
226  };
227 
229  void reverse();
230 
232  //
236  void normalize()
237  {
238  if(p1.compareTo(p0) < 0) {
239  reverse();
240  }
241  };
242 
244  double angle() const
245  {
246  return std::atan2(p1.y - p0.y, p1.x - p0.x);
247  };
248 
250  //
253  CoordinateXY midPoint() const
254  {
255  return midPoint(p0, p1);
256  };
257 
258  static CoordinateXY midPoint(const CoordinateXY& pt0, const CoordinateXY& pt1)
259  {
260  return CoordinateXY(
261  (pt0.x + pt1.x) / 2,
262  (pt0.y + pt1.y) / 2);
263  }
264 
266  double distance(const LineSegment& ls) const
267  {
268  return algorithm::Distance::segmentToSegment(p0, p1, ls.p0, ls.p1);
269  };
270 
272  double distance(const CoordinateXY& p) const
273  {
274  return algorithm::Distance::pointToSegment(p, p0, p1);
275  };
276 
286  double distancePerpendicular(const CoordinateXY& p) const
287  {
288  if (p0.equals2D(p1))
289  return p0.distance(p);
291  };
292 
304  double distancePerpendicularOriented(const CoordinateXY& p) const;
305 
320  void pointAlong(double segmentLengthFraction, Coordinate& ret) const
321  {
322  ret = Coordinate(
323  p0.x + segmentLengthFraction * (p1.x - p0.x),
324  p0.y + segmentLengthFraction * (p1.y - p0.y));
325  };
326 
351  void pointAlongOffset(double segmentLengthFraction,
352  double offsetDistance,
353  Coordinate& ret) const;
354 
355 
368  LineSegment offset(double offsetDistance);
369 
370 
388  double projectionFactor(const CoordinateXY& p) const;
389 
405  double segmentFraction(const CoordinateXY& inputPt) const;
406 
415  void project(const Coordinate& p, Coordinate& ret) const;
416 
417  CoordinateXY project(const CoordinateXY& p) const;
418 
434  bool project(const LineSegment& seg, LineSegment& ret) const;
435 
437  //
442  void closestPoint(const CoordinateXY& p, CoordinateXY& ret) const;
443 
453  bool equalsTopo(const LineSegment& other) const;
454 
461  std::array<Coordinate, 2> closestPoints(const LineSegment& line);
462 
463  std::array<Coordinate, 2> closestPoints(const LineSegment* line)
464  {
465  assert(line);
466  return closestPoints(*line);
467  }
468 
481  Coordinate intersection(const LineSegment& line) const;
482 
500 
507  std::unique_ptr<LineString> toGeometry(const GeometryFactory& gf) const;
508 
509 
521  inline int compareTo(const LineSegment& other) const
522  {
523  int comp0 = p0.compareTo(other.p0);
524  if (comp0 != 0) {
525  return comp0;
526  }
527  return p1.compareTo(other.p1);
528  }
529 
530  std::ostream& operator<< (std::ostream& o);
531 
532  inline bool operator==(const LineSegment& rhs) const {
533  return compareTo(rhs) == 0;
534  };
535 
536  inline bool operator<(const LineSegment& rhs) const {
537  return compareTo(rhs) < 0;
538  };
539 
540  inline bool operator>(const LineSegment& rhs) const {
541  return compareTo(rhs) > 0;
542  };
543 
544  struct HashCode {
545  inline std::size_t operator()(const LineSegment & s) const {
546  std::size_t h = std::hash<double>{}(s.p0.x);
547  h ^= (std::hash<double>{}(s.p0.y) << 1);
548  h ^= (std::hash<double>{}(s.p1.x) << 1);
549  return h ^ (std::hash<double>{}(s.p1.y) << 1);
550  }
551 
552  inline std::size_t operator()(const LineSegment * s) const {
553  std::size_t h = std::hash<double>{}(s->p0.x);
554  h ^= (std::hash<double>{}(s->p0.y) << 1);
555  h ^= (std::hash<double>{}(s->p1.x) << 1);
556  return h ^ (std::hash<double>{}(s->p1.y) << 1);
557  }
558 
559  };
560 
561  using UnorderedSet = std::unordered_set<LineSegment, HashCode>;
562 
563 
564 private:
565  void project(double factor, CoordinateXY& ret) const;
566 
567 };
568 
569 
570 // std::ostream& operator<< (std::ostream& o, const LineSegment& l);
571 
572 
573 } // namespace geos::geom
574 } // namespace geos
static double pointToSegment(const geom::CoordinateXY &p, const geom::CoordinateXY &A, const geom::CoordinateXY &B)
static double segmentToSegment(const geom::CoordinateXY &A, const geom::CoordinateXY &B, const geom::CoordinateXY &C, const geom::CoordinateXY &D)
static double pointToLinePerpendicular(const geom::CoordinateXY &p, const geom::CoordinateXY &A, const geom::CoordinateXY &B)
static int index(const geom::CoordinateXY &p1, const geom::CoordinateXY &p2, const geom::CoordinateXY &q)
Returns the orientation index of the direction of the point q relative to a directed infinite line sp...
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:216
Supplies a set of utility methods for building Geometry objects from CoordinateSequence or other Geom...
Definition: GeometryFactory.h:65
Definition: LineSegment.h:61
bool isVertical() const
Definition: LineSegment.h:156
LineSegment(const Coordinate &c0, const Coordinate &c1)
Segment end.
Definition: LineSegment.h:68
double minX() const
gets the minimum X ordinate value
Definition: LineSegment.h:114
int compareTo(const LineSegment &other) const
Compares this object with the specified object for order.
Definition: LineSegment.h:521
int orientationIndex(const CoordinateXY &p) const
Definition: LineSegment.h:202
void pointAlongOffset(double segmentLengthFraction, double offsetDistance, Coordinate &ret) const
Computes the Coordinate that lies a given fraction along the line defined by this segment and offset ...
bool project(const LineSegment &seg, LineSegment &ret) const
Project a line segment onto this line segment and return the resulting line segment.
std::unique_ptr< LineString > toGeometry(const GeometryFactory &gf) const
double minY() const
gets the minimum Y ordinate value
Definition: LineSegment.h:126
void pointAlong(double segmentLengthFraction, Coordinate &ret) const
Computes the Coordinate that lies a given fraction along the line defined by this segment.
Definition: LineSegment.h:320
void project(const Coordinate &p, Coordinate &ret) const
Compute the projection of a point onto the line determined by this line segment.
double maxX() const
gets the maximum X ordinate value
Definition: LineSegment.h:120
bool equalsTopo(const LineSegment &other) const
Returns true if other is topologically equal to this LineSegment (e.g. irrespective of orientation).
void reverse()
Reverses the direction of the line segment.
CoordinateXY midPoint() const
Computes the midpoint of the segment.
Definition: LineSegment.h:253
double distance(const LineSegment &ls) const
Computes the distance between this line segment and another one.
Definition: LineSegment.h:266
int orientationIndex(const LineSegment &seg) const
void normalize()
Puts the line segment into a normalized form.
Definition: LineSegment.h:236
bool isHorizontal() const
Definition: LineSegment.h:147
double getLength() const
Computes the length of the line segment.
Definition: LineSegment.h:138
Coordinate p1
Segment start.
Definition: LineSegment.h:66
double distancePerpendicular(const CoordinateXY &p) const
Definition: LineSegment.h:286
Coordinate lineIntersection(const LineSegment &line) const
Computes the intersection point of the lines defined by two segments, if there is one.
LineSegment offset(double offsetDistance)
int orientationIndex(const Coordinate &p) const
Determines the orientation index of a Coordinate relative to this segment.
Definition: LineSegment.h:223
double angle() const
Definition: LineSegment.h:244
Coordinate intersection(const LineSegment &line) const
double maxY() const
gets the maximum Y ordinate value
Definition: LineSegment.h:132
std::array< Coordinate, 2 > closestPoints(const LineSegment &line)
double distance(const CoordinateXY &p) const
Computes the distance between this line segment and a point.
Definition: LineSegment.h:272
void closestPoint(const CoordinateXY &p, CoordinateXY &ret) const
Computes the closest point on this line segment to another point.
double distancePerpendicularOriented(const CoordinateXY &p) const
double segmentFraction(const CoordinateXY &inputPt) const
Computes the fraction of distance (in [0.0, 1.0]) that the projection of a point occurs along this li...
double projectionFactor(const CoordinateXY &p) const
Compute the projection factor for the projection of the point p onto this LineSegment.
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:453
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25