/** * Take the given line segment @a lineSeg, compare it with the partition * plane and determine into which of the two sets it should be. If the * line segment is found to intersect the partition, the intercept point * is determined and the line segment then split in two at this point. * Each piece of the line segment is then added to the relevant set. * * If the line segment is collinear with, or intersects the partition then * a new intercept is added to the partitioning half-plane. * * @note Any existing @em twin of @a lineSeg is so too handled uniformly. * * @param seg Line segment to be "partitioned". * @param rights Set of line segments on the right side of the partition. * @param lefts Set of line segments on the left side of the partition. */ void divideOneSegment(LineSegmentSide &seg, LineSegmentBlockTreeNode &rights, LineSegmentBlockTreeNode &lefts) { coord_t fromDist, toDist; LineRelationship rel = hplane.relationship(seg, &fromDist, &toDist); switch(rel) { case Collinear: { interceptPartition(seg, LineSegment::From); interceptPartition(seg, LineSegment::To); // Direction (vs that of the partition plane) determines in which // subset this line segment belongs. if(seg.direction().dot(hplane.partition().direction) < 0) { linkLineSegmentInBlockTree(lefts, seg); } else { linkLineSegmentInBlockTree(rights, seg); } break; } case Right: case RightIntercept: if(rel == RightIntercept) { // Direction determines which edge of the line segment interfaces // with the new half-plane intercept. interceptPartition(seg, (fromDist < DIST_EPSILON? LineSegment::From : LineSegment::To)); } linkLineSegmentInBlockTree(rights, seg); break; case Left: case LeftIntercept: if(rel == LeftIntercept) { interceptPartition(seg, (fromDist > -DIST_EPSILON? LineSegment::From : LineSegment::To)); } linkLineSegmentInBlockTree(lefts, seg); break; case Intersects: { // Calculate the intersection point and split this line segment. Vector2d point = intersectPartition(seg, fromDist, toDist); LineSegmentSide &newFrontRight = splitLineSegment(seg, point); // Ensure the new back left segment is inserted into the same block as // the old back right segment. if(LineSegmentBlockTreeNode *backLeftBlock = (LineSegmentBlockTreeNode *)seg.back().blockTreeNodePtr()) { linkLineSegmentInBlockTree(*backLeftBlock, newFrontRight.back()); } interceptPartition(seg, LineSegment::To); // Direction determines which subset the line segments are added to. if(fromDist < 0) { linkLineSegmentInBlockTree(rights, newFrontRight); linkLineSegmentInBlockTree(lefts, seg); } else { linkLineSegmentInBlockTree(rights, seg); linkLineSegmentInBlockTree(lefts, newFrontRight); } break; } } }