Logo Search packages:      
Sourcecode: inkscape version File versions

int Geom::winding ( Path const &  path,
Point  p 
)

This function computes the winding of the path, given a reference point. Positive values correspond to counter-clockwise in the mathematical coordinate system, and clockwise in screen coordinates. This particular implementation casts a ray in the positive x direction. It iterates the path, checking for intersection with the bounding boxes. If an intersection is found, the initial/final Y value of the curve is used to derive a delta on the winding value. If the point is within the bounding box, the curve specific winding function is called.

Definition at line 24 of file path-intersection.cpp.

References Geom::D2< Interval >::contains(), Geom::D2< Interval >::height(), Geom::D2< Interval >::left(), and Geom::D2< Interval >::right().

                                       {
  //start on a segment which is not a horizontal line with y = p[y]
  Path::const_iterator start;
  for(Path::const_iterator iter = path.begin(); ; ++iter) {
    if(iter == path.end_closed()) { return 0; }
    if(iter->initialPoint()[Y]!=p[Y])   { start = iter; break; }
    if(iter->finalPoint()[Y]!=p[Y])     { start = iter; break; }
    if(iter->boundsFast()->height()!=0.){ start = iter; break; }
  }
  int wind = 0;
  unsigned cnt = 0;
  bool starting = true;
  for (Path::const_iterator iter = start; iter != start || starting
       ; ++iter, iter = (iter == path.end_closed()) ? path.begin() : iter )
  {
    cnt++;
    if(cnt > path.size()) return wind;  //some bug makes this required
    starting = false;
    Rect bounds = *(iter->boundsFast());
    Coord x = p[X], y = p[Y];
    
    if(x > bounds.right() || !bounds[Y].contains(y)) continue; //ray doesn't intersect box
    
    Point final = iter->finalPoint();
    Point initial = iter->initialPoint();
    Cmp final_to_ray = cmp(final[Y], y);
    Cmp initial_to_ray = cmp(initial[Y], y);
    
    // if y is included, these will have opposite values, giving order.
    Cmp c = cmp(final_to_ray, initial_to_ray); 
    if(x < bounds.left()) {
        // ray goes through bbox
        // winding delta determined by position of endpoints
        if(final_to_ray != EQUAL_TO) {
            wind += int(c); // GT = counter-clockwise = 1; LT = clockwise = -1; EQ = not-included = 0
            //std::cout << int(c) << " ";
            goto cont;
        }
    } else {
        //inside bbox, use custom per-curve winding thingie
        int delt = iter->winding(p);
        wind += delt;
        //std::cout << "n" << delt << " ";
    }
    //Handling the special case of an endpoint on the ray:
    if(final[Y] == y) {
        //Traverse segments until it breaks away from y
        //99.9% of the time this will happen the first go
        Path::const_iterator next = iter;
        next++;
        for(; ; next++) {
            if(next == path.end_closed()) next = path.begin();
            Rect bnds = *(next->boundsFast());
            //TODO: X considerations
            if(bnds.height() > 0) {
                //It has diverged
                if(bnds.contains(p)) {
                    const double fudge = 0.01;
                    if(cmp(y, next->valueAt(fudge, Y)) == initial_to_ray) {
                        wind += int(c);
                        //std::cout << "!!!!!" << int(c) << " ";
                    }
                    iter = next; // No increment, as the rest of the thing hasn't been counted.
                } else {
                    Coord ny = next->initialPoint()[Y];
                    if(cmp(y, ny) == initial_to_ray) {
                        //Is a continuation through the ray, so counts windingwise
                        wind += int(c);
                        //std::cout << "!!!!!" << int(c) << " ";
                    }
                    iter = ++next;
                }
                goto cont;
            }
            if(next==start) return wind;
        }
        //Looks like it looped, which means everything's flat
        return 0;
    }
    
    cont:(void)0;
  }
  return wind;
}


Generated by  Doxygen 1.6.0   Back to index