예제 #1
0
Geom::Path half_outline_old(Geom::Path const& input, double width, double miter, Inkscape::LineJoinType join = Inkscape::JOIN_BEVEL)
{
    Geom::Path res;
    if (input.size() == 0) return res;

    Geom::Point tang1 = input[0].unitTangentAt(0);
    Geom::Point start = input.initialPoint() + tang1 * width;
    Geom::Path temp;
    Geom::Point tang[2];

    res.setStitching(true);
    temp.setStitching(true);

    res.start(start);

    // Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well
    const size_t k = (input.back_closed().isDegenerate() && input.closed())
            ?input.size_default()-1:input.size_default();
    for (size_t u = 0; u < k; u += 2) {
        temp.clear();

        offset_curve_old(temp, &input[u], width);

        // on the first run through, there isn't a join
        if (u == 0) {
            res.append(temp);
        } else {
            tangents_old(tang, input[u-1], input[u]);
            outline_join(res, temp, tang[0], tang[1], width, miter, join);
        }

        // odd number of paths
        if (u < k - 1) {
            temp.clear();
            offset_curve_old(temp, &input[u+1], width);
            tangents_old(tang, input[u], input[u+1]);
            outline_join(res, temp, tang[0], tang[1], width, miter, join);
        }
    }

    if (input.closed()) {
        Geom::Curve const &c1 = res.back();
        Geom::Curve const &c2 = res.front();
        temp.clear();
        temp.append(c1);
        Geom::Path temp2;
        temp2.append(c2);
        tangents_old(tang, input.back(), input.front());
        outline_join(temp, temp2, tang[0], tang[1], width, miter, join);
        res.erase(res.begin());
        res.erase_last();
        //
        res.append(temp);
        res.close();
    }

    return res;
}
예제 #2
0
/* rectangular cutter.
ctr    "center" of rectangle (might not actually be in the center with respect to leading/trailing edges
pos    vector from center to leading edge
neg    vector from center to trailing edge
width  vector to side edge
*/
Geom::PathVector PrintMetafile::rect_cutter(Geom::Point ctr, Geom::Point pos, Geom::Point neg, Geom::Point width)
{
    std::vector<Geom::Path> outres;
    Geom::Path cutter;
    cutter.start(ctr + pos - width);
    cutter.appendNew<Geom::LineSegment>(ctr + pos + width);
    cutter.appendNew<Geom::LineSegment>(ctr + neg + width);
    cutter.appendNew<Geom::LineSegment>(ctr + neg - width);
    cutter.close();
    outres.push_back(cutter);
    return outres;
}
예제 #3
0
void Inkscape::ObjectSnapper::_snapPathsConstrained(IntermSnapResults &isr,
                                     SnapCandidatePoint const &p,
                                     SnapConstraint const &c,
                                     Geom::Point const &p_proj_on_constraint) const
{

    _collectPaths(p_proj_on_constraint, p.getSourceType(), p.getSourceNum() <= 0);

    // Now we can finally do the real snapping, using the paths collected above

    SPDesktop const *dt = _snapmanager->getDesktop();
    g_assert(dt != NULL);

    Geom::Point direction_vector = c.getDirection();
    if (!is_zero(direction_vector)) {
        direction_vector = Geom::unit_vector(direction_vector);
    }

    // The intersection point of the constraint line with any path, must lie within two points on the
    // SnapConstraint: p_min_on_cl and p_max_on_cl. The distance between those points is twice the snapping tolerance
    Geom::Point const p_min_on_cl = dt->dt2doc(p_proj_on_constraint - getSnapperTolerance() * direction_vector);
    Geom::Point const p_max_on_cl = dt->dt2doc(p_proj_on_constraint + getSnapperTolerance() * direction_vector);
    Geom::Coord tolerance = getSnapperTolerance();

    // PS: Because the paths we're about to snap to are all expressed relative to document coordinate system, we will have
    // to convert the snapper coordinates from the desktop coordinates to document coordinates

    std::vector<Geom::Path> constraint_path;
    if (c.isCircular()) {
        Geom::Circle constraint_circle(dt->dt2doc(c.getPoint()), c.getRadius());
        constraint_circle.getPath(constraint_path);
    } else {
        Geom::Path constraint_line;
        constraint_line.start(p_min_on_cl);
        constraint_line.appendNew<Geom::LineSegment>(p_max_on_cl);
        constraint_path.push_back(constraint_line);
    }
    // Length of constraint_path will always be one

    bool strict_snapping = _snapmanager->snapprefs.getStrictSnapping();

    // Find all intersections of the constrained path with the snap target candidates
    std::vector<Geom::Point> intersections;
    for (std::vector<SnapCandidatePath >::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); ++k) {
        if (k->path_vector && _allowSourceToSnapToTarget(p.getSourceType(), (*k).target_type, strict_snapping)) {
            // Do the intersection math
            Geom::CrossingSet cs = Geom::crossings(constraint_path, *(k->path_vector));
            // Store the results as intersection points
            unsigned int index = 0;
            for (Geom::CrossingSet::const_iterator i = cs.begin(); i != cs.end(); ++i) {
                if (index >= constraint_path.size()) {
                    break;
                }
                // Reconstruct and store the points of intersection
                for (Geom::Crossings::const_iterator m = (*i).begin(); m != (*i).end(); ++m) {
                    intersections.push_back(constraint_path[index].pointAt((*m).ta));
                }
                index++;
            }

            //Geom::crossings will not consider the closing segment apparently, so we'll handle that separately here
            //TODO: This should have been fixed in rev. #9859, which makes this workaround obsolete
            for(Geom::PathVector::iterator it_pv = k->path_vector->begin(); it_pv != k->path_vector->end(); ++it_pv) {
                if (it_pv->closed()) {
                    // Get the closing linesegment and convert it to a path
                    Geom::Path cls;
                    cls.close(false);
                    cls.append(it_pv->back_closed());
                    // Intersect that closing path with the constrained path
                    Geom::Crossings cs = Geom::crossings(constraint_path.front(), cls);
                    // Reconstruct and store the points of intersection
                    index = 0; // assuming the constraint path vector has only one path
                    for (Geom::Crossings::const_iterator m = cs.begin(); m != cs.end(); ++m) {
                        intersections.push_back(constraint_path[index].pointAt((*m).ta));
                    }
                }
            }

            // Convert the collected points of intersection to snapped points
            for (std::vector<Geom::Point>::iterator p_inters = intersections.begin(); p_inters != intersections.end(); ++p_inters) {
                // Convert to desktop coordinates
                (*p_inters) = dt->doc2dt(*p_inters);
                // Construct a snapped point
                Geom::Coord dist = Geom::L2(p.getPoint() - *p_inters);
                SnappedPoint s = SnappedPoint(*p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);;
                // Store the snapped point
                if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it
                    isr.points.push_back(s);
                }
            }
        }
    }
}