Skip to content

Commit

Permalink
[Algorithms] JoinByNearest: accept max_distance == 0.0 (fixes #38761)
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault authored and nyalldawson committed Sep 15, 2020
1 parent 11471bf commit 53c5c33
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 1 deletion.
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ nearest_lines_to_polys_max_distance_0.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>10</gml:X><gml:Y>5</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:nearest_lines_to_polys_max_distance_0 fid="polys.0">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -0.784492588369441,2.79526795895097 2.84914481185861,2.77371721778791 2.97844925883694,2.0 2.30005017001229,2.31222976119276 1.7306157354618,2.18318129988597 1.8047712914227,1.30692158433784 1.67006135290115,0.930982619199196 1.75463252921878,0.447776631639586 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:name>aaaaa</ogr:name>
<ogr:intval>33</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
<ogr:fid_2>lines.1</ogr:fid_2>
<ogr:n>1</ogr:n>
<ogr:distance>0</ogr:distance>
<ogr:feature_x>-1</ogr:feature_x>
<ogr:feature_y>-1</ogr:feature_y>
<ogr:nearest_x>-1</ogr:nearest_x>
<ogr:nearest_y>-1</ogr:nearest_y>
</ogr:nearest_lines_to_polys_max_distance_0>
</gml:featureMember>
<gml:featureMember>
<ogr:nearest_lines_to_polys_max_distance_0 fid="polys.1">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:name>Aaaaa</ogr:name>
<ogr:intval>-33</ogr:intval>
<ogr:floatval>0</ogr:floatval>
<ogr:fid_2 xsi:nil="true"/>
<ogr:n xsi:nil="true"/>
<ogr:distance xsi:nil="true"/>
<ogr:feature_x xsi:nil="true"/>
<ogr:feature_y xsi:nil="true"/>
<ogr:nearest_x xsi:nil="true"/>
<ogr:nearest_y xsi:nil="true"/>
</ogr:nearest_lines_to_polys_max_distance_0>
</gml:featureMember>
<gml:featureMember>
<ogr:nearest_lines_to_polys_max_distance_0 fid="polys.3">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7.43101482326112,-0.247833523375142 7,-2 9.11852907639681,0.204732041049031 7.43101482326112,-0.247833523375142</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:name>ASDF</ogr:name>
<ogr:intval>0</ogr:intval>
<ogr:floatval xsi:nil="true"/>
<ogr:fid_2>lines.5</ogr:fid_2>
<ogr:n>1</ogr:n>
<ogr:distance>0</ogr:distance>
<ogr:feature_x>10</ogr:feature_x>
<ogr:feature_y>0.751595020683033</ogr:feature_y>
<ogr:nearest_x>10</ogr:nearest_x>
<ogr:nearest_y>0.751595020683033</ogr:nearest_y>
</ogr:nearest_lines_to_polys_max_distance_0>
</gml:featureMember>
<gml:featureMember>
<ogr:nearest_lines_to_polys_max_distance_0 fid="polys.3">
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7.43101482326112,-0.247833523375142 7,-2 9.11852907639681,0.204732041049031 7.43101482326112,-0.247833523375142</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty>
<ogr:name>ASDF</ogr:name>
<ogr:intval>0</ogr:intval>
<ogr:floatval xsi:nil="true"/>
<ogr:fid_2>lines.4</ogr:fid_2>
<ogr:n>2</ogr:n>
<ogr:distance>0</ogr:distance>
<ogr:feature_x>7</ogr:feature_x>
<ogr:feature_y>-3</ogr:feature_y>
<ogr:nearest_x>7</ogr:nearest_x>
<ogr:nearest_y>-3</ogr:nearest_y>
</ogr:nearest_lines_to_polys_max_distance_0>
</gml:featureMember>
<gml:featureMember>
<ogr:nearest_lines_to_polys_max_distance_0 fid="polys.4">
<ogr:name xsi:nil="true"/>
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
<ogr:fid_2 xsi:nil="true"/>
<ogr:n xsi:nil="true"/>
<ogr:distance xsi:nil="true"/>
<ogr:feature_x xsi:nil="true"/>
<ogr:feature_y xsi:nil="true"/>
<ogr:nearest_x xsi:nil="true"/>
<ogr:nearest_y xsi:nil="true"/>
</ogr:nearest_lines_to_polys_max_distance_0>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="nearest_lines_to_polys_max_distance_0" type="ogr:nearest_lines_to_polys_max_distance_0_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="nearest_lines_to_polys_max_distance_0_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="fid_2" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="n" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="distance" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="feature_x" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="feature_y" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="nearest_x" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="nearest_y" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Expand Up @@ -2052,6 +2052,24 @@ tests:
type: vector
pk: [fid,fid_2]

- algorithm: native:joinbynearest
name: Nearest lines to polys, max distance 0
params:
INPUT:
name: snap_polys.gml|layername=snap_polys
type: vector
INPUT_2:
name: snap_lines.gml|layername=snap_lines
type: vector
MAX_DISTANCE: 0.0
NEIGHBORS: 1
PREFIX: ''
results:
OUTPUT:
name: expected/nearest_lines_to_polys_max_distance_0.gml
type: vector
pk: [fid,fid_2]

- algorithm: native:joinbynearest
name: Nearest points to lines, with max distance
params:
Expand Down
8 changes: 7 additions & 1 deletion src/analysis/processing/qgsalgorithmjoinbynearest.cpp
Expand Up @@ -19,6 +19,8 @@
#include "qgsprocessingoutputs.h"
#include "qgslinestring.h"

#include <algorithm>

///@cond PRIVATE

QString QgsJoinByNearestAlgorithm::name() const
Expand Down Expand Up @@ -258,7 +260,11 @@ QVariantMap QgsJoinByNearestAlgorithm::processAlgorithm( const QVariantMap &para
else
{
// note - if using same source as target, we have to get one extra neighbor, since the first match will be the input feature
const QList< QgsFeatureId > nearest = index.nearestNeighbor( f.geometry(), neighbors + ( sameSourceAndTarget ? 1 : 0 ), std::isnan( maxDistance ) ? 0 : maxDistance );

// if the user didn't specify a distance (isnan), then use 0 for nearestNeighbor() parameter
// if the user specified 0 exactly, then use the smallest positive double value instead
const double searchDistance = std::isnan( maxDistance ) ? 0 : std::max( std::numeric_limits<double>::min(), maxDistance );
const QList< QgsFeatureId > nearest = index.nearestNeighbor( f.geometry(), neighbors + ( sameSourceAndTarget ? 1 : 0 ), searchDistance );

if ( nearest.count() > neighbors + ( sameSourceAndTarget ? 1 : 0 ) )
{
Expand Down

0 comments on commit 53c5c33

Please sign in to comment.