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 )
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 = fabs(
M_PI_2 / 90 );
507 double a1 = atan2( circlePoint1.
y() - centerY, circlePoint1.
x() - centerX );
508 double a2 = atan2( circlePoint2.
y() - centerY, circlePoint2.
x() - centerX );
509 double a3 = atan2( circlePoint3.
y() - centerY, circlePoint3.
x() - centerX );
525 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint1 );
526 if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 )
543 if (( addP2 &&
angle > a2 ) )
545 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint2 );
549 x = centerX + radius * cos(
angle );
550 y = centerY + radius * sin(
angle );
552 if ( !hasZ && !hasM )
560 z = interpolateArc(
angle, a1, a2, a3, circlePoint1.
z(), circlePoint2.
z(), circlePoint3.
z() );
564 m = interpolateArc(
angle, a1, a2, a3, circlePoint1.
m(), circlePoint2.
m(), circlePoint3.
m() );
567 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(),
QgsPointV2( pointWkbType, x, y, z, m ) );
570 stringPoints.
insert( clockwise ? 0 : stringPoints.
size(), circlePoint3 );
571 points.
append( stringPoints );
576 double side = (( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
595 double QgsCircularStringV2::interpolateArc(
double angle,
double a1,
double a2,
double a3,
double zm1,
double zm2,
double zm3 )
const 601 return zm1 + ( zm2 - zm1 ) * (
angle - a1 ) / ( a2 - a1 );
603 return zm2 + ( zm3 - zm2 ) * (
angle - a2 ) / ( a3 - a2 );
609 return zm1 + ( zm2 - zm1 ) * ( a1 -
angle ) / ( a1 - a2 );
611 return zm2 + ( zm3 - zm2 ) * ( a2 -
angle ) / ( a2 - a3 );
626 double* zArray = mZ.
data();
632 zArray =
new double[nPoints];
633 for (
int i = 0; i < nPoints; ++i )
650 for (
int i = 0; i < nPoints; ++i )
653 t.
map( mX.
at( i ), mY.
at( i ), &x, &y );
660 void QgsCircularStringV2::clip(
const QgsRectangle& rect )
679 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
683 for (
int j = 1; j < pt.
size(); ++j )
685 path.
lineTo( pt.
at( j ).x(), pt.
at( j ).y() );
691 if ( nPoints % 2 == 0 )
693 path.
lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
699 double centerX, centerY, radius;
701 radius, centerX, centerY );
706 double diameter = 2 * radius;
707 path.
arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
733 bool vertexNrEven = ( position.
vertex % 2 == 0 );
753 mX[position.
vertex] = newPos.
x();
754 mY[position.
vertex] = newPos.
y();
757 mZ[position.
vertex] = newPos.
z();
761 mM[position.
vertex] = newPos.
m();
774 if ( position.
vertex < 1 || position.
vertex > ( nVertices - 2 ) )
779 if ( position.
vertex < ( nVertices - 2 ) )
816 bool minDistLeftOf =
false;
818 double currentDist = 0.0;
821 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
823 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
824 if ( currentDist < minDist )
826 minDist = currentDist;
827 minDistSegmentPoint = segmentPt;
839 segmentPt = minDistSegmentPoint;
840 vertexAfter = minDistVertexAfter;
841 vertexAfter.
part = 0;
842 vertexAfter.
ring = 0;
845 *leftOf = minDistLeftOf;
865 for (
int i = 0; i < maxIndex; i += 2 )
879 sum += 0.5 * ( mX[i] * mY[i+2] - mY[i] * mX[i+2] );
882 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
883 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
885 double radius, centerX, centerY;
889 double r2 = radius * radius;
900 double cov = 0.5 - d * sqrt( r2 - d * d ) / (
M_PI * r2 ) - 1 /
M_PI * asin( d / radius );
901 double circleChordArea = 0;
902 if ( circlePointLeftOfLine == centerPointLeftOfLine )
904 circleChordArea =
M_PI * r2 * ( 1 - cov );
908 circleChordArea =
M_PI * r2 * cov;
911 if ( !circlePointLeftOfLine )
913 sum += circleChordArea;
917 sum -= circleChordArea;
922 double QgsCircularStringV2::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
925 double radius, centerX, centerY;
950 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
951 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
958 segmentPt.
setX( pt.
x() );
959 segmentPt.
setY( pt.
y() );
965 *
leftOf = clockwise ? sqrDistance > radius : sqrDistance < radius;
971 void QgsCircularStringV2::insertVertexBetween(
int after,
int before,
int pointOnCircle )
973 double xAfter = mX.
at( after );
974 double yAfter = mY.
at( after );
975 double xBefore = mX.
at( before );
976 double yBefore = mY.
at( before );
977 double xOnCircle = mX.
at( pointOnCircle );
978 double yOnCircle = mY.
at( pointOnCircle );
980 double radius, centerX, centerY;
983 double x = ( xAfter + xBefore ) / 2.0;
984 double y = ( yAfter + yBefore ) / 2.0;
987 mX.
insert( before, newVertex.
x() );
988 mY.
insert( before, newVertex.
y() );
992 mZ.
insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
996 mM.
insert( before, ( mM[after] + mM[before] ) / 2.0 );
1003 int before = vId.
vertex - 1;
1005 int after = vId.
vertex + 1;
1007 if ( vId.
vertex % 2 != 0 )
1041 int vertex1 = vId.
vertex - 2;
1042 int vertex2 = vId.
vertex - 1;
1043 int vertex3 = vId.
vertex;
1046 int vertex4 = vId.
vertex + 1;
1047 int vertex5 = vId.
vertex + 2;
1059 std::reverse( copy->mX.
begin(), copy->mX.
end() );
1060 std::reverse( copy->mY.
begin(), copy->mY.
end() );
1063 std::reverse( copy->mZ.
begin(), copy->mZ.
end() );
1067 std::reverse( copy->mM.
begin(), copy->mM.
end() );
1083 for (
int i = 0; i < nPoints; ++i )
1101 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...
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.
const T & at(int i) const
virtual QgsLineStringV2 * curveToLine() const override
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
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.
QgsCurveV2 * segmentize() const override
Returns a geometry without curves.
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.
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)
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 combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
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.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform) override
Transforms the geometry using a coordinate transform.
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.
virtual QString geometryType() const override
Returns a unique string representing the geometry type.
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 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.
static Type parseType(const QString &wktStr)
Attempts to extract the WKB type from a WKT string.
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.