Let tangent arc modify the original entities.
Modifying the original entities instead of deleting them, retains the original associated constraints. This makes creating rounded rectangles a lot easier.pull/380/head
parent
c0678d7bdd
commit
e69478e61a
|
@ -88,6 +88,8 @@ Bugs fixed:
|
||||||
* A step rotate/translate group using a group forced to triangle mesh
|
* A step rotate/translate group using a group forced to triangle mesh
|
||||||
as a source group also gets forced to triangle mesh.
|
as a source group also gets forced to triangle mesh.
|
||||||
* Paste Transformed with a negative scale does not invert arcs.
|
* Paste Transformed with a negative scale does not invert arcs.
|
||||||
|
* The tangent arc now modifies the original entities instead of deleting
|
||||||
|
them, such that their constraints are retained.
|
||||||
|
|
||||||
2.x
|
2.x
|
||||||
---
|
---
|
||||||
|
|
108
src/modify.cpp
108
src/modify.cpp
|
@ -161,19 +161,32 @@ Vector GraphicsWindow::ParametricCurve::TangentAt(double t) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hRequest GraphicsWindow::ParametricCurve::CreateRequestTrimmedTo(double t,
|
/** Changes or copies the given entity and connects it to the arc.
|
||||||
bool extraConstraints, hEntity orig, hEntity arc, bool arcFinish)
|
* \param t Where on this parametric curve does it connect to the arc.
|
||||||
|
* \param reuseOrig Should the original entity be modified
|
||||||
|
* \param orig The original entity.
|
||||||
|
* \param arc The arc that will be connected to.
|
||||||
|
* \param arcFinish Whether to connect to the end point of the arc.
|
||||||
|
* \param pointf When changing the original entity, whether the end point should be modified.
|
||||||
|
*/
|
||||||
|
void GraphicsWindow::ParametricCurve::CreateRequestTrimmedTo(double t,
|
||||||
|
bool reuseOrig, hEntity orig, hEntity arc, bool arcFinish, bool pointf)
|
||||||
{
|
{
|
||||||
hRequest hr;
|
hRequest hr;
|
||||||
Entity *e;
|
Entity *e;
|
||||||
if(isLine) {
|
if(isLine) {
|
||||||
hr = SS.GW.AddRequest(Request::Type::LINE_SEGMENT, /*rememberForUndo=*/false),
|
if (reuseOrig) {
|
||||||
e = SK.GetEntity(hr.entity(0));
|
e = SK.GetEntity(orig);
|
||||||
SK.GetEntity(e->point[0])->PointForceTo(PointAt(t));
|
int i = pointf ? 1 : 0;
|
||||||
SK.GetEntity(e->point[1])->PointForceTo(PointAt(1));
|
SK.GetEntity(e->point[i])->PointForceTo(PointAt(t));
|
||||||
ConstrainPointIfCoincident(e->point[0]);
|
ConstrainPointIfCoincident(e->point[i]);
|
||||||
ConstrainPointIfCoincident(e->point[1]);
|
} else {
|
||||||
if(extraConstraints) {
|
hr = SS.GW.AddRequest(Request::Type::LINE_SEGMENT, /*rememberForUndo=*/false),
|
||||||
|
e = SK.GetEntity(hr.entity(0));
|
||||||
|
SK.GetEntity(e->point[0])->PointForceTo(PointAt(t));
|
||||||
|
SK.GetEntity(e->point[1])->PointForceTo(PointAt(1));
|
||||||
|
ConstrainPointIfCoincident(e->point[0]);
|
||||||
|
ConstrainPointIfCoincident(e->point[1]);
|
||||||
Constraint::Constrain(Constraint::Type::PT_ON_LINE,
|
Constraint::Constrain(Constraint::Type::PT_ON_LINE,
|
||||||
hr.entity(1), Entity::NO_ENTITY, orig);
|
hr.entity(1), Entity::NO_ENTITY, orig);
|
||||||
}
|
}
|
||||||
|
@ -181,26 +194,32 @@ hRequest GraphicsWindow::ParametricCurve::CreateRequestTrimmedTo(double t,
|
||||||
Entity::NO_ENTITY, Entity::NO_ENTITY,
|
Entity::NO_ENTITY, Entity::NO_ENTITY,
|
||||||
arc, e->h, /*other=*/arcFinish, /*other2=*/false);
|
arc, e->h, /*other=*/arcFinish, /*other2=*/false);
|
||||||
} else {
|
} else {
|
||||||
hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false),
|
if (reuseOrig) {
|
||||||
e = SK.GetEntity(hr.entity(0));
|
e = SK.GetEntity(orig);
|
||||||
SK.GetEntity(e->point[0])->PointForceTo(p0);
|
int i = pointf ? 2 : 1;
|
||||||
if(dtheta > 0) {
|
SK.GetEntity(e->point[i])->PointForceTo(PointAt(t));
|
||||||
SK.GetEntity(e->point[1])->PointForceTo(PointAt(t));
|
ConstrainPointIfCoincident(e->point[i]);
|
||||||
SK.GetEntity(e->point[2])->PointForceTo(PointAt(1));
|
|
||||||
} else {
|
} else {
|
||||||
SK.GetEntity(e->point[2])->PointForceTo(PointAt(t));
|
hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false),
|
||||||
SK.GetEntity(e->point[1])->PointForceTo(PointAt(1));
|
e = SK.GetEntity(hr.entity(0));
|
||||||
|
SK.GetEntity(e->point[0])->PointForceTo(p0);
|
||||||
|
if(dtheta > 0) {
|
||||||
|
SK.GetEntity(e->point[1])->PointForceTo(PointAt(t));
|
||||||
|
SK.GetEntity(e->point[2])->PointForceTo(PointAt(1));
|
||||||
|
} else {
|
||||||
|
SK.GetEntity(e->point[2])->PointForceTo(PointAt(t));
|
||||||
|
SK.GetEntity(e->point[1])->PointForceTo(PointAt(1));
|
||||||
|
}
|
||||||
|
ConstrainPointIfCoincident(e->point[0]);
|
||||||
|
ConstrainPointIfCoincident(e->point[1]);
|
||||||
|
ConstrainPointIfCoincident(e->point[2]);
|
||||||
}
|
}
|
||||||
ConstrainPointIfCoincident(e->point[0]);
|
|
||||||
ConstrainPointIfCoincident(e->point[1]);
|
|
||||||
ConstrainPointIfCoincident(e->point[2]);
|
|
||||||
// The tangency constraint alone is enough to fully constrain it,
|
// The tangency constraint alone is enough to fully constrain it,
|
||||||
// so there's no need for more.
|
// so there's no need for more.
|
||||||
Constraint::Constrain(Constraint::Type::CURVE_CURVE_TANGENT,
|
Constraint::Constrain(Constraint::Type::CURVE_CURVE_TANGENT,
|
||||||
Entity::NO_ENTITY, Entity::NO_ENTITY,
|
Entity::NO_ENTITY, Entity::NO_ENTITY,
|
||||||
arc, e->h, /*other=*/arcFinish, /*other2=*/(dtheta < 0));
|
arc, e->h, /*other=*/arcFinish, /*other2=*/(dtheta < 0));
|
||||||
}
|
}
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -388,6 +407,27 @@ void GraphicsWindow::MakeTangentArc() {
|
||||||
|
|
||||||
SS.UndoRemember();
|
SS.UndoRemember();
|
||||||
|
|
||||||
|
if (SS.tangentArcModify) {
|
||||||
|
// Delete the coincident constraint for the removed point.
|
||||||
|
SK.constraint.ClearTags();
|
||||||
|
for(i = 0; i < SK.constraint.n; i++) {
|
||||||
|
Constraint *cs = &(SK.constraint.elem[i]);
|
||||||
|
if(cs->group.v != activeGroup.v) continue;
|
||||||
|
if(cs->workplane.v != ActiveWorkplane().v) continue;
|
||||||
|
if(cs->type != Constraint::Type::POINTS_COINCIDENT) continue;
|
||||||
|
if (SK.GetEntity(cs->ptA)->PointGetNum().Equals(pshared)) {
|
||||||
|
cs->tag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SK.constraint.RemoveTagged();
|
||||||
|
} else {
|
||||||
|
// Make the original entities construction, or delete them
|
||||||
|
// entirely, according to user preference.
|
||||||
|
SK.GetRequest(hreq[0])->construction = true;
|
||||||
|
SK.GetRequest(hreq[1])->construction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and position the new tangent arc.
|
||||||
hRequest harc = AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false);
|
hRequest harc = AddRequest(Request::Type::ARC_OF_CIRCLE, /*rememberForUndo=*/false);
|
||||||
Entity *earc = SK.GetEntity(harc.entity(0));
|
Entity *earc = SK.GetEntity(harc.entity(0));
|
||||||
hEntity hearc = earc->h;
|
hEntity hearc = earc->h;
|
||||||
|
@ -398,27 +438,11 @@ void GraphicsWindow::MakeTangentArc() {
|
||||||
|
|
||||||
earc = NULL;
|
earc = NULL;
|
||||||
|
|
||||||
pc[0].CreateRequestTrimmedTo(t[0], !SS.tangentArcDeleteOld,
|
// Modify or duplicate the original entities and connect them to the tangent arc.
|
||||||
hent[0], hearc, /*arcFinish=*/(b == 1));
|
pc[0].CreateRequestTrimmedTo(t[0], SS.tangentArcModify,
|
||||||
pc[1].CreateRequestTrimmedTo(t[1], !SS.tangentArcDeleteOld,
|
hent[0], hearc, /*arcFinish=*/(b == 1), pointf[0]);
|
||||||
hent[1], hearc, /*arcFinish=*/(a == 1));
|
pc[1].CreateRequestTrimmedTo(t[1], SS.tangentArcModify,
|
||||||
|
hent[1], hearc, /*arcFinish=*/(a == 1), pointf[1]);
|
||||||
// Now either make the original entities construction, or delete them
|
|
||||||
// entirely, according to user preference.
|
|
||||||
Request *re;
|
|
||||||
SK.request.ClearTags();
|
|
||||||
for(re = SK.request.First(); re; re = SK.request.NextAfter(re)) {
|
|
||||||
if(re->h.v == hreq[0].v || re->h.v == hreq[1].v) {
|
|
||||||
if(SS.tangentArcDeleteOld) {
|
|
||||||
re->tag = 1;
|
|
||||||
} else {
|
|
||||||
re->construction = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(SS.tangentArcDeleteOld) {
|
|
||||||
DeleteTaggedRequests();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hEntity GraphicsWindow::SplitLine(hEntity he, Vector pinter) {
|
hEntity GraphicsWindow::SplitLine(hEntity he, Vector pinter) {
|
||||||
|
|
|
@ -638,7 +638,7 @@ public:
|
||||||
// as special requests.
|
// as special requests.
|
||||||
double tangentArcRadius;
|
double tangentArcRadius;
|
||||||
bool tangentArcManual;
|
bool tangentArcManual;
|
||||||
bool tangentArcDeleteOld;
|
bool tangentArcModify;
|
||||||
|
|
||||||
// The platform-dependent code calls this before entering the msg loop
|
// The platform-dependent code calls this before entering the msg loop
|
||||||
void Init();
|
void Init();
|
||||||
|
|
|
@ -643,7 +643,7 @@ void TextWindow::ScreenChangeTangentArc(int link, uint32_t v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'a': SS.tangentArcManual = !SS.tangentArcManual; break;
|
case 'a': SS.tangentArcManual = !SS.tangentArcManual; break;
|
||||||
case 'd': SS.tangentArcDeleteOld = !SS.tangentArcDeleteOld; break;
|
case 'm': SS.tangentArcModify = !SS.tangentArcModify; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TextWindow::ShowTangentArc() {
|
void TextWindow::ShowTangentArc() {
|
||||||
|
@ -662,9 +662,9 @@ void TextWindow::ShowTangentArc() {
|
||||||
Printf(false, " %Fd%f%La%s choose radius automatically%E",
|
Printf(false, " %Fd%f%La%s choose radius automatically%E",
|
||||||
&ScreenChangeTangentArc,
|
&ScreenChangeTangentArc,
|
||||||
!SS.tangentArcManual ? CHECK_TRUE : CHECK_FALSE);
|
!SS.tangentArcManual ? CHECK_TRUE : CHECK_FALSE);
|
||||||
Printf(false, " %Fd%f%Ld%s delete original entities afterward%E",
|
Printf(false, " %Fd%f%Lm%s modify original entities%E",
|
||||||
&ScreenChangeTangentArc,
|
&ScreenChangeTangentArc,
|
||||||
SS.tangentArcDeleteOld ? CHECK_TRUE : CHECK_FALSE);
|
SS.tangentArcModify ? CHECK_TRUE : CHECK_FALSE);
|
||||||
|
|
||||||
Printf(false, "");
|
Printf(false, "");
|
||||||
Printf(false, "To create a tangent arc at a point,");
|
Printf(false, "To create a tangent arc at a point,");
|
||||||
|
|
7
src/ui.h
7
src/ui.h
|
@ -668,8 +668,8 @@ public:
|
||||||
Vector TangentAt(double t);
|
Vector TangentAt(double t);
|
||||||
double LengthForAuto();
|
double LengthForAuto();
|
||||||
|
|
||||||
hRequest CreateRequestTrimmedTo(double t, bool extraConstraints,
|
void CreateRequestTrimmedTo(double t, bool reuseOrig,
|
||||||
hEntity orig, hEntity arc, bool arcFinish);
|
hEntity orig, hEntity arc, bool arcFinish, bool pointf);
|
||||||
void ConstrainPointIfCoincident(hEntity hpt);
|
void ConstrainPointIfCoincident(hEntity hpt);
|
||||||
};
|
};
|
||||||
void MakeTangentArc();
|
void MakeTangentArc();
|
||||||
|
@ -718,6 +718,7 @@ public:
|
||||||
void HitTestMakeSelection(Point2d mp);
|
void HitTestMakeSelection(Point2d mp);
|
||||||
void ClearSelection();
|
void ClearSelection();
|
||||||
void ClearNonexistentSelectionItems();
|
void ClearNonexistentSelectionItems();
|
||||||
|
/// This structure is filled by a call to GroupSelection().
|
||||||
struct {
|
struct {
|
||||||
std::vector<hEntity> point;
|
std::vector<hEntity> point;
|
||||||
std::vector<hEntity> entity;
|
std::vector<hEntity> entity;
|
||||||
|
@ -740,7 +741,7 @@ public:
|
||||||
int stylables;
|
int stylables;
|
||||||
int constraintLabels;
|
int constraintLabels;
|
||||||
int withEndpoints;
|
int withEndpoints;
|
||||||
int n;
|
int n; ///< Number of selected items
|
||||||
} gs;
|
} gs;
|
||||||
void GroupSelection();
|
void GroupSelection();
|
||||||
bool IsSelected(Selection *s);
|
bool IsSelected(Selection *s);
|
||||||
|
|
Loading…
Reference in New Issue