double OGRCompoundCurve::get_Area() const { if( IsEmpty() || !get_IsClosed() ) return 0; // Optimization for convex rings. if( IsConvex() ) { // Compute area of shape without the circular segments. OGRPointIterator* poIter = getPointIterator(); OGRLineString oLS; oLS.setNumPoints( getNumPoints() ); OGRPoint p; for( int i = 0; poIter->getNextPoint(&p); i++ ) { oLS.setPoint( i, p.getX(), p.getY() ); } double dfArea = oLS.get_Area(); delete poIter; // Add the area of the spherical segments. dfArea += get_AreaOfCurveSegments(); return dfArea; } OGRLineString* poLS = CurveToLine(); double dfArea = poLS->get_Area(); delete poLS; return dfArea; }
bool Polygon::DiagonalExists(int i, int j) const { assume(p.size() >= 3); assume(i >= 0); assume(j >= 0); assume(i < (int)p.size()); assume(j < (int)p.size()); #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS if (p.size() < 3 || i < 0 || j < 0 || i >= (int)p.size() || j >= (int)p.size()) return false; #endif assume(IsPlanar()); assume(i != j); if (i == j) // Degenerate if i == j. return false; if (i > j) Swap(i, j); assume(i+1 != j); if (i+1 == j) // Is this LineSegment an edge of this polygon? return false; Plane polygonPlane = PlaneCCW(); LineSegment diagonal = polygonPlane.Project(LineSegment(p[i], p[j])); // First check that this diagonal line is not intersected by an edge of this polygon. for(int k = 0; k < (int)p.size(); ++k) if (!(k == i || k+1 == i || k == j)) if (polygonPlane.Project(LineSegment(p[k], p[k+1])).Intersects(diagonal)) return false; return IsConvex(); }
double OGRCircularString::get_Area() const { if( IsEmpty() || !get_IsClosed() ) return 0; double cx = 0.0; double cy = 0.0; double square_R = 0.0; if( IsFullCircle(cx, cy, square_R) ) { return M_PI * square_R; } // Optimization for convex rings. if( IsConvex() ) { // Compute area of shape without the circular segments. double dfArea = get_LinearArea(); // Add the area of the spherical segments. dfArea += get_AreaOfCurveSegments(); return dfArea; } OGRLineString* poLS = CurveToLine(); const double dfArea = poLS->get_Area(); delete poLS; return dfArea; }
bool Polyhedron::ContainsConvex(const float3 &point) const { assume(IsConvex()); for(int i = 0; i < NumFaces(); ++i) if (FacePlane(i).SignedDistance(point) > 0.f) return false; return true; }
Polygon::Polygon(std::vector<sf::Vector2f> points, sf::Color color, sf::Vector2f position) { //No points = nothing to do if (points.size() < 0) return; //Check if shape is concave or convex if (IsConvex(points)) { //If it is convex, we only have 1 shape in m_shapes CreateConvexPolygon(points, color); } m_shape.setPosition(position); }
bool Polyhedron::ClipLineSegmentToConvexPolyhedron(const float3 &ptA, const float3 &dir, float &tFirst, float &tLast) const { assume(IsConvex()); // Intersect line segment against each plane. for(int i = 0; i < NumFaces(); ++i) { /* Denoting the dot product of vectors a and b with <a,b>, we have: The points P on the plane p satisfy the equation <P, p.normal> == p.d. The points P on the line have the parametric equation P = ptA + dir * t. Solving for the distance along the line for intersection gives t = (p.d - <p.normal, ptA>) / <p.normal, dir>. */ Plane p = FacePlane(i); float denom = Dot(p.normal, dir); float dist = p.d - Dot(p.normal, ptA); // Avoid division by zero. In this case the line segment runs parallel to the plane. if (Abs(denom) < 1e-5f) { // If <P, p.normal> < p.d, then the point lies in the negative halfspace of the plane, which is inside the polyhedron. // If <P, p.normal> > p.d, then the point lies in the positive halfspace of the plane, which is outside the polyhedron. // Therefore, if p.d - <ptA, p.normal> == dist < 0, then the whole line is outside the polyhedron. if (dist < 0.f) return false; } else { float t = dist / denom; if (denom < 0.f) // When entering halfspace, update tFirst if t is larger. tFirst = Max(t, tFirst); else // When exiting halfspace, updeate tLast if t is smaller. tLast = Min(t, tLast); if (tFirst > tLast) return false; // We clipped the whole line segment. } } return true; }
float3 Polyhedron::ClosestPointConvex(const float3 &point) const { assume(IsConvex()); if (ContainsConvex(point)) return point; float3 closestPoint = float3::nan; float closestDistance = FLT_MAX; for(int i = 0; i < NumFaces(); ++i) { float3 closestOnPoly = FacePolygon(i).ClosestPoint(point); float d = closestOnPoly.DistanceSq(point); if (d < closestDistance) { closestPoint = closestOnPoly; closestDistance = d; } } return closestPoint; }
void VoronoiPolygonSite::DrawSiteFilled() { // DETERMINE WINDING ORDER (ONLY DRAW CAP ON CCW, "OUTSIDE" IS REALLY OUTSIDE) if (OrderingIsCCW(Pts,NumPts)) { // DETERMINE IF POLYGON IS CONVEX OR NONCONVEX if (IsConvex(Pts,NumPts)) { glBegin(GL_POLYGON); for (int k=0; k<(NumPts*2); k+=2) glVertex2fv(&(Pts[k])); glEnd(); } else // NONCONVEX POLYGONS MUST BE TRIANGULATED (OPENGL DOES NOT HANDLE NONCONVEX) { //DrawNonconvexPoly(Pts,NumPts); DrawSiteFilledWithTessPoly(Pts, NumPts); } } else { DrawSiteFilledWithTessPoly(Pts, NumPts); } }
TriangulateEC<Real>::TriangulateEC (int iQuantity, const Vector2<Real>* akPosition, Query::Type eQueryType, Real fEpsilon, int*& raiIndex) { assert(iQuantity >= 3 && akPosition); if (eQueryType == Query::QT_FILTERED) { assert((Real)0.0 <= fEpsilon && fEpsilon <= (Real)1.0); } Vector2<Real>* akSPosition = 0; Vector2<Real> kMin, kMax, kRange; Real fScale; int i; switch (eQueryType) { case Query::QT_INT64: // Transform the vertices to the square [0,2^{20}]^2. Vector2<Real>::ComputeExtremes(iQuantity,akPosition,kMin,kMax); kRange = kMax - kMin; fScale = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]); fScale *= (Real)(1 << 20); akSPosition = WM4_NEW Vector2<Real>[iQuantity]; for (i = 0; i < iQuantity; i++) { akSPosition[i] = (akPosition[i] - kMin)*fScale; } m_pkQuery = WM4_NEW Query2Int64<Real>(iQuantity,akSPosition); break; case Query::QT_INTEGER: // Transform the vertices to the square [0,2^{24}]^2. Vector2<Real>::ComputeExtremes(iQuantity,akPosition,kMin,kMax); kRange = kMax - kMin; fScale = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]); fScale *= (Real)(1 << 24); akSPosition = WM4_NEW Vector2<Real>[iQuantity]; for (i = 0; i < iQuantity; i++) { akSPosition[i] = (akPosition[i] - kMin)*fScale; } m_pkQuery = WM4_NEW Query2TInteger<Real>(iQuantity,akSPosition); break; case Query::QT_REAL: // Transform the vertices to the square [0,1]^2. Vector2<Real>::ComputeExtremes(iQuantity,akPosition,kMin,kMax); kRange = kMax - kMin; fScale = (kRange[0] >= kRange[1] ? kRange[0] : kRange[1]); akSPosition = WM4_NEW Vector2<Real>[iQuantity]; for (i = 0; i < iQuantity; i++) { akSPosition[i] = (akPosition[i] - kMin)*fScale; } m_pkQuery = WM4_NEW Query2<Real>(iQuantity,akSPosition); break; case Query::QT_RATIONAL: // No transformation of the input data. m_pkQuery = WM4_NEW Query2TRational<Real>(iQuantity,akPosition); break; case Query::QT_FILTERED: // No transformation of the input data. m_pkQuery = WM4_NEW Query2Filtered<Real>(iQuantity,akPosition, fEpsilon); break; } int iQm1 = iQuantity - 1; raiIndex = WM4_NEW int[3*iQm1]; int* piIndex = raiIndex; m_akVertex = WM4_NEW Vertex[iQuantity]; m_iCFirst = -1; m_iCLast = -1; m_iRFirst = -1; m_iRLast = -1; m_iEFirst = -1; m_iELast = -1; // Create a circular list of the polygon vertices for dynamic removal of // vertices. Keep track of two linear sublists, one for the convex // vertices and one for the reflex vertices. This is an O(N) process // where N is the number of polygon vertices. for (i = 0; i <= iQm1; i++) { // link the vertices Vertex& rkV = V(i); rkV.VPrev = (i > 0 ? i-1 : iQm1); rkV.VNext = (i < iQm1 ? i+1 : 0); // link the convex/reflex vertices if (IsConvex(i)) { InsertAfterC(i); } else { InsertAfterR(i); } } if (m_iRFirst == -1) { // polygon is convex, just triangle fan it for (i = 1; i < iQm1; i++) { *piIndex++ = 0; *piIndex++ = i; *piIndex++ = i+1; } return; } // Identify the ears and build a circular list of them. Let V0, V1, and // V2 be consecutive vertices forming a triangle T. The vertex V1 is an // ear if no other vertices of the polygon lie inside T. Although it is // enough to show that V1 is not an ear by finding at least one other // vertex inside T, it is sufficient to search only the reflex vertices. // This is an O(C*R) process where C is the number of convex vertices and // R is the number of reflex vertices, N = C+R. The order is O(N^2), for // example when C = R = N/2. for (i = m_iCFirst; i != -1; i = V(i).SNext) { if (IsEar(i)) { InsertEndE(i); } } V(m_iEFirst).EPrev = m_iELast; V(m_iELast).ENext = m_iEFirst; // Remove the ears, one at a time. while (true) { // add triangle of ear to output int iVPrev = V(m_iEFirst).VPrev; int iVNext = V(m_iEFirst).VNext; *piIndex++ = iVPrev; *piIndex++ = m_iEFirst; *piIndex++ = iVNext; // remove the vertex corresponding to the ear RemoveV(m_iEFirst); if (--iQuantity == 3) { // Only one triangle remains, just remove the ear and copy it. RemoveE(); iVPrev = V(m_iEFirst).VPrev; iVNext = V(m_iEFirst).VNext; *piIndex++ = iVPrev; *piIndex++ = m_iEFirst; *piIndex++ = iVNext; break; } // removal of the ear can cause an adjacent vertex to become an ear bool bWasReflex; Vertex& rkVPrev = V(iVPrev); if (!rkVPrev.IsEar) { bWasReflex = !rkVPrev.IsConvex; if (IsConvex(iVPrev)) { if (bWasReflex) { RemoveR(iVPrev); } if (IsEar(iVPrev)) { InsertBeforeE(iVPrev); } } } Vertex& rkVNext = V(iVNext); if (!rkVNext.IsEar) { bWasReflex = !rkVNext.IsConvex; if (IsConvex(iVNext)) { if (bWasReflex) { RemoveR(iVNext); } if (IsEar(iVNext)) { InsertAfterE(iVNext); } } } // remove the ear RemoveE(); } WM4_DELETE[] akSPosition; WM4_DELETE m_pkQuery; }