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/Geometry.java rev. 1.112 18 * 19 **********************************************************************/ 20 21 #ifndef GEOS_GEOM_GEOMETRY_H 22 #define GEOS_GEOM_GEOMETRY_H 23 24 #ifndef USE_UNSTABLE_GEOS_CPP_API 25 #ifndef _MSC_VER 26 # warning "The GEOS C++ API is unstable, please use the C API instead" 27 # warning "HINT: #include geos_c.h" 28 #else 29 #pragma message("The GEOS C++ API is unstable, please use the C API instead") 30 #pragma message("HINT: #include geos_c.h") 31 #endif 32 #endif 33 34 #include <geos/export.h> 35 #include <geos/inline.h> 36 #include <geos/geom/Envelope.h> 37 #include <geos/geom/Dimension.h> // for Dimension::DimensionType 38 #include <geos/geom/GeometryComponentFilter.h> // for inheritance 39 #include <geos/geom/IntersectionMatrix.h> 40 41 #include <algorithm> 42 #include <string> 43 #include <iostream> 44 #include <vector> 45 #include <memory> 46 47 #ifdef _MSC_VER 48 #pragma warning(push) 49 #pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class 50 #pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list 51 #endif 52 53 // Forward declarations 54 namespace geos { 55 namespace geom { 56 class Coordinate; 57 class CoordinateFilter; 58 class CoordinateSequence; 59 class CoordinateSequenceFilter; 60 class GeometryComponentFilter; 61 class GeometryFactory; 62 class GeometryFilter; 63 class PrecisionModel; 64 class Point; 65 } 66 namespace io { // geos.io 67 class Unload; 68 } // namespace geos.io 69 } 70 71 namespace geos { 72 namespace geom { // geos::geom 73 74 /// Geometry types 75 enum GeometryTypeId { 76 /// a point 77 GEOS_POINT, 78 /// a linestring 79 GEOS_LINESTRING, 80 /// a linear ring (linestring with 1st point == last point) 81 GEOS_LINEARRING, 82 /// a polygon 83 GEOS_POLYGON, 84 /// a collection of points 85 GEOS_MULTIPOINT, 86 /// a collection of linestrings 87 GEOS_MULTILINESTRING, 88 /// a collection of polygons 89 GEOS_MULTIPOLYGON, 90 /// a collection of heterogeneus geometries 91 GEOS_GEOMETRYCOLLECTION 92 }; 93 94 enum GeometrySortIndex { 95 SORTINDEX_POINT = 0, 96 SORTINDEX_MULTIPOINT = 1, 97 SORTINDEX_LINESTRING = 2, 98 SORTINDEX_LINEARRING = 3, 99 SORTINDEX_MULTILINESTRING = 4, 100 SORTINDEX_POLYGON = 5, 101 SORTINDEX_MULTIPOLYGON = 6, 102 SORTINDEX_GEOMETRYCOLLECTION = 7 103 }; 104 105 /** 106 * \class Geometry geom.h geos.h 107 * 108 * \brief Basic implementation of Geometry, constructed and 109 * destructed by GeometryFactory. 110 * 111 * <code>clone</code> returns a deep copy of the object. 112 * Use GeometryFactory to construct. 113 * 114 * <H3>Binary Predicates</H3> 115 * Because it is not clear at this time 116 * what semantics for spatial 117 * analysis methods involving <code>GeometryCollection</code>s would be useful, 118 * <code>GeometryCollection</code>s are not supported as arguments to binary 119 * predicates (other than <code>convexHull</code>) or the <code>relate</code> 120 * method. 121 * 122 * <H3>Set-Theoretic Methods</H3> 123 * 124 * The spatial analysis methods will 125 * return the most specific class possible to represent the result. If the 126 * result is homogeneous, a <code>Point</code>, <code>LineString</code>, or 127 * <code>Polygon</code> will be returned if the result contains a single 128 * element; otherwise, a <code>MultiPoint</code>, <code>MultiLineString</code>, 129 * or <code>MultiPolygon</code> will be returned. If the result is 130 * heterogeneous a <code>GeometryCollection</code> will be returned. <P> 131 * 132 * Because it is not clear at this time what semantics for set-theoretic 133 * methods involving <code>GeometryCollection</code>s would be useful, 134 * <code>GeometryCollections</code> 135 * are not supported as arguments to the set-theoretic methods. 136 * 137 * <H4>Representation of Computed Geometries </H4> 138 * 139 * The SFS states that the result 140 * of a set-theoretic method is the "point-set" result of the usual 141 * set-theoretic definition of the operation (SFS 3.2.21.1). However, there are 142 * sometimes many ways of representing a point set as a <code>Geometry</code>. 143 * <P> 144 * 145 * The SFS does not specify an unambiguous representation of a given point set 146 * returned from a spatial analysis method. One goal of JTS is to make this 147 * specification precise and unambiguous. JTS will use a canonical form for 148 * <code>Geometry</code>s returned from spatial analysis methods. The canonical 149 * form is a <code>Geometry</code> which is simple and noded: 150 * <UL> 151 * <LI> Simple means that the Geometry returned will be simple according to 152 * the JTS definition of <code>isSimple</code>. 153 * <LI> Noded applies only to overlays involving <code>LineString</code>s. It 154 * means that all intersection points on <code>LineString</code>s will be 155 * present as endpoints of <code>LineString</code>s in the result. 156 * </UL> 157 * This definition implies that non-simple geometries which are arguments to 158 * spatial analysis methods must be subjected to a line-dissolve process to 159 * ensure that the results are simple. 160 * 161 * <H4> Constructed Points And The Precision Model </H4> 162 * 163 * The results computed by the set-theoretic methods may 164 * contain constructed points which are not present in the input Geometry. 165 * These new points arise from intersections between line segments in the 166 * edges of the input Geometry. In the general case it is not 167 * possible to represent constructed points exactly. This is due to the fact 168 * that the coordinates of an intersection point may contain twice as many bits 169 * of precision as the coordinates of the input line segments. In order to 170 * represent these constructed points explicitly, JTS must truncate them to fit 171 * the PrecisionModel. 172 * 173 * Unfortunately, truncating coordinates moves them slightly. Line segments 174 * which would not be coincident in the exact result may become coincident in 175 * the truncated representation. This in turn leads to "topology collapses" -- 176 * situations where a computed element has a lower dimension than it would in 177 * the exact result. 178 * 179 * When JTS detects topology collapses during the computation of spatial 180 * analysis methods, it will throw an exception. If possible the exception will 181 * report the location of the collapse. 182 * 183 * equals(Object) and hashCode are not overridden, so that when two 184 * topologically equal Geometries are added to HashMaps and HashSets, they 185 * remain distinct. This behaviour is desired in many cases. 186 * 187 */ 188 class GEOS_DLL Geometry { 189 190 public: 191 192 friend class GeometryFactory; 193 194 /// A vector of const Geometry pointers 195 using ConstVect = std::vector<const Geometry*>; 196 197 /// A vector of non-const Geometry pointers 198 using NonConstVect = std::vector<Geometry*>; 199 200 /// An unique_ptr of Geometry 201 using Ptr = std::unique_ptr<Geometry> ; 202 203 /// Make a deep-copy of this Geometry 204 virtual std::unique_ptr<Geometry> clone() const = 0; 205 206 /// Destroy Geometry and all components 207 virtual ~Geometry(); 208 209 210 /** 211 * \brief 212 * Gets the factory which contains the context in which this 213 * geometry was created. 214 * 215 * @return the factory for this geometry 216 */ 217 const GeometryFactory* getFactory()218 getFactory() const 219 { 220 return _factory; 221 } 222 223 /** 224 * \brief 225 * A simple scheme for applications to add their own custom data to 226 * a Geometry. 227 * An example use might be to add an object representing a 228 * Coordinate Reference System. 229 * 230 * Note that user data objects are not present in geometries created 231 * by construction methods. 232 * 233 * @param newUserData an object, the semantics for which are 234 * defined by the application using this Geometry 235 */ 236 void setUserData(void * newUserData)237 setUserData(void* newUserData) 238 { 239 _userData = newUserData; 240 } 241 242 /** 243 * \brief 244 * Gets the user data object for this geometry, if any. 245 * 246 * @return the user data object, or <code>null</code> if none set 247 */ 248 void* getUserData()249 getUserData() const 250 { 251 return _userData; 252 } 253 254 /** \brief 255 * Returns the ID of the Spatial Reference System used by the Geometry. 256 * 257 * GEOS supports Spatial Reference System information in the simple way 258 * defined in the SFS. A Spatial Reference System ID (SRID) is present 259 * in each Geometry object. Geometry provides basic accessor operations 260 * for this field, but no others. The SRID is represented as an integer. 261 * 262 * @return the ID of the coordinate space in which the Geometry is defined. 263 */ 264 virtual int getSRID()265 getSRID() const 266 { 267 return SRID; 268 } 269 270 /** \brief 271 * Sets the ID of the Spatial Reference System used by the Geometry. 272 */ 273 virtual void setSRID(int newSRID)274 setSRID(int newSRID) 275 { 276 SRID = newSRID; 277 } 278 279 /** 280 * \brief 281 * Get the PrecisionModel used to create this Geometry. 282 */ 283 const PrecisionModel* getPrecisionModel() const; 284 285 /// Returns a vertex of this Geometry, or NULL if this is the empty geometry. 286 virtual const Coordinate* getCoordinate() const = 0; //Abstract 287 288 /** 289 * \brief 290 * Returns this Geometry vertices. 291 * Caller takes ownership of the returned object. 292 */ 293 virtual std::unique_ptr<CoordinateSequence> getCoordinates() const = 0; //Abstract 294 295 /// Returns the count of this Geometrys vertices. 296 virtual std::size_t getNumPoints() const = 0; //Abstract 297 298 /// Returns false if the Geometry not simple. 299 virtual bool isSimple() const; 300 301 /// Return a string representation of this Geometry type 302 virtual std::string getGeometryType() const = 0; //Abstract 303 304 /// Return an integer representation of this Geometry type 305 virtual GeometryTypeId getGeometryTypeId() const = 0; //Abstract 306 307 /// Returns the number of geometries in this collection 308 /// (or 1 if this is not a collection) 309 virtual std::size_t getNumGeometries()310 getNumGeometries() const 311 { 312 return 1; 313 } 314 315 /// \brief Returns a pointer to the nth Geometry in this collection 316 /// (or self if this is not a collection) 317 virtual const Geometry* getGeometryN(std::size_t)318 getGeometryN(std::size_t /*n*/) const 319 { 320 return this; 321 } 322 323 /** 324 * \brief Tests the validity of this <code>Geometry</code>. 325 * 326 * Subclasses provide their own definition of "valid". 327 * 328 * @return <code>true</code> if this <code>Geometry</code> is valid 329 * 330 * @see IsValidOp 331 */ 332 virtual bool isValid() const; 333 334 /// Returns whether or not the set of points in this Geometry is empty. 335 virtual bool isEmpty() const = 0; //Abstract 336 337 /// Polygon overrides to check for actual rectangle 338 virtual bool isRectangle()339 isRectangle() const 340 { 341 return false; 342 } 343 344 /// Returns the dimension of this Geometry (0=point, 1=line, 2=surface) 345 virtual Dimension::DimensionType getDimension() const = 0; //Abstract 346 347 /// Checks whether this Geometry consists only of components having dimension d. isDimensionStrict(Dimension::DimensionType d)348 virtual bool isDimensionStrict(Dimension::DimensionType d) const { 349 return d == getDimension(); 350 } 351 isPuntal()352 bool isPuntal() const { 353 return isDimensionStrict(Dimension::P); 354 } 355 isLineal()356 bool isLineal() const { 357 return isDimensionStrict(Dimension::L); 358 } 359 isPolygonal()360 bool isPolygonal() const { 361 return isDimensionStrict(Dimension::A); 362 } 363 isCollection()364 bool isCollection() const { 365 int t = getGeometryTypeId(); 366 return t == GEOS_GEOMETRYCOLLECTION || 367 t == GEOS_MULTIPOINT || 368 t == GEOS_MULTILINESTRING || 369 t == GEOS_MULTIPOLYGON; 370 } 371 372 /// Returns the coordinate dimension of this Geometry (2=XY, 3=XYZ, 4=XYZM in future). 373 virtual uint8_t getCoordinateDimension() const = 0; //Abstract 374 375 /** 376 * \brief 377 * Returns the boundary, or an empty geometry of appropriate 378 * dimension if this <code>Geometry</code> is empty. 379 * 380 * (In the case of zero-dimensional geometries, 381 * an empty GeometryCollection is returned.) 382 * For a discussion of this function, see the OpenGIS Simple 383 * Features Specification. As stated in SFS Section 2.1.13.1, 384 * "the boundary of a Geometry is a set of Geometries of the 385 * next lower dimension." 386 * 387 * @return the closure of the combinatorial boundary 388 * of this <code>Geometry</code>. 389 * Ownershipof the returned object transferred to caller. 390 */ 391 virtual std::unique_ptr<Geometry> getBoundary() const = 0; //Abstract 392 393 /// Returns the dimension of this Geometrys inherent boundary. 394 virtual int getBoundaryDimension() const = 0; //Abstract 395 396 /// Returns this Geometrys bounding box. 397 virtual std::unique_ptr<Geometry> getEnvelope() const; 398 399 /** \brief 400 * Returns the minimum and maximum x and y values in this Geometry, 401 * or a null Envelope if this Geometry is empty. 402 */ 403 virtual const Envelope* getEnvelopeInternal() const; 404 405 /** 406 * Tests whether this geometry is disjoint from the specified geometry. 407 * 408 * The <code>disjoint</code> predicate has the following equivalent 409 * definitions: 410 * - The two geometries have no point in common 411 * - The DE-9IM Intersection Matrix for the two geometries matches 412 * <code>[FF*FF****]</code> 413 * - <code>! g.intersects(this)</code> 414 * (<code>disjoint</code> is the inverse of <code>intersects</code>) 415 * 416 * @param other the Geometry with which to compare this Geometry 417 * @return true if the two <code>Geometry</code>s are disjoint 418 * 419 * @see Geometry::intersects 420 */ 421 virtual bool disjoint(const Geometry* other) const; 422 423 /** \brief 424 * Returns true if the DE-9IM intersection matrix for the two 425 * Geometrys is FT*******, F**T***** or F***T****. 426 */ 427 virtual bool touches(const Geometry* other) const; 428 429 /// Returns true if disjoint returns false. 430 virtual bool intersects(const Geometry* g) const; 431 432 /** 433 * Tests whether this geometry crosses the specified geometry. 434 * 435 * The <code>crosses</code> predicate has the following equivalent 436 * definitions: 437 * - The geometries have some but not all interior points in common. 438 * - The DE-9IM Intersection Matrix for the two geometries matches 439 * - <code>[T*T******]</code> (for P/L, P/A, and L/A situations) 440 * - <code>[T*****T**]</code> (for L/P, A/P, and A/L situations) 441 * - <code>[0********]</code> (for L/L situations) 442 * For any other combination of dimensions this predicate returns 443 * <code>false</code>. 444 * 445 * The SFS defined this predicate only for P/L, P/A, L/L, and L/A 446 * situations. 447 * JTS extends the definition to apply to L/P, A/P and A/L situations 448 * as well, in order to make the relation symmetric. 449 * 450 * @param g the <code>Geometry</code> with which to compare this 451 * <code>Geometry</code> 452 *@return <code>true</code> if the two <code>Geometry</code>s cross. 453 */ 454 virtual bool crosses(const Geometry* g) const; 455 456 /** \brief 457 * Returns true if the DE-9IM intersection matrix for the two 458 * Geometrys is T*F**F***. 459 */ 460 virtual bool within(const Geometry* g) const; 461 462 /// Returns true if other.within(this) returns true. 463 virtual bool contains(const Geometry* g) const; 464 465 /** \brief 466 * Returns true if the DE-9IM intersection matrix for the two 467 * Geometrys is T*T***T** (for two points or two surfaces) 468 * 1*T***T** (for two curves). 469 */ 470 virtual bool overlaps(const Geometry* g) const; 471 472 /** 473 * \brief 474 * Returns true if the elements in the DE-9IM intersection matrix 475 * for the two Geometrys match the elements in intersectionPattern. 476 * 477 * IntersectionPattern elements may be: 0 1 2 T ( = 0, 1 or 2) 478 * F ( = -1) * ( = -1, 0, 1 or 2). 479 * 480 * For more information on the DE-9IM, see the OpenGIS Simple 481 * Features Specification. 482 * 483 * @throws util::IllegalArgumentException if either arg is a collection 484 * 485 */ 486 bool relate(const Geometry* g, 487 const std::string& intersectionPattern) const; 488 489 bool relate(const Geometry & g,const std::string & intersectionPattern)490 relate(const Geometry& g, const std::string& intersectionPattern) const 491 { 492 return relate(&g, intersectionPattern); 493 } 494 495 /// Returns the DE-9IM intersection matrix for the two Geometrys. 496 std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const; 497 relate(const Geometry & g)498 std::unique_ptr<IntersectionMatrix> relate(const Geometry& g) const 499 { 500 return relate(&g); 501 } 502 503 /** 504 * \brief 505 * Returns true if the DE-9IM intersection matrix for the two 506 * Geometrys is T*F**FFF*. 507 */ 508 virtual bool equals(const Geometry* g) const; 509 510 /** \brief 511 * Returns <code>true</code> if this geometry covers the 512 * specified geometry. 513 * 514 * The <code>covers</code> predicate has the following 515 * equivalent definitions: 516 * 517 * - Every point of the other geometry is a point of this geometry. 518 * - The DE-9IM Intersection Matrix for the two geometries is 519 * <code>T*****FF*</code> 520 * or <code>*T****FF*</code> 521 * or <code>***T**FF*</code> 522 * or <code>****T*FF*</code> 523 * - <code>g.coveredBy(this)</code> 524 * (<code>covers</code> is the inverse of <code>coveredBy</code>) 525 * 526 * If either geometry is empty, the value of this predicate 527 * is <tt>false</tt>. 528 * 529 * This predicate is similar to {@link #contains}, 530 * but is more inclusive (i.e. returns <tt>true</tt> for more cases). 531 * In particular, unlike <code>contains</code> it does not distinguish 532 * between points in the boundary and in the interior of geometries. 533 * For most situations, <code>covers</code> should be used in 534 * preference to <code>contains</code>. 535 * As an added benefit, <code>covers</code> is more amenable to 536 * optimization, and hence should be more performant. 537 * 538 * @param g 539 * the <code>Geometry</code> with which to compare this 540 * <code>Geometry</code> 541 * 542 * @return <code>true</code> if this <code>Geometry</code> 543 * covers <code>g</code> 544 * 545 * @see Geometry::contains 546 * @see Geometry::coveredBy 547 */ 548 bool covers(const Geometry* g) const; 549 550 /** \brief 551 * Tests whether this geometry is covered by the 552 * specified geometry. 553 * 554 * The <code>coveredBy</code> predicate has the following 555 * equivalent definitions: 556 * 557 * - Every point of this geometry is a point of the other geometry. 558 * - The DE-9IM Intersection Matrix for the two geometries matches 559 * <code>[T*F**F***]</code> 560 * or <code>[*TF**F***]</code> 561 * or <code>[**FT*F***]</code> 562 * or <code>[**F*TF***]</code> 563 * - <code>g.covers(this)</code> 564 * (<code>coveredBy</code> is the converse of <code>covers</code>) 565 * 566 * If either geometry is empty, the value of this predicate 567 * is <tt>false</tt>. 568 * 569 * This predicate is similar to {@link #within}, 570 * but is more inclusive (i.e. returns <tt>true</tt> for more cases). 571 * 572 * @param g the <code>Geometry</code> with which to compare 573 * this <code>Geometry</code> 574 * @return <code>true</code> if this <code>Geometry</code> 575 * is covered by <code>g</code> 576 * 577 * @see Geometry#within 578 * @see Geometry#covers 579 */ 580 bool coveredBy(const Geometry * g)581 coveredBy(const Geometry* g) const 582 { 583 return g->covers(this); 584 } 585 586 587 /// Returns the Well-known Text representation of this Geometry. 588 virtual std::string toString() const; 589 590 virtual std::string toText() const; 591 592 /// Returns a buffer region around this Geometry having the given width. 593 /// 594 /// @throws util::TopologyException if a robustness error occurs 595 /// 596 std::unique_ptr<Geometry> buffer(double distance) const; 597 598 /// \brief 599 /// Returns a buffer region around this Geometry having the 600 /// given width and with a specified number of segments used 601 /// to approximate curves. 602 /// 603 /// @throws util::TopologyException if a robustness error occurs 604 /// 605 std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments) const; 606 607 /** \brief 608 * Computes a buffer area around this geometry having the given 609 * width and with a specified accuracy of approximation for circular 610 * arcs, and using a specified end cap style. 611 * 612 * Buffer area boundaries can contain circular arcs. 613 * To represent these arcs using linear geometry they must be 614 * approximated with line segments. 615 * 616 * The <code>quadrantSegments</code> argument allows controlling the 617 * accuracy of the approximation by specifying the number of line 618 * segments used to represent a quadrant of a circle 619 * 620 * The end cap style specifies the buffer geometry that will be 621 * created at the ends of linestrings. The styles provided are: 622 * 623 * - BufferOp::CAP_ROUND - (default) a semi-circle 624 * - BufferOp::CAP_BUTT - a straight line perpendicular to the 625 * end segment 626 * - BufferOp::CAP_SQUARE - a half-square 627 * 628 * 629 * @param distance the width of the buffer 630 * (may be positive, negative or 0) 631 * 632 * @param quadrantSegments the number of line segments used 633 * to represent a quadrant of a circle 634 * 635 * @param endCapStyle the end cap style to use 636 * 637 * @return an area geometry representing the buffer region 638 * 639 * @throws util::TopologyException if a robustness error occurs 640 * 641 * @see BufferOp 642 */ 643 std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments, 644 int endCapStyle) const; 645 646 /// \brief 647 /// Returns the smallest convex Polygon that contains 648 /// all the points in the Geometry. 649 virtual std::unique_ptr<Geometry> convexHull() const; 650 651 /** \brief 652 * Computes a new geometry which has all component coordinate sequences 653 * in reverse order (opposite orientation) to this one. 654 * 655 * @return a reversed geometry 656 */ 657 virtual std::unique_ptr<Geometry> reverse() const = 0; 658 659 /** \brief 660 * Returns a Geometry representing the points shared by 661 * this Geometry and other. 662 * 663 * @throws util::TopologyException if a robustness error occurs 664 * @throws util::IllegalArgumentException if either input is a 665 * non-empty GeometryCollection 666 * 667 */ 668 std::unique_ptr<Geometry> intersection(const Geometry* other) const; 669 670 /** \brief 671 * Returns a Geometry representing all the points in this Geometry 672 * and other. 673 * 674 * @throws util::TopologyException if a robustness error occurs 675 * @throws util::IllegalArgumentException if either input is a 676 * non-empty GeometryCollection 677 * 678 */ 679 std::unique_ptr<Geometry> Union(const Geometry* other) const; 680 // throw(IllegalArgumentException *, TopologyException *); 681 682 /** \brief 683 * Computes the union of all the elements of this geometry. Heterogeneous 684 * [GeometryCollections](@ref GeometryCollection) are fully supported. 685 * 686 * The result obeys the following contract: 687 * 688 * - Unioning a set of [LineStrings](@ref LineString) has the effect of fully noding 689 * and dissolving the linework. 690 * - Unioning a set of [Polygons](@ref Polygon) will always 691 * return a polygonal geometry (unlike Geometry::Union(const Geometry* other) const), 692 * which may return geometrys of lower dimension if a topology collapse 693 * occurred. 694 * 695 * @return the union geometry 696 * 697 * @see UnaryUnionOp 698 */ 699 Ptr Union() const; 700 // throw(IllegalArgumentException *, TopologyException *); 701 702 /** 703 * \brief 704 * Returns a Geometry representing the points making up this 705 * Geometry that do not make up other. 706 * 707 * @throws util::TopologyException if a robustness error occurs 708 * @throws util::IllegalArgumentException if either input is a 709 * non-empty GeometryCollection 710 * 711 */ 712 std::unique_ptr<Geometry> difference(const Geometry* other) const; 713 714 /** \brief 715 * Returns a set combining the points in this Geometry not in other, 716 * and the points in other not in this Geometry. 717 * 718 * @throws util::TopologyException if a robustness error occurs 719 * @throws util::IllegalArgumentException if either input is a 720 * non-empty GeometryCollection 721 * 722 */ 723 std::unique_ptr<Geometry> symDifference(const Geometry* other) const; 724 725 /** \brief 726 * Returns true iff the two Geometrys are of the same type and their 727 * vertices corresponding by index are equal up to a specified tolerance. 728 */ 729 virtual bool equalsExact(const Geometry* other, double tolerance = 0) 730 const = 0; // Abstract 731 732 virtual void apply_rw(const CoordinateFilter* filter) = 0; //Abstract 733 virtual void apply_ro(CoordinateFilter* filter) const = 0; //Abstract 734 virtual void apply_rw(GeometryFilter* filter); 735 virtual void apply_ro(GeometryFilter* filter) const; 736 virtual void apply_rw(GeometryComponentFilter* filter); 737 virtual void apply_ro(GeometryComponentFilter* filter) const; 738 739 /** 740 * Performs an operation on the coordinates in this Geometry's 741 * CoordinateSequences. 742 * If the filter reports that a coordinate value has been changed, 743 * {@link #geometryChanged} will be called automatically. 744 * 745 * @param filter the filter to apply 746 */ 747 virtual void apply_rw(CoordinateSequenceFilter& filter) = 0; 748 749 /** 750 * Performs a read-only operation on the coordinates in this 751 * Geometry's CoordinateSequences. 752 * 753 * @param filter the filter to apply 754 */ 755 virtual void apply_ro(CoordinateSequenceFilter& filter) const = 0; 756 757 /** \brief 758 * Apply a filter to each component of this geometry. 759 * The filter is expected to provide a .filter(const Geometry*) 760 * method. 761 * 762 * I intend similar templated methods to replace 763 * all the virtual apply_rw and apply_ro functions... 764 * --strk(2005-02-06); 765 */ 766 template <class T> 767 void applyComponentFilter(T & f)768 applyComponentFilter(T& f) const 769 { 770 for(std::size_t i = 0, n = getNumGeometries(); i < n; ++i) { 771 f.filter(getGeometryN(i)); 772 } 773 } 774 775 /** 776 * Reorganizes this Geometry into normal form (or canonical form). 777 * Starting point of rings is lower left, collections are ordered 778 * by geometry type, etc. 779 */ 780 virtual void normalize() = 0; //Abstract 781 782 /// Comparator for sorting geometry 783 virtual int compareTo(const Geometry* geom) const; 784 785 /** \brief 786 * Returns the minimum distance between this Geometry 787 * and the Geometry g 788 */ 789 virtual double distance(const Geometry* g) const; 790 791 /// Returns the area of this Geometry. 792 virtual double getArea() const; 793 794 /// Returns the length of this Geometry. 795 virtual double getLength() const; 796 797 /** \brief 798 * Tests whether the distance from this Geometry to another 799 * is less than or equal to a specified value. 800 * 801 * @param geom the Geometry to check the distance to 802 * @param cDistance the distance value to compare 803 * @return <code>true</code> if the geometries are less than 804 * <code>distance</code> apart. 805 * 806 * @todo doesn't seem to need being virtual, make it concrete 807 */ 808 virtual bool isWithinDistance(const Geometry* geom, 809 double cDistance) const; 810 811 /** \brief 812 * Computes the centroid of this <code>Geometry</code>. 813 * 814 * The centroid is equal to the centroid of the set of component 815 * Geometries of highest dimension (since the lower-dimension geometries 816 * contribute zero "weight" to the centroid) 817 * 818 * @return a {@link Point} which is the centroid of this Geometry 819 */ 820 virtual std::unique_ptr<Point> getCentroid() const; 821 822 /// Computes the centroid of this Geometry as a Coordinate 823 // 824 /// Returns false if centroid cannot be computed (EMPTY geometry) 825 /// 826 virtual bool getCentroid(Coordinate& ret) const; 827 828 /** \brief 829 * Computes an interior point of this <code>Geometry</code>. 830 * 831 * An interior point is guaranteed to lie in the interior of the Geometry, 832 * if it possible to calculate such a point exactly. Otherwise, 833 * the point may lie on the boundary of the geometry. 834 * 835 * @return a Point which is in the interior of this Geometry, or 836 * null if the geometry doesn't have an interior (empty) 837 */ 838 std::unique_ptr<Point> getInteriorPoint() const; 839 840 /** 841 * \brief 842 * Notifies this Geometry that its Coordinates have been changed 843 * by an external party (using a CoordinateFilter, for example). 844 */ 845 virtual void geometryChanged(); 846 847 /** 848 * \brief 849 * Notifies this Geometry that its Coordinates have been changed 850 * by an external party. 851 */ 852 void geometryChangedAction(); 853 854 protected: 855 856 /// The bounding box of this Geometry 857 mutable std::unique_ptr<Envelope> envelope; 858 859 /// Returns true if the array contains any non-empty Geometrys. 860 template<typename T> hasNonEmptyElements(const std::vector<T> * geometries)861 static bool hasNonEmptyElements(const std::vector<T>* geometries) { 862 return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return !g->isEmpty(); }); 863 } 864 865 /// Returns true if the CoordinateSequence contains any null elements. 866 static bool hasNullElements(const CoordinateSequence* list); 867 868 /// Returns true if the vector contains any null elements. 869 template<typename T> hasNullElements(const std::vector<T> * geometries)870 static bool hasNullElements(const std::vector<T>* geometries) { 871 return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return g == nullptr; }); 872 } 873 874 // static void reversePointOrder(CoordinateSequence* coordinates); 875 // static Coordinate& minCoordinate(CoordinateSequence* coordinates); 876 // static void scroll(CoordinateSequence* coordinates,Coordinate* firstCoordinate); 877 // static int indexOf(Coordinate* coordinate,CoordinateSequence* coordinates); 878 // 879 /** \brief 880 * Returns whether the two Geometrys are equal, from the point 881 * of view of the equalsExact method. 882 */ 883 virtual bool isEquivalentClass(const Geometry* other) const; 884 885 static void checkNotGeometryCollection(const Geometry* g); 886 // throw(IllegalArgumentException *); 887 888 //virtual void checkEqualSRID(Geometry *other); 889 890 //virtual void checkEqualPrecisionModel(Geometry *other); 891 892 virtual Envelope::Ptr computeEnvelopeInternal() const = 0; //Abstract 893 894 virtual int compareToSameClass(const Geometry* geom) const = 0; //Abstract 895 896 int compare(std::vector<Coordinate> a, std::vector<Coordinate> b) const; 897 898 int compare(std::vector<Geometry*> a, std::vector<Geometry*> b) const; 899 900 int compare(const std::vector<std::unique_ptr<Geometry>> & a, const std::vector<std::unique_ptr<Geometry>> & b) const; 901 902 bool equal(const Coordinate& a, const Coordinate& b, 903 double tolerance) const; 904 int SRID; 905 906 Geometry(const Geometry& geom); 907 908 /** \brief 909 * Construct a geometry with the given GeometryFactory. 910 * 911 * Will keep a reference to the factory, so don't 912 * delete it until al Geometry objects referring to 913 * it are deleted. 914 * 915 * @param factory 916 */ 917 Geometry(const GeometryFactory* factory); 918 919 template<typename T> toGeometryArray(std::vector<std::unique_ptr<T>> && v)920 static std::vector<std::unique_ptr<Geometry>> toGeometryArray(std::vector<std::unique_ptr<T>> && v) { 921 static_assert(std::is_base_of<Geometry, T>::value, ""); 922 std::vector<std::unique_ptr<Geometry>> gv(v.size()); 923 for (size_t i = 0; i < v.size(); i++) { 924 gv[i] = std::move(v[i]); 925 } 926 return gv; 927 } 928 929 protected: 930 931 virtual int getSortIndex() const = 0; 932 933 934 private: 935 936 class GEOS_DLL GeometryChangedFilter : public GeometryComponentFilter { 937 public: 938 void filter_rw(Geometry* geom) override; 939 }; 940 941 static GeometryChangedFilter geometryChangedFilter; 942 943 /// The GeometryFactory used to create this Geometry 944 /// 945 /// Externally owned 946 /// 947 const GeometryFactory* _factory; 948 949 void* _userData; 950 }; 951 952 /// \brief 953 /// Write the Well-known Binary representation of this Geometry 954 /// as an HEX string to the given output stream 955 /// 956 GEOS_DLL std::ostream& operator<< (std::ostream& os, const Geometry& geom); 957 958 struct GEOS_DLL GeometryGreaterThen { 959 bool operator()(const Geometry* first, const Geometry* second); 960 }; 961 962 963 /// Return current GEOS version 964 GEOS_DLL std::string geosversion(); 965 966 /** 967 * \brief 968 * Return the version of JTS this GEOS 969 * release has been ported from. 970 */ 971 GEOS_DLL std::string jtsport(); 972 973 // We use this instead of std::pair<unique_ptr<Geometry>> because C++11 974 // forbids that construct: 975 // http://lwg.github.com/issues/lwg-closed.html#2068 976 struct GeomPtrPair { 977 typedef std::unique_ptr<Geometry> GeomPtr; 978 GeomPtr first; 979 GeomPtr second; 980 }; 981 982 } // namespace geos::geom 983 } // namespace geos 984 985 #ifdef _MSC_VER 986 #pragma warning(pop) 987 #endif 988 989 #endif // ndef GEOS_GEOM_GEOMETRY_H 990