804
/** Make selected segments curves / lines. */
804
// \todo The three functions setSegmentType, setArcSegmentLarge, setArcSegmentSweep could be
805
// refactored to share the code that iterates over all selected segments.
807
/** Make selected segments curves / lines / arcs. */
805
808
void PathManipulator::setSegmentType(SegmentType type)
807
810
if (_num_selected == 0) return;
811
814
if (!(k && j->selected() && k->selected())) continue;
813
816
case SEGMENT_STRAIGHT:
814
if (j->front()->isDegenerate() && k->back()->isDegenerate())
817
if ((j->front()->isDegenerate() && k->back()->isDegenerate())
818
&& (j->arc_rx()->isDegenerate() && j->arc_ry()->isDegenerate()))
816
820
j->front()->move(*j);
817
821
k->back()->move(*k);
822
j->retractArcHandles();
819
824
case SEGMENT_CUBIC_BEZIER:
820
825
if (!j->front()->isDegenerate() || !k->back()->isDegenerate())
822
827
// move both handles to 1/3 of the line
823
828
j->front()->move(j->position() + (k->position() - j->position()) / 3);
824
829
k->back()->move(k->position() + (j->position() - k->position()) / 3);
830
j->arc_rx()->move(*j);
831
j->arc_ry()->move(*j);
832
j->retractArcHandles();
834
case SEGMENT_ELIPTICAL_ARC:
835
if (!(j->front()->isDegenerate() && k->back()->isDegenerate())){
836
j->front()->move(*j);
840
if (j->arc_rx()->isDegenerate() && j->arc_ry()->isDegenerate()){
841
Geom::Point midPointOffset = ((k->position() - j->position()) / 2);
842
Geom::Point handleOrigin = j->position()+midPointOffset;
844
j->arc_rx()->setOffset(midPointOffset);
845
j->arc_ry()->setOffset(midPointOffset);
846
j->arc_rx()->move(j->position() + ((k->position() - handleOrigin) / 2));
847
j->updateArcHandleConstriants(j->arc_rx());
855
/** Set the large flag on selected arcs */
856
void PathManipulator::setArcSegmentLarge(bool large){
857
if (_num_selected == 0) return;
858
for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
859
for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) {
860
NodeList::iterator k = j.next();
861
if (!(k && j->selected() && k->selected())) continue;
862
// This code executes for every selected segment
863
if (!j->arc_rx()->isDegenerate() || !j->arc_ry()->isDegenerate()){
864
// This code executes for every selected ARC segment
865
*(j->arc_large()) = large;
871
/** Set the sweep flag on selected arcs */
872
void PathManipulator::toggleArcSegmentSweep(){
873
if (_num_selected == 0) return;
874
for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
875
for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) {
876
NodeList::iterator k = j.next();
877
if (!(k && j->selected() && k->selected())) continue;
878
// This code executes for every selected segment
879
if (!j->arc_rx()->isDegenerate() || !j->arc_ry()->isDegenerate()){
880
// This code executes for every selected ARC segment
881
*(j->arc_sweep()) = !*j->arc_sweep();
1150
1206
// sanitize pathvector and store it in SPCurve,
1151
1207
// so that _updateDragPoint doesn't crash on paths with naked movetos
1152
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers(_spcurve->get_pathvector());
1208
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers_and_arcs(_spcurve->get_pathvector());
1153
1210
for (Geom::PathVector::iterator i = pathv.begin(); i != pathv.end(); ) {
1154
1211
// NOTE: this utilizes the fact that Geom::PathVector is an std::vector.
1155
1212
// When we erase an element, the next one slides into position,
1199
1256
previous_node->front()->setPosition((*bezier)[1]);
1200
1257
current_node ->back() ->setPosition((*bezier)[2]);
1259
Geom::EllipticalArc const *arc = dynamic_cast<Geom::EllipticalArc const*>(&*cit);
1262
Geom::Coord angleX = arc->rotationAngle();
1263
Geom::Coord angleY = angleX + Geom::rad_from_deg(90);
1264
previous_node->moveArcHandles(current_node->position() - previous_node->position(), arc->ray(Geom::X), arc->ray(Geom::Y), angleX, angleY);
1265
*(previous_node->arc_large()) = arc->largeArc();
1266
*(previous_node->arc_sweep()) = arc->sweep();
1202
1268
previous_node = current_node;
1204
1270
// If the path is closed, make the list cyclic
1397
1463
* @relates PathManipulator */
1398
1464
void build_segment(Geom::PathBuilder &builder, Node *prev_node, Node *cur_node)
1400
if (cur_node->back()->isDegenerate() && prev_node->front()->isDegenerate())
1402
// NOTE: It seems like the renderer cannot correctly handle vline / hline segments,
1403
// and trying to display a path using them results in funny artifacts.
1404
builder.lineTo(cur_node->position());
1406
// this is a bezier segment
1408
prev_node->front()->position(),
1409
cur_node->back()->position(),
1466
if (prev_node->arc_rx()->isDegenerate() || prev_node->arc_ry()->isDegenerate() ){
1467
// This is not an eliptical arc, check if it is a straight line or bezier
1468
if (cur_node->back()->isDegenerate() && prev_node->front()->isDegenerate())
1470
// NOTE: It seems like the renderer cannot correctly handle vline / hline segments,
1471
// and trying to display a path using them results in funny artifacts.
1472
builder.lineTo(cur_node->position());
1474
// this is a bezier segment
1476
prev_node->front()->position(),
1477
cur_node->back()->position(),
1478
cur_node->position());
1482
// This is an eliptical arc, get the x and y set by the xy handle
1483
Geom::Coord rx = prev_node->arc_rx()->length();
1484
Geom::Coord ry = prev_node->arc_ry()->length();
1485
Geom::Angle rot = prev_node->arc_rx()->angle();
1491
*prev_node->arc_large(),
1492
*prev_node->arc_sweep(),
1410
1493
cur_node->position());