Implement splitting at point with "Split Curves at Intersection".
This commit is contained in:
parent
9cd0044803
commit
d471e65e7d
@ -22,6 +22,8 @@ New sketch features:
|
|||||||
* When adding a constraint which has a label and is redundant with another
|
* When adding a constraint which has a label and is redundant with another
|
||||||
constraint, the constraint is added as a reference, avoiding an error.
|
constraint, the constraint is added as a reference, avoiding an error.
|
||||||
* Datum points can be copied and pasted.
|
* Datum points can be copied and pasted.
|
||||||
|
* "Split Curves at Intersection" can now split curves at point lying on curve,
|
||||||
|
not just at intersection of two curves.
|
||||||
|
|
||||||
New constraint features:
|
New constraint features:
|
||||||
* When dragging an arc or rectangle point, it will be automatically
|
* When dragging an arc or rectangle point, it will be automatically
|
||||||
|
@ -603,35 +603,62 @@ void GraphicsWindow::SplitLinesOrCurves() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroupSelection();
|
GroupSelection();
|
||||||
if(!(gs.n == 2 &&(gs.lineSegments +
|
int n = gs.lineSegments + gs.circlesOrArcs + gs.cubics + gs.periodicCubics;
|
||||||
gs.circlesOrArcs +
|
if(!((n == 2 && gs.points == 0) || (n == 1 && gs.points == 1))) {
|
||||||
gs.cubics +
|
Error(_("Select two entities that intersect each other "
|
||||||
gs.periodicCubics) == 2))
|
"(e.g. two lines/circles/arcs or a line/circle/arc and a point)."));
|
||||||
{
|
|
||||||
Error(_("Select two entities that intersect each other (e.g. two lines "
|
|
||||||
"or two circles or a circle and a line)."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool splitAtPoint = (gs.points == 1);
|
||||||
hEntity ha = gs.entity[0],
|
hEntity ha = gs.entity[0],
|
||||||
hb = gs.entity[1];
|
hb = splitAtPoint ? gs.point[0] : gs.entity[1];
|
||||||
|
|
||||||
Entity *ea = SK.GetEntity(ha),
|
Entity *ea = SK.GetEntity(ha),
|
||||||
*eb = SK.GetEntity(hb);
|
*eb = SK.GetEntity(hb);
|
||||||
|
SPointList inters = {};
|
||||||
// Compute the possibly-rational Bezier curves for each of these entities
|
SBezierList sbla = {},
|
||||||
SBezierList sbla, sblb;
|
|
||||||
sbla = {};
|
|
||||||
sblb = {};
|
sblb = {};
|
||||||
|
Vector pi = Vector::From(0, 0, 0);
|
||||||
|
|
||||||
|
SK.constraint.ClearTags();
|
||||||
|
|
||||||
|
// First, decide the point where we're going to make the split.
|
||||||
|
bool foundInters = false;
|
||||||
|
if(splitAtPoint) {
|
||||||
|
// One of the entities is a point, and this point must be on the other entity.
|
||||||
|
// Verify that a corresponding point-coincident constraint exists for the point/entity.
|
||||||
|
Vector p0, p1;
|
||||||
|
if(ea->type == Entity::Type::LINE_SEGMENT) {
|
||||||
|
p0 = ea->EndpointStart();
|
||||||
|
p1 = ea->EndpointFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Constraint &c : SK.constraint) {
|
||||||
|
if(c.ptA.request().v == hb.request().v &&
|
||||||
|
c.entityA.request().v == ha.request().v) {
|
||||||
|
pi = SK.GetEntity(c.ptA)->PointGetNum();
|
||||||
|
|
||||||
|
if(ea->type == Entity::Type::LINE_SEGMENT && !pi.OnLineSegment(p0, p1)) {
|
||||||
|
// The point isn't between line endpoints, so there isn't an actual
|
||||||
|
// intersection.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.tag = 1;
|
||||||
|
foundInters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Compute the possibly-rational Bezier curves for each of these non-point entities...
|
||||||
ea->GenerateBezierCurves(&sbla);
|
ea->GenerateBezierCurves(&sbla);
|
||||||
eb->GenerateBezierCurves(&sblb);
|
eb->GenerateBezierCurves(&sblb);
|
||||||
// and then compute the points where they intersect, based on those curves.
|
// ... and then compute the points where they intersect, based on those curves.
|
||||||
SPointList inters = {};
|
|
||||||
sbla.AllIntersectionsWith(&sblb, &inters);
|
sbla.AllIntersectionsWith(&sblb, &inters);
|
||||||
|
|
||||||
|
// If there's multiple points, then take the one closest to the mouse pointer.
|
||||||
if(inters.l.n > 0) {
|
if(inters.l.n > 0) {
|
||||||
Vector pi = Vector::From(0, 0, 0);
|
|
||||||
// If there's multiple points, then take the one closest to the
|
|
||||||
// mouse pointer.
|
|
||||||
double dmin = VERY_POSITIVE;
|
double dmin = VERY_POSITIVE;
|
||||||
SPoint *sp;
|
SPoint *sp;
|
||||||
for(sp = inters.l.First(); sp; sp = inters.l.NextAfter(sp)) {
|
for(sp = inters.l.First(); sp; sp = inters.l.NextAfter(sp)) {
|
||||||
@ -641,16 +668,47 @@ void GraphicsWindow::SplitLinesOrCurves() {
|
|||||||
pi = sp->p;
|
pi = sp->p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foundInters = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, actually split the entities.
|
||||||
|
if(foundInters) {
|
||||||
SS.UndoRemember();
|
SS.UndoRemember();
|
||||||
|
|
||||||
|
// Remove any constraints we're going to replace.
|
||||||
|
SK.constraint.RemoveTagged();
|
||||||
|
|
||||||
hEntity hia = SplitEntity(ha, pi),
|
hEntity hia = SplitEntity(ha, pi),
|
||||||
hib = SplitEntity(hb, pi);
|
hib = {};
|
||||||
// SplitEntity adds the coincident constraints to join the split halves
|
// SplitEntity adds the coincident constraints to join the split halves
|
||||||
// of each original entity; and then we add the constraint to join
|
// of each original entity; and then we add the constraint to join
|
||||||
// the two entities together at the split point.
|
// the two entities together at the split point.
|
||||||
|
if(splitAtPoint) {
|
||||||
|
// Remove datum point, as it has now been superseded by the split point.
|
||||||
|
SK.request.ClearTags();
|
||||||
|
for(Request &r : SK.request) {
|
||||||
|
if(r.h.v == hb.request().v) {
|
||||||
|
if(r.type == Request::Type::DATUM_POINT) {
|
||||||
|
// Delete datum point.
|
||||||
|
r.tag = 1;
|
||||||
|
FixConstraintsForRequestBeingDeleted(r.h);
|
||||||
|
} else {
|
||||||
|
// Add constraint if not datum point, but endpoint of line/arc etc.
|
||||||
|
Constraint::ConstrainCoincident(hia, hb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SK.request.RemoveTagged();
|
||||||
|
} else {
|
||||||
|
// Split second non-point entity and add constraint.
|
||||||
|
hib = SplitEntity(hb, pi);
|
||||||
if(hia.v && hib.v) {
|
if(hia.v && hib.v) {
|
||||||
Constraint::ConstrainCoincident(hia, hib);
|
Constraint::ConstrainCoincident(hia, hib);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Error(_("Can't split; no intersection found."));
|
Error(_("Can't split; no intersection found."));
|
||||||
}
|
}
|
||||||
@ -661,4 +719,3 @@ void GraphicsWindow::SplitLinesOrCurves() {
|
|||||||
sblb.Clear();
|
sblb.Clear();
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user