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  p0.z + segmentLengthFraction * (p1.z - p0.z));
326  };
327 
352  void pointAlongOffset(double segmentLengthFraction,
353  double offsetDistance,
354  Coordinate& ret) const;
355 
356 
369  LineSegment offset(double offsetDistance);
370 
371 
389  double projectionFactor(const CoordinateXY& p) const;
390 
406  double segmentFraction(const CoordinateXY& inputPt) const;
407 
416  void project(const Coordinate& p, Coordinate& ret) const;
417 
418  CoordinateXY project(const CoordinateXY& p) const;
419 
435  bool project(const LineSegment& seg, LineSegment& ret) const;
436 
438  //
443  void closestPoint(const CoordinateXY& p, CoordinateXY& ret) const;
444 
454  bool equalsTopo(const LineSegment& other) const;
455 
462  std::array<Coordinate, 2> closestPoints(const LineSegment& line);
463 
464  std::array<Coordinate, 2> closestPoints(const LineSegment* line)
465  {
466  assert(line);
467  return closestPoints(*line);
468  }
469 
482  Coordinate intersection(const LineSegment& line) const;
483 
501 
508  std::unique_ptr<LineString> toGeometry(const GeometryFactory& gf) const;
509 
510 
522  inline int compareTo(const LineSegment& other) const
523  {
524  int comp0 = p0.compareTo(other.p0);
525  if (comp0 != 0) {
526  return comp0;
527  }
528  return p1.compareTo(other.p1);
529  }
530 
531  std::ostream& operator<< (std::ostream& o);
532 
533  inline bool operator==(const LineSegment& rhs) const {
534  return compareTo(rhs) == 0;
535  };
536 
537  inline bool operator<(const LineSegment& rhs) const {
538  return compareTo(rhs) < 0;
539  };
540 
541  inline bool operator>(const LineSegment& rhs) const {
542  return compareTo(rhs) > 0;
543  };
544 
545  struct HashCode {
546  inline std::size_t operator()(const LineSegment & s) const {
547  std::size_t h = std::hash<double>{}(s.p0.x);
548  h ^= (std::hash<double>{}(s.p0.y) << 1);
549  h ^= (std::hash<double>{}(s.p1.x) << 1);
550  return h ^ (std::hash<double>{}(s.p1.y) << 1);
551  }
552 
553  inline std::size_t operator()(const LineSegment * s) const {
554  std::size_t h = std::hash<double>{}(s->p0.x);
555  h ^= (std::hash<double>{}(s->p0.y) << 1);
556  h ^= (std::hash<double>{}(s->p1.x) << 1);
557  return h ^ (std::hash<double>{}(s->p1.y) << 1);
558  }
559 
560  };
561 
562  using UnorderedSet = std::unordered_set<LineSegment, HashCode>;
563 
564 
565 private:
566  void project(double factor, CoordinateXY& ret) const;
567 
568 };
569 
570 
571 // std::ostream& operator<< (std::ostream& o, const LineSegment& l);
572 
573 
574 } // namespace geos::geom
575 } // 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
double z
z-coordinate
Definition: Coordinate.h:236
Supplies a set of utility methods for building Geometry objects from CoordinateSequence or other Geom...
Definition: GeometryFactory.h:70
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:522
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