bool QgsTriangle::moveVertex( QgsVertexId vId, const QgsPoint &newPos ) { if ( !mExteriorRing || vId.part != 0 || vId.ring != 0 || vId.vertex < 0 || vId.vertex > 4 ) { return false; } if ( vId.vertex == 4 ) { vId.vertex = 0; } QgsPoint p1( vId.vertex == 0 ? newPos : vertexAt( 0 ) ); QgsPoint p2( vId.vertex == 1 ? newPos : vertexAt( 1 ) ); QgsPoint p3( vId.vertex == 2 ? newPos : vertexAt( 2 ) ); if ( !validateGeom( p1, p2, p3 ) ) { return false; } int n = mExteriorRing->numPoints(); bool success = mExteriorRing->moveVertex( vId, newPos ); if ( success ) { // If first or last vertex is moved, also move the last/first vertex if ( vId.vertex == 0 ) mExteriorRing->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos ); clearCache(); } return success; }
QVector<QgsLineString> QgsTriangle::altitudes() const { QVector<QgsLineString> alt; alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 0 ), vertexAt( 2 ), vertexAt( 1 ) ) ); alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 1 ), vertexAt( 0 ), vertexAt( 2 ) ) ); alt.append( QgsGeometryUtils::perpendicularSegment( vertexAt( 2 ), vertexAt( 0 ), vertexAt( 1 ) ) ); return alt; }
ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule) : ExclusionShape() , m_vertices(vertices) , m_fillRule(fillRule) { unsigned nVertices = numberOfVertices(); m_edges.resize(nVertices); m_empty = nVertices < 3; if (nVertices) m_boundingBox.setLocation(vertexAt(0)); if (m_empty) return; unsigned minVertexIndex = 0; for (unsigned i = 1; i < nVertices; ++i) { const FloatPoint& vertex = vertexAt(i); if (vertex.y() < vertexAt(minVertexIndex).y() || (vertex.y() == vertexAt(minVertexIndex).y() && vertex.x() < vertexAt(minVertexIndex).x())) minVertexIndex = i; } FloatPoint nextVertex = vertexAt((minVertexIndex + 1) % nVertices); FloatPoint prevVertex = vertexAt((minVertexIndex + nVertices - 1) % nVertices); bool clockwise = determinant(vertexAt(minVertexIndex) - prevVertex, nextVertex - prevVertex) > 0; unsigned edgeIndex = 0; unsigned vertexIndex1 = 0; do { m_boundingBox.extend(vertexAt(vertexIndex1)); unsigned vertexIndex2 = findNextEdgeVertexIndex(vertexIndex1, clockwise); m_edges[edgeIndex].polygon = this; m_edges[edgeIndex].vertexIndex1 = vertexIndex1; m_edges[edgeIndex].vertexIndex2 = vertexIndex2; m_edges[edgeIndex].edgeIndex = edgeIndex; edgeIndex++; vertexIndex1 = vertexIndex2; } while (vertexIndex1); if (edgeIndex > 3) { const ExclusionPolygonEdge& firstEdge = m_edges[0]; const ExclusionPolygonEdge& lastEdge = m_edges[edgeIndex - 1]; if (areCollinearPoints(lastEdge.vertex1(), lastEdge.vertex2(), firstEdge.vertex2())) { m_edges[0].vertexIndex1 = lastEdge.vertexIndex1; edgeIndex--; } } m_edges.resize(edgeIndex); m_empty = m_edges.size() < 3; if (m_empty) return; for (unsigned i = 0; i < m_edges.size(); i++) { ExclusionPolygonEdge* edge = &m_edges[i]; m_edgeTree.add(EdgeInterval(edge->minY(), edge->maxY(), edge)); } }
bool QgsTriangle::operator==( const QgsTriangle &other ) const { if ( isEmpty() && other.isEmpty() ) { return true; } else if ( isEmpty() || other.isEmpty() ) { return false; } return ( ( vertexAt( 0 ) == other.vertexAt( 0 ) ) && ( vertexAt( 1 ) == other.vertexAt( 1 ) ) && ( vertexAt( 2 ) == other.vertexAt( 2 ) ) ); }
unsigned ExclusionPolygon::findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const { unsigned nVertices = numberOfVertices(); unsigned vertexIndex2 = nextVertexIndex(vertexIndex1, nVertices, clockwise); while (vertexIndex2 && areCoincidentPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2))) vertexIndex2 = nextVertexIndex(vertexIndex2, nVertices, clockwise); while (vertexIndex2) { unsigned vertexIndex3 = nextVertexIndex(vertexIndex2, nVertices, clockwise); if (!areCollinearPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2), vertexAt(vertexIndex3))) break; vertexIndex2 = vertexIndex3; } return vertexIndex2; }
QgsTriangle QgsTriangle::medial() const { QgsPoint p1, p2, p3; p1 = QgsGeometryUtils::midpoint( vertexAt( 0 ), vertexAt( 1 ) ); p2 = QgsGeometryUtils::midpoint( vertexAt( 1 ), vertexAt( 2 ) ); p3 = QgsGeometryUtils::midpoint( vertexAt( 2 ), vertexAt( 0 ) ); return QgsTriangle( p1, p2, p3 ); }
QVector<double> QgsTriangle::lengths() const { QVector<double> lengths; lengths.append( vertexAt( 0 ).distance( vertexAt( 1 ) ) ); lengths.append( vertexAt( 1 ).distance( vertexAt( 2 ) ) ); lengths.append( vertexAt( 2 ).distance( vertexAt( 0 ) ) ); return lengths; }
QgsPoint QgsTriangle::inscribedCenter() const { QVector<double> l = lengths(); double x = ( l.at( 0 ) * vertexAt( 2 ).x() + l.at( 1 ) * vertexAt( 0 ).x() + l.at( 2 ) * vertexAt( 1 ).x() ) / perimeter(); double y = ( l.at( 0 ) * vertexAt( 2 ).y() + l.at( 1 ) * vertexAt( 0 ).y() + l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter(); return QgsPoint( x, y ); }
QVector<QgsLineString> QgsTriangle::medians() const { QVector<QgsLineString> med; QgsLineString med1; QgsLineString med2; QgsLineString med3; med1.setPoints( QgsPointSequence() << vertexAt( 0 ) << QgsGeometryUtils::midpoint( vertexAt( 1 ), vertexAt( 2 ) ) ); med2.setPoints( QgsPointSequence() << vertexAt( 1 ) << QgsGeometryUtils::midpoint( vertexAt( 0 ), vertexAt( 2 ) ) ); med3.setPoints( QgsPointSequence() << vertexAt( 2 ) << QgsGeometryUtils::midpoint( vertexAt( 0 ), vertexAt( 1 ) ) ); med.append( med1 ); med.append( med2 ); med.append( med3 ); return med; }
QgsPointV2 QgsAbstractGeometryV2::centroid() const { // http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon // Pick the first ring of first part for the moment int n = vertexCount( 0, 0 ); if ( n == 1 ) { return vertexAt( QgsVertexId( 0, 0, 0 ) ); } double A = 0.; double Cx = 0.; double Cy = 0.; int i = 0, j = 1; if ( vertexAt( QgsVertexId( 0, 0, 0 ) ) != vertexAt( QgsVertexId( 0, 0, n - 1 ) ) ) { i = n - 1; j = 0; } for ( ; j < n; i = j++ ) { QgsPointV2 vi = vertexAt( QgsVertexId( 0, 0, i ) ); QgsPointV2 vj = vertexAt( QgsVertexId( 0, 0, j ) ); double d = vi.x() * vj.y() - vj.x() * vi.y(); A += d; Cx += ( vi.x() + vj.x() ) * d; Cy += ( vi.y() + vj.y() ) * d; } if ( A < 1E-12 ) { Cx = Cy = 0.; for ( int i = 0; i < n - 1; ++i ) { QgsPointV2 vi = vertexAt( QgsVertexId( 0, 0, i ) ); Cx += vi.x(); Cy += vi.y(); } return QgsPointV2( Cx / ( n - 1 ), Cy / ( n - 1 ) ); } else { return QgsPointV2( Cx / ( 3. * A ), Cy / ( 3. * A ) ); } }
QVector<double> QgsTriangle::angles() const { QVector<double> angles; double ax, ay, bx, by, cx, cy; ax = vertexAt( 0 ).x(); ay = vertexAt( 0 ).y(); bx = vertexAt( 1 ).x(); by = vertexAt( 1 ).y(); cx = vertexAt( 2 ).x(); cy = vertexAt( 2 ).y(); double a1 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( cx, cy, ax, ay, bx, by ), M_PI ); double a2 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( ax, ay, bx, by, cx, cy ), M_PI ); double a3 = std::fmod( QgsGeometryUtils::angleBetweenThreePoints( bx, by, cx, cy, ax, ay ), M_PI ); angles.append( ( a1 > M_PI_2 ? a1 - M_PI_2 : a1 ) ); angles.append( ( a2 > M_PI_2 ? a2 - M_PI_2 : a2 ) ); angles.append( ( a3 > M_PI_2 ? a3 - M_PI_2 : a3 ) ); return angles; }
double QgsTriangle::circumscribedRadius() const { double r, x, y; QgsGeometryUtils::circleCenterRadius( vertexAt( 0 ), vertexAt( 1 ), vertexAt( 2 ), r, x, y ); return r; }
QVector<QgsLineString> QgsTriangle::bisectors( double lengthTolerance ) const { QVector<QgsLineString> bis; QgsLineString bis1; QgsLineString bis2; QgsLineString bis3; QgsPoint incenter = inscribedCenter(); QgsPoint out; QgsGeometryUtils::segmentIntersection( vertexAt( 0 ), incenter, vertexAt( 1 ), vertexAt( 2 ), out, lengthTolerance ); bis1.setPoints( QgsPointSequence() << vertexAt( 0 ) << out ); QgsGeometryUtils::segmentIntersection( vertexAt( 1 ), incenter, vertexAt( 0 ), vertexAt( 2 ), out, lengthTolerance ); bis2.setPoints( QgsPointSequence() << vertexAt( 1 ) << out ); QgsGeometryUtils::segmentIntersection( vertexAt( 2 ), incenter, vertexAt( 0 ), vertexAt( 1 ), out, lengthTolerance ); bis3.setPoints( QgsPointSequence() << vertexAt( 2 ) << out ); bis.append( bis1 ); bis.append( bis2 ); bis.append( bis3 ); return bis; }
QgsPointV2 QgsTriangle::circumscribedCenter() const { double r, x, y; QgsGeometryUtils::circleCenterRadius( vertexAt( 0 ), vertexAt( 1 ), vertexAt( 2 ), r, x, y ); return QgsPointV2( x, y ); }