27 #include <QPainterPath> 45 return *otherLine == *
this;
72 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
85 if ( nPoints > 0 && nPoints % 2 == 0 )
98 double centerX, centerY, radius;
121 QgsPointSequenceV2 compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
123 for ( ; cpIt != compassPoints.
constEnd(); ++cpIt )
125 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
130 QgsPointSequenceV2 QgsCircularStringV2::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
134 QgsPointV2 nPoint( centerX, centerY + radius );
135 QgsPointV2 ePoint( centerX + radius, centerY );
136 QgsPointV2 sPoint( centerX, centerY - radius );
137 QgsPointV2 wPoint( centerX - radius, centerY );
139 if ( p3Angle >= p1Angle )
141 if ( p2Angle > p1Angle && p2Angle < p3Angle )
143 if ( p1Angle <= 90 && p3Angle >= 90 )
145 pointList.
append( nPoint );
147 if ( p1Angle <= 180 && p3Angle >= 180 )
149 pointList.
append( wPoint );
151 if ( p1Angle <= 270 && p3Angle >= 270 )
153 pointList.
append( sPoint );
158 pointList.
append( ePoint );
159 if ( p1Angle >= 90 || p3Angle <= 90 )
161 pointList.
append( nPoint );
163 if ( p1Angle >= 180 || p3Angle <= 180 )
165 pointList.
append( wPoint );
167 if ( p1Angle >= 270 || p3Angle <= 270 )
169 pointList.
append( sPoint );
175 if ( p2Angle < p1Angle && p2Angle > p3Angle )
177 if ( p1Angle >= 270 && p3Angle <= 270 )
179 pointList.
append( sPoint );
181 if ( p1Angle >= 180 && p3Angle <= 180 )
183 pointList.
append( wPoint );
185 if ( p1Angle >= 90 && p3Angle <= 90 )
187 pointList.
append( nPoint );
192 pointList.
append( ePoint );
193 if ( p1Angle <= 270 || p3Angle >= 270 )
195 pointList.
append( sPoint );
197 if ( p1Angle <= 180 || p3Angle >= 180 )
199 pointList.
append( wPoint );
201 if ( p1Angle <= 90 || p3Angle >= 90 )
203 pointList.
append( nPoint );
232 for (
int i = 0; i < nVertices; ++i )
265 int size =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
273 unsigned char* geomPtr =
new unsigned char[binarySize];
276 wkb << static_cast<quint32>(
wkbType() );
329 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
360 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
362 segmentize(
pointN( i ),
pointN( i + 1 ),
pointN( i + 2 ), points, tolerance, toleranceType );
371 return qMin( mX.
size(), mY.
size() );
376 if ( qMin( mX.
size(), mY.
size() ) <= i )
381 double x = mX.
at( i );
382 double y = mY.
at( i );
415 for (
int i = 0; i < nPts; ++i )
425 if ( points.
size() < 1 )
437 bool hasZ = firstPt.
is3D();
461 for (
int i = 0; i < points.
size(); ++i )
463 mX[i] = points[i].x();
464 mY[i] = points[i].y();
467 mZ[i] = points[i].z();
471 mM[i] = points[i].m();
478 bool clockwise =
false;
479 int segSide = segmentSide( p1, p3, p2 );
485 QgsPointV2 circlePoint1 = clockwise ? p3 : p1;
487 QgsPointV2 circlePoint3 = clockwise ? p1 : p3 ;
496 if ( circlePoint1 != circlePoint3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
504 double increment = tolerance;
507 double halfAngle = acos( -tolerance / radius + 1 );
508 increment = 2 * halfAngle;
512 double a1 = atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
513 double a2 = atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
514 double a3 = atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
530 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint1 );
531 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
548 if (( addP2 &&
angle > a2 ) )
550 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint2 );
554 x = centerX + radius * cos(
angle );
555 y = centerY + radius * sin(
angle );
557 if ( !hasZ && !hasM )
565 z = interpolateArc(
angle, a1, a2, a3, circlePoint1.
z(), circlePoint2.
z(), circlePoint3.
z() );
569 m = interpolateArc(
angle, a1, a2, a3, circlePoint1.
m(), circlePoint2.
m(), circlePoint3.
m() );
572 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(),
QgsPointV2( pointWkbType, x, y, z, m ) );
575 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint3 );
576 points.
append( stringPoints );
581 double side = (( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
600 double QgsCircularStringV2::interpolateArc(
double angle,
double a1,
double a2,
double a3,
double zm1,
double zm2,
double zm3 )
const 606 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
608 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
614 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
616 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
631 double* zArray = mZ.
data();
635 bool useDummyZ = !hasZ || !transformZ;
638 zArray =
new double[nPoints];
639 for (
int i = 0; i < nPoints; ++i )
656 for (
int i = 0; i < nPoints; ++i )
659 t.
map( mX.
at( i ), mY.
at( i ), &x, &y );
666 void QgsCircularStringV2::clip(
const QgsRectangle& rect )
685 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
689 for (
int j = 1; j < pt.
size(); ++j )
691 path.
lineTo( pt.
at( j ).x(), pt.
at( j ).y() );
697 if ( nPoints % 2 == 0 )
699 path.
lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
705 double centerX, centerY, radius;
707 radius, centerX, centerY );
712 double diameter = 2 * radius;
713 path.
arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
739 bool vertexNrEven = ( position.
vertex % 2 == 0 );
759 mX[position.
vertex] = newPos.
x();
760 mY[position.
vertex] = newPos.
y();
763 mZ[position.
vertex] = newPos.
z();
767 mM[position.
vertex] = newPos.
m();
781 if ( position.
vertex < 0 || position.
vertex > ( nVertices - 1 ) )
786 if ( position.
vertex < ( nVertices - 2 ) )
823 bool minDistLeftOf =
false;
825 double currentDist = 0.0;
828 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
830 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
831 if ( currentDist < minDist )
833 minDist = currentDist;
834 minDistSegmentPoint = segmentPt;
846 segmentPt = minDistSegmentPoint;
847 vertexAfter = minDistVertexAfter;
848 vertexAfter.
part = 0;
849 vertexAfter.
ring = 0;
852 *leftOf = minDistLeftOf;
872 for (
int i = 0; i < maxIndex; i += 2 )
886 sum += 0.5 * ( mX[i] * mY[i+2] - mY[i] * mX[i+2] );
889 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
890 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
892 double radius, centerX, centerY;
896 double r2 = radius * radius;
907 double cov = 0.5 - d * sqrt( r2 - d * d ) / (
M_PI * r2 ) - 1 /
M_PI * asin( d / radius );
908 double circleChordArea = 0;
909 if ( circlePointLeftOfLine == centerPointLeftOfLine )
911 circleChordArea =
M_PI * r2 * ( 1 - cov );
915 circleChordArea =
M_PI * r2 * cov;
918 if ( !circlePointLeftOfLine )
920 sum += circleChordArea;
924 sum -= circleChordArea;
929 double QgsCircularStringV2::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
932 double radius, centerX, centerY;
957 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
958 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
965 segmentPt.
setX( pt.
x() );
966 segmentPt.
setY( pt.
y() );
972 *
leftOf = clockwise ? sqrDistance > radius : sqrDistance < radius;
978 void QgsCircularStringV2::insertVertexBetween(
int after,
int before,
int pointOnCircle )
980 double xAfter = mX.
at( after );
981 double yAfter = mY.
at( after );
982 double xBefore = mX.
at( before );
983 double yBefore = mY.
at( before );
984 double xOnCircle = mX.
at( pointOnCircle );
985 double yOnCircle = mY.
at( pointOnCircle );
987 double radius, centerX, centerY;
990 double x = ( xAfter + xBefore ) / 2.0;
991 double y = ( yAfter + yBefore ) / 2.0;
994 mX.
insert( before, newVertex.
x() );
995 mY.
insert( before, newVertex.
y() );
999 mZ.
insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
1003 mM.
insert( before, ( mM[after] + mM[before] ) / 2.0 );
1010 int before = vId.
vertex - 1;
1012 int after = vId.
vertex + 1;
1014 if ( vId.
vertex % 2 != 0 )
1048 int vertex1 = vId.
vertex - 2;
1049 int vertex2 = vId.
vertex - 1;
1050 int vertex3 = vId.
vertex;
1053 int vertex4 = vId.
vertex + 1;
1054 int vertex5 = vId.
vertex + 2;
1066 std::reverse( copy->mX.
begin(), copy->mX.
end() );
1067 std::reverse( copy->mY.
begin(), copy->mY.
end() );
1070 std::reverse( copy->mZ.
begin(), copy->mZ.
end() );
1074 std::reverse( copy->mM.
begin(), copy->mM.
end() );
1090 for (
int i = 0; i < nPoints; ++i )
1108 for (
int i = 0; i < nPoints; ++i )
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual bool dropMValue() override
Drops any measure values which exist in the geometry.
A rectangle specified with double values.
static QgsPointV2 pointOnLineWithDistance(const QgsPointV2 &startPoint, const QgsPointV2 &directionPoint, double distance)
Returns a point a specified distance toward a second point.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
static double circleTangentDirection(const QgsPointV2 &tangentPoint, const QgsPointV2 &cp1, const QgsPointV2 &cp2, const QgsPointV2 &cp3)
Calculates the direction angle of a circle tangent (clockwise from north in radians) ...
virtual QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
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 (...
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
static bool circleAngleBetween(double angle, double angle1, double angle2, bool clockwise)
Returns true if, in a circle, angle is between angle1 and angle2.
QPointF currentPosition() const
static double ccwAngle(double dy, double dx)
Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 an...
virtual QgsLineStringV2 * 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...
QDomNode appendChild(const QDomNode &newChild)
void push_back(const T &value)
static double averageAngle(double x1, double y1, double x2, double y2, double x3, double y3)
Angle between two linear segments.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Circular string geometry type.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequenceV2 &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
virtual bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
virtual bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
const T & at(int i) const
void addToPainterPath(QPainterPath &path) const override
Adds a curve to a painter path.
void insert(int i, const T &value)
static void circleCenterRadius(const QgsPointV2 &pt1, const QgsPointV2 &pt2, const QgsPointV2 &pt3, double &radius, double ¢erX, double ¢erY)
Returns radius and center of the circle through pt1, pt2, pt3.
virtual bool operator!=(const QgsCurveV2 &other) const override
void moveTo(const QPointF &point)
void setX(double x)
Sets the point's x-coordinate.
static double leftOfLine(double x, double y, double x1, double y1, double x2, double y2)
Returns < 0 if point(x/y) is left of the line x1,y1 -> x2,y2.
virtual void clear() override
Clears the geometry, ie reset it to a null geometry.
static double circleLength(double x1, double y1, double x2, double y2, double x3, double y3)
Length of a circular string segment defined by pt1, pt2, pt3.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
double z() const
Returns the point's z-coordinate.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
double y() const
Returns the point's y-coordinate.
static endian_t endian()
Returns whether this machine uses big or little endian.
virtual bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
void setY(double y)
Sets the point's y-coordinate.
virtual double length() const override
Returns the length of the geometry.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
virtual bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
static bool circleClockwise(double angle1, double angle2, double angle3)
Returns true if circle is ordered clockwise.
void append(const T &value)
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
virtual void clearCache() const override
Clears any cached parameters associated with the geometry, eg bounding boxes.
static double sqrDistance2D(const QgsPointV2 &pt1, const QgsPointV2 &pt2)
Returns the squared 2D distance between two points.
Utility class for identifying a unique vertex within a geometry.
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
Line string geometry type, with support for z-dimension and m-values.
static QString pointsToWKT(const QgsPointSequenceV2 &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
void lineTo(const QPointF &endPoint)
void setPoints(const QgsPointSequenceV2 &points)
Resets the line string to match the specified list of points.
bool isMeasure() const
Returns true if the geometry contains m values.
Point geometry type, with support for z-dimension and m-values.
QgsPointV2 pointN(int i) const
Returns the point at index i within the circular string.
bool pointAt(int node, QgsPointV2 &point, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
QgsWKBTypes::Type mWkbType
void sumUpArea(double &sum) const override
Sums up the area of the curve by iterating over the vertices (shoelace formula).
virtual bool moveVertex(QgsVertexId position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
double x() const
Returns the point's x-coordinate.
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
static bool angleOnCircle(double angle, double angle1, double angle2, double angle3)
Returns true if an angle is between angle1 and angle3 on a circle described by angle1, angle2 and angle3.
virtual QgsPointV2 startPoint() const override
Returns the starting point of the curve.
double closestSegment(const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon) const override
Searches for the closest segment of the geometry to a given point.
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
virtual QgsCircularStringV2 * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
static QDomElement pointsToGML3(const QgsPointSequenceV2 &points, QDomDocument &doc, int precision, const QString &ns, bool is3D)
Returns a gml::posList DOM element.
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsCircularStringV2 * clone() const override
Clones the geometry by performing a deep copy.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
void setPoints(const QgsPointSequenceV2 &points)
Sets the circular string's points.
virtual QgsPointV2 endPoint() const override
Returns the end point of the curve.
static Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
const T & at(int i) const
virtual bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
void drawPath(const QPainterPath &path)
static QgsPointSequenceV2 pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
static double sweepAngle(double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3)
Calculates angle of a circular string part defined by pt1, pt2, pt3.
void insert(int i, const T &value)
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
static Type flatType(Type type)
Returns the flat type for a WKB type.
void points(QgsPointSequenceV2 &pts) const override
Returns a list of points within the curve.
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'.
QgsWKBTypes::Type readHeader() const
const_iterator constEnd() const
const_iterator constBegin() const
Abstract base class for curved geometry type.
QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
virtual bool insertVertex(QgsVertexId position, const QgsPointV2 &vertex) override
Inserts a vertex into the geometry.
void arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
double m() const
Returns the point's m value.
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
virtual bool operator==(const QgsCurveV2 &other) const override
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
int numPoints() const override
Returns the number of points in the curve.