GEOS  3.13.1
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 
254  CoordinateXY midPoint() const
255  {
256  return midPoint(p0, p1);
257  };
258 
259  static CoordinateXY midPoint(const CoordinateXY& pt0, const CoordinateXY& pt1)
260  {
261  return CoordinateXY(
262  (pt0.x + pt1.x) / 2,
263  (pt0.y + pt1.y) / 2);
264  }
265 
267  double distance(const LineSegment& ls) const
268  {
269  return algorithm::Distance::segmentToSegment(p0, p1, ls.p0, ls.p1);
270  };
271 
273  double distance(const CoordinateXY& p) const
274  {
275  return algorithm::Distance::pointToSegment(p, p0, p1);
276  };
277 
287  double distancePerpendicular(const CoordinateXY& p) const
288  {
289  if (p0.equals2D(p1))
290  return p0.distance(p);
292  };
293 
305  double distancePerpendicularOriented(const CoordinateXY& p) const;
306 
321  void pointAlong(double segmentLengthFraction, Coordinate& ret) const
322  {
323  ret = Coordinate(
324  p0.x + segmentLengthFraction * (p1.x - p0.x),
325  p0.y + segmentLengthFraction * (p1.y - p0.y),
326  p0.z + segmentLengthFraction * (p1.z - p0.z));
327  };
328 
353  void pointAlongOffset(double segmentLengthFraction,
354  double offsetDistance,
355  Coordinate& ret) const;
356 
357 
370  LineSegment offset(double offsetDistance);
371 
372 
390  double projectionFactor(const CoordinateXY& p) const;
391 
407  double segmentFraction(const CoordinateXY& inputPt) const;
408 
417  void project(const Coordinate& p, Coordinate& ret) const;
418 
419  CoordinateXY project(const CoordinateXY& p) const;
420 
436  bool project(const LineSegment& seg, LineSegment& ret) const;
437 
439  //
444  void closestPoint(const CoordinateXY& p, CoordinateXY& ret) const;
445 
455  bool equalsTopo(const LineSegment& other) const;
456 
463  std::array<Coordinate, 2> closestPoints(const LineSegment& line);
464 
465  std::array<Coordinate, 2> closestPoints(const LineSegment* line)
466  {
467  assert(line);
468  return closestPoints(*line);
469  }
470 
483  Coordinate intersection(const LineSegment& line) const;
484 
501  Coordinate lineIntersection(const LineSegment& line) const;
502 
509  std::unique_ptr<LineString> toGeometry(const GeometryFactory& gf) const;
510 
511 
523  inline int compareTo(const LineSegment& other) const
524  {
525  int comp0 = p0.compareTo(other.p0);
526  if (comp0 != 0) {
527  return comp0;
528  }
529  return p1.compareTo(other.p1);
530  }
531 
532  std::ostream& operator<< (std::ostream& o);
533 
534  inline bool operator==(const LineSegment& rhs) const {
535  return compareTo(rhs) == 0;
536  };
537 
538  inline bool operator<(const LineSegment& rhs) const {
539  return compareTo(rhs) < 0;
540  };
541 
542  inline bool operator>(const LineSegment& rhs) const {
543  return compareTo(rhs) > 0;
544  };
545 
546  struct HashCode {
547  inline std::size_t operator()(const LineSegment & s) const {
548  std::size_t h = std::hash<double>{}(s.p0.x);
549  h ^= (std::hash<double>{}(s.p0.y) << 1);
550  h ^= (std::hash<double>{}(s.p1.x) << 1);
551  return h ^ (std::hash<double>{}(s.p1.y) << 1);
552  }
553 
554  inline std::size_t operator()(const LineSegment * s) const {
555  std::size_t h = std::hash<double>{}(s->p0.x);
556  h ^= (std::hash<double>{}(s->p0.y) << 1);
557  h ^= (std::hash<double>{}(s->p1.x) << 1);
558  return h ^ (std::hash<double>{}(s->p1.y) << 1);
559  }
560 
561  };
562 
563  using UnorderedSet = std::unordered_set<LineSegment, HashCode>;
564 
565 
566 private:
567  void project(double factor, CoordinateXY& ret) const;
568 
569 };
570 
571 
572 // std::ostream& operator<< (std::ostream& o, const LineSegment& l);
573 
574 
575 } // namespace geos::geom
576 } // namespace geos
static double pointToSegment(const geom::CoordinateXY &p, const geom::CoordinateXY &A, const geom::CoordinateXY &B)
int orientationIndex(const Coordinate &p) const
Determines the orientation index of a Coordinate relative to this segment.
Definition: LineSegment.h:223
Definition: LineSegment.h:61
Coordinate p1
Segment start.
Definition: LineSegment.h:66
double distancePerpendicular(const CoordinateXY &p) const
Definition: LineSegment.h:287
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:217
bool isVertical() const
Definition: LineSegment.h:156
double minX() const
gets the minimum X ordinate value
Definition: LineSegment.h:114
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:458
int compareTo(const LineSegment &other) const
Compares this object with the specified object for order.
Definition: LineSegment.h:523
bool isHorizontal() const
Definition: LineSegment.h:147
double minY() const
gets the minimum Y ordinate value
Definition: LineSegment.h:126
double maxY() const
gets the maximum Y ordinate value
Definition: LineSegment.h:132
LineSegment(const Coordinate &c0, const Coordinate &c1)
Segment end.
Definition: LineSegment.h:68
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25
double getLength() const
Computes the length of the line segment.
Definition: LineSegment.h:138
double distance(const CoordinateXY &p) const
Computes the distance between this line segment and a point.
Definition: LineSegment.h:273
double distance(const LineSegment &ls) const
Computes the distance between this line segment and another one.
Definition: LineSegment.h:267
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:321
int orientationIndex(const CoordinateXY &p) const
Definition: LineSegment.h:202
static double segmentToSegment(const geom::CoordinateXY &A, const geom::CoordinateXY &B, const geom::CoordinateXY &C, const geom::CoordinateXY &D)
double maxX() const
gets the maximum X ordinate value
Definition: LineSegment.h:120
double angle() const
Definition: LineSegment.h:244
double z
z-coordinate
Definition: Coordinate.h:241
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...
static double pointToLinePerpendicular(const geom::CoordinateXY &p, const geom::CoordinateXY &A, const geom::CoordinateXY &B)
void normalize()
Puts the line segment into a normalized form.
Definition: LineSegment.h:236
CoordinateXY midPoint() const
Computes the midpoint of the segment.
Definition: LineSegment.h:254