30 #include <QDomDocument> 46 if ( points.isEmpty() )
53 mX.resize( points.count() );
54 mY.resize( points.count() );
55 double *x = mX.data();
56 double *y = mY.data();
61 mZ.resize( points.count() );
66 mM.resize( points.count() );
84 int pointCount = std::min( x.size(), y.size() );
85 if ( x.size() == pointCount )
91 mX = x.mid( 0, pointCount );
93 if ( y.size() == pointCount )
99 mY = y.mid( 0, pointCount );
101 if ( !z.isEmpty() && z.count() >= pointCount )
104 if ( z.size() == pointCount )
110 mZ = z.mid( 0, pointCount );
113 if ( !m.isEmpty() && m.count() >= pointCount )
116 if ( m.size() == pointCount )
122 mM = m.mid( 0, pointCount );
130 mX.reserve( points.size() );
131 mY.reserve( points.size() );
148 if ( mX.count() != otherLine->mX.count() )
151 for (
int i = 0; i < mX.count(); ++i )
192 bool res =
snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
193 result->mX, result->mY, result->mZ, result->mM );
195 return result.release();
202 if ( mX.count() <= 2 )
205 double prevX = mX.at( 0 );
206 double prevY = mY.at( 0 );
208 bool useZ = hasZ && useZValues;
209 double prevZ = useZ ? mZ.at( 0 ) : 0;
211 int remaining = mX.count();
212 while ( i < remaining )
214 double currentX = mX.at( i );
215 double currentY = mY.at( i );
216 double currentZ = useZ ? mZ.at( i ) : 0;
253 importVerticesFromWkb( wkbPtr );
260 importVerticesFromWkb( wkb );
265 double xmin = std::numeric_limits<double>::max();
266 double ymin = std::numeric_limits<double>::max();
267 double xmax = -std::numeric_limits<double>::max();
268 double ymax = -std::numeric_limits<double>::max();
270 for (
double x : mX )
277 for (
double y : mY )
309 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
313 wkbArray.resize( binarySize );
316 wkb << static_cast<quint32>(
wkbType() );
343 QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral(
"LineString" ) );
346 return elemLineString;
350 return elemLineString;
358 QDomElement elemLineString = doc.createElementNS( ns, QStringLiteral(
"LineString" ) );
361 return elemLineString;
364 return elemLineString;
384 int size = mX.size();
386 for (
int i = 1; i < size; ++i )
388 dx = mX.at( i ) - mX.at( i - 1 );
389 dy = mY.at( i ) - mY.at( i - 1 );
390 length += std::sqrt( dx * dx + dy * dy );
421 Q_UNUSED( tolerance );
422 Q_UNUSED( toleranceType );
438 if ( i < 0 || i >= mX.size() )
443 double x = mX.at( i );
444 double y = mY.at( i );
445 double z = std::numeric_limits<double>::quiet_NaN();
446 double m = std::numeric_limits<double>::quiet_NaN();
464 else if ( hasZ && hasM )
487 if ( index >= 0 && index < mX.size() )
488 return mX.at( index );
495 if ( index >= 0 && index < mY.size() )
496 return mY.at( index );
503 if ( index >= 0 && index < mZ.size() )
504 return mZ.at( index );
506 return std::numeric_limits<double>::quiet_NaN();
511 if ( index >= 0 && index < mM.size() )
512 return mM.at( index );
514 return std::numeric_limits<double>::quiet_NaN();
519 if ( index >= 0 && index < mX.size() )
526 if ( index >= 0 && index < mY.size() )
533 if ( index >= 0 && index < mZ.size() )
539 if ( index >= 0 && index < mM.size() )
553 for (
int i = 0; i < nPoints; ++i )
555 pts.push_back(
pointN( i ) );
563 if ( points.isEmpty() )
570 const QgsPoint &firstPt = points.at( 0 );
571 bool hasZ = firstPt.
is3D();
576 mX.resize( points.size() );
577 mY.resize( points.size() );
580 mZ.resize( points.size() );
588 mM.resize( points.size() );
595 for (
int i = 0; i < points.size(); ++i )
597 mX[i] = points.at( i ).x();
598 mY[i] = points.at( i ).y();
601 double z = points.at( i ).z();
602 mZ[i] = std::isnan( z ) ? 0 : z;
606 double m = points.at( i ).m();
607 mM[i] = std::isnan( m ) ? 0 : m;
660 mZ.insert( mZ.count(), mX.size() - mZ.size(), std::numeric_limits<double>::quiet_NaN() );
673 mM.insert( mM.count(), mX.size() - mM.size(), std::numeric_limits<double>::quiet_NaN() );
683 std::reverse( copy->mX.begin(), copy->mX.end() );
684 std::reverse( copy->mY.begin(), copy->mY.end() );
687 std::reverse( copy->mZ.begin(), copy->mZ.end() );
691 std::reverse( copy->mM.begin(), copy->mM.end() );
715 if ( path.isEmpty() || path.currentPosition() != QPointF( mX.at( 0 ), mY.at( 0 ) ) )
717 path.moveTo( mX.at( 0 ), mY.at( 0 ) );
720 for (
int i = 1; i < nPoints; ++i )
722 path.lineTo( mX.at( i ), mY.at( i ) );
735 return compoundCurve;
740 if ( mX.size() < 2 || mY.size() < 2 )
744 if ( startDistance > 0 )
746 double currentLen = std::sqrt( std::pow( mX.at( 0 ) - mX.at( 1 ), 2 ) +
747 std::pow( mY.at( 0 ) - mY.at( 1 ), 2 ) );
748 double newLen = currentLen + startDistance;
749 mX[ 0 ] = mX.at( 1 ) + ( mX.at( 0 ) - mX.at( 1 ) ) / currentLen * newLen;
750 mY[ 0 ] = mY.at( 1 ) + ( mY.at( 0 ) - mY.at( 1 ) ) / currentLen * newLen;
753 if ( endDistance > 0 )
755 int last = mX.size() - 1;
756 double currentLen = std::sqrt( std::pow( mX.at( last ) - mX.at( last - 1 ), 2 ) +
757 std::pow( mY.at( last ) - mY.at( last - 1 ), 2 ) );
758 double newLen = currentLen + endDistance;
759 mX[ last ] = mX.at( last - 1 ) + ( mX.at( last ) - mX.at( last - 1 ) ) / currentLen * newLen;
760 mY[ last ] = mY.at( last - 1 ) + ( mY.at( last ) - mY.at( last - 1 ) ) / currentLen * newLen;
766 auto result = qgis::make_unique< QgsLineString >();
768 return result.release();
773 return QStringLiteral(
"LineString" );
789 double *zArray =
nullptr;
795 std::unique_ptr< double[] > dummyZ;
796 if ( !hasZ || !transformZ )
798 dummyZ.reset(
new double[nPoints]() );
799 zArray = dummyZ.get();
814 for (
int i = 0; i < nPoints; ++i )
817 t.map( mX.at( i ), mY.at( i ), &x, &y );
822 mZ[i] = mZ.at( i ) * zScale + zTranslate;
826 mM[i] = mM.at( i ) * mScale + mTranslate;
840 if ( position.
vertex < 0 || position.
vertex > mX.size() )
850 mX.insert( position.
vertex, vertex.
x() );
851 mY.insert( position.
vertex, vertex.
y() );
854 mZ.insert( position.
vertex, vertex.
z() );
858 mM.insert( position.
vertex, vertex.
m() );
866 if ( position.
vertex < 0 || position.
vertex >= mX.size() )
870 mX[position.
vertex] = newPos.
x();
871 mY[position.
vertex] = newPos.
y();
874 mZ[position.
vertex] = newPos.
z();
878 mM[position.
vertex] = newPos.
m();
886 if ( position.
vertex >= mX.size() || position.
vertex < 0 )
891 mX.remove( position.
vertex );
892 mY.remove( position.
vertex );
895 mZ.remove( position.
vertex );
899 mM.remove( position.
vertex );
939 double sqrDist = std::numeric_limits<double>::max();
940 double leftOfDist = std::numeric_limits<double>::max();
945 double segmentPtX, segmentPtY;
950 int size = mX.size();
951 if ( size == 0 || size == 1 )
956 for (
int i = 1; i < size; ++i )
958 double prevX = mX.at( i - 1 );
959 double prevY = mY.at( i - 1 );
960 double currentX = mX.at( i );
961 double currentY = mY.at( i );
963 if ( testDist < sqrDist )
966 segmentPt.
setX( segmentPtX );
967 segmentPt.
setY( segmentPtY );
968 vertexAfter.
part = 0;
969 vertexAfter.
ring = 0;
980 if (
qgsDoubleNear( testDist, leftOfDist ) && left != prevLeftOf && prevLeftOf != 0 )
993 leftOfDist = testDist;
997 else if ( testDist < leftOfDist )
1000 leftOfDist = testDist;
1031 if ( numPoints == 1 )
1032 return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
1034 double totalLineLength = 0.0;
1035 double prevX = mX.at( 0 );
1036 double prevY = mY.at( 0 );
1042 double currentX = mX.at( i );
1043 double currentY = mY.at( i );
1044 double segmentLength = std::sqrt( std::pow( currentX - prevX, 2.0 ) +
1045 std::pow( currentY - prevY, 2.0 ) );
1050 sumX += segmentLength * 0.5 * ( currentX + prevX );
1051 sumY += segmentLength * 0.5 * ( currentY + prevY );
1057 return QgsPoint( mX.at( 0 ), mY.at( 0 ) );
1059 return QgsPoint( sumX / totalLineLength, sumY / totalLineLength );
1073 for (
int i = 0; i < maxIndex; ++i )
1075 sum += 0.5 * ( mX.at( i ) * mY.at( i + 1 ) - mY.at( i ) * mX.at( i + 1 ) );
1079 void QgsLineString::importVerticesFromWkb(
const QgsConstWkbPtr &wkb )
1085 mX.resize( nVertices );
1086 mY.resize( nVertices );
1087 hasZ ? mZ.resize( nVertices ) : mZ.clear();
1088 hasM ? mM.resize( nVertices ) : mM.clear();
1089 for (
int i = 0; i < nVertices; ++i )
1122 if ( mX.count() < 2 )
1132 double previousX = mX.at(
numPoints() - 2 );
1133 double previousY = mY.at(
numPoints() - 2 );
1134 double currentX = mX.at( 0 );
1135 double currentY = mY.at( 0 );
1136 double afterX = mX.at( 1 );
1137 double afterY = mY.at( 1 );
1140 else if ( vertex.
vertex == 0 )
1153 double previousX = mX.at( vertex.
vertex - 1 );
1154 double previousY = mY.at( vertex.
vertex - 1 );
1155 double currentX = mX.at( vertex.
vertex );
1156 double currentY = mY.at( vertex.
vertex );
1157 double afterX = mX.at( vertex.
vertex + 1 );
1158 double afterY = mY.at( vertex.
vertex + 1 );
1165 if ( startVertex.
vertex < 0 || startVertex.
vertex >= mX.count() - 1 )
1168 double dx = mX.at( startVertex.
vertex + 1 ) - mX.at( startVertex.
vertex );
1169 double dy = mY.at( startVertex.
vertex + 1 ) - mY.at( startVertex.
vertex );
1170 return std::sqrt( dx * dx + dy * dy );
1195 mZ.reserve( nPoints );
1196 for (
int i = 0; i < nPoints; ++i )
1226 mM.reserve( nPoints );
1227 for (
int i = 0; i < nPoints; ++i )
1266 addZValue( std::numeric_limits<double>::quiet_NaN() );
bool isMeasure() const
Returns true if the geometry contains m values.
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
void append(const QgsLineString *line)
Appends the contents of another line string to the end of this line string.
A rectangle specified with double values.
bool isEmpty() const override
Returns true if the geometry is empty.
void setPoints(const QgsPointSequence &points)
Resets the line string to match the specified list of points.
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
int dimension() const override
Returns the inherent dimension of the geometry.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction...
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Angle between two linear segments.
QString geometryType() const override
Returns a unique string representing the geometry type.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
QgsPoint centroid() const override
Returns the centroid of the geometry.
A class to represent a 2D point.
void setYAt(int index, double y)
Sets the y-coordinate of the specified node in the line string.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
bool pointAt(int node, QgsPoint &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
static endian_t endian()
Returns whether this machine uses big or little endian.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QgsPoint endPoint() const override
Returns the end point of the curve.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
void addCurve(QgsCurve *c)
Adds a curve to the geometry (takes ownership)
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
QgsWkbTypes::Type mWkbType
int numPoints() const override
Returns the number of points in the curve.
bool convertTo(QgsWkbTypes::Type type) override
Converts the geometry to a specified type.
QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
QString wktTypeStr() const
Returns the WKT type string of the geometry.
QPolygonF asQPolygonF() const
Returns a QPolygonF representing the points.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
static QString pointsToWKT(const QgsPointSequence &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
Type
The WKB type describes the number of dimensions a geometry has.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
static QDomElement pointsToGML2(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns)
Returns a gml::coordinates DOM element.
Utility class for identifying a unique vertex within a geometry.
QgsLineString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
static QDomElement pointsToGML3(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, bool is3D)
Returns a gml::posList DOM element.
bool equals(const QgsCurve &other) const override
Checks whether this curve exactly equals another curve.
double mAt(int index) const
Returns the m value of the specified node in the line string.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
void close()
Closes the line string by appending the first point to the end of the line, if it is not already clos...
Abstract base class for curved geometry type.
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
void setZAt(int index, double z)
Sets the z-coordinate of the specified node in the line string.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QgsPoint startPoint() const override
Returns the starting point of the curve.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString asJson(int precision=17) const override
Returns a GeoJSON representation of the geometry.
void setX(double x)
Sets the point's x-coordinate.
virtual bool isClosed() const
Returns true if the curve is closed.
bool snapToGridPrivate(double hSpacing, double vSpacing, double dSpacing, double mSpacing, const QVector< double > &srcX, const QVector< double > &srcY, const QVector< double > &srcZ, const QVector< double > &srcM, QVector< double > &outX, QVector< double > &outY, QVector< double > &outZ, QVector< double > &outM) const
Helper function for QgsCurve subclasses to snap to grids.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
void setY(double y)
Sets the point's y-coordinate.
void setMAt(int index, double m)
Sets the m value of the specified node in the line string.
QVector< QgsPoint > QgsPointSequence
bool removeDuplicateNodes(double epsilon=4 *DBL_EPSILON, bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
QgsLineString * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid...
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
static QgsPointSequence pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
Line string geometry type, with support for z-dimension and m-values.
static int leftOfLine(double x, double y, double x1, double y1, double x2, double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> ( x2, y2).
QByteArray asWkb() const override
Returns a WKB representation of the geometry.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
bool dropMValue() override
Drops any measure values which exist in the geometry.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequence &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
static Type zmType(Type type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
virtual bool convertTo(QgsWkbTypes::Type type)
Converts the geometry to a specified type.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Compound curve geometry type.
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
QgsLineString * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
double length() const override
Returns the length of the geometry.
QgsCompoundCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsCompoundCurve.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *DBL_EPSILON) const override
Searches for the closest segment of the geometry to a given point.
static Type flatType(Type type)
Returns the flat type for a WKB type.
QgsWkbTypes::Type readHeader() const
readHeader
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negativ values mean left a...
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
void extend(double startDistance, double endDistance)
Extends the line geometry by extrapolating out the start or end of the line by a specified distance...