// This function returns the outermost intersection point between the path (a connector) // and the item given. If the item is a group, then the component items are considered. // 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 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); Geom::PathVector conn_pv = conn_curve->get_pathvector(); // If this is not the starting point, use Geom::Path::reverse() to reverse the path if (!at_start) { // connectors are actually a single path, so consider the first element from a Geom::PathVector conn_pv[0] = conn_pv[0].reverse(); } // 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); if (!result) // No intersection point has been found (why?) // just default to connector end intersect_pos = 0; // If not at the starting point, recompute position with respect to original path if (!at_start) intersect_pos = conn_pv[0].size() - intersect_pos; // Free the curve copy. conn_curve->unref(); return result; }
static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item, const Geom::Affine& item_transform, double& intersect_pos) { double initial_pos = intersect_pos; // if this is a group... if (SP_IS_GROUP(item)) { SPGroup* group = SP_GROUP(item); // consider all first-order children double child_pos = 0.0; std::vector<SPItem*> g = sp_item_group_item_list(group); for (std::vector<SPItem*>::const_iterator i = g.begin();i!=g.end();i++) { SPItem* child_item = *i; try_get_intersect_point_with_item_recursive(conn_pv, child_item, item_transform * child_item->transform, child_pos); if (intersect_pos < child_pos) intersect_pos = child_pos; } return intersect_pos != initial_pos; } // if this is not a shape, nothing to be done if (!SP_IS_SHAPE(item)) return false; // make sure it has an associated curve SPCurve* item_curve = SP_SHAPE(item)->getCurve(); if (!item_curve) return false; // apply transformations (up to common ancestor) item_curve->transform(item_transform); const Geom::PathVector& curve_pv = item_curve->get_pathvector(); Geom::CrossingSet cross = crossings(conn_pv, curve_pv); // iterate over all Crossings //TODO: check correctness of the following code: inner loop uses loop variable // with a name identical to the loop variable of the outer loop. Then rename. for (Geom::CrossingSet::const_iterator i = cross.begin(); i != cross.end(); ++i) { const Geom::Crossings& cr = *i; for (Geom::Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) { const Geom::Crossing& cr_pt = *i; if ( intersect_pos < cr_pt.ta) intersect_pos = cr_pt.ta; } } item_curve->unref(); return intersect_pos != initial_pos; }
static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item, const Geom::Matrix& item_transform, double& intersect_pos) { double initial_pos = intersect_pos; // if this is a group... if (SP_IS_GROUP(item)) { SPGroup* group = SP_GROUP(item); // consider all first-order children 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) intersect_pos = child_pos; } return intersect_pos != initial_pos; } // if this is not a shape, nothing to be done if (!SP_IS_SHAPE(item)) return false; // make sure it has an associated curve SPCurve* item_curve = sp_shape_get_curve(SP_SHAPE(item)); if (!item_curve) return false; // apply transformations (up to common ancestor) item_curve->transform(item_transform); const Geom::PathVector& curve_pv = item_curve->get_pathvector(); Geom::CrossingSet cross = crossings(conn_pv, curve_pv); // iterate over all Crossings for (Geom::CrossingSet::const_iterator i = cross.begin(); i != cross.end(); i++) { const Geom::Crossings& cr = *i; for (Geom::Crossings::const_iterator i = cr.begin(); i != cr.end(); i++) { const Geom::Crossing& cr_pt = *i; if ( intersect_pos < cr_pt.ta) intersect_pos = cr_pt.ta; } } item_curve->unref(); return intersect_pos != initial_pos; }