示例#1
0
Geom::PathVector
LPEGears::doEffect_path (Geom::PathVector const &path_in)
{
    Geom::PathVector path_out;
    Geom::Path gearpath = path_in[0];

    Geom::Path::iterator it(gearpath.begin());
    if ( it == gearpath.end() ) return path_out;

    Gear * gear = new Gear(teeth, 200.0, phi * M_PI / 180);
    Geom::Point gear_centre = (*it).finalPoint();
    gear->centre(gear_centre);
    gear->angle(atan2((*it).initialPoint() - gear_centre));

    ++it;
	if ( it == gearpath.end() ) return path_out;
    gear->pitch_radius(Geom::distance(gear_centre, (*it).finalPoint()));

    path_out.push_back( gear->path());

    for (++it; it != gearpath.end() ; ++it) {
        // iterate through Geom::Curve in path_in
        Gear* gearnew = new Gear(gear->spawn( (*it).finalPoint() ));
        path_out.push_back( gearnew->path() );
        delete gear;
        gear = gearnew;
    }
    delete gear;

    return path_out;
}
static void sp_svg_write_path(Inkscape::SVG::PathString & str, Geom::Path const & p) {
    str.moveTo( p.initialPoint()[0], p.initialPoint()[1] );

    for(Geom::Path::const_iterator cit = p.begin(); cit != p.end_open(); ++cit) {
        sp_svg_write_curve(str, &(*cit));
    }

    if (p.closed()) {
        str.closePath();
    }
}
/* 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;
}
示例#4
0
void
LPESimplify::drawHandleLine(Geom::Point p,Geom::Point p2)
{
    Geom::Path path;
    path.start( p );
    double diameter = radius_helper_nodes;
    if(helper_size > 0 && Geom::distance(p,p2) > (diameter * 0.35)) {
        Geom::Ray ray2(p, p2);
        p2 =  p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35));
    }
    path.appendNew<Geom::LineSegment>( p2 );
    hp.push_back(path);
}
示例#5
0
static void _circle(Geom::Point center, double radius, std::vector<Geom::Path> &path_out) {
    using namespace Geom;

    Geom::Path pb;

    D2<SBasis> B;
    Linear bo = Linear(0, 2 * M_PI);

    B[0] = cos(bo,4);
    B[1] = sin(bo,4);

    B = B * radius + center;

    pb.append(SBasisCurve(B));

    path_out.push_back(pb);
}
示例#6
0
/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */
static void
feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
{
    if (!area)
        return;
    if (path.empty())
        return;

    // Transform all coordinates to coords within "area"
    Geom::Point shift = area->min();
    Geom::Rect view = *area;
    view.expandBy (stroke_width);
    view = view * (Geom::Affine)Geom::Translate(-shift);
    //  Pass transformation to feed_curve, so that we don't need to create a whole new path.
    Geom::Affine transshift(trans * Geom::Translate(-shift));

    Geom::Point initial = path.initialPoint() * transshift;
    cairo_move_to(ct, initial[0], initial[1] );

    for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
        feed_curve_to_cairo(ct, *cit, transshift, view, optimize_stroke);
    }

    if (path.closed()) {
        if (!optimize_stroke) {
            cairo_close_path(ct);
        } else {
            cairo_line_to(ct, initial[0], initial[1]);
            /* We cannot use cairo_close_path(ct) here because some parts of the path may have been
               clipped and not drawn (maybe the before last segment was outside view area), which 
               would result in closing the "subpath" after the last interruption, not the entire path.

               However, according to cairo documentation:
               The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate
               in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead,
               there is a line join connecting the final and initial segments of the sub-path. 

               The correct fix will be possible when cairo introduces methods for moving without
               ending/starting subpaths, which we will use for skipping invisible segments; then we
               will be able to use cairo_close_path here. This issue also affects ps/eps/pdf export,
               see bug 168129
            */
        }
    }
}
示例#7
0
Geom::Path Layout::baseline() const
{
    iterator pos = this->begin();
    Geom::Point left_pt = this->characterAnchorPoint(pos);
    pos.thisEndOfLine();
    Geom::Point right_pt = this->characterAnchorPoint(pos);

    if (this->_blockProgression() == LEFT_TO_RIGHT || this->_blockProgression() == RIGHT_TO_LEFT) {
        left_pt = Geom::Point(left_pt[Geom::Y], left_pt[Geom::X]);
        right_pt = Geom::Point(right_pt[Geom::Y], right_pt[Geom::X]);
    }

    Geom::Path baseline;
    baseline.start(left_pt);
    baseline.appendNew<Geom::LineSegment>(right_pt);

    return baseline;
}
示例#8
0
/** Feeds path-creating calls to the cairo context translating them from the Path */
static void
feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
{
    if (path.empty())
        return;

    cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] );

    for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
        feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used
    }

    if (path.closed()) {
        cairo_close_path(ct);
    }
}
示例#9
0
void offset_curve_old(Geom::Path& res, Geom::Curve const* current, double width)
{
    double const tolerance = 0.0025;
    size_t levels = 8;

    if (current->isDegenerate()) return; // don't do anything

    // TODO: we can handle SVGEllipticalArc here as well, do that!

    if (Geom::BezierCurve const *b = dynamic_cast<Geom::BezierCurve const*>(current)) {
        size_t order = b->order();
        switch (order) {
        case 1:
            res.append(offset_line_old(static_cast<Geom::LineSegment const&>(*current), width));
            break;
        case 2: {
            Geom::QuadraticBezier const& q = static_cast<Geom::QuadraticBezier const&>(*current);
            offset_quadratic_old(res, q, width, tolerance, levels);
            break;
        }
        case 3: {
            Geom::CubicBezier const& cb = static_cast<Geom::CubicBezier const&>(*current);
            offset_cubic_old(res, cb, width, tolerance, levels);
            break;
        }
        default: {
            Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(current->toSBasis(), tolerance);
            for (size_t i = 0; i < sbasis_path.size(); ++i)
                offset_curve_old(res, &sbasis_path[i], width);
            break;
        }
        }
    } else {
        Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(current->toSBasis(), 0.1);
        for (size_t i = 0; i < sbasis_path.size(); ++i)
            offset_curve_old(res, &sbasis_path[i], width);
    }
}
示例#10
0
void offset_cubic_old(Geom::Path& p, Geom::CubicBezier const& bez, double width, double tol, size_t levels)
{
    using Geom::X;
    using Geom::Y;

    Geom::Point start_pos = bez.initialPoint();
    Geom::Point end_pos = bez.finalPoint();

    Geom::Point start_normal = Geom::rot90(bez.unitTangentAt(0));
    Geom::Point end_normal = -Geom::rot90(Geom::unitTangentAt(Geom::reverse(bez.toSBasis()), 0.));

    // offset the start and end control points out by the width
    Geom::Point start_new = start_pos + start_normal*width;
    Geom::Point end_new = end_pos + end_normal*width;

    // --------
    double start_rad, end_rad;
    double start_len, end_len; // tangent lengths
    get_cubic_data_old(bez, 0, start_len, start_rad);
    get_cubic_data_old(bez, 1, end_len, end_rad);

    double start_off = 1, end_off = 1;
    // correction of the lengths of the tangent to the offset
    if (!Geom::are_near(start_rad, 0))
        start_off += width / start_rad;
    if (!Geom::are_near(end_rad, 0))
        end_off += width / end_rad;
    start_off *= start_len;
    end_off *= end_len;
    // --------

    Geom::Point mid1_new = start_normal.ccw()*start_off;
    mid1_new = Geom::Point(start_new[X] + mid1_new[X]/3., start_new[Y] + mid1_new[Y]/3.);
    Geom::Point mid2_new = end_normal.ccw()*end_off;
    mid2_new = Geom::Point(end_new[X] - mid2_new[X]/3., end_new[Y] - mid2_new[Y]/3.);

    // create the estimate curve
    Geom::CubicBezier c = Geom::CubicBezier(start_new, mid1_new, mid2_new, end_new);

    // reached maximum recursive depth
    // don't bother with any more correction
    if (levels == 0) {
        p.append(c);
        return;
    }

    // check the tolerance for our estimate to be a parallel curve
    Geom::Point chk = c.pointAt(.5);
    Geom::Point req = bez.pointAt(.5) + Geom::rot90(bez.unitTangentAt(.5))*width; // required accuracy

    Geom::Point const diff = req - chk;
    double const err = Geom::dot(diff, diff);

    if (err < tol) {
        if (Geom::are_near(start_new, p.finalPoint())) {
            p.setFinal(start_new); // if it isn't near, we throw
        }

        // we're good, curve is accurate enough
        try {
          p.append(c);}
        catch (...) {

        }

        return;
    } else {
        // split the curve in two
        std::pair<Geom::CubicBezier, Geom::CubicBezier> s = bez.subdivide(.5);
        offset_cubic_old(p, s.first, width, tol, levels - 1);
        offset_cubic_old(p, s.second, width, tol, levels - 1);
    }
}
示例#11
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;
}
示例#12
0
    virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
        D2<SBasis2d> sb2;
        for(unsigned dim = 0; dim < 2; dim++) {
            sb2[dim].us = 2;
            sb2[dim].vs = 2;
            const int depth = sb2[dim].us*sb2[dim].vs;
            sb2[dim].resize(depth, Linear2d(0));
        }
        Geom::Point dir(1,-2);
        if(hand.pts.empty()) {
            for(unsigned vi = 0; vi < sb2[0].vs; vi++)
                for(unsigned ui = 0; ui < sb2[0].us; ui++)
                    for(unsigned iv = 0; iv < 2; iv++)
                        for(unsigned iu = 0; iu < 2; iu++)
                            hand.pts.push_back(Geom::Point((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
                                                           (2*(iv+vi)/(2.*vi+1)+1)*width/4.));

        }

        for(int dim = 0; dim < 2; dim++) {
            Geom::Point dir(0,0);
            dir[dim] = 1;
            for(unsigned vi = 0; vi < sb2[dim].vs; vi++)
                for(unsigned ui = 0; ui < sb2[dim].us; ui++)
                    for(unsigned iv = 0; iv < 2; iv++)
                        for(unsigned iu = 0; iu < 2; iu++) {
                            unsigned corner = iu + 2*iv;
                            unsigned i = ui + vi*sb2[dim].us;
                            Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
                                             (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
                            if(vi == 0 && ui == 0) {
                                base = Geom::Point(width/4., width/4.);
                            }
                            double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir);
                            sb2[dim][i][corner] = dl/(width/2)*pow(4.0,(double)ui+vi);
                        }
        }
        cairo_d2_sb2d(cr, sb2, dir*0.1, width);
        cairo_set_source_rgba (cr, 0., 0., 0, 0.5);
        cairo_stroke(cr);
        for(unsigned vi = 0; vi < v_subs; vi++) {
            double tv = vi * inv_v_subs;
            for(unsigned ui = 0; ui < u_subs; ui++) {
                double tu = ui * inv_u_subs;

                Geom::Path pb;
                D2<SBasis> B;
                D2<SBasis> tB;

                B[0] = Linear(tu-fudge, tu+fudge + inv_u_subs );
                B[1] = Linear(tv-fudge, tv-fudge);
                tB = compose_each(sb2, B);
                tB = tB*(width/2) + Geom::Point(width/4, width/4);
                pb.append(tB);

                B[0] = Linear(tu+fudge + inv_u_subs , tu+fudge + inv_u_subs);
                B[1] = Linear(tv-fudge,               tv+fudge + inv_v_subs);
                tB = compose_each(sb2, B);
                tB = tB*(width/2) + Geom::Point(width/4, width/4);
                pb.append(tB);

                B[0] = Linear(tu+fudge + inv_u_subs, tu-fudge);
                B[1] = Linear(tv+fudge + inv_v_subs, tv+fudge + inv_v_subs);
                tB = compose_each(sb2, B);
                tB = tB*(width/2) + Geom::Point(width/4, width/4);
                pb.append(tB);

                B[0] = Linear(tu-fudge,              tu-fudge);
                B[1] = Linear(tv+fudge + inv_v_subs, tv-fudge);
                tB = compose_each(sb2, B);
                tB = tB*(width/2) + Geom::Point(width/4, width/4);
                pb.append(tB);

                cairo_path(cr, pb);

                //std::cout <<  pb.peek().end() - pb.peek().begin() << std::endl;
                cairo_set_source_rgba (cr, tu, tv, 0, 1);
                cairo_fill(cr);
            }
        }
        //*notify << "bo = " << sb2.index(0,0);
        Toy::draw(cr, notify, width, height, save,timer_stream);
    }
示例#13
0
Geom::Path Gear::path() {
    Geom::Path pb;

    // angle covered by a full tooth and fillet
    double tooth_rotation = 2.0 * tooth_thickness_angle();
    // angle covered by an involute
    double involute_advance = involute_intersect_angle(outer_radius()) - involute_intersect_angle(root_radius());
    // angle covered by the tooth tip
    double tip_advance = tooth_thickness_angle() - (2 * (involute_intersect_angle(outer_radius()) - involute_intersect_angle(pitch_radius())));
    // angle covered by the toothe root
    double root_advance = (tooth_rotation - tip_advance) - (2.0 * involute_advance);
    // begin drawing the involute at t if the root circle is larger than the base circle
    double involute_t = involute_swath_angle(root_radius())/involute_swath_angle(outer_radius());

    //rewind angle to start drawing from the leading edge of the tooth
    double first_tooth_angle = _angle - ((0.5 * tip_advance) + involute_advance);

    Geom::Point prev;
    for (int i=0; i < _number_of_teeth; i++)
    {
        double cursor = first_tooth_angle + (i * tooth_rotation);

        D2<SBasis> leading_I = compose(_involute(cursor, cursor + involute_swath_angle(outer_radius())), Linear(involute_t,1));
        if(i != 0) makeContinuous(leading_I, prev);
        pb.append(SBasisCurve(leading_I));
        cursor += involute_advance;
        prev = leading_I.at1();

        D2<SBasis> tip = _arc(cursor, cursor+tip_advance, outer_radius());
        makeContinuous(tip, prev);
        pb.append(SBasisCurve(tip));
        cursor += tip_advance;
        prev = tip.at1();

        cursor += involute_advance;
        D2<SBasis> trailing_I = compose(_involute(cursor, cursor - involute_swath_angle(outer_radius())), Linear(1,involute_t));
        makeContinuous(trailing_I, prev);
        pb.append(SBasisCurve(trailing_I));
        prev = trailing_I.at1();

        if (base_radius() > root_radius()) {
            Geom::Point leading_start = trailing_I.at1();
            Geom::Point leading_end = (root_radius() * unit_vector(leading_start - _centre)) + _centre;
            prev = leading_end;
            pb.appendNew<LineSegment>(leading_end);
        }

        D2<SBasis> root = _arc(cursor, cursor+root_advance, root_radius());
        makeContinuous(root, prev);
        pb.append(SBasisCurve(root));
        //cursor += root_advance;
        prev = root.at1();

        if (base_radius() > root_radius()) {
            Geom::Point trailing_start = root.at1();
            Geom::Point trailing_end = (base_radius() * unit_vector(trailing_start - _centre)) + _centre;
            pb.appendNew<LineSegment>(trailing_end);
            prev = trailing_end;
        }
    }

    return pb;
}
示例#14
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);
                }
            }
        }
    }
}
示例#15
0
文件: toy.cpp 项目: mental/lib2geom
int main(int argc, char **argv) {
    char const *const filename = (argc >= 2
                                  ? argv[1]
                                  : "toy.svgd");
    FILE* f = fopen(filename, "r");
    if (!f) {
        perror(filename);
        return 1;
    }
    display_path = read_svgd(f);

    Geom::Rect r = display_path.bbox();
    
    display_path = display_path*Geom::translate(-r.min());
    Geom::scale sc(r.max() - r.min());
    display_path = display_path*(sc.inverse()*Geom::scale(500,500));
    
    gtk_init (&argc, &argv);

    gdk_rgb_init();

    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title(GTK_WINDOW(window), "text toy");

    gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);

    gtk_signal_connect(GTK_OBJECT(window),
                       "delete_event",
                       GTK_SIGNAL_FUNC(delete_event_cb),
                       NULL);

    gtk_widget_push_visual(gdk_rgb_get_visual());
    gtk_widget_push_colormap(gdk_rgb_get_cmap());
    canvas = gtk_drawing_area_new();

    gtk_signal_connect(GTK_OBJECT (canvas),
                       "expose_event",
                       GTK_SIGNAL_FUNC(expose_event),
                       0);
    gtk_widget_add_events(canvas, (GDK_BUTTON_PRESS_MASK |
                                   GDK_BUTTON_RELEASE_MASK |
                                   GDK_KEY_PRESS_MASK    |
                                   GDK_POINTER_MOTION_MASK));
    gtk_signal_connect(GTK_OBJECT (canvas),
                       "button_press_event",
                       GTK_SIGNAL_FUNC(mouse_event),
                       0);
    gtk_signal_connect(GTK_OBJECT (canvas),
                       "button_release_event",
                       GTK_SIGNAL_FUNC(mouse_release_event),
                       0);
    gtk_signal_connect(GTK_OBJECT (canvas),
                       "motion_notify_event",
                       GTK_SIGNAL_FUNC(mouse_motion_event),
                       0);
    gtk_signal_connect(GTK_OBJECT(canvas),
                       "key_press_event",
                       GTK_SIGNAL_FUNC(key_release_event),
                       0);

    gtk_widget_pop_colormap();
    gtk_widget_pop_visual();

    GtkWidget *vb = gtk_vbox_new(0, 0);


    gtk_container_add(GTK_CONTAINER(window), vb);

    gtk_box_pack_start(GTK_BOX(vb), canvas, TRUE, TRUE, 0);

    gtk_window_set_default_size(GTK_WINDOW(window), 600, 600);

    gtk_widget_show_all(window);

    dash_gc = gdk_gc_new(canvas->window);
    gint8 dash_list[] = {4, 4};
    gdk_gc_set_dashes(dash_gc, 0, dash_list, 2);
    GdkColor colour;
    colour.red = 0xffff;
    colour.green = 0xffff;
    colour.blue = 0xffff;

    plain_gc = gdk_gc_new(canvas->window);
    
    //gdk_gc_set_rgb_fg_color(dash_gc, &colour);
    gdk_rgb_find_color(gtk_widget_get_colormap(canvas), &colour);
    gdk_window_set_background(canvas->window, &colour);
    gdk_gc_set_line_attributes(dash_gc, 1, GDK_LINE_ON_OFF_DASH,
                               GDK_CAP_BUTT,GDK_JOIN_MITER);

    /* Make sure the canvas can receive key press events. */
    GTK_WIDGET_SET_FLAGS(canvas, GTK_CAN_FOCUS);
    assert(GTK_WIDGET_CAN_FOCUS(canvas));
    gtk_widget_grab_focus(canvas);
    assert(gtk_widget_is_focus(canvas));

    gtk_main();

    return 0;
}
示例#16
0
文件: toy.cpp 项目: mental/lib2geom
static gboolean
expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
    int width = 256;
    int height = 256;
    std::ostringstream notify;
    gdk_drawable_get_size(widget->window, &width, &height);

    for(int i = 0; i < display_path.handles.size(); i++) {
        draw_handle(widget->window, display_path.handles[i]);
    }
    draw_path(widget->window, display_path);
    //draw_elip(widget->window, handles);
    
    Geom::Point dir(1,1);
    /*
    vector<Geom::Path::Location> pts = find_vector_extreme_points(display_path, dir);
    
    for(int i = 0; i < pts.size(); i++) {
        draw_circ(widget->window, display_path.point_at(pts[i]));
        }*/
    
    double dist = INFINITY;

    Geom::Path::Location pl = 
        display_path.nearest_location(old_mouse_point, dist);
    {
        Geom::Point pos, tgt, acc;
        display_path.point_tangent_acc_at (pl, pos, tgt, acc);
        draw_circ(widget->window, pos);
        double kurvature = dot(acc, rot90(tgt))/pow(Geom::L2(tgt),3);
        
        if(fabs(kurvature) > 0.001)
            draw_ray(widget->window, pos, 
                     (1./kurvature)*Geom::unit_vector(rot90(tgt)));
        else // just normal
            draw_ray(widget->window, pos, rot90(tgt));
            
    }
    Geom::Path pth = display_path.subpath(display_path.begin(), display_path.end());
    pth = pth*Geom::translate(Geom::Point(30, 30));
    draw_path(widget->window, pth);
    Bezier a, b;
    const int curve_seg = 3;
    Geom::Path::Elem ai(*display_path.indexed_elem(curve_seg)), bi(*pth.indexed_elem(curve_seg));
    
    for(int i = 0; i < 4; i++) {
        a.p[i] = ai[i];
        b.p[i] = bi[i];
    }
    
    std::vector<std::pair <double, double> > ts = Geom::FindIntersections(a, b);
    for(int i = 0; i < ts.size(); i++) {
        Geom::Path::Location pl(display_path.indexed_elem(curve_seg), ts[i].first);
        
        draw_handle(widget->window, display_path.point_at(pl));
        Geom::Path::Location p2(pth.indexed_elem(curve_seg), ts[i].second);
        
        draw_circ(widget->window, display_path.point_at(p2));
    }
    
    
    /*
    vector<Geom::Path::Location> pts = 
        find_inflection_points(display_path);
  
    for(int i = 0; i < pts.size(); i++) {
        Geom::Point pos, tgt, acc;
        display_path.point_tangent_acc_at (pts[i], pos, tgt, acc);
        //tgt *= 0.1;
        //acc *= 0.1;
        draw_handle(widget->window, display_path.point_at(pts[i]));
        draw_circ(widget->window, pos);
        
        //draw_ray(widget->window, pos+tgt, acc);
    }
    */
    notify << "path length: " << arc_length_integrating(display_path, 1e3) << "\n";
    

    {
        notify << std::ends;
        PangoLayout *layout = gtk_widget_create_pango_layout(widget, notify.str().c_str());
        PangoRectangle logical_extent;
        pango_layout_get_pixel_extents(layout,
                                       NULL,
                                       &logical_extent);
        
        gdk_draw_layout(widget->window,
                        widget->style->fg_gc[GTK_STATE_NORMAL],
                        0, height-logical_extent.height, layout);
    }
    
    return TRUE;
}
示例#17
0
std::vector<Geom::Path>
LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
{
    using namespace Geom;

    std::vector<Geom::Path> generating_path = generator.get_pathvector();
    
    if (generating_path.size()==0) {
        return path_in;
    }

    //Collect transform matrices.
    Matrix m0;
    Geom::Path refpath = ref_path.get_pathvector().front();
    Point A = refpath.pointAt(0);
    Point B = refpath.pointAt(refpath.size());
    Point u = B-A;
    m0 = Matrix(u[X], u[Y],-u[Y], u[X], A[X], A[Y]);
    
    //FIXME: a path is used as ref instead of 2 points to work around path/point param incompatibility bug.
    //Point u = refB-refA;
    //m0 = Matrix(u[X], u[Y],-u[Y], u[X], refA[X], refA[Y]);
    m0 = m0.inverse();

    std::vector<Matrix> transforms;
    for (unsigned i=0; i<generating_path.size(); i++){
        Matrix m;
        if(generating_path[i].size()==1){
            Point p = generating_path[i].pointAt(0);
            Point u = generating_path[i].pointAt(1)-p;
            m = Matrix(u[X], u[Y],-u[Y], u[X], p[X], p[Y]);
            m = m0*m;
            transforms.push_back(m);
        }else if(generating_path[i].size()>=2){
            Point p = generating_path[i].pointAt(1);
            Point u = generating_path[i].pointAt(2)-p;
            Point v = p-generating_path[i].pointAt(0);
            if (similar_only.get_value()){
                int sign = (u[X]*v[Y]-u[Y]*v[X]>=0?1:-1);
                v[X] = -u[Y]*sign;
                v[Y] =  u[X]*sign;
            }
            m = Matrix(u[X], u[Y],v[X], v[Y], p[X], p[Y]);
            m = m0*m;
            transforms.push_back(m);
        }
    }

    if (transforms.size()==0){
        return path_in;
    }

    //Do nothing if the output is too complex... 
    int path_in_complexity = 0;
    for (unsigned k = 0; k < path_in.size(); k++){
            path_in_complexity+=path_in[k].size();
    }    
    double complexity = pow(transforms.size(),nbgenerations)*path_in_complexity;
    if (drawall.get_value()){
        int k = transforms.size();
        if(k>1){
            complexity = (pow(k,nbgenerations+1)-1)/(k-1)*path_in_complexity;
        }else{
            complexity = nbgenerations*k*path_in_complexity;
        }
    }else{
        complexity = pow(transforms.size(),nbgenerations)*path_in_complexity;
    }
    if (complexity > double(maxComplexity)){
        g_warning("VonKoch lpe's output too complex. Effect bypassed.");
        return path_in;
    }

    //Generate path:
    std::vector<Geom::Path> pathi = path_in;
    std::vector<Geom::Path> path_out = path_in;
    
    for (unsigned i = 0; i<nbgenerations; i++){
        if (drawall.get_value()){
            path_out =  path_in;
            complexity = path_in_complexity;
        }else{
            path_out = std::vector<Geom::Path>();
            complexity = 0;
        }
        for (unsigned j = 0; j<transforms.size(); j++){
            for (unsigned k = 0; k<pathi.size() && complexity < maxComplexity; k++){
                path_out.push_back(pathi[k]*transforms[j]); 
                complexity+=pathi[k].size();
            }
        }
        pathi = path_out;
    }
    return path_out;
}