27 #include <QPainterPath>
57 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
70 if ( nPoints > 0 && nPoints % 2 == 0 )
83 double centerX, centerY, radius;
106 QList<QgsPointV2> compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
108 for ( ; cpIt != compassPoints.
constEnd(); ++cpIt )
110 bbox.combineExtentWith( cpIt->x(), cpIt->y() );
115 QList<QgsPointV2> QgsCircularStringV2::compassPointsOnSegment(
double p1Angle,
double p2Angle,
double p3Angle,
double centerX,
double centerY,
double radius )
119 QgsPointV2 nPoint( centerX, centerY + radius );
120 QgsPointV2 ePoint( centerX + radius, centerY );
121 QgsPointV2 sPoint( centerX, centerY - radius );
122 QgsPointV2 wPoint( centerX - radius, centerY );
124 if ( p3Angle >= p1Angle )
126 if ( p2Angle > p1Angle && p2Angle < p3Angle )
128 if ( p1Angle <= 90 && p3Angle >= 90 )
130 pointList.
append( nPoint );
132 if ( p1Angle <= 180 && p3Angle >= 180 )
134 pointList.
append( wPoint );
136 if ( p1Angle <= 270 && p3Angle >= 270 )
138 pointList.
append( sPoint );
143 pointList.
append( ePoint );
144 if ( p1Angle >= 90 || p3Angle <= 90 )
146 pointList.
append( nPoint );
148 if ( p1Angle >= 180 || p3Angle <= 180 )
150 pointList.
append( wPoint );
152 if ( p1Angle >= 270 || p3Angle <= 270 )
154 pointList.
append( sPoint );
160 if ( p2Angle < p1Angle && p2Angle > p3Angle )
162 if ( p1Angle >= 270 && p3Angle <= 270 )
164 pointList.
append( sPoint );
166 if ( p1Angle >= 180 && p3Angle <= 180 )
168 pointList.
append( wPoint );
170 if ( p1Angle >= 90 && p3Angle <= 90 )
172 pointList.
append( nPoint );
177 pointList.
append( ePoint );
178 if ( p1Angle <= 270 || p3Angle >= 270 )
180 pointList.
append( sPoint );
182 if ( p1Angle <= 180 || p3Angle >= 180 )
184 pointList.
append( wPoint );
186 if ( p1Angle <= 90 || p3Angle >= 90 )
188 pointList.
append( nPoint );
219 for (
int i = 0; i < nVertices; ++i )
252 int size =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
260 unsigned char* geomPtr =
new unsigned char[binarySize];
263 wkb << static_cast<quint32>(
wkbType() );
316 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
347 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
358 return qMin( mX.
size(), mY.
size() );
363 if ( qMin( mX.
size(), mY.
size() ) <= i )
368 double x = mX.
at( i );
369 double y = mY.
at( i );
402 for (
int i = 0; i < nPts; ++i )
410 if ( points.
size() < 1 )
418 bool hasZ = firstPt.
is3D();
442 for (
int i = 0; i < points.
size(); ++i )
444 mX[i] = points[i].x();
445 mY[i] = points[i].y();
448 mZ[i] = points[i].z();
452 mM[i] = points[i].m();
464 int segSide = segmentSide( p1, p3, p2 );
466 if ( p1 != p3 && ( radius < 0 ||
qgsDoubleNear( segSide, 0.0 ) ) )
474 bool clockwise =
false;
480 double increment = fabs(
M_PI_2 / 90 );
483 double a1 = atan2( p1.
y() - centerY, p1.
x() - centerX );
484 double a2 = atan2( p2.
y() - centerY, p2.
x() - centerX );
485 double a3 = atan2( p3.
y() - centerY, p3.
x() - centerX );
513 if ( p2 != p3 && p1 != p2 )
517 x = centerX + radius * cos(
angle );
518 y = centerY + radius * sin(
angle );
520 if ( !hasZ && !hasM )
528 z = interpolateArc(
angle, a1, a2, a3, p1.
z(), p2.
z(), p3.
z() );
532 m = interpolateArc(
angle, a1, a2, a3, p1.
m(), p2.
m(), p3.
m() );
543 double side = (( pt2.
x() - pt1.
x() ) * ( pt3.
y() - pt1.
y() ) - ( pt3.
x() - pt1.
x() ) * ( pt2.
y() - pt1.
y() ) );
562 double QgsCircularStringV2::interpolateArc(
double angle,
double a1,
double a2,
double a3,
double zm1,
double zm2,
double zm3 )
const
568 return zm1 + ( zm2 - zm1 ) * ( angle - a1 ) / ( a2 - a1 );
570 return zm2 + ( zm3 - zm2 ) * ( angle - a2 ) / ( a3 - a2 );
576 return zm1 + ( zm2 - zm1 ) * ( a1 - angle ) / ( a1 - a2 );
578 return zm2 + ( zm3 - zm2 ) * ( a2 - angle ) / ( a2 - a3 );
591 double* zArray = mZ.
data();
597 zArray =
new double[nPoints];
598 for (
int i = 0; i < nPoints; ++i )
613 for (
int i = 0; i < nPoints; ++i )
616 t.
map( mX[i], mY[i], &x, &y );
617 mX[i] = x; mY[i] = y;
622 void QgsCircularStringV2::clip(
const QgsRectangle& rect )
641 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
645 for (
int j = 1; j < pt.
size(); ++j )
647 path.
lineTo( pt.
at( j ).x(), pt.
at( j ).y() );
653 if ( nPoints % 2 == 0 )
655 path.
lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] );
661 double centerX, centerY, radius;
663 radius, centerX, centerY );
668 double diameter = 2 * radius;
669 path.
arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
695 bool vertexNrEven = ( position.
vertex % 2 == 0 );
715 mX[position.
vertex] = newPos.
x();
716 mY[position.
vertex] = newPos.
y();
719 mZ[position.
vertex] = newPos.
z();
723 mM[position.
vertex] = newPos.
m();
736 if ( position.
vertex < 1 || position.
vertex > ( nVertices - 2 ) )
741 if ( position.
vertex < ( nVertices - 2 ) )
777 bool minDistLeftOf =
false;
779 double currentDist = 0.0;
782 for (
int i = 0; i < ( nPoints - 2 ) ; i += 2 )
784 currentDist = closestPointOnArc( mX[i], mY[i], mX[i + 1], mY[i + 1], mX[i + 2], mY[i + 2], pt, segmentPt, vertexAfter, leftOf, epsilon );
785 if ( currentDist < minDist )
787 minDist = currentDist;
788 minDistSegmentPoint = segmentPt;
797 segmentPt = minDistSegmentPoint;
798 vertexAfter = minDistVertexAfter;
799 vertexAfter.
part = 0; vertexAfter.
ring = 0;
802 *leftOf = minDistLeftOf;
822 for (
int i = 0; i < maxIndex; i += 2 )
836 sum += 0.5 * ( mX[i] * mY[i+2] - mY[i] * mX[i+2] );
839 double midPointX = ( p1.
x() + p3.
x() ) / 2.0;
840 double midPointY = ( p1.
y() + p3.
y() ) / 2.0;
842 double radius, centerX, centerY;
846 double r2 = radius * radius;
857 double cov = 0.5 - d * sqrt( r2 - d * d ) / (
M_PI * r2 ) - 1 /
M_PI * asin( d / radius );
858 double circleChordArea = 0;
859 if ( circlePointLeftOfLine == centerPointLeftOfLine )
861 circleChordArea =
M_PI * r2 * ( 1 - cov );
865 circleChordArea =
M_PI * r2 * cov;
868 if ( !circlePointLeftOfLine )
870 sum += circleChordArea;
874 sum -= circleChordArea;
879 double QgsCircularStringV2::closestPointOnArc(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
882 double radius, centerX, centerY;
907 segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3;
908 vertexAfter.
vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2;
915 segmentPt.
setX( pt.
x() );
916 segmentPt.
setY( pt.
y() );
922 *leftOf = clockwise ? sqrDistance > radius : sqrDistance < radius;
928 void QgsCircularStringV2::insertVertexBetween(
int after,
int before,
int pointOnCircle )
930 double xAfter = mX[after];
931 double yAfter = mY[after];
932 double xBefore = mX[before];
933 double yBefore = mY[before];
934 double xOnCircle = mX[ pointOnCircle ];
935 double yOnCircle = mY[ pointOnCircle ];
937 double radius, centerX, centerY;
940 double x = ( xAfter + xBefore ) / 2.0;
941 double y = ( yAfter + yBefore ) / 2.0;
944 mX.
insert( before, newVertex.
x() );
945 mY.
insert( before, newVertex.
y() );
949 mZ.
insert( before, ( mZ[after] + mZ[before] ) / 2.0 );
953 mM.
insert( before, ( mM[after] + mM[before] ) / 2.0 );
959 int before = vId.
vertex - 1;
961 int after = vId.
vertex + 1;
963 if ( vId.
vertex % 2 != 0 )
997 int vertex1 = vId.
vertex - 2;
998 int vertex2 = vId.
vertex - 1;
1002 int vertex4 = vId.
vertex + 1;
1003 int vertex5 = vId.
vertex + 2;
1022 for (
int i = 0; i < nPoints; ++i )
1039 for (
int i = 0; i < nPoints; ++i )
QgsWKBTypes::Type wkbType() const
Returns the WKB type of 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
Calculates 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.
virtual bool fromWkb(const unsigned char *wkb) override
Sets the geometry from a WKB string.
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.
Circular string geometry type.
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
static QString pointsToWKT(const QList< QgsPointV2 > &points, int precision, bool is3D, bool isMeasure)
Returns a WKT coordinate list.
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.
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
void moveTo(const QPointF &point)
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.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
static endian_t endian()
Returns whether this machine uses big or little endian.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
virtual double length() const override
Returns the length of the geometry.
QgsPointV2 pointN(int i) const
Returns the point at index i within the circular string.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
QgsWKBTypes::Type readHeader() const
static Type flatType(Type type)
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
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)
void drawAsPolygon(QPainter &p) const override
Draws the curve as a polygon on the specified QPainter.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
void setPoints(const QList< QgsPointV2 > &points)
Sets the circular string's points.
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.
bool isMeasure() const
Returns true if the geometry contains m values.
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
Line string geometry type.
void lineTo(const QPointF &endPoint)
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
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
Calculates the area of the curve.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
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 bool deleteVertex(const QgsVertexId &position) override
Deletes a vertex within the geometry.
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)
static QDomElement pointsToGML3(const QList< QgsPointV2 > &points, QDomDocument &doc, int precision, const QString &ns, bool is3D)
Returns a gml::posList DOM element.
virtual bool insertVertex(const QgsVertexId &position, const QgsPointV2 &vertex) override
Inserts a vertex into the geometry.
virtual bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool moveVertex(const QgsVertexId &position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
virtual QgsCircularStringV2 * clone() const override
Clones the geometry by performing a deep copy.
virtual QgsPointV2 endPoint() const override
Returns the end point of the curve.
const T & at(int i) const
bool pointAt(int i, QgsPointV2 &vertex, QgsVertexId::VertexType &type) const override
Returns the point and vertex id of a point within the curve.
void points(QList< QgsPointV2 > &pts) const override
Returns a list of points within the curve.
void drawPath(const QPainterPath &path)
void setPoints(const QList< QgsPointV2 > &points)
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.
QgsAbstractGeometryV2 * segmentize() const override
Returns a version of the geometry without curves.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
static QList< QgsPointV2 > pointsFromWKT(const QString &wktCoordinateList, bool is3D, bool isMeasure)
Returns a list of points contained in a WKT string.
QgsRectangle mBoundingBox
double vertexAngle(const QgsVertexId &vertex) const override
Returns approximate rotation angle for a vertex.
static Type parseType(const QString &wktStr)
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'.
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.
static void pointsToWKB(QgsWkbPtr &wkb, const QList< QgsPointV2 > &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
void arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
int numPoints() const override
Returns the number of points in the curve.