~danieljabailey/inkscape/arc_node_editor

« back to all changes in this revision

Viewing changes to src/ui/tool/path-manipulator.cpp

  • Committer: Daniel Bailey
  • Date: 2016-05-15 20:44:44 UTC
  • Revision ID: d@nielbailey.com-20160515204444-tak344mvzf55nhwk
Added support for editting arc segments in the node editor

Show diffs side-by-side

added added

removed removed

Lines of Context:
801
801
    }
802
802
}
803
803
 
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.
 
806
 
 
807
/** Make selected segments curves / lines / arcs. */
805
808
void PathManipulator::setSegmentType(SegmentType type)
806
809
{
807
810
    if (_num_selected == 0) return;
811
814
            if (!(k && j->selected() && k->selected())) continue;
812
815
            switch (type) {
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()))
815
819
                    break;
816
820
                j->front()->move(*j);
817
821
                k->back()->move(*k);
 
822
                j->retractArcHandles();
818
823
                break;
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);
825
 
                break;
 
830
                j->arc_rx()->move(*j);
 
831
                j->arc_ry()->move(*j);
 
832
                j->retractArcHandles();
 
833
                break;
 
834
            case SEGMENT_ELIPTICAL_ARC:
 
835
                if (!(j->front()->isDegenerate() && k->back()->isDegenerate())){
 
836
                    j->front()->move(*j);
 
837
                    k->back()->move(*k);
 
838
                }
 
839
 
 
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;
 
843
 
 
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());
 
848
                }
 
849
                break;
 
850
            }
 
851
        }
 
852
    }
 
853
}
 
854
 
 
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;
 
866
            }
 
867
        }
 
868
    }
 
869
}
 
870
 
 
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();
826
882
            }
827
883
        }
828
884
    }
1149
1205
 
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());
 
1209
 
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]);
1201
1258
            }
 
1259
            Geom::EllipticalArc const *arc = dynamic_cast<Geom::EllipticalArc const*>(&*cit);
 
1260
            if (arc)
 
1261
            {
 
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();
 
1267
            }
1202
1268
            previous_node = current_node;
1203
1269
        }
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)
1399
1465
{
1400
 
    if (cur_node->back()->isDegenerate() && prev_node->front()->isDegenerate())
1401
 
    {
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());
1405
 
    } else {
1406
 
        // this is a bezier segment
1407
 
        builder.curveTo(
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())
 
1469
        {
 
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());
 
1473
        } else {
 
1474
            // this is a bezier segment
 
1475
            builder.curveTo(
 
1476
                prev_node->front()->position(),
 
1477
                cur_node->back()->position(),
 
1478
                cur_node->position());
 
1479
        }
 
1480
    }
 
1481
    else{
 
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();
 
1486
 
 
1487
        builder.arcTo(
 
1488
            rx,
 
1489
            ry,
 
1490
            rot,
 
1491
            *prev_node->arc_large(),
 
1492
            *prev_node->arc_sweep(),
1410
1493
            cur_node->position());
1411
1494
    }
1412
1495
}