IntersectResult PolygonSegmentIntersect(Segment* edge, TYPE* polygon) { { Rectangle* bb1 = polygon->GetBoundingBox(); Rectangle* bb2 = edge->GetBoundingBox(); if (!bb1->Collide(bb2, true)) return IR_SEPERATE; } Rectangle* bb1 = edge->GetBoundingBox(); Node* node_c = edge->A(); Node* node_d = edge->B(); Segment* edge_cd = new Segment(node_c, node_d); Nodes::iterator it = polygon->begin(); IntersectResult ret = IR_SEPERATE; int index = 0; for (; it != polygon->end();it++,index++) { if(typeid(polygon) == typeid(OpenPolygon*)) if(polygon->IsPortal(index)) continue; Node* node_a = *it; Node* node_b = *(polygon->GetNext(it)); Segment* edge_ab = new Segment(node_a, node_b); edge_ab->Calculate(); Rectangle* bb2 = edge_ab->GetBoundingBox(); if (bb1->Collide(bb2, true)) { IntersectResult result = SegmentSegmentIntersect(edge_ab, edge_cd); if (result == IR_INTERSECT) return IR_INTERSECT; if (result == IR_TOUCH) { if (node_c->Equal(node_a) || node_d->Equal(node_a)) { ret = IR_TOUCH; } // CAD straight else if (GetConvex(node_c, node_a, node_d) == CR_STRAIGHT) { Node* node_z = *(polygon->GetPrevious(it)); // Z and B in 2 different plane seperated by CD if (GetConvex(node_c, node_z, node_d) != GetConvex(node_c, node_b, node_d)) { return IR_INTERSECT; } else { ret = IR_TOUCH; } } else { ret = IR_TOUCH; } } } } return ret; }
/*------------------------------------------------ NAME: SegmentSegmentIntersect DATE: 11st JAN 2014 TASK: return ralation of 2 segment, seperate, touch, or intersect -------------------------------------------------*/ IntersectResult SegmentSegmentIntersect(Segment* s1, Segment* s2) { Rectangle* bb1 = s1->GetBoundingBox(); Rectangle* bb2 = s2->GetBoundingBox(); if (!bb1->Collide(bb2, true)) return IR_SEPERATE; Node *a = s1->A(); Node *b = s1->B(); Node *c = s2->A(); Node *d = s2->B(); return SegmentSegmentIntersect(a->X(), a->Y(), b->X(), b->Y(), c->X(), c->Y(), d->X(), d->Y()); }
/** * uses iteration of SegmentSegmentIntersect. * * returns the number of intersections it finds */ int SegmentPolylineIntersect( const ON_3dPoint& P, const ON_3dPoint& Q, const ON_Polyline& pline, ON_SimpleArray<ON_3dPoint> out, double tol ) { int rv = 0; int my_rv = 0; /* what this function will return at the end */ ON_3dPoint result[2]; for (int i = 0; i < (pline.Count() - 1); i++) { rv = SegmentSegmentIntersect(P, Q, pline[i], pline[i+1], result, tol); if (out) { /* the output field can be made null to use the function to check for intersections but not return them */ for (int j = 0; j < rv; j++) { out.Append(result[j]); } } my_rv += rv; } return my_rv; }
bool PointInPolyline( const ON_3dPoint& P, const ON_Polyline pline, double tol ) { if (!pline.IsClosed(tol)) { /* no inside to speak of */ return false; } /* First we need to find a point that's in the plane and outside the polyline */ ON_BoundingBox bbox; PolylineBBox(pline, &bbox); ON_3dPoint adder; int i; for (i = 0; i < pline.Count(); i++) { adder = P - pline[i]; if (!VNEAR_ZERO(adder, tol)) { break; } } ON_3dPoint DistantPoint = P; int multiplier = 2; do { DistantPoint += adder*multiplier; multiplier = multiplier*multiplier; } while (bbox.IsPointIn(DistantPoint, false)); bool inside = false; int rv; ON_3dPoint result[2]; for (i = 0; i < pline.Count() - 1; i++) { rv = SegmentSegmentIntersect(P, DistantPoint, pline[i], pline[i + 1], result, tol); if (rv == 1) { inside = !inside; } else if (rv == 2) { bu_exit(-1, "This is very unlikely bug in PointInPolyline which needs to be fixed\n"); } } return inside; }
/** * intersects a triangle ABC with a line PQ * * return values: * -1: error * 0: no intersection * 1: intersects in a point * 2: intersects in a line */ int SegmentTriangleIntersect( const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c, const ON_3dPoint& p, const ON_3dPoint& q, ON_3dPoint out[2], double tol ) { ON_3dPoint triangle[3] = {a, b, c}; /* it'll be nice to have this as an array too*/ /* First we need to get our plane into point normal form (N \dot (P - P0) = 0) * Where N is a normal vector, and P0 is a point in the plane * P0 can be any of {a, b, c} so that's easy * Finding N */ double normal[3]; VCROSS(normal, b - a, c - a); VUNITIZE(normal); ON_3dPoint P0 = a; /* could be b or c*/ /* Now we've got our plane in a manageable form (two of them actually) * So here's the rest of the plan: * Every point P on the line can be written as: P = p + u (q - p) * We just need to find u * We know that when u is correct: * normal dot (q + u * (q-p) = N dot P0 * N dot (P0 - p) * so u = -------------- * N dot (q - p) */ if (!NEAR_ZERO(VDOT(normal, (p-q)), tol)) {/* if this is 0 it indicates the line and plane are parallel*/ double u = VDOT(normal, (P0 - p))/VDOT(normal, (q - p)); if (u < 0.0 || u > 1.0) /* this means we're on the line but not the line segment*/ return 0; /* so we can return early*/ ON_3dPoint P = p + u * (q - p); if (PointInTriangle(a, b, c, P, tol)) { out[0] = P; return 1; } return 0; } else { /* If we're here it means that the line and plane are parallel*/ if (NEAR_ZERO(VDOT(normal, p-P0), tol)) {/* yahtzee!!*/ /* The line segment is in the same plane as the triangle*/ /* So first we check if the points are inside or outside the triangle*/ bool p_in = PointInTriangle(a, b, c, p, tol); bool q_in = PointInTriangle(a, b , c , q , tol); ON_3dPoint x[2]; /* a place to put our results*/ if (q_in && p_in) { out[0] = p; out[1] = q; return 2; } else if (q_in || p_in) { if (q_in) out[0] = q; else out[0] = p; int i; int rv; for (i=0; i<3; i++) { rv = SegmentSegmentIntersect(triangle[i], triangle[(i+1)%3], p, q, x, tol); if (rv == 1) { out[1] = x[0]; return 1; } else if (rv == 2) { out[0] = x[0]; out[1] = x[1]; return 2; } } } else { /* neither q nor p is in the triangle*/ int i; int points_found = 0; int rv; for (i = 0; i < 3; i++) { rv = SegmentSegmentIntersect(triangle[i], triangle[(i+1)%3], p, q, x, tol); if (rv == 1) { if (points_found == 0 || !VNEAR_EQUAL(out[0], x[0], tol)) { /* in rare cases we can get the same point twice*/ out[points_found] = x[0]; points_found++; } } else if (rv == 2) { out[0] = x[0]; out[1] = x[1]; return 2; } } return points_found; } } else return 0; } return -1; }