bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy ) const { BOX2I bbox = BBox(); bbox.Inflate( aAccuracy ); if( !m_closed || PointCount() < 3 || !BBox().Contains( aPt ) ) return false; bool inside = false; /** * To check for interior points, we draw a line in the positive x direction from * the point. If it intersects an even number of segments, the point is outside the * line chain (it had to first enter and then exit). Otherwise, it is inside the chain. * * Note: slope might be denormal here in the case of a horizontal line but we require our * y to move from above to below the point (or vice versa) */ for( int i = 0; i < PointCount(); i++ ) { const auto p1 = CPoint( i ); const auto p2 = CPoint( i + 1 ); // CPoint wraps, so ignore counts const auto diff = p2 - p1; if( diff.y != 0 ) { const int d = rescale( diff.x, ( aPt.y - p1.y ), diff.y ); if( ( ( p1.y > aPt.y ) != ( p2.y > aPt.y ) ) && ( aPt.x - p1.x < d ) ) inside = !inside; } } return inside && !PointOnEdge( aPt, aAccuracy ); }
int PointInPolygon(int n, Point p[]) { int i, area = 0; for (i = 0; i < n; ++i) { //area += p[(i+1) % n].y * (p[i].x - p[(i+2) % n].x); // 如果将式子展开,可以简化成这个样子,减小运算量 area += p[i].x * p[(i+1)%n].y - p[i].y * p[(i+1) % n].x; } return (abs(area) - PointOnEdge(n, p)) / 2 + 1; }
float3 Polygon::RandomPointOnEdge(LCG &rng) const { return PointOnEdge(rng.Float()); }
vec AABB::RandomPointOnEdge(LCG &rng) const { int i = rng.Int(0, 11); float f = rng.Float(); return PointOnEdge(i, f); }
float3 OBB::RandomPointOnEdge(LCG &rng) const { return PointOnEdge(rng.Int(0, 11), rng.Float()); }