From 11c5de79de3c200331e168a745b0505a50aeffea Mon Sep 17 00:00:00 2001 From: "Arcadie M. Cracan" Date: Sun, 27 Dec 2009 12:21:31 +0200 Subject: [PATCH] Connector tool: make connectors avoid the convex hull of shapes. --- src/conn-avoid-ref.cpp | 294 +++++++++++++++++++------------------- src/connector-context.cpp | 114 +++++++-------- src/sp-conn-end.cpp | 33 ++--- 3 files changed, 219 insertions(+), 222 deletions(-) diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index c04ad9e49..b2aa0ce6b 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -19,6 +19,7 @@ #include "2geom/line.h" #include "2geom/crossing.h" #include "2geom/convex-cover.h" +#include "helper/geom-curves.h" #include "svg/stringstream.h" #include "conn-avoid-ref.h" #include "connection-points.h" @@ -32,6 +33,7 @@ #include "desktop.h" #include "desktop-handles.h" #include "sp-namedview.h" +#include "sp-item-group.h" #include "inkscape.h" #include @@ -56,7 +58,7 @@ SPAvoidRef::~SPAvoidRef() { _transformed_connection.disconnect(); - // If the document is being destroyed then the router instance + // If the document is being destroyed then the router instance // and the ShapeRefs will have been destroyed with it. const bool routerInstanceExists = (item->document->router != NULL); @@ -103,10 +105,10 @@ void SPAvoidRef::setConnectionPoints(gchar const *value) Update the connectors for which the endpoint has changed. */ - + gchar ** strarray = g_strsplit(value, "|", 0); gchar ** iter = strarray; - + while (*iter != NULL) { ConnectionPoint cp; Inkscape::SVGIStringStream is(*iter); @@ -167,17 +169,19 @@ void SPAvoidRef::setConnectionPoints(gchar const *value) { SPPath* path = SP_PATH(i->data); SPConnEnd** connEnds = path->connEndPair.getConnEnds(); - for (int ix=0; ix<2; ++ix) - if (connEnds[ix]->type == ConnPointUserDefined) - if (updates.find(connEnds[ix]->id) != updates.end()) - if (path->connEndPair.isAutoRoutingConn()) + for (int ix=0; ix<2; ++ix) { + if (connEnds[ix]->type == ConnPointUserDefined) { + if (updates.find(connEnds[ix]->id) != updates.end()) { + if (path->connEndPair.isAutoRoutingConn()) { path->connEndPair.tellLibavoidNewEndpoints(); - else - { + } else { } - else - if (deletes.find(connEnds[ix]->id) != deletes.end()) - sp_conn_end_detach(path, ix); + } + else if (deletes.find(connEnds[ix]->id) != deletes.end()) { + sp_conn_end_detach(path, ix); + } + } + } } g_slist_free(conns); // Remove all deleted connection points @@ -189,7 +193,7 @@ void SPAvoidRef::setConnectionPoints(gchar const *value) void SPAvoidRef::setConnectionPointsAttrUndoable(const gchar* value, const gchar* action) { SPDocument* doc = SP_OBJECT_DOCUMENT(item); - + sp_object_setAttribute( SP_OBJECT(item), "inkscape:connection-points", value, 0 ); item->updateRepr(); sp_document_ensure_up_to_date(doc); @@ -229,8 +233,8 @@ void SPAvoidRef::addConnectionPoint(ConnectionPoint &cp) } else ostr<<'|'<setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Added a new connection point") ); + + this->setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Add a new connection point") ); } void SPAvoidRef::updateConnectionPoint(ConnectionPoint &cp) @@ -255,7 +259,7 @@ void SPAvoidRef::updateConnectionPoint(ConnectionPoint &cp) else ostr<<'|'<<*to_write; } - this->setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Moved a connection point") ); + this->setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Move a connection point") ); } } @@ -263,21 +267,19 @@ void SPAvoidRef::deleteConnectionPoint(ConnectionPoint &cp) { Inkscape::SVGOStringStream ostr; IdConnectionPointMap::iterator cp_pos = connection_points.find( cp.id ); - if ( cp_pos != connection_points.end() ) - { + if ( cp_pos != connection_points.end() ) { bool first = true; - for (IdConnectionPointMap::iterator it = connection_points.begin(); it != connection_points.end(); ++it) - { - if ( it != cp_pos ) - if ( first ) - { + for (IdConnectionPointMap::iterator it = connection_points.begin(); it != connection_points.end(); ++it) { + if ( it != cp_pos ) { + if ( first ) { first = false; ostr<second; - } - else + } else { ostr<<'|'<second; + } + } } - this->setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Removed a connection point") ); + this->setConnectionPointsAttrUndoable( ostr.str().c_str(), _("Remove a connection point") ); } } @@ -304,7 +306,7 @@ void SPAvoidRef::handleSettingChange(void) setting = new_setting; Router *router = item->document->router; - + _transformed_connection.disconnect(); if (new_setting) { Avoid::Polygon poly = avoid_item_poly(item); @@ -314,19 +316,19 @@ void SPAvoidRef::handleSettingChange(void) const char *id = SP_OBJECT_REPR(item)->attribute("id"); g_assert(id != NULL); - + // Get a unique ID for the item. GQuark itemID = g_quark_from_string(id); shapeRef = new Avoid::ShapeRef(router, poly, itemID); - + router->addShape(shapeRef); } } else { g_assert(shapeRef); - + router->removeShape(shapeRef); delete shapeRef; shapeRef = NULL; @@ -341,7 +343,7 @@ GSList *SPAvoidRef::getAttachedShapes(const unsigned int type) Avoid::IntList shapes; GQuark shapeId = g_quark_from_string(item->id); item->document->router->attachedShapes(shapes, shapeId, type); - + Avoid::IntList::iterator finish = shapes.end(); for (Avoid::IntList::iterator i = shapes.begin(); i != finish; ++i) { const gchar *connId = g_quark_to_string(*i); @@ -365,7 +367,7 @@ GSList *SPAvoidRef::getAttachedConnectors(const unsigned int type) Avoid::IntList conns; GQuark shapeId = g_quark_from_string(item->id); item->document->router->attachedConns(conns, shapeId, type); - + Avoid::IntList::iterator finish = conns.end(); for (Avoid::IntList::iterator i = conns.begin(); i != finish; ++i) { const gchar *connId = g_quark_to_string(*i); @@ -386,6 +388,7 @@ Geom::Point SPAvoidRef::getConnectionPointPos(const int type, const int id) g_assert(item); Geom::Point pos; const Geom::Matrix& transform = sp_item_i2doc_affine(item); + // TODO investigate why this was asking for the active desktop: SPDesktop *desktop = inkscape_active_desktop(); if ( type == ConnPointDefault ) @@ -419,146 +422,139 @@ bool SPAvoidRef::isValidConnPointId( const int type, const int id ) else return connection_points.find( id ) != connection_points.end(); } - + return true; } -static Avoid::Polygon avoid_item_poly(SPItem const *item) +static std::vector approxCurveWithPoints(SPCurve *curve) { - SPDesktop *desktop = inkscape_active_desktop(); - g_assert(desktop != NULL); - - // TODO: The right way to do this is to return the convex hull of - // the object, or an approximation in the case of a rounded - // object. Specific SPItems will need to have a new - // function that returns points for the convex hull. - // For some objects it is enough to feed the snappoints to - // some convex hull code, though not NR::ConvexHull as this - // only keeps the bounding box of the convex hull currently. - - double spacing = desktop->namedview->connector_spacing; - - // [sommer] If item is a shape, use an approximation of its convex hull + // The number of segments to use for not straight curves approximation + const unsigned NUM_SEGS = 4; + + const Geom::PathVector& curve_pv = curve->get_pathvector(); + + // The structure to hold the output + std::vector poly_points; + + // Iterate over all curves, adding the endpoints for linear curves and + // sampling the other curves + double seg_size = 1.0 / NUM_SEGS; + double at; + at = 0; + Geom::PathVector::const_iterator pit = curve_pv.begin(); + while (pit != curve_pv.end()) { - // MJW: Disable this for the moment. It still has some issues. - const bool convex_hull_approximation_enabled = false; - - if ( convex_hull_approximation_enabled && SP_IS_SHAPE (item) ) { - // The number of points to use for approximation - const unsigned NUM_POINTS = 64; - -// printf("[sommer] is a shape\n"); - SPCurve* curve = sp_shape_get_curve (SP_SHAPE (item)); - if (curve) { -// printf("[sommer] is a curve\n"); - - // apply all transformations - Geom::Matrix itd_mat = sp_item_i2doc_affine(item); - curve->transform(itd_mat); - - // iterate over all paths - const Geom::PathVector& curve_pv = curve->get_pathvector(); - std::vector hull_points; - for (Geom::PathVector::const_iterator i = curve_pv.begin(); i != curve_pv.end(); i++) { - const Geom::Path& curve_pv_path = *i; -// printf("[sommer] tracing sub-path\n"); - - // FIXME: enlarge path by "desktop->namedview->connector_spacing" (using sp_selected_path_do_offset)? - - // use appropriate fraction of points for this path (first one gets any remainder) - unsigned num_points = NUM_POINTS / curve_pv.size(); - if (i == curve_pv.begin()) num_points += NUM_POINTS - (num_points * curve_pv.size()); - printf("[sommer] using %d points for this path\n", num_points); - - // sample points along the path for approximation of convex hull - for (unsigned n = 0; n < num_points; n++) { - double at = curve_pv_path.size() / static_cast(num_points) * n; - Geom::Point pt = curve_pv_path.pointAt(at); - hull_points.push_back(pt); - } + Geom::Path::const_iterator cit = pit->begin(); + while (cit != pit->end()) + if (dynamic_cast(&*cit)) + { + at += seg_size; + if (at <= 1.0 ) + poly_points.push_back(cit->pointAt(at)); + else + { + at = 0.0; + ++cit; } + } + else + { + poly_points.push_back(cit->finalPoint()); + ++cit; + } + ++pit; + } + return poly_points; +} - curve->unref(); - - // create convex hull from all sampled points - Geom::ConvexHull hull(hull_points); +static std::vector approxItemWithPoints(SPItem const *item, const Geom::Matrix& item_transform) +{ + // The structure to hold the output + std::vector poly_points; - // store expanded convex hull in Avoid::Polygn - unsigned n = 0; - Avoid::Polygon poly; - const Geom::Point& old_pt = *hull.boundary.begin(); + if (SP_IS_GROUP(item)) + { + SPGroup* group = SP_GROUP(item); + // consider all first-order children + for (GSList const* i = sp_item_group_item_list(group); i != NULL; i = i->next) { + SPItem* child_item = SP_ITEM(i->data); + std::vector child_points = approxItemWithPoints(child_item, item_transform * child_item->transform); + poly_points.insert(poly_points.end(), child_points.begin(), child_points.end()); + } + } + else if (SP_IS_SHAPE(item)) + { + SPCurve* item_curve = sp_shape_get_curve(SP_SHAPE(item)); + // make sure it has an associated curve + if (item_curve) + { + // apply transformations (up to common ancestor) + item_curve->transform(item_transform); + std::vector curve_points = approxCurveWithPoints(item_curve); + poly_points.insert(poly_points.end(), curve_points.begin(), curve_points.end()); + item_curve->unref(); + } + } - Geom::Line hull_edge(*hull.boundary.begin(), *(hull.boundary.begin()+1)); - Geom::Line parallel_hull_edge; - parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); - parallel_hull_edge.versor(hull_edge.versor()); - Geom::Line bisector = Geom::make_angle_bisector_line( *(hull.boundary.end()), *hull.boundary.begin(), - *(hull.boundary.begin()+1)); - Geom::OptCrossing int_pt = Geom::intersection(parallel_hull_edge, bisector); + return poly_points; +} +static Avoid::Polygon avoid_item_poly(SPItem const *item) +{ + SPDesktop *desktop = inkscape_active_desktop(); + g_assert(desktop != NULL); + double spacing = desktop->namedview->connector_spacing; - if (int_pt) - { - Avoid::Point avoid_pt((parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::X], - (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::Y]); -// printf("[sommer] %f, %f\n", old_pt[Geom::X], old_pt[Geom::Y]); -/* printf("[sommer] %f, %f\n", (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::X], - (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::Y]);*/ - poly.ps.push_back(avoid_pt); - } - for (std::vector::const_iterator i = hull.boundary.begin() + 1; i != hull.boundary.end(); i++, n++) { - const Geom::Point& old_pt = *i; - Geom::Line hull_edge(*i, *(i+1)); - Geom::Line parallel_hull_edge; - parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); - parallel_hull_edge.versor(hull_edge.versor()); - Geom::Line bisector = Geom::make_angle_bisector_line( *(i-1), *i, *(i+1)); - Geom::OptCrossing intersect_pt = Geom::intersection(parallel_hull_edge, bisector); - - if (int_pt) - { - Avoid::Point avoid_pt((parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::X], - (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::Y]); -/* printf("[sommer] %f, %f\n", old_pt[Geom::X], old_pt[Geom::Y]); - printf("[sommer] %f, %f\n", (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::X], - (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::Y]);*/ - poly.ps.push_back(avoid_pt); - } - } - + Geom::Matrix itd_mat = sp_item_i2doc_affine(item); + std::vector hull_points; + hull_points = approxItemWithPoints(item, itd_mat); - return poly; - }// else printf("[sommer] is no curve\n"); - }// else printf("[sommer] is no shape\n"); - } - - Geom::OptRect rHull = item->getBounds(sp_item_i2doc_affine(item)); - if (!rHull) { - return Avoid::Polygon(); - } + // create convex hull from all sampled points + Geom::ConvexHull hull(hull_points); - // Add a little buffer around the edge of each object. - Geom::Rect rExpandedHull = *rHull; - rExpandedHull.expandBy(spacing); - Avoid::Polygon poly(4); + // enlarge path by "desktop->namedview->connector_spacing" + // store expanded convex hull in Avoid::Polygn + Avoid::Polygon poly; - for (size_t n = 0; n < 4; ++n) { - Geom::Point hullPoint = rExpandedHull.corner(n); - poly.ps[n].x = hullPoint[Geom::X]; - poly.ps[n].y = hullPoint[Geom::Y]; + Geom::Line hull_edge(hull[-1], hull[0]); + Geom::Line prev_parallel_hull_edge; + prev_parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); + prev_parallel_hull_edge.versor(hull_edge.versor()); + int hull_size = hull.boundary.size(); + for (int i = 0; i <= hull_size; ++i) + { + hull_edge.setBy2Points(hull[i], hull[i+1]); + Geom::Line parallel_hull_edge; + parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); + parallel_hull_edge.versor(hull_edge.versor()); + + // determine the intersection point + + Geom::OptCrossing int_pt = Geom::intersection(parallel_hull_edge, prev_parallel_hull_edge); + if (int_pt) + { + Avoid::Point avoid_pt((parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::X], + (parallel_hull_edge.origin()+parallel_hull_edge.versor()*int_pt->ta)[Geom::Y]); + poly.ps.push_back(avoid_pt); + } + else + { + // something went wrong... + std::cout<<"conn-avoid-ref.cpp: avoid_item_poly: Geom:intersection failed."<isLayer(SP_ITEM(child)) && - !SP_ITEM(child)->isLocked() && + !SP_ITEM(child)->isLocked() && !desktop->itemIsHidden(SP_ITEM(child)) && (!initialised || SP_ITEM(child)->avoidRef->shapeRef) ) @@ -595,7 +591,7 @@ void init_avoided_shape_geometry(SPDesktop *desktop) SPDocument *document = sp_desktop_document(desktop); bool saved = sp_document_get_undo_sensitive(document); sp_document_set_undo_sensitive(document, false); - + bool initialised = false; GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop, initialised); diff --git a/src/connector-context.cpp b/src/connector-context.cpp index 228c81d29..307d59d1f 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -35,7 +35,7 @@ * Gobbling away all duplicates after the current can occasionally result * in the path lagging behind the mouse cursor if it is no longer being * dragged. - * o Fix up libavoid's representation after undo actions. It doesn't see + * o Fix up libavoid's representation after undo actions. It doesn't see * any transform signals and hence doesn't know shapes have moved back to * there earlier positions. * o Decide whether drawing/editing mode should be an Inkscape preference @@ -46,83 +46,83 @@ * ---------------------------------------------------------------------------- * * mjwybrow's observations on acracan's Summer of Code connector work: - * + * * - GUI comments: - * + * * - Buttons for adding and removing user-specified connection * points should probably have "+" and "-" symbols on them so they * are consistent with the similar buttons for the node tool. - * - Controls on the connector tool be should be reordered logically, + * - Controls on the connector tool be should be reordered logically, * possibly as follows: - * - * *Connector*: [Polyline-radio-button] [Orthgonal-radio-button] + * + * *Connector*: [Polyline-radio-button] [Orthgonal-radio-button] * [Curvature-control] | *Shape*: [Avoid-button] [Dont-avoid-button] * [Spacing-control] | *Connection pts*: [Edit-mode] [Add-pt] [Rm-pt] - * - * I think that the network layout controls be moved to the - * Align and Distribute dialog (there is already the layout button + * + * I think that the network layout controls be moved to the + * Align and Distribute dialog (there is already the layout button * there, but no options are exposed). - * + * * I think that the style change between polyline and orthogonal * would be much clearer with two buttons (radio behaviour -- just * one is true). - * - * The other tools show a label change from "New:" to "Change:" + * + * The other tools show a label change from "New:" to "Change:" * depending on whether an object is selected. We could consider * this but there may not be space. - * + * * The Add-pt and Rm-pt buttons should be greyed out (inactive) if * we are not in connection point editing mode. And probably also * if there is no shape selected, i.e. at the times they have no * effect when clicked. - * - * Likewise for the avoid/ignore shapes buttons. These should be + * + * Likewise for the avoid/ignore shapes buttons. These should be * inactive when a shape is not selected in the connector context. - * + * * - When creating/editing connection points: - * + * * - Strange things can happen if you have connectors selected, or - * try rerouting connectors by dragging their endpoints when in + * try rerouting connectors by dragging their endpoints when in * connection point editing mode. - * + * * - Possibly the selected shape's connection points should always * be shown (i.e., have knots) when in editing mode. - * + * * - It is a little strange to be able to place connection points * competely outside shapes. Especially when you later can't draw * connectors to them since the knots are only visible when you * are over the shape. I think that you should only be able to - * place connection points inside or on the boundary of the shape + * place connection points inside or on the boundary of the shape * itself. - * - * - The intended ability to place a new point at the current cursor + * + * - The intended ability to place a new point at the current cursor * position by pressing RETURN does not seem to work. - * + * * - The Status bar tooltip should change to reflect editing mode * and tell the user about RETURN and how to use the tool. - * + * * - Connection points general: - * - * - Connection points that were inside the shape can end up outside + * + * - Connection points that were inside the shape can end up outside * after a rotation is applied to the shape in the select tool. * It doesn't seem like the correct transform is being applied to * these, or it is being applied at the wrong time. I'd expect * connection points to rotate with the shape, and stay at the * same position "on the shape" - * + * * - I was able to make the connectors attached to a shape fall off * the shape after scaling it. Not sure the exact cause, but may * require more investigation/debugging. - * + * * - The user-defined connection points should be either absolute * (as the current ones are) or defined as a percentage of the * shape. These would be based on a toggle setting on the * toolbar, and they would be placed in exactly the same way by * the user. The only difference would be that they would be * store as percentage positions in the SVG connection-points - * property and that they would update/move automatically if the + * property and that they would update/move automatically if the * object was resized or scaled. - * + * * - Thinking more, I think you always want to store and think about * the positions of connection points to be pre-transform, but * obviously the shape transform is applied to them. That way, @@ -130,14 +130,14 @@ * the shape transform is altered. The Percentage version would * compute their position from the pre-transform dimensions and * then have the transform applied to them, for example. - * + * * - The connection points in the test_connection_points.svg file * seem to follow the shape when it is moved, but connection * points I add to new shapes, do not follow the shape, either * when the shape is just moved or transformed. There is - * something wrong here. What exactly should the behaviour be + * something wrong here. What exactly should the behaviour be * currently? - * + * * - I see that connection points are specified at absolute canvas * positions. I really think that they should be specified in * shape coordinated relative to the shapes. There may be @@ -333,7 +333,7 @@ sp_connector_context_init(SPConnectorContext *cc) cc->clickedhandle = NULL; new (&cc->connpthandles) ConnectionPointMap(); - + for (int i = 0; i < 2; ++i) { cc->endpt_handle[i] = NULL; cc->endpt_handler_id[i] = 0; @@ -353,7 +353,7 @@ sp_connector_context_dispose(GObject *object) cc->sel_changed_connection.disconnect(); if (!cc->connpthandles.empty()) { - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); + for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it) { g_object_unref(it->first); } @@ -413,7 +413,7 @@ sp_connector_context_setup(SPEventContext *ec) cc_selection_changed(cc->selection, (gpointer) cc); cc->within_tolerance = false; - + sp_event_context_read(ec, "curvature"); sp_event_context_read(ec, "orthogonal"); sp_event_context_read(ec, "mode"); @@ -472,7 +472,7 @@ void sp_connector_context_switch_mode(SPEventContext* ec, unsigned int newMode) { cc->selection->set( SP_OBJECT( cc->active_shape ) ); } - else + else { SPItem* item = cc->selection->singleItem(); if ( item ) @@ -537,7 +537,7 @@ cc_clear_active_shape(SPConnectorContext *cc) // Hide the connection points if they exist. if (cc->connpthandles.size()) { - for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); + for (ConnectionPointMap::iterator it = cc->connpthandles.begin(); it != cc->connpthandles.end(); ++it) { sp_knot_hide(it->first); } @@ -616,7 +616,7 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G SPConnectorContext *cc = SP_CONNECTOR_CONTEXT(event_context); Geom::Point p(event->button.x, event->button.y); - + switch (event->type) { case GDK_BUTTON_RELEASE: if (event->button.button == 1 && !event_context->space_panning) { @@ -660,11 +660,11 @@ sp_connector_context_item_handler(SPEventContext *event_context, SPItem *item, G if (cc->mode == SP_CONNECTOR_CONTEXT_DRAWING_MODE || (cc->mode == SP_CONNECTOR_CONTEXT_EDITING_MODE && !cc->selected_handle)) { if (cc_item_is_shape(item)) { - + // I don't really understand what the above does, // so I commented it. // This is a shape, so show connection point(s). - /* if (!(cc->active_shape) + /* if (!(cc->active_shape) // Don't show handle for another handle. // || (cc->connpthandles.find((SPKnot*) item) != cc->connpthandles.end()) ) @@ -847,7 +847,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const cc->xp = bevent.x; cc->yp = bevent.y; cc->within_tolerance = true; - + ConnectionPointMap::iterator const& active_knot_it = cc->connpthandles.find( cc->active_handle ); switch (cc->state) @@ -934,7 +934,7 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons { SnapManager &m = dt->namedview->snap_manager; m.setup(dt); - + switch (cc->state) { case SP_CONNECTOR_CONTEXT_DRAGGING: { @@ -1074,7 +1074,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con switch ( cc->state ) { case SP_CONNECTOR_CONTEXT_DRAGGING: - + if (!cc->within_tolerance) { // sp_event_context_snap_window_open(event_context); @@ -1094,7 +1094,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con case SP_CONNECTOR_CONTEXT_NEWCONNPOINT: // sp_event_context_snap_window_open( event_context ); m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); - + sp_knot_set_position(cc->selected_handle, p, 0); // sp_event_context_snap_window_closed(event_context); @@ -1118,7 +1118,7 @@ connector_handle_button_release(SPConnectorContext *const cc, GdkEventButton con } } } - + return ret; } @@ -1196,8 +1196,8 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Geom::Point p = cc->selected_handle->pos; - SPEventContext* event_context = SP_EVENT_CONTEXT( cc ); - +// SPEventContext* event_context = SP_EVENT_CONTEXT( cc ); + if (!cc->within_tolerance) { // sp_event_context_snap_window_open(event_context); @@ -1229,11 +1229,11 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Geom::Point p = cc->selected_handle->pos; - SPEventContext* event_context = SP_EVENT_CONTEXT( cc ); - +// SPEventContext* event_context = SP_EVENT_CONTEXT( cc ); + // sp_event_context_snap_window_open( event_context ); m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); - + sp_knot_set_position(cc->selected_handle, p, 0); // sp_event_context_snap_window_closed(event_context); @@ -1263,7 +1263,7 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) cc->selected_handle = NULL; ret = TRUE; } - + break; } } @@ -1453,7 +1453,7 @@ spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) // Process pending updates. cc->newconn->updateRepr(); sp_document_ensure_up_to_date(doc); - + if (connection) { // Adjust endpoints to shape edge. sp_conn_reroute_path_immediate(SP_PATH(cc->newconn)); @@ -1461,7 +1461,7 @@ spcc_flush_white(SPConnectorContext *cc, SPCurve *gc) } // Only set the selection after we are finished with creating the attributes of - // the connector. Otherwise, the selection change may alter the defaults for + // the connector. Otherwise, the selection change may alter the defaults for // values like curvature in the connector context, preventing subsequent lookup // of their original values. cc->selection->set(repr); @@ -1630,7 +1630,7 @@ static void cc_active_shape_add_knot(SPDesktop* desktop, SPItem* item, Connectio static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item) { g_assert(item != NULL ); - + std::map* connpts = &item->avoidRef->connection_points; if (cc->active_shape != item) @@ -1671,7 +1671,7 @@ static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item) if ( connpts->size() ) for (std::map::iterator it = connpts->begin(); it != connpts->end(); ++it) cc_active_shape_add_knot(cc->desktop, item, cc->connpthandles, it->second); - + // Also add default connection points // For now, only centre default connection point will // be available diff --git a/src/sp-conn-end.cpp b/src/sp-conn-end.cpp index 52914ee9e..224442eb8 100644 --- a/src/sp-conn-end.cpp +++ b/src/sp-conn-end.cpp @@ -46,14 +46,14 @@ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_p // if this is a group... if (SP_IS_GROUP(item)) { SPGroup* group = SP_GROUP(item); - + // consider all first-order children - double child_pos = std::numeric_limits::max(); + double child_pos = 0.0; for (GSList const* i = sp_item_group_item_list(group); i != NULL; i = i->next) { SPItem* child_item = SP_ITEM(i->data); try_get_intersect_point_with_item_recursive(conn_pv, child_item, item_transform * child_item->transform, child_pos); - if (intersect_pos > child_pos) + if (intersect_pos < child_pos) intersect_pos = child_pos; } return intersect_pos != initial_pos; @@ -77,7 +77,7 @@ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_p for (Geom::Crossings::const_iterator i = cr.begin(); i != cr.end(); i++) { const Geom::Crossing& cr_pt = *i; - if ( intersect_pos > cr_pt.ta) + if ( intersect_pos < cr_pt.ta) intersect_pos = cr_pt.ta; } } @@ -93,9 +93,9 @@ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_p // The transforms given should be to a common ancestor of both the path and item. // static bool try_get_intersect_point_with_item(SPPath* conn, SPItem* item, - const Geom::Matrix& item_transform, const Geom::Matrix& conn_transform, + const Geom::Matrix& item_transform, const Geom::Matrix& conn_transform, const bool at_start, double& intersect_pos) { - + // Copy the curve and apply transformations up to common ancestor. SPCurve* conn_curve = conn->curve->copy(); conn_curve->transform(conn_transform); @@ -109,8 +109,8 @@ static bool try_get_intersect_point_with_item(SPPath* conn, SPItem* item, conn_pv[0] = conn_pv[0].reverse(); } - // We start with the intersection point at the end of the path - intersect_pos = conn_pv[0].size(); + // We start with the intersection point at the beginning of the path + intersect_pos = 0.0; // Find the intersection. bool result = try_get_intersect_point_with_item_recursive(conn_pv, item, item_transform, intersect_pos); @@ -130,7 +130,7 @@ static bool try_get_intersect_point_with_item(SPPath* conn, SPItem* item, static void -sp_conn_get_route_and_redraw(SPPath *const path, +sp_conn_get_route_and_redraw(SPPath *const path, const bool updatePathRepr = true) { // Get the new route around obstacles. @@ -138,7 +138,7 @@ sp_conn_get_route_and_redraw(SPPath *const path, if (!rerouted) { return; } - + SPItem *h2attItem[2]; path->connEndPair.getAttachedItems(h2attItem); @@ -146,7 +146,7 @@ sp_conn_get_route_and_redraw(SPPath *const path, SPObject const *const ancestor = get_nearest_common_ancestor(path_item, h2attItem); Geom::Matrix const path2anc(i2anc_affine(path_item, ancestor)); - // Set sensible values incase there the connector ends are not + // Set sensible values incase there the connector ends are not // attached to any shapes. Geom::PathVector conn_pv = path->curve->get_pathvector(); double endPos[2] = { 0, conn_pv[0].size() }; @@ -241,7 +241,7 @@ sp_conn_end_detach(SPObject *const owner, unsigned const handle_ix) } void -SPConnEnd::setAttacherHref(gchar const *value, SPPath* path) +SPConnEnd::setAttacherHref(gchar const *value, SPPath* /*path*/) { if ( value && href && ( strcmp(value, href) == 0 ) ) { /* No change, do nothing. */ @@ -293,7 +293,7 @@ SPConnEnd::setAttacherHref(gchar const *value, SPPath* path) } } // Check to see if the connection point changed and update it. - // + // if ( !value_strarray[1] ) { @@ -353,12 +353,12 @@ SPConnEnd::setAttacherHref(gchar const *value, SPPath* path) validRef = false; } } - + if ( changed ) { // We still have to verify that the reference to the // connection point is a valid one. - + // Get the item the connector is attached to SPItem* item = ref.getObject(); if ( item && !item->avoidRef->isValidConnPointId( type, id ) ) @@ -370,7 +370,8 @@ SPConnEnd::setAttacherHref(gchar const *value, SPPath* path) // Update the connector if (path->connEndPair.isAutoRoutingConn()) { path->connEndPair.tellLibavoidNewEndpoints(); - }*/ + } +*/ } if ( !validRef ) -- 2.30.2