153
157
((SPObjectClass *) ge_parent_class)->update(object, ctx, flags);
161
sp_genericellipse_update_patheffect(SPShape *shape, bool write)
163
sp_genericellipse_set_shape(shape);
166
Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
167
if ( shape->curve != NULL ) {
168
NArtBpath *abp = sp_curve_first_bpath(shape->curve);
170
gchar *str = sp_svg_write_path(abp);
171
repr->setAttribute("d", str);
174
repr->setAttribute("d", "");
177
repr->setAttribute("d", NULL);
181
((SPObject *)shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
158
187
/* fixme: Think (Lauris) */
160
189
static void sp_genericellipse_set_shape(SPShape *shape)
162
double cx, cy, rx, ry, s, e;
163
192
double x0, y0, x1, y1, x2, y2, x3, y3;
165
194
gint slice = FALSE;
247
274
SPCurve *c = sp_curve_new_from_bpath(nr_artpath_affine(bpath, aff));
248
275
g_assert(c != NULL);
277
sp_shape_perform_path_effect(c, SP_SHAPE (ellipse));
250
278
sp_shape_set_curve_insync((SPShape *) ellipse, c, TRUE);
251
279
sp_curve_unref(c);
254
282
static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p)
256
SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
284
g_assert(item != NULL);
285
g_assert(SP_IS_GENERICELLIPSE(item));
287
SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item);
288
sp_genericellipse_normalize(ellipse);
258
289
NR::Matrix const i2d = sp_item_i2d_affine(item);
261
*p = NR::Point(ge->cx.computed, ge->cy.computed) * i2d;
291
// figure out if we have a slice, whilst guarding against rounding errors
293
double len = fmod(ellipse->end - ellipse->start, SP_2PI);
294
if (len < 0.0) len += SP_2PI;
295
if (fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8) {
297
ellipse->end = ellipse->start + SP_2PI;
263
// TODO: add the ends of radii
302
double rx = ellipse->rx.computed;
303
double ry = ellipse->ry.computed;
304
double cx = ellipse->cx.computed;
305
double cy = ellipse->cy.computed;
307
// Snap to the 4 quadrant points of the ellipse, but only if the arc
308
// spans far enough to include them
310
for (angle = 0; angle < SP_2PI; angle += M_PI_2) {
311
if (angle >= ellipse->start && angle <= ellipse->end) {
312
*p = NR::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d;
316
// And if we have a slice, also snap to the endpoints and the centre point
318
// Add the centre, if we have a closed slice
319
if (ellipse->closed) {
320
*p = NR::Point(cx, cy) * i2d;
322
// Add the start point, if it's not coincident with a quadrant point
323
if (fmod(ellipse->start, M_PI_2) != 0.0 ) {
324
*p = NR::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d;
326
// Add the end point, if it's not coincident with a quadrant point
327
if (fmod(ellipse->end, M_PI_2) != 0.0 ) {
328
*p = NR::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d;
285
352
if (flags & SP_OBJECT_WRITE_EXT) {
286
353
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
287
repr = sp_repr_new("svg:path");
354
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
355
repr = xml_doc->createElement("svg:path");
290
358
sp_repr_set_svg_double(repr, "sodipodi:cx", ellipse->cx.computed);
376
444
ellipse = SP_GENERICELLIPSE(object);
378
446
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
379
repr = sp_repr_new("svg:ellipse");
447
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
448
repr = xml_doc->createElement("svg:ellipse");
382
451
sp_repr_set_svg_double(repr, "cx", ellipse->cx.computed);
523
592
ellipse = SP_GENERICELLIPSE(object);
525
594
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
526
repr = sp_repr_new("svg:circle");
595
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
596
repr = xml_doc->createElement("svg:circle");
529
599
sp_repr_set_svg_double(repr, "cx", ellipse->cx.computed);
659
729
sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr)
663
Inkscape::SVGOStringStream os;
665
731
SPGenericEllipse *ge = SP_GENERICELLIPSE(arc);
733
Inkscape::SVG::PathString str;
667
735
NR::Point p1 = sp_arc_get_xy(arc, ge->start);
668
736
NR::Point p2 = sp_arc_get_xy(arc, ge->end);
670
dt = fmod(ge->end - ge->start, SP_2PI);
737
double rx = ge->rx.computed;
738
double ry = ge->ry.computed;
742
double dt = fmod(ge->end - ge->start, SP_2PI);
671
743
if (fabs(dt) < 1e-6) {
672
744
NR::Point ph = sp_arc_get_xy(arc, (ge->start + ge->end) / 2.0);
673
os << "M " << p1[NR::X] << " " << p1[NR::Y]
674
<< " A " << ge->rx.computed << " " << ge->ry.computed
675
<< " 0 1 1 " << " " << ph[NR::X] << "," << ph[NR::Y]
676
<< " A " << ge->rx.computed << " " << ge->ry.computed
677
<< " 0 1 1 " << " " << p2[NR::X] << " " << p2[NR::Y] << " z";
745
str.arcTo(rx, ry, 0, true, true, ph)
746
.arcTo(rx, ry, 0, true, true, p2)
679
fa = (fabs(dt) > M_PI) ? 1 : 0;
680
fs = (dt > 0) ? 1 : 0;
682
g_print("start:%g end:%g fa=%d fs=%d\n", ge->start, ge->end, fa, fs);
749
bool fa = (fabs(dt) > M_PI);
751
str.arcTo(rx, ry, 0, fa, fs, p2);
684
752
if (ge->closed) {
685
os << "M " << p1[NR::X] << "," << p1[NR::Y]
686
<< " A " << ge->rx.computed << "," << ge->ry.computed
687
<< " 0 " << fa << " " << fs << " " << p2[NR::X] << "," << p2[NR::Y]
688
<< " L " << ge->cx.computed << "," << ge->cy.computed << " z";
690
os << "M " << p1[NR::X] << "," << p1[NR::Y]
691
<< " A " << ge->rx.computed << "," << ge->ry.computed
692
<< " 0 " << fa << " " << fs << " " << p2[NR::X] << "," << p2[NR::Y];
753
NR::Point center = NR::Point(ge->cx.computed, ge->cy.computed);
754
str.lineTo(center).closePath();
696
repr->setAttribute("d", os.str().c_str());
758
repr->setAttribute("d", str.c_str());