Geom::Point StarKnotHolderEntity2::knot_get() const { g_assert(item != NULL); SPStar const *star = SP_STAR(item); return sp_star_get_xy(star, SP_STAR_POINT_KNOT2, 0); }
static Geom::Point sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ) { // the point whose neighboring curve handle we're calculating Geom::Point o = sp_star_get_xy (star, point, index); // indices of previous and next points gint pi = (index > 0)? (index - 1) : (star->sides - 1); gint ni = (index < star->sides - 1)? (index + 1) : 0; // the other point type SPStarPoint other = (point == SP_STAR_POINT_KNOT2? SP_STAR_POINT_KNOT1 : SP_STAR_POINT_KNOT2); // the neighbors of o; depending on flatsided, they're either the same type (polygon) or the other type (star) Geom::Point prev = (star->flatsided? sp_star_get_xy (star, point, pi) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT2? index : pi)); Geom::Point next = (star->flatsided? sp_star_get_xy (star, point, ni) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT1? index : ni)); // prev-next midpoint Geom::Point mid = 0.5 * (prev + next); // point to which we direct the bissector of the curve handles; // it's far enough outside the star on the perpendicular to prev-next through mid Geom::Point biss = mid + 100000 * rot90_rel (mid, next); // lengths of vectors to prev and next gdouble prev_len = Geom::L2 (prev - o); gdouble next_len = Geom::L2 (next - o); // unit-length vector perpendicular to o-biss Geom::Point rot = rot90_rel (o, biss); // multiply rot by star->rounded coefficient and the distance to the star point; flip for next Geom::Point ret; if (previ) { ret = (star->rounded * prev_len) * rot; } else { ret = (star->rounded * next_len * -1) * rot; } if (star->randomized == 0) { // add the vector to o to get the final curvepoint return o + ret; } else { // the seed corresponding to the exact point guint32 seed = point_unique_int (o); // randomly rotate (by step 3 from the seed) and scale (by step 4) the vector ret = ret * Geom::Affine (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3))); ret *= ( 1 + star->randomized * rnd (seed, 4)); // the randomized corner point Geom::Point o_randomized = sp_star_get_xy (star, point, index, true); return o_randomized + ret; } }
void SPStar::set_shape() { // perhaps we should convert all our shapes into LPEs without source path // and with knotholders for parameters, then this situation will be handled automatically // by disabling the entire stack (including the shape LPE) if (hasBrokenPathEffect()) { g_warning ("The star shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as star will remove the bad LPE"); if (this->getRepr()->attribute("d")) { // unconditionally read the curve from d, if any, to preserve appearance Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d")); SPCurve *cold = new SPCurve(pv); this->setCurveInsync( cold, TRUE); this->setCurveBeforeLPE(cold); cold->unref(); } return; } SPCurve *c = new SPCurve (); bool not_rounded = (fabs (this->rounded) < 1e-4); // note that we pass randomized=true to sp_star_get_xy, because the curve must be randomized; // other places that call that function (e.g. the knotholder) need the exact point // draw 1st segment c->moveto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); if (this->flatsided == false) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true)); } } // draw all middle segments for (gint i = 1; i < sides; i++) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } else { if (this->flatsided == false) { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } } if (this->flatsided == false) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true)); } } } // draw last segment if (!not_rounded) { if (this->flatsided == false) { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, sides - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, sides - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); } } c->closepath(); /* Reset the shape'scurve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ this->setCurveInsync( c, TRUE); this->setCurveBeforeLPE( c ); if (hasPathEffect() && pathEffectsEnabled()) { SPCurve *c_lpe = c->copy(); bool success = this->performPathEffect(c_lpe); if (success) { this->setCurveInsync( c_lpe, TRUE); } c_lpe->unref(); } c->unref(); }