Coverage Report

Created: 2025-10-10 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/geom/Geometry.cpp
Line
Count
Source
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
#include <geos/geom/HeuristicOverlay.h>
22
#include <geos/geom/Geometry.h>
23
#include <geos/geom/GeometryFactory.h>
24
#include <geos/geom/PrecisionModel.h>
25
#include <geos/geom/CoordinateSequence.h>
26
#include <geos/geom/GeometryComponentFilter.h>
27
#include <geos/geom/GeometryFilter.h>
28
#include <geos/geom/GeometryCollection.h>
29
#include <geos/geom/Point.h>
30
#include <geos/geom/MultiPoint.h>
31
#include <geos/geom/LineString.h>
32
#include <geos/geom/LinearRing.h>
33
#include <geos/geom/MultiLineString.h>
34
#include <geos/geom/MultiPolygon.h>
35
#include <geos/geom/IntersectionMatrix.h>
36
#include <geos/util/IllegalArgumentException.h>
37
#include <geos/algorithm/Centroid.h>
38
#include <geos/algorithm/InteriorPointPoint.h>
39
#include <geos/algorithm/InteriorPointLine.h>
40
#include <geos/algorithm/InteriorPointArea.h>
41
#include <geos/algorithm/ConvexHull.h>
42
#include <geos/algorithm/locate/SimplePointInAreaLocator.h>
43
#include <geos/geom/prep/PreparedGeometryFactory.h>
44
#include <geos/operation/intersection/Rectangle.h>
45
#include <geos/operation/intersection/RectangleIntersection.h>
46
#include <geos/operation/predicate/RectangleContains.h>
47
#include <geos/operation/predicate/RectangleIntersects.h>
48
#include <geos/operation/relate/RelateOp.h>
49
#include <geos/operation/relateng/RelateNG.h>
50
#include <geos/operation/relateng/RelatePredicate.h>
51
#include <geos/operation/valid/IsValidOp.h>
52
#include <geos/operation/union/UnaryUnionOp.h>
53
#include <geos/operation/buffer/BufferOp.h>
54
#include <geos/operation/distance/DistanceOp.h>
55
#include <geos/operation/valid/IsSimpleOp.h>
56
#include <geos/operation/overlayng/OverlayNGRobust.h>
57
#include <geos/operation/overlayng/OverlayUtil.h>
58
#include <geos/io/WKBWriter.h>
59
#include <geos/io/WKTWriter.h>
60
#include <geos/version.h>
61
62
#include <algorithm>
63
#include <string>
64
#include <typeinfo>
65
#include <vector>
66
#include <cassert>
67
#include <memory>
68
69
#ifdef _MSC_VER
70
#  ifdef MSVC_USE_VLD
71
#    include <vld.h>
72
#  endif
73
#endif
74
75
#define SHORTCIRCUIT_PREDICATES 1
76
//#define USE_RECTANGLE_INTERSECTION 1
77
#define USE_RELATENG 1
78
79
using namespace geos::algorithm;
80
using namespace geos::operation::valid;
81
using namespace geos::operation::relate;
82
using namespace geos::operation::buffer;
83
using namespace geos::operation::distance;
84
using namespace geos::operation;
85
using geos::operation::overlayng::OverlayNG;
86
87
88
namespace geos {
89
namespace geom { // geos::geom
90
91
92
/*
93
 * Return current GEOS version
94
 */
95
std::string
96
geosversion()
97
0
{
98
0
    return GEOS_VERSION;
99
0
}
100
101
/*
102
 * Return the version of JTS this GEOS
103
 * release has been ported from.
104
 */
105
std::string
106
jtsport()
107
0
{
108
0
    return GEOS_JTS_PORT;
109
0
}
110
111
Geometry::GeometryChangedFilter Geometry::geometryChangedFilter;
112
113
Geometry::Geometry(const GeometryFactory* newFactory)
114
    :
115
22.7M
    _factory(newFactory),
116
22.7M
    _userData(nullptr)
117
22.7M
{
118
22.7M
    if(_factory == nullptr) {
119
0
        _factory = GeometryFactory::getDefaultInstance();
120
0
    }
121
22.7M
    SRID = _factory->getSRID();
122
22.7M
    _factory->addRef();
123
22.7M
}
124
125
Geometry::Geometry(const Geometry& geom)
126
    :
127
35.5M
    SRID(geom.getSRID()),
128
35.5M
    _factory(geom._factory),
129
35.5M
    _userData(nullptr)
130
35.5M
{
131
35.5M
    _factory->addRef();
132
35.5M
}
133
134
bool
135
Geometry::hasNullElements(const CoordinateSequence* list)
136
0
{
137
0
    std::size_t npts = list->getSize();
138
0
    for(std::size_t i = 0; i < npts; ++i) {
139
0
        if(list->getAt(i).isNull()) {
140
0
            return true;
141
0
        }
142
0
    }
143
0
    return false;
144
0
}
145
146
/* public */
147
bool
148
Geometry::isWithinDistance(const Geometry* geom, double cDistance) const
149
0
{
150
0
    return DistanceOp::isWithinDistance(*this, *geom, cDistance);
151
0
}
152
153
/*public*/
154
std::unique_ptr<Point>
155
Geometry::getCentroid() const
156
0
{
157
0
    Coordinate centPt;
158
0
    if(! getCentroid(centPt)) {
159
0
        return getFactory()->createPoint(getCoordinateDimension());
160
0
    }
161
162
    // We don't use createPointFromInternalCoord here
163
    // because ::getCentroid() takes care about rounding
164
0
    return std::unique_ptr<Point>(getFactory()->createPoint(centPt));
165
0
}
166
167
/* public */
168
bool
169
Geometry::isMixedDimension() const
170
47.9k
{
171
47.9k
    Dimension::DimensionType baseDim = Dimension::DONTCARE;
172
47.9k
    return isMixedDimension(&baseDim);
173
47.9k
}
174
175
/* public */
176
bool
177
Geometry::isMixedDimension(Dimension::DimensionType* baseDim) const
178
15.8M
{
179
15.8M
    if (isCollection()) {
180
15.8M
        for (std::size_t i = 0; i < getNumGeometries(); i++) {
181
15.7M
            if (getGeometryN(i)->isMixedDimension(baseDim))
182
10.5k
                return true;
183
15.7M
        }
184
68.3k
        return false;
185
78.8k
    }
186
15.7M
    else {
187
15.7M
        if (*baseDim == Dimension::DONTCARE) {
188
46.8k
            *baseDim = getDimension();
189
46.8k
            return false;
190
46.8k
        }
191
15.6M
        return *baseDim != getDimension();
192
15.7M
    }
193
15.8M
}
194
195
/*public*/
196
bool
197
Geometry::getCentroid(CoordinateXY& ret) const
198
0
{
199
0
    if(isEmpty()) {
200
0
        return false;
201
0
    }
202
0
    if(! Centroid::getCentroid(*this, ret)) {
203
0
        return false;
204
0
    }
205
0
    getPrecisionModel()->makePrecise(ret); // not in JTS
206
0
    return true;
207
0
}
208
209
std::unique_ptr<Point>
210
Geometry::getInteriorPoint() const
211
0
{
212
0
    geos::util::ensureNoCurvedComponents(this);
213
214
0
    Coordinate interiorPt;
215
0
    int dim = getDimension();
216
0
    if(dim == 0) {
217
0
        InteriorPointPoint intPt(this);
218
0
        if(! intPt.getInteriorPoint(interiorPt)) {
219
0
            return getFactory()->createPoint(getCoordinateDimension()); // POINT EMPTY
220
0
        }
221
0
    }
222
0
    else if(dim == 1) {
223
0
        InteriorPointLine intPt(this);
224
0
        if(! intPt.getInteriorPoint(interiorPt)) {
225
0
            return getFactory()->createPoint(getCoordinateDimension()); // POINT EMPTY
226
0
        }
227
0
    }
228
0
    else {
229
0
        InteriorPointArea intPt(this);
230
0
        if(! intPt.getInteriorPoint(interiorPt)) {
231
0
            return getFactory()->createPoint(getCoordinateDimension()); // POINT EMPTY
232
0
        }
233
0
    }
234
0
    std::unique_ptr<Point> p(getFactory()->createPointFromInternalCoord(&interiorPt, this));
235
0
    return p;
236
0
}
237
238
/**
239
 * Notifies this Geometry that its Coordinates have been changed by an external
240
 * party (using a CoordinateFilter, for example). The Geometry will flush
241
 * and/or update any information it has cached (such as its {@link Envelope} ).
242
 */
243
void
244
Geometry::geometryChanged()
245
37.9k
{
246
37.9k
    apply_rw(&geometryChangedFilter);
247
37.9k
}
248
249
bool
250
Geometry::isValid() const
251
0
{
252
0
    return IsValidOp(this).isValid();
253
0
}
254
255
std::unique_ptr<Geometry>
256
Geometry::getEnvelope() const
257
0
{
258
0
    return std::unique_ptr<Geometry>(getFactory()->toGeometry(getEnvelopeInternal()));
259
0
}
260
261
bool
262
Geometry::disjoint(const Geometry* g) const
263
0
{
264
0
#if USE_RELATENG
265
0
    return operation::relateng::RelateNG::disjoint(this, g);
266
#else
267
    return !intersects(g);
268
#endif
269
0
}
270
271
bool
272
Geometry::touches(const Geometry* g) const
273
0
{
274
0
#ifdef SHORTCIRCUIT_PREDICATES
275
    // short-circuit test
276
0
    if(! getEnvelopeInternal()->intersects(g->getEnvelopeInternal())) {
277
0
        return false;
278
0
    }
279
0
#endif
280
281
0
#if USE_RELATENG
282
0
    return operation::relateng::RelateNG::touches(this, g);
283
#else
284
    std::unique_ptr<IntersectionMatrix> im(relate(g));
285
    bool res = im->isTouches(getDimension(), g->getDimension());
286
    return res;
287
#endif
288
0
}
289
290
bool
291
Geometry::intersects(const Geometry* g) const
292
0
{
293
0
#ifdef SHORTCIRCUIT_PREDICATES
294
    // short-circuit test
295
0
    if(! getEnvelopeInternal()->intersects(g->getEnvelopeInternal())) {
296
0
        return false;
297
0
    }
298
0
#endif
299
300
    /*
301
     * TODO: (MD) Add optimizations:
302
     *
303
     * - for P-A case:
304
     * If P is in env(A), test for point-in-poly
305
     *
306
     * - for A-A case:
307
     * If env(A1).overlaps(env(A2))
308
     * test for overlaps via point-in-poly first (both ways)
309
     * Possibly optimize selection of point to test by finding point of A1
310
     * closest to centre of env(A2).
311
     * (Is there a test where we shouldn't bother - e.g. if env A
312
     * is much smaller than env B, maybe there's no point in testing
313
     * pt(B) in env(A)?
314
     */
315
316
    // optimization for rectangle arguments
317
0
    if(isRectangle()) {
318
0
        const Polygon* p = detail::down_cast<const Polygon*>(this);
319
0
        return predicate::RectangleIntersects::intersects(*p, *g);
320
0
    }
321
0
    if(g->isRectangle()) {
322
0
        const Polygon* p = detail::down_cast<const Polygon*>(g);
323
0
        return predicate::RectangleIntersects::intersects(*p, *this);
324
0
    }
325
326
0
    auto typ = getGeometryTypeId();
327
0
    if (typ == GEOS_CURVEPOLYGON && g->getGeometryTypeId() == GEOS_POINT) {
328
0
        auto loc = locate::SimplePointInAreaLocator::locatePointInSurface(*g->getCoordinate(), *detail::down_cast<const Surface*>(this));
329
0
        return loc != Location::EXTERIOR;
330
0
    } else if (typ == GEOS_POINT && g->getGeometryTypeId() == GEOS_CURVEPOLYGON) {
331
0
        auto loc = locate::SimplePointInAreaLocator::locatePointInSurface(*getCoordinate(), *detail::down_cast<const Surface*>(g));
332
0
        return loc != Location::EXTERIOR;
333
0
    }
334
335
0
#if USE_RELATENG
336
0
    return operation::relateng::RelateNG::intersects(this, g);
337
#else
338
    if (typ == GEOS_GEOMETRYCOLLECTION) {
339
        auto im = relate(g);
340
        bool res = im->isIntersects();
341
        return res;
342
    } else {
343
        return prep::PreparedGeometryFactory::prepare(this)->intersects(g);
344
    }
345
#endif
346
0
}
347
348
/*public*/
349
bool
350
Geometry::covers(const Geometry* g) const
351
0
{
352
0
#if USE_RELATENG
353
0
    return operation::relateng::RelateNG::covers(this, g);
354
#else
355
    // optimization - lower dimension cannot cover areas
356
    if(g->getDimension() == 2 && getDimension() < 2) {
357
        return false;
358
    }
359
360
    // optimization - P cannot cover a non-zero-length L
361
    // Note that a point can cover a zero-length lineal geometry
362
    if(g->getDimension() == 1 && getDimension() < 1 && g->getLength() > 0.0) {
363
        return false;
364
    }
365
366
#ifdef SHORTCIRCUIT_PREDICATES
367
    // short-circuit test
368
    if(! getEnvelopeInternal()->covers(g->getEnvelopeInternal())) {
369
        return false;
370
    }
371
#endif
372
373
    // optimization for rectangle arguments
374
    if(isRectangle()) {
375
        // since we have already tested that the test envelope
376
        // is covered
377
        return true;
378
    }
379
380
    std::unique_ptr<IntersectionMatrix> im(relate(g));
381
    return im->isCovers();
382
#endif
383
0
}
384
385
/*public*/
386
bool
387
Geometry::coveredBy(const Geometry* g) const
388
0
{
389
0
#if USE_RELATENG
390
0
    return operation::relateng::RelateNG::coveredBy(this, g);
391
#else
392
    return covers(g, this);
393
#endif
394
0
}
395
396
bool
397
Geometry::crosses(const Geometry* g) const
398
0
{
399
0
#if USE_RELATENG
400
0
    return operation::relateng::RelateNG::crosses(this, g);
401
#else
402
403
#ifdef SHORTCIRCUIT_PREDICATES
404
    // short-circuit test
405
    if(! getEnvelopeInternal()->intersects(g->getEnvelopeInternal())) {
406
        return false;
407
    }
408
#endif
409
    std::unique_ptr<IntersectionMatrix> im(relate(g));
410
    bool res = im->isCrosses(getDimension(), g->getDimension());
411
    return res;
412
413
#endif
414
0
}
415
416
bool
417
Geometry::within(const Geometry* g) const
418
0
{
419
0
#if USE_RELATENG
420
0
    return operation::relateng::RelateNG::within(this, g);
421
#else
422
    return g->contains(this);
423
#endif
424
0
}
425
426
bool
427
Geometry::contains(const Geometry* g) const
428
0
{
429
0
#if USE_RELATENG
430
0
    return operation::relateng::RelateNG::contains(this, g);
431
#else
432
433
    // optimization - lower dimension cannot contain areas
434
    if(g->getDimension() == 2 && getDimension() < 2) {
435
        return false;
436
    }
437
438
    // optimization - P cannot contain a non-zero-length L
439
    // Note that a point can contain a zero-length lineal geometry,
440
    // since the line has no boundary due to Mod-2 Boundary Rule
441
    if(g->getDimension() == 1 && getDimension() < 1 && g->getLength() > 0.0) {
442
        return false;
443
    }
444
445
#ifdef SHORTCIRCUIT_PREDICATES
446
    // short-circuit test
447
    if(! getEnvelopeInternal()->contains(g->getEnvelopeInternal())) {
448
        return false;
449
    }
450
#endif
451
452
    // optimization for rectangle arguments
453
    if(isRectangle()) {
454
        const Polygon* p = detail::down_cast<const Polygon*>(this);
455
        return predicate::RectangleContains::contains(*p, *g);
456
    }
457
    // Incorrect: contains is not commutative
458
    //if (g->isRectangle()) {
459
    //  return predicate::RectangleContains::contains((const Polygon&)*g, *this);
460
    //}
461
462
    std::unique_ptr<IntersectionMatrix> im(relate(g));
463
    bool res = im->isContains();
464
    return res;
465
#endif
466
0
}
467
468
bool
469
Geometry::overlaps(const Geometry* g) const
470
0
{
471
0
#if USE_RELATENG
472
0
    return operation::relateng::RelateNG::overlaps(this, g);
473
#else
474
475
#ifdef SHORTCIRCUIT_PREDICATES
476
    // short-circuit test
477
    if(! getEnvelopeInternal()->intersects(g->getEnvelopeInternal())) {
478
        return false;
479
    }
480
#endif
481
    std::unique_ptr<IntersectionMatrix> im(relate(g));
482
    bool res = im->isOverlaps(getDimension(), g->getDimension());
483
    return res;
484
485
#endif
486
0
}
487
488
bool
489
Geometry::relate(const Geometry* g, const std::string& intersectionPattern) const
490
0
{
491
0
#if USE_RELATENG
492
0
    return operation::relateng::RelateNG::relate(this, g, intersectionPattern);
493
#else
494
    std::unique_ptr<IntersectionMatrix> im(relate(g));
495
    bool res = im->matches(intersectionPattern);
496
    return res;
497
#endif
498
0
}
499
500
bool
501
Geometry::equals(const Geometry* g) const
502
0
{
503
0
#if USE_RELATENG
504
0
    return operation::relateng::RelateNG::equalsTopo(this, g);
505
#else
506
507
#ifdef SHORTCIRCUIT_PREDICATES
508
    // short-circuit test
509
    if(! getEnvelopeInternal()->equals(g->getEnvelopeInternal())) {
510
        return false;
511
    }
512
#endif
513
514
    if(isEmpty()) {
515
        return g->isEmpty();
516
    }
517
    else if(g->isEmpty()) {
518
        return isEmpty();
519
    }
520
521
    std::unique_ptr<IntersectionMatrix> im(relate(g));
522
    bool res = im->isEquals(getDimension(), g->getDimension());
523
    return res;
524
#endif
525
0
}
526
527
std::unique_ptr<IntersectionMatrix>
528
Geometry::relate(const Geometry* other) const
529
0
{
530
0
#if USE_RELATENG
531
0
    return operation::relateng::RelateNG::relate(this, other);
532
#else
533
    return RelateOp::relate(this, other);
534
#endif
535
0
}
536
537
std::unique_ptr<IntersectionMatrix>
538
Geometry::relate(const Geometry& other) const
539
0
{
540
0
    return relate(&other);
541
0
}
542
543
std::string
544
Geometry::toString() const
545
0
{
546
0
    return toText();
547
0
}
548
549
std::ostream&
550
operator<< (std::ostream& os, const Geometry& geom)
551
0
{
552
0
    io::WKBWriter writer;
553
0
    writer.writeHEX(geom, os);
554
0
    return os;
555
0
}
556
557
std::string
558
Geometry::toText() const
559
0
{
560
0
    io::WKTWriter writer;
561
    // To enable "GEOS<3.12" outputs, uncomment the following:
562
    // writer.setTrim(false);
563
    // writer.setOutputDimension(2);
564
0
    return writer.write(this);
565
0
}
566
567
std::unique_ptr<Geometry>
568
Geometry::buffer(double p_distance) const
569
0
{
570
0
    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance));
571
0
}
572
573
std::unique_ptr<Geometry>
574
Geometry::buffer(double p_distance, int quadrantSegments) const
575
0
{
576
0
    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance, quadrantSegments));
577
0
}
578
579
std::unique_ptr<Geometry>
580
Geometry::buffer(double p_distance, int quadrantSegments, int endCapStyle) const
581
0
{
582
0
    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance, quadrantSegments, endCapStyle));
583
0
}
584
585
std::unique_ptr<Geometry>
586
Geometry::convexHull() const
587
0
{
588
0
    return ConvexHull(this).getConvexHull();
589
0
}
590
591
std::unique_ptr<Geometry>
592
Geometry::intersection(const Geometry* other) const
593
8.41k
{
594
    /*
595
     * TODO: MD - add optimization for P-A case using Point-In-Polygon
596
     */
597
598
#ifdef USE_RECTANGLE_INTERSECTION
599
    // optimization for rectangle arguments
600
    using operation::intersection::Rectangle;
601
    using operation::intersection::RectangleIntersection;
602
    if(isRectangle()) {
603
        const Envelope* env = getEnvelopeInternal();
604
        Rectangle rect(env->getMinX(), env->getMinY(),
605
                       env->getMaxX(), env->getMaxY());
606
        return RectangleIntersection::clip(*other, rect).release();
607
    }
608
    if(other->isRectangle()) {
609
        const Envelope* env = other->getEnvelopeInternal();
610
        Rectangle rect(env->getMinX(), env->getMinY(),
611
                       env->getMaxX(), env->getMaxY());
612
        return RectangleIntersection::clip(*this, rect).release();
613
    }
614
#endif
615
616
8.41k
    return HeuristicOverlay(this, other, OverlayNG::INTERSECTION);
617
8.41k
}
618
619
std::unique_ptr<Geometry>
620
Geometry::Union(const Geometry* other) const
621
8.41k
{
622
8.41k
    return HeuristicOverlay(this, other, OverlayNG::UNION);
623
8.41k
}
624
625
/* public */
626
Geometry::Ptr
627
Geometry::Union() const
628
0
{
629
0
    using geos::operation::geounion::UnaryUnionOp;
630
0
    return UnaryUnionOp::Union(*this);
631
0
}
632
633
std::unique_ptr<Geometry>
634
Geometry::difference(const Geometry* other) const
635
8.41k
{
636
8.41k
    return HeuristicOverlay(this, other, OverlayNG::DIFFERENCE);
637
8.41k
}
638
639
std::unique_ptr<Geometry>
640
Geometry::symDifference(const Geometry* other) const
641
0
{
642
0
    return HeuristicOverlay(this, other, OverlayNG::SYMDIFFERENCE);
643
0
}
644
645
int
646
Geometry::compareTo(const Geometry* geom) const
647
0
{
648
    // compare to self
649
0
    if(this == geom) {
650
0
        return 0;
651
0
    }
652
653
0
    if(getSortIndex() != geom->getSortIndex()) {
654
0
        int diff = getSortIndex() - geom->getSortIndex();
655
0
        return (diff > 0) - (diff < 0); // signum()
656
0
    }
657
0
    if(isEmpty() && geom->isEmpty()) {
658
0
        return 0;
659
0
    }
660
0
    if(isEmpty()) {
661
0
        return -1;
662
0
    }
663
0
    if(geom->isEmpty()) {
664
0
        return 1;
665
0
    }
666
0
    return compareToSameClass(geom);
667
0
}
668
669
bool
670
Geometry::isEquivalentClass(const Geometry* other) const
671
0
{
672
0
    if(typeid(*this) == typeid(*other)) {
673
0
        return true;
674
0
    }
675
0
    else {
676
0
        return false;
677
0
    }
678
0
}
679
680
/*public static*/
681
void
682
Geometry::checkNotGeometryCollection(const Geometry* g)
683
//throw(IllegalArgumentException *)
684
0
{
685
0
    if(g->getSortIndex() == SORTINDEX_GEOMETRYCOLLECTION) {
686
0
        throw  geos::util::IllegalArgumentException("This method does not support GeometryCollection arguments\n");
687
0
    }
688
0
}
689
690
691
void
692
Geometry::GeometryChangedFilter::filter_rw(Geometry* geom)
693
37.9k
{
694
37.9k
    geom->geometryChangedAction();
695
37.9k
}
696
697
698
/**
699
 *  Returns the minimum distance between this Geometry
700
 *  and the other Geometry
701
 *
702
 * @param  other  the Geometry from which to compute the distance
703
 */
704
double
705
Geometry::distance(const Geometry* other) const
706
0
{
707
0
    return DistanceOp::distance(this, other);
708
0
}
709
710
/**
711
 *  Returns the area of this <code>Geometry</code>.
712
 *  Areal Geometries have a non-zero area.
713
 *  They override this function to compute the area.
714
 *  Others return 0.0
715
 *
716
 * @return the area of the Geometry
717
 */
718
double
719
Geometry::getArea() const
720
5.29M
{
721
5.29M
    return 0.0;
722
5.29M
}
723
724
/**
725
 *  Returns the length of this <code>Geometry</code>.
726
 *  Linear geometries return their length.
727
 *  Areal geometries return their perimeter.
728
 *  They override this function to compute the area.
729
 *  Others return 0.0
730
 *
731
 * @return the length of the Geometry
732
 */
733
double
734
Geometry::getLength() const
735
0
{
736
0
    return 0.0;
737
0
}
738
739
Geometry::~Geometry()
740
58.3M
{
741
58.3M
    _factory->dropRef();
742
58.3M
}
743
744
bool
745
GeometryGreaterThen::operator()(const Geometry* first, const Geometry* second)
746
0
{
747
0
    if(first->compareTo(second) > 0) {
748
0
        return true;
749
0
    }
750
0
    else {
751
0
        return false;
752
0
    }
753
0
}
754
755
bool
756
Geometry::equal(const CoordinateXY& a, const CoordinateXY& b,
757
                double tolerance) const
758
0
{
759
0
    if(tolerance == 0) {
760
0
        return a == b; // 2D only !!!
761
0
    }
762
    //double dist=a.distance(b);
763
0
    return a.distance(b) <= tolerance;
764
0
}
765
766
void
767
Geometry::apply_ro(GeometryFilter* filter) const
768
0
{
769
0
    filter->filter_ro(this);
770
0
}
771
772
void
773
Geometry::apply_rw(GeometryFilter* filter)
774
0
{
775
0
    filter->filter_rw(this);
776
0
}
777
778
void
779
Geometry::apply_ro(GeometryComponentFilter* filter) const
780
0
{
781
0
    filter->filter_ro(this);
782
0
}
783
784
void
785
Geometry::apply_rw(GeometryComponentFilter* filter)
786
0
{
787
0
    filter->filter_rw(this);
788
0
}
789
790
bool
791
Geometry::isSimple() const
792
0
{
793
0
    operation::valid::IsSimpleOp op(*this);
794
0
    return op.isSimple();
795
0
}
796
797
/* public */
798
const PrecisionModel*
799
Geometry::getPrecisionModel() const
800
247k
{
801
247k
    return _factory->getPrecisionModel();
802
247k
}
803
804
bool
805
26.5M
Geometry::hasCurvedComponents() const {
806
26.5M
    return false;
807
26.5M
}
808
809
} // namespace geos::geom
810
} // namespace geos
811
812