Logo Search packages:      
Sourcecode: inkscape version File versions

double sp_offset_distance_to_original ( SPOffset offset,
NR::Point  px 
)

Distance to the original path; that function is called from object-edit to set the radius when the control knot moves.

The sign of the result is the radius we're going to offset the shape with, so result > 0 ==outset and result < 0 ==inset. thus result<0 means 'px inside source'.

Todo:
Awfully damn stupid method: uncross the source path EACH TIME you need to compute the distance. The good way to do this would be to store the uncrossed source path somewhere, and delete it when the context is finished. Hopefully this part is much faster than actually computing the offset (which happen just after), so the time spent in this function should end up being negligible with respect to the delay of one context.

Definition at line 873 of file sp-offset.cpp.

References Geom::cross(), Geom::dot(), SPOffset::originalPath, and vectors_are_clockwise().

{
    if (offset == NULL || offset->originalPath == NULL
        || ((Path *) offset->originalPath)->descr_cmd.size() <= 1)
        return 1.0;
    double dist = 1.0;
    Shape *theShape = new Shape;
    Shape *theRes = new Shape;

    /** \todo
     * Awfully damn stupid method: uncross the source path EACH TIME you
     * need to compute the distance. The good way to do this would be to
     * store the uncrossed source path somewhere, and delete it when the
     * context is finished. Hopefully this part is much faster than actually
     * computing the offset (which happen just after), so the time spent in
     * this function should end up being negligible with respect to the
     * delay of one context.
     */
    // move
    ((Path *) offset->originalPath)->Convert (1.0);
    ((Path *) offset->originalPath)->Fill (theShape, 0);
    theRes->ConvertToShape (theShape, fill_oddEven);

    if (theRes->numberOfEdges() <= 1)
    {

    }
    else
    {
        double ptDist = -1.0;
        bool ptSet = false;
        double arDist = -1.0;
        bool arSet = false;
        // first get the minimum distance to the points
        for (int i = 0; i < theRes->numberOfPoints(); i++)
        {
            if (theRes->getPoint(i).totalDegree() > 0)
          {
                NR::Point nx = theRes->getPoint(i).x;
                NR::Point nxpx = px-nx;
                double ndist = sqrt (dot(nxpx,nxpx));
                if (ptSet == false || fabs (ndist) < fabs (ptDist))
                {
                    // we have a new minimum distance
                    // now we need to wheck if px is inside or outside (for the sign)
                    nx = px - theRes->getPoint(i).x;
                    double nlen = sqrt (dot(nx , nx));
                    nx /= nlen;
                    int pb, cb, fb;
                    fb = theRes->getPoint(i).incidentEdge[LAST];
                    pb = theRes->getPoint(i).incidentEdge[LAST];
                    cb = theRes->getPoint(i).incidentEdge[FIRST];
                    do
                    {
                        // one angle
                        NR::Point prx, nex;
                        prx = theRes->getEdge(pb).dx;
                        nlen = sqrt (dot(prx, prx));
                        prx /= nlen;
                        nex = theRes->getEdge(cb).dx;
                        nlen = sqrt (dot(nex , nex));
                        nex /= nlen;
                        if (theRes->getEdge(pb).en == i)
                        {
                            prx = -prx;
                        }
                        if (theRes->getEdge(cb).en == i)
                        {
                            nex = -nex;
                        }

                        if (vectors_are_clockwise (nex, nx, prx))
                        {
                            // we're in that angle. set the sign, and exit that loop
                            if (theRes->getEdge(cb).st == i)
                            {
                                ptDist = -ndist;
                                ptSet = true;
                            }
                            else
                            {
                                ptDist = ndist;
                                ptSet = true;
                            }
                            break;
                        }
                        pb = cb;
                        cb = theRes->NextAt (i, cb);
                    }
                    while (cb >= 0 && pb >= 0 && pb != fb);
                }
          }
        }
        // loop over the edges to try to improve the distance
        for (int i = 0; i < theRes->numberOfEdges(); i++)
        {
            NR::Point sx = theRes->getPoint(theRes->getEdge(i).st).x;
            NR::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
            NR::Point nx = ex - sx;
            double len = sqrt (dot(nx,nx));
            if (len > 0.0001)
          {
                NR::Point   pxsx=px-sx;
                double ab = dot(nx,pxsx);
                if (ab > 0 && ab < len * len)
                {
                    // we're in the zone of influence of the segment
                    double ndist = (cross(pxsx,nx)) / len;
                    if (arSet == false || fabs (ndist) < fabs (arDist))
                    {
                        arDist = ndist;
                        arSet = true;
                    }
                }
          }
        }
        if (arSet || ptSet)
        {
            if (arSet == false)
                arDist = ptDist;
            if (ptSet == false)
                ptDist = arDist;
            if (fabs (ptDist) < fabs (arDist))
                dist = ptDist;
            else
                dist = arDist;
        }
    }

    delete theShape;
    delete theRes;

    return dist;
}


Generated by  Doxygen 1.6.0   Back to index