Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmultipoint.cpp
3 : : -------------------------------------------------------------------
4 : : Date : 29 Oct 2014
5 : : Copyright : (C) 2014 by Marco Hugentobler
6 : : email : marco.hugentobler at sourcepole dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgsmultipoint.h"
17 : : #include "qgsapplication.h"
18 : : #include "qgsgeometryutils.h"
19 : : #include "qgspoint.h"
20 : : #include "qgswkbptr.h"
21 : :
22 : : #include <QJsonArray>
23 : : #include <QJsonObject>
24 : : #include <QRegularExpression>
25 : : #include <nlohmann/json.hpp>
26 : :
27 : 692 : QgsMultiPoint::QgsMultiPoint()
28 : 1384 : {
29 : 692 : mWkbType = QgsWkbTypes::MultiPoint;
30 : 692 : }
31 : :
32 : 9 : QgsPoint *QgsMultiPoint::pointN( int index )
33 : : {
34 : 9 : return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
35 : : }
36 : :
37 : 25 : const QgsPoint *QgsMultiPoint::pointN( int index ) const
38 : : {
39 : 25 : return qgsgeometry_cast< const QgsPoint * >( geometryN( index ) );
40 : : }
41 : :
42 : 417 : QString QgsMultiPoint::geometryType() const
43 : : {
44 : 834 : return QStringLiteral( "MultiPoint" );
45 : : }
46 : :
47 : 1 : QgsMultiPoint *QgsMultiPoint::createEmptyWithSameType() const
48 : : {
49 : 1 : auto result = std::make_unique< QgsMultiPoint >();
50 : 1 : result->mWkbType = mWkbType;
51 : 1 : return result.release();
52 : 1 : }
53 : :
54 : 3 : QgsMultiPoint *QgsMultiPoint::clone() const
55 : : {
56 : 3 : return new QgsMultiPoint( *this );
57 : 0 : }
58 : :
59 : 1 : QgsMultiPoint *QgsMultiPoint::toCurveType() const
60 : : {
61 : 1 : return clone();
62 : : }
63 : :
64 : 425 : bool QgsMultiPoint::fromWkt( const QString &wkt )
65 : : {
66 : 425 : QString collectionWkt( wkt );
67 : : //test for non-standard MultiPoint(x1 y1, x2 y2) format
68 : 426 : const thread_local QRegularExpression regex( QStringLiteral( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" ), QRegularExpression::CaseInsensitiveOption );
69 : 425 : const QRegularExpressionMatch match = regex.match( collectionWkt );
70 : 425 : if ( match.hasMatch() )
71 : : {
72 : : //alternate style without extra brackets, upgrade to standard
73 : 6 : collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
74 : 6 : }
75 : :
76 : 850 : return fromCollectionWkt( collectionWkt, QVector<QgsAbstractGeometry *>() << new QgsPoint, QStringLiteral( "Point" ) );
77 : 425 : }
78 : :
79 : 443 : void QgsMultiPoint::clear()
80 : : {
81 : 443 : QgsGeometryCollection::clear();
82 : 443 : mWkbType = QgsWkbTypes::MultiPoint;
83 : 443 : }
84 : :
85 : 3 : QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
86 : : {
87 : 6 : QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
88 : :
89 : 3 : if ( isEmpty() )
90 : 1 : return elemMultiPoint;
91 : :
92 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries )
93 : : {
94 : 4 : if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
95 : : {
96 : 8 : QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
97 : 4 : elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
98 : 4 : elemMultiPoint.appendChild( elemPointMember );
99 : 4 : }
100 : : }
101 : :
102 : 2 : return elemMultiPoint;
103 : 3 : }
104 : :
105 : 3 : QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
106 : : {
107 : 6 : QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
108 : :
109 : 3 : if ( isEmpty() )
110 : 1 : return elemMultiPoint;
111 : :
112 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries )
113 : : {
114 : 4 : if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
115 : : {
116 : 8 : QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
117 : 4 : elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
118 : 4 : elemMultiPoint.appendChild( elemPointMember );
119 : 4 : }
120 : : }
121 : :
122 : 2 : return elemMultiPoint;
123 : 3 : }
124 : :
125 : 4 : json QgsMultiPoint::asJsonObject( int precision ) const
126 : : {
127 : 20 : json j
128 : 12 : {
129 : 4 : { "type", "MultiPoint" },
130 : 4 : { "coordinates", json::array() },
131 : : };
132 : 12 : for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
133 : : {
134 : 8 : const QgsPoint *point = static_cast<const QgsPoint *>( geom );
135 : 8 : if ( point->is3D() )
136 : 0 : j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
137 : : else
138 : 16 : j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
139 : : }
140 : 4 : return j;
141 : 4 : }
142 : :
143 : :
144 : 8 : int QgsMultiPoint::nCoordinates() const
145 : : {
146 : 8 : return mGeometries.size();
147 : : }
148 : :
149 : 133 : bool QgsMultiPoint::addGeometry( QgsAbstractGeometry *g )
150 : : {
151 : 133 : if ( !qgsgeometry_cast<QgsPoint *>( g ) )
152 : : {
153 : 2 : delete g;
154 : 2 : return false;
155 : : }
156 : 131 : if ( mGeometries.empty() )
157 : : {
158 : 53 : setZMTypeFromSubGeometry( g, QgsWkbTypes::MultiPoint );
159 : 53 : }
160 : 131 : if ( is3D() && !g->is3D() )
161 : 4 : g->addZValue();
162 : 127 : else if ( !is3D() && g->is3D() )
163 : 2 : g->dropZValue();
164 : 131 : if ( isMeasure() && !g->isMeasure() )
165 : 4 : g->addMValue();
166 : 127 : else if ( !isMeasure() && g->isMeasure() )
167 : 2 : g->dropMValue();
168 : :
169 : 131 : return QgsGeometryCollection::addGeometry( g );
170 : 133 : }
171 : :
172 : 4 : bool QgsMultiPoint::insertGeometry( QgsAbstractGeometry *g, int index )
173 : : {
174 : 4 : if ( !g || QgsWkbTypes::flatType( g->wkbType() ) != QgsWkbTypes::Point )
175 : : {
176 : 4 : delete g;
177 : 4 : return false;
178 : : }
179 : :
180 : 0 : return QgsGeometryCollection::insertGeometry( g, index );
181 : 4 : }
182 : :
183 : 2 : QgsAbstractGeometry *QgsMultiPoint::boundary() const
184 : : {
185 : 2 : return nullptr;
186 : : }
187 : :
188 : 11 : int QgsMultiPoint::vertexNumberFromVertexId( QgsVertexId id ) const
189 : : {
190 : 11 : if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
191 : 9 : return -1;
192 : :
193 : 2 : return id.part; // can shortcut the calculation, since each part will have 1 vertex
194 : 11 : }
195 : :
196 : 0 : double QgsMultiPoint::segmentLength( QgsVertexId ) const
197 : : {
198 : 0 : return 0.0;
199 : : }
200 : :
201 : 1 : bool QgsMultiPoint::isValid( QString &, int ) const
202 : : {
203 : 1 : return true;
204 : : }
205 : :
206 : 2 : void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
207 : : {
208 : 6 : mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
209 : 6 : [&filter]( const QgsAbstractGeometry * part )
210 : : {
211 : 4 : if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
212 : : {
213 : 4 : if ( !filter( *point ) )
214 : : {
215 : 2 : delete point;
216 : 2 : return true;
217 : : }
218 : : else
219 : : {
220 : 2 : return false;
221 : : }
222 : : }
223 : : else
224 : : {
225 : 0 : delete part;
226 : 0 : return true;
227 : : }
228 : 6 : } ), mGeometries.end() ); // clazy:exclude=detaching-member
229 : 2 : }
230 : :
231 : 19 : bool QgsMultiPoint::wktOmitChildType() const
232 : : {
233 : 19 : return true;
234 : : }
|