Coverage Report

Created: 2022-08-24 06:40

/src/geos/src/linearref/LocationIndexOfPoint.cpp
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 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: linearref/LocationIndexOfPoint.java r466
18
 *
19
 **********************************************************************/
20
21
22
#include <geos/geom/LineSegment.h>
23
#include <geos/linearref/LinearIterator.h>
24
#include <geos/linearref/LinearLocation.h>
25
#include <geos/linearref/LocationIndexOfPoint.h>
26
#include <geos/util/IllegalArgumentException.h>
27
28
#include <cassert>
29
#include <limits>
30
31
32
33
using namespace geos::geom;
34
35
namespace geos {
36
namespace linearref { // geos.linearref
37
38
LinearLocation
39
LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt,
40
                                       const LinearLocation* minIndex) const
41
0
{
42
0
    double minDistance = DoubleInfinity;
43
0
    std::size_t minComponentIndex = 0;
44
0
    std::size_t minSegmentIndex = 0;
45
0
    double minFrac = -1.0;
46
47
0
    LineSegment seg;
48
0
    for(LinearIterator it(linearGeom);
49
0
            it.hasNext(); it.next()) {
50
0
        if(! it.isEndOfLine()) {
51
0
            seg.p0 = it.getSegmentStart();
52
0
            seg.p1 = it.getSegmentEnd();
53
0
            double segDistance = seg.distance(inputPt);
54
0
            double segFrac = seg.segmentFraction(inputPt);
55
56
0
            auto candidateComponentIndex = it.getComponentIndex();
57
0
            auto candidateSegmentIndex = it.getVertexIndex();
58
0
            if(segDistance < minDistance) {
59
                // ensure after minLocation, if any
60
0
                if(!minIndex ||
61
0
                        minIndex->compareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0) {
62
                    // otherwise, save this as new minimum
63
0
                    minComponentIndex = candidateComponentIndex;
64
0
                    minSegmentIndex = candidateSegmentIndex;
65
0
                    minFrac = segFrac;
66
0
                    minDistance = segDistance;
67
0
                }
68
0
            }
69
0
        }
70
0
    }
71
0
    LinearLocation loc(minComponentIndex, minSegmentIndex, minFrac);
72
0
    return loc;
73
0
}
74
75
76
LinearLocation
77
LocationIndexOfPoint::indexOf(const Geometry* linearGeom, const Coordinate& inputPt)
78
0
{
79
0
    LocationIndexOfPoint locater(linearGeom);
80
0
    return locater.indexOf(inputPt);
81
0
}
82
83
LinearLocation
84
LocationIndexOfPoint::indexOfAfter(const Geometry* linearGeom, const Coordinate& inputPt,
85
                                   const LinearLocation* minIndex)
86
0
{
87
0
    LocationIndexOfPoint locater(linearGeom);
88
0
    return locater.indexOfAfter(inputPt, minIndex);
89
0
}
90
91
LocationIndexOfPoint::LocationIndexOfPoint(const Geometry* p_linearGeom) :
92
    linearGeom(p_linearGeom)
93
0
{}
94
95
LinearLocation
96
LocationIndexOfPoint::indexOf(const Coordinate& inputPt) const
97
0
{
98
0
    return indexOfFromStart(inputPt, nullptr);
99
0
}
100
101
LinearLocation
102
LocationIndexOfPoint::indexOfAfter(const Coordinate& inputPt,
103
                                   const LinearLocation* minIndex) const
104
0
{
105
0
    if(!minIndex) {
106
0
        return indexOf(inputPt);
107
0
    }
108
109
    // sanity check for minLocation at or past end of line
110
0
    LinearLocation endLoc = LinearLocation::getEndLocation(linearGeom);
111
0
    if(endLoc.compareTo(*minIndex) <= 0) {
112
0
        return endLoc;
113
0
    }
114
115
0
    LinearLocation closestAfter = indexOfFromStart(inputPt, minIndex);
116
    /*
117
     * Return the minDistanceLocation found.
118
     * This will not be null, since it was initialized to minLocation
119
     */
120
0
    if(closestAfter.compareTo(*minIndex) < 0) {
121
0
        throw util::IllegalArgumentException("computed location is before specified minimum location");
122
0
    }
123
0
    return closestAfter;
124
0
}
125
}
126
}