Implement helical extrusion groups.
parent
b3f739f2c4
commit
986da7d224
|
@ -5,7 +5,7 @@ Changelog
|
|||
---
|
||||
|
||||
New sketch features:
|
||||
* New group, revolve.
|
||||
* New groups, revolution and helical extrusion.
|
||||
* Extrude, lathe, translate and rotate groups can use the "assembly"
|
||||
boolean operation, to increase performance.
|
||||
* The solid model of extrude and lathe groups can be suppressed,
|
||||
|
|
|
@ -88,6 +88,7 @@ void Entity::GetReferencePoints(std::vector<Vector> *refs) {
|
|||
case Type::POINT_N_TRANS:
|
||||
case Type::POINT_N_ROT_TRANS:
|
||||
case Type::POINT_N_ROT_AA:
|
||||
case Type::POINT_N_ROT_AXIS_TRANS:
|
||||
case Type::POINT_IN_3D:
|
||||
case Type::POINT_IN_2D:
|
||||
refs->push_back(PointGetNum());
|
||||
|
@ -502,6 +503,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
|
|||
case Type::POINT_N_TRANS:
|
||||
case Type::POINT_N_ROT_TRANS:
|
||||
case Type::POINT_N_ROT_AA:
|
||||
case Type::POINT_N_ROT_AXIS_TRANS:
|
||||
case Type::POINT_IN_3D:
|
||||
case Type::POINT_IN_2D: {
|
||||
if(how == DrawAs::HIDDEN) return;
|
||||
|
|
|
@ -245,6 +245,7 @@ bool EntityBase::IsPoint() const {
|
|||
case Type::POINT_N_TRANS:
|
||||
case Type::POINT_N_ROT_TRANS:
|
||||
case Type::POINT_N_ROT_AA:
|
||||
case Type::POINT_N_ROT_AXIS_TRANS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -454,10 +455,38 @@ void EntityBase::PointForceTo(Vector p) {
|
|||
// in order to avoid jumps when you cross from +pi to -pi
|
||||
while(dtheta < -PI) dtheta += 2*PI;
|
||||
while(dtheta > PI) dtheta -= 2*PI;
|
||||
// this extra *2 explains the mystery *4
|
||||
SK.GetParam(param[3])->val = (thetai + dtheta)/(timesApplied*2);
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::POINT_N_ROT_AXIS_TRANS: {
|
||||
if(timesApplied == 0) break;
|
||||
// is the point on the rotation axis?
|
||||
Vector offset = Vector::From(param[0], param[1], param[2]);
|
||||
Vector normal = Vector::From(param[4], param[5], param[6]).WithMagnitude(1.0);
|
||||
Vector check = numPoint.Minus(offset).Cross(normal);
|
||||
if (check.Dot(check) < LENGTH_EPS) { // if so, do extrusion style drag
|
||||
Vector trans = (p.Minus(numPoint));
|
||||
SK.GetParam(param[7])->val = trans.Dot(normal)/timesApplied;
|
||||
} else { // otherwise do rotation style
|
||||
Vector u = normal.Normal(0), v = normal.Normal(1);
|
||||
Vector po = p.Minus(offset), numo = numPoint.Minus(offset);
|
||||
double thetap = atan2(v.Dot(po), u.Dot(po));
|
||||
double thetan = atan2(v.Dot(numo), u.Dot(numo));
|
||||
double thetaf = (thetap - thetan);
|
||||
double thetai = (SK.GetParam(param[3])->val)*timesApplied*2;
|
||||
double dtheta = thetaf - thetai;
|
||||
// Take the smallest possible change in the actual step angle,
|
||||
// in order to avoid jumps when you cross from +pi to -pi
|
||||
while(dtheta < -PI) dtheta += 2*PI;
|
||||
while(dtheta > PI) dtheta -= 2*PI;
|
||||
// this extra *2 explains the mystery *4
|
||||
SK.GetParam(param[3])->val = (thetai + dtheta)/(timesApplied*2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::POINT_N_COPY:
|
||||
// Nothing to do; it's a static copy
|
||||
break;
|
||||
|
@ -506,6 +535,17 @@ Vector EntityBase::PointGetNum() const {
|
|||
break;
|
||||
}
|
||||
|
||||
case Type::POINT_N_ROT_AXIS_TRANS: {
|
||||
Vector offset = Vector::From(param[0], param[1], param[2]);
|
||||
Vector displace = Vector::From(param[4], param[5], param[6])
|
||||
.WithMagnitude(SK.GetParam(param[7])->val).ScaledBy(timesApplied);
|
||||
Quaternion q = PointGetQuaternion();
|
||||
p = numPoint.Minus(offset);
|
||||
p = q.Rotate(p);
|
||||
p = p.Plus(offset).Plus(displace);
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::POINT_N_COPY:
|
||||
p = numPoint;
|
||||
break;
|
||||
|
@ -555,6 +595,18 @@ ExprVector EntityBase::PointGetExprs() const {
|
|||
r = orig.Plus(trans);
|
||||
break;
|
||||
}
|
||||
case Type::POINT_N_ROT_AXIS_TRANS: {
|
||||
ExprVector orig = ExprVector::From(numPoint);
|
||||
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
||||
ExprVector displace = ExprVector::From(param[4], param[5], param[6])
|
||||
.WithMagnitude(Expr::From(1.0)).ScaledBy(Expr::From(timesApplied)).ScaledBy(Expr::From(param[7]));
|
||||
|
||||
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
|
||||
orig = orig.Minus(trans);
|
||||
orig = q.Rotate(orig);
|
||||
r = orig.Plus(trans).Plus(displace);
|
||||
break;
|
||||
}
|
||||
case Type::POINT_N_COPY:
|
||||
r = ExprVector::From(numPoint);
|
||||
break;
|
||||
|
@ -633,7 +685,7 @@ ExprQuaternion EntityBase::GetAxisAngleQuaternionExprs(int param0) const {
|
|||
Quaternion EntityBase::PointGetQuaternion() const {
|
||||
Quaternion q;
|
||||
|
||||
if(type == Type::POINT_N_ROT_AA) {
|
||||
if(type == Type::POINT_N_ROT_AA || type == Type::POINT_N_ROT_AXIS_TRANS) {
|
||||
q = GetAxisAngleQuaternion(3);
|
||||
} else if(type == Type::POINT_N_ROT_TRANS) {
|
||||
q = Quaternion::From(param[3], param[4], param[5], param[6]);
|
||||
|
@ -807,7 +859,7 @@ bool EntityBase::IsInPlane(Vector norm, double distance) const {
|
|||
|
||||
case Type::CIRCLE:
|
||||
case Type::ARC_OF_CIRCLE: {
|
||||
// If it is an (arc of) a circle, check whether the normals
|
||||
// If it is an (arc of) a circle, check whether the normals
|
||||
// are parallel and the mid point is in the plane.
|
||||
Vector n = Normal()->NormalN();
|
||||
if (!norm.Equals(n) && !norm.Equals(n.Negated())) return false;
|
||||
|
|
|
@ -445,6 +445,7 @@ void SolveSpaceUI::MarkDraggedParams() {
|
|||
switch(pt->type) {
|
||||
case Entity::Type::POINT_N_TRANS:
|
||||
case Entity::Type::POINT_IN_3D:
|
||||
case Entity::Type::POINT_N_ROT_AXIS_TRANS:
|
||||
sys.dragged.Add(&(pt->param[0]));
|
||||
sys.dragged.Add(&(pt->param[1]));
|
||||
sys.dragged.Add(&(pt->param[2]));
|
||||
|
|
|
@ -105,6 +105,7 @@ const MenuEntry Menu[] = {
|
|||
{ 1, N_("Step &Rotating"), Command::GROUP_ROT, S|'r', KN, mGrp },
|
||||
{ 1, NULL, Command::NONE, 0, KN, NULL },
|
||||
{ 1, N_("E&xtrude"), Command::GROUP_EXTRUDE, S|'x', KN, mGrp },
|
||||
{ 1, N_("&Helix"), Command::GROUP_HELIX, S|'h', KN, mGrp },
|
||||
{ 1, N_("&Lathe"), Command::GROUP_LATHE, S|'l', KN, mGrp },
|
||||
{ 1, N_("Re&volve"), Command::GROUP_REVOLVE, S|'v', KN, mGrp },
|
||||
{ 1, NULL, Command::NONE, 0, KN, NULL },
|
||||
|
|
126
src/group.cpp
126
src/group.cpp
|
@ -208,6 +208,30 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
|
|||
g.name = C_("group-name", "revolve");
|
||||
break;
|
||||
|
||||
case Command::GROUP_HELIX:
|
||||
if(gs.points == 1 && gs.vectors == 1 && gs.n == 2) {
|
||||
g.predef.origin = gs.point[0];
|
||||
g.predef.entityB = gs.vector[0];
|
||||
} else if(gs.lineSegments == 1 && gs.n == 1) {
|
||||
g.predef.origin = SK.GetEntity(gs.entity[0])->point[0];
|
||||
g.predef.entityB = gs.entity[0];
|
||||
// since a line segment is a vector
|
||||
} else {
|
||||
Error(_("Bad selection for new helix group. This group can "
|
||||
"be created with:\n\n"
|
||||
" * a point and a line segment or normal "
|
||||
"(revolved about an axis parallel to line / "
|
||||
"normal, through point)\n"
|
||||
" * a line segment (revolved about line segment)\n"));
|
||||
return;
|
||||
}
|
||||
g.type = Type::HELIX;
|
||||
g.opA = SS.GW.activeGroup;
|
||||
g.valA = 2;
|
||||
g.subtype = Subtype::ONE_SIDED;
|
||||
g.name = C_("group-name", "helix");
|
||||
break;
|
||||
|
||||
case Command::GROUP_ROT: {
|
||||
if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) {
|
||||
g.predef.origin = gs.point[0];
|
||||
|
@ -368,7 +392,7 @@ std::string Group::DescriptionString() {
|
|||
|
||||
void Group::Activate() {
|
||||
if(type == Type::EXTRUDE || type == Type::LINKED || type == Type::LATHE ||
|
||||
type == Type::REVOLVE || type == Type::TRANSLATE || type == Type::ROTATE) {
|
||||
type == Type::REVOLVE || type == Type::HELIX || type == Type::TRANSLATE || type == Type::ROTATE) {
|
||||
SS.GW.showFaces = true;
|
||||
} else {
|
||||
SS.GW.showFaces = false;
|
||||
|
@ -460,11 +484,11 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
// adds entities, which may cause a realloc.
|
||||
CopyEntity(entity, SK.GetEntity(he), ai, REMAP_BOTTOM,
|
||||
h.param(0), h.param(1), h.param(2),
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::N_TRANS);
|
||||
CopyEntity(entity, SK.GetEntity(he), af, REMAP_TOP,
|
||||
h.param(0), h.param(1), h.param(2),
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::N_TRANS);
|
||||
MakeExtrusionLines(entity, he);
|
||||
}
|
||||
|
@ -492,17 +516,17 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
// adds entities, which may cause a realloc.
|
||||
CopyEntity(entity, SK.GetEntity(predef.origin), 0, ai,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::NUMERIC);
|
||||
|
||||
CopyEntity(entity, SK.GetEntity(he), 0, REMAP_LATHE_START,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::NUMERIC);
|
||||
|
||||
CopyEntity(entity, SK.GetEntity(he), 0, REMAP_LATHE_END,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::NUMERIC);
|
||||
|
||||
MakeLatheCircles(entity, param, he, axis_pos, axis_dir, ai);
|
||||
|
@ -527,7 +551,6 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
AddParam(param, h.param(5), axis_dir.y);
|
||||
AddParam(param, h.param(6), axis_dir.z);
|
||||
|
||||
int n = 2;
|
||||
int ai = 1;
|
||||
|
||||
for(i = 0; i < entity->n; i++) {
|
||||
|
@ -539,17 +562,17 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
hEntity he = e->h;
|
||||
|
||||
CopyEntity(entity, SK.GetEntity(predef.origin), 0, ai, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, CopyAs::NUMERIC);
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, CopyAs::NUMERIC);
|
||||
|
||||
for(a = 0; a < 2; a++) {
|
||||
if(e->group != opA)
|
||||
continue;
|
||||
|
||||
e->CalculateNumerical(false);
|
||||
CopyEntity(entity, e, a * 2 - (subtype == Subtype::ONE_SIDED ? 0 : (n - 1)),
|
||||
(a == (n - 1)) ? REMAP_LATHE_END : REMAP_LATHE_START, h.param(0),
|
||||
h.param(1), h.param(2), h.param(3), h.param(4), h.param(5),
|
||||
h.param(6), CopyAs::N_ROT_AA);
|
||||
CopyEntity(entity, e, a * 2 - (subtype == Subtype::ONE_SIDED ? 0 : 1),
|
||||
(a == 1) ? REMAP_LATHE_END : REMAP_LATHE_START, h.param(0),
|
||||
h.param(1), h.param(2), h.param(3), h.param(4), h.param(5),
|
||||
h.param(6), NO_PARAM, CopyAs::N_ROT_AA);
|
||||
}
|
||||
// Arcs are not generated for revolve groups, for now, because our current arc
|
||||
// entity is not chiral, and dragging a revolve may break the arc by inverting it.
|
||||
|
@ -561,6 +584,63 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
return;
|
||||
}
|
||||
|
||||
case Type::HELIX: {
|
||||
Vector axis_pos = SK.GetEntity(predef.origin)->PointGetNum();
|
||||
Vector axis_dir = SK.GetEntity(predef.entityB)->VectorGetNum();
|
||||
|
||||
// The center of rotation
|
||||
AddParam(param, h.param(0), axis_pos.x);
|
||||
AddParam(param, h.param(1), axis_pos.y);
|
||||
AddParam(param, h.param(2), axis_pos.z);
|
||||
// The rotation quaternion
|
||||
AddParam(param, h.param(3), 30 * PI / 180);
|
||||
AddParam(param, h.param(4), axis_dir.x);
|
||||
AddParam(param, h.param(5), axis_dir.y);
|
||||
AddParam(param, h.param(6), axis_dir.z);
|
||||
// distance to translate along the rotation axis
|
||||
AddParam(param, h.param(7), 20);
|
||||
|
||||
int ai = 1;
|
||||
|
||||
for(i = 0; i < entity->n; i++) {
|
||||
Entity *e = &(entity->elem[i]);
|
||||
if(e->group.v != opA.v)
|
||||
continue;
|
||||
|
||||
e->CalculateNumerical(/*forExport=*/false);
|
||||
|
||||
CopyEntity(entity, SK.GetEntity(predef.origin), 0, ai, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, CopyAs::NUMERIC);
|
||||
|
||||
for(a = 0; a < 2; a++) {
|
||||
e->CalculateNumerical(false);
|
||||
CopyEntity(entity, e, a * 2 - (subtype == Subtype::ONE_SIDED ? 0 : 1),
|
||||
(a == 1) ? REMAP_LATHE_END : REMAP_LATHE_START, h.param(0),
|
||||
h.param(1), h.param(2), h.param(3), h.param(4), h.param(5),
|
||||
h.param(6), h.param(7), CopyAs::N_ROT_AXIS_TRANS);
|
||||
}
|
||||
// For point entities on the axis, create a construction line
|
||||
if(e->IsPoint()) {
|
||||
Vector check = e->PointGetNum().Minus(axis_pos).Cross(axis_dir);
|
||||
if (check.Dot(check) < LENGTH_EPS) {
|
||||
Entity *ep = SK.GetEntity(e->h);
|
||||
Entity en = {};
|
||||
// A point gets extruded to form a line segment
|
||||
en.point[0] = Remap(ep->h, REMAP_LATHE_START);
|
||||
en.point[1] = Remap(ep->h, REMAP_LATHE_END);
|
||||
en.group = h;
|
||||
en.construction = ep->construction;
|
||||
en.style = ep->style;
|
||||
en.h = Remap(ep->h, REMAP_PT_TO_LINE);
|
||||
en.type = Entity::Type::LINE_SEGMENT;
|
||||
entity->Add(&en);
|
||||
}
|
||||
}
|
||||
ai++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case Type::TRANSLATE: {
|
||||
// inherit meshCombine from source group
|
||||
Group *srcg = SK.GetGroup(opA);
|
||||
|
@ -585,7 +665,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
a*2 - (subtype == Subtype::ONE_SIDED ? 0 : (n-1)),
|
||||
(a == (n - 1)) ? REMAP_LAST : a,
|
||||
h.param(0), h.param(1), h.param(2),
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
|
||||
CopyAs::N_TRANS);
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +700,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
a*2 - (subtype == Subtype::ONE_SIDED ? 0 : (n-1)),
|
||||
(a == (n - 1)) ? REMAP_LAST : a,
|
||||
h.param(0), h.param(1), h.param(2),
|
||||
h.param(3), h.param(4), h.param(5), h.param(6),
|
||||
h.param(3), h.param(4), h.param(5), h.param(6), NO_PARAM,
|
||||
CopyAs::N_ROT_AA);
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +721,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
Entity *ie = &(impEntity.elem[i]);
|
||||
CopyEntity(entity, ie, 0, 0,
|
||||
h.param(0), h.param(1), h.param(2),
|
||||
h.param(3), h.param(4), h.param(5), h.param(6),
|
||||
h.param(3), h.param(4), h.param(5), h.param(6), NO_PARAM,
|
||||
CopyAs::N_ROT_TRANS);
|
||||
}
|
||||
return;
|
||||
|
@ -670,7 +750,7 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *l) {
|
|||
Expr::From(h.param(5)),
|
||||
Expr::From(h.param(6)) };
|
||||
AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0);
|
||||
} else if(type == Type::ROTATE || type == Type::REVOLVE) {
|
||||
} else if(type == Type::ROTATE || type == Type::REVOLVE || type == Type::HELIX) {
|
||||
// The axis and center of rotation are specified numerically
|
||||
#define EC(x) (Expr::From(x))
|
||||
#define EP(x) (Expr::From(h.param(x)))
|
||||
|
@ -867,7 +947,7 @@ void Group::MakeExtrusionTopBottomFaces(IdList<Entity,hEntity> *el, hEntity pt)
|
|||
void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
||||
Entity *ep, int timesApplied, int remap,
|
||||
hParam dx, hParam dy, hParam dz,
|
||||
hParam qw, hParam qvx, hParam qvy, hParam qvz,
|
||||
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam dist,
|
||||
CopyAs as)
|
||||
{
|
||||
Entity en = {};
|
||||
|
@ -891,6 +971,7 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||
case Entity::Type::POINT_N_TRANS:
|
||||
case Entity::Type::POINT_N_ROT_TRANS:
|
||||
case Entity::Type::POINT_N_ROT_AA:
|
||||
case Entity::Type::POINT_N_ROT_AXIS_TRANS:
|
||||
case Entity::Type::POINT_IN_3D:
|
||||
case Entity::Type::POINT_IN_2D:
|
||||
if(as == CopyAs::N_TRANS) {
|
||||
|
@ -903,6 +984,8 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||
} else {
|
||||
if(as == CopyAs::N_ROT_AA) {
|
||||
en.type = Entity::Type::POINT_N_ROT_AA;
|
||||
} else if (as == CopyAs::N_ROT_AXIS_TRANS) {
|
||||
en.type = Entity::Type::POINT_N_ROT_AXIS_TRANS;
|
||||
} else {
|
||||
en.type = Entity::Type::POINT_N_ROT_TRANS;
|
||||
}
|
||||
|
@ -913,6 +996,9 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||
en.param[4] = qvx;
|
||||
en.param[5] = qvy;
|
||||
en.param[6] = qvz;
|
||||
if (as == CopyAs::N_ROT_AXIS_TRANS) {
|
||||
en.param[7] = dist;
|
||||
}
|
||||
}
|
||||
en.numPoint = (ep->actPoint).ScaledBy(scale);
|
||||
break;
|
||||
|
@ -924,8 +1010,8 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||
case Entity::Type::NORMAL_IN_2D:
|
||||
if(as == CopyAs::N_TRANS || as == CopyAs::NUMERIC) {
|
||||
en.type = Entity::Type::NORMAL_N_COPY;
|
||||
} else {
|
||||
if(as == CopyAs::N_ROT_AA) {
|
||||
} else { // N_ROT_AXIS_TRANS probably doesn't warrant a new entity Type
|
||||
if(as == CopyAs::N_ROT_AA || as == CopyAs::N_ROT_AXIS_TRANS) {
|
||||
en.type = Entity::Type::NORMAL_N_ROT_AA;
|
||||
} else {
|
||||
en.type = Entity::Type::NORMAL_N_ROT;
|
||||
|
@ -960,7 +1046,7 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
|
|||
} else if (as == CopyAs::NUMERIC) {
|
||||
en.type = Entity::Type::FACE_NORMAL_PT;
|
||||
} else {
|
||||
if(as == CopyAs::N_ROT_AA) {
|
||||
if(as == CopyAs::N_ROT_AA || as == CopyAs::N_ROT_AXIS_TRANS) {
|
||||
en.type = Entity::Type::FACE_N_ROT_AA;
|
||||
} else {
|
||||
en.type = Entity::Type::FACE_N_ROT_TRANS;
|
||||
|
|
|
@ -296,6 +296,7 @@ void Group::GenerateShellAndMesh() {
|
|||
} else if(type == Type::REVOLVE && haveSrc) {
|
||||
Group *src = SK.GetGroup(opA);
|
||||
double anglef = SK.GetParam(h.param(3))->val * 4; // why the 4 is needed?
|
||||
double dists = 0, distf = 0;
|
||||
double angles = 0.0;
|
||||
if(subtype != Subtype::ONE_SIDED) {
|
||||
anglef *= 0.5;
|
||||
|
@ -309,11 +310,34 @@ void Group::GenerateShellAndMesh() {
|
|||
SBezierLoopSet *sbls;
|
||||
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
|
||||
if(fabs(anglef - angles) < 2 * PI) {
|
||||
thisShell.MakeFromHelicalRevolutionOf(sbls, pt, axis, color, this, angles, anglef);
|
||||
thisShell.MakeFromHelicalRevolutionOf(sbls, pt, axis, color, this,
|
||||
angles, anglef, dists, distf);
|
||||
} else {
|
||||
thisShell.MakeFromRevolutionOf(sbls, pt, axis, color, this);
|
||||
}
|
||||
}
|
||||
} else if(type == Type::HELIX && haveSrc) {
|
||||
Group *src = SK.GetGroup(opA);
|
||||
double anglef = SK.GetParam(h.param(3))->val * 4; // why the 4 is needed?
|
||||
double dists = 0, distf = 0;
|
||||
double angles = 0.0;
|
||||
distf = SK.GetParam(h.param(7))->val * 2; // dist is applied twice
|
||||
if(subtype != Subtype::ONE_SIDED) {
|
||||
anglef *= 0.5;
|
||||
angles = -anglef;
|
||||
distf *= 0.5;
|
||||
dists = -distf;
|
||||
}
|
||||
Vector pt = SK.GetEntity(predef.origin)->PointGetNum(),
|
||||
axis = SK.GetEntity(predef.entityB)->VectorGetNum();
|
||||
axis = axis.WithMagnitude(1);
|
||||
|
||||
SBezierLoopSetSet *sblss = &(src->bezierLoops);
|
||||
SBezierLoopSet *sbls;
|
||||
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
|
||||
thisShell.MakeFromHelicalRevolutionOf(sbls, pt, axis, color, this,
|
||||
angles, anglef, dists, distf);
|
||||
}
|
||||
} else if(type == Type::LINKED) {
|
||||
// The imported shell or mesh are copied over, with the appropriate
|
||||
// transformation applied. We also must remap the face entities.
|
||||
|
@ -488,6 +512,7 @@ bool Group::IsMeshGroup() {
|
|||
case Group::Type::EXTRUDE:
|
||||
case Group::Type::LATHE:
|
||||
case Group::Type::REVOLVE:
|
||||
case Group::Type::HELIX:
|
||||
case Group::Type::ROTATE:
|
||||
case Group::Type::TRANSLATE:
|
||||
return true;
|
||||
|
|
|
@ -151,6 +151,7 @@ public:
|
|||
N_TRANS,
|
||||
N_ROT_AA,
|
||||
N_ROT_TRANS,
|
||||
N_ROT_AXIS_TRANS,
|
||||
};
|
||||
|
||||
enum class Type : uint32_t {
|
||||
|
@ -159,6 +160,7 @@ public:
|
|||
EXTRUDE = 5100,
|
||||
LATHE = 5101,
|
||||
REVOLVE = 5102,
|
||||
HELIX = 5103,
|
||||
ROTATE = 5200,
|
||||
TRANSLATE = 5201,
|
||||
LINKED = 5300
|
||||
|
@ -286,7 +288,7 @@ public:
|
|||
void CopyEntity(EntityList *el,
|
||||
Entity *ep, int timesApplied, int remap,
|
||||
hParam dx, hParam dy, hParam dz,
|
||||
hParam qw, hParam qvx, hParam qvy, hParam qvz,
|
||||
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam dist,
|
||||
CopyAs as);
|
||||
|
||||
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
||||
|
@ -387,6 +389,7 @@ public:
|
|||
POINT_N_ROT_TRANS = 2011,
|
||||
POINT_N_COPY = 2012,
|
||||
POINT_N_ROT_AA = 2013,
|
||||
POINT_N_ROT_AXIS_TRANS = 2014,
|
||||
|
||||
NORMAL_IN_3D = 3000,
|
||||
NORMAL_IN_2D = 3001,
|
||||
|
@ -426,7 +429,7 @@ public:
|
|||
hEntity distance;
|
||||
// The only types that have their own params are points, normals,
|
||||
// and directions.
|
||||
hParam param[7];
|
||||
hParam param[8];
|
||||
|
||||
// Transformed points/normals/distances have their numerical base
|
||||
Vector numPoint;
|
||||
|
|
|
@ -606,8 +606,8 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, Rgb
|
|||
}
|
||||
}
|
||||
|
||||
bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis)
|
||||
// Check that the direction of revolution ends up parallel to the normal of
|
||||
bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis, double da, double dx)
|
||||
// Check that the direction of revolution/extrusion ends up parallel to the normal of
|
||||
// the sketch, on the side of the axis where the sketch is.
|
||||
{
|
||||
SBezierLoop *sbl;
|
||||
|
@ -631,9 +631,10 @@ bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector
|
|||
}
|
||||
}
|
||||
Vector ptc = pto.ClosestPointOnLine(pt, axis),
|
||||
up = (pto.Minus(ptc)).WithMagnitude(1),
|
||||
vp = (sbls->normal).Cross(up);
|
||||
return (vp.Dot(axis) < 0);
|
||||
up = axis.Cross(pto.Minus(ptc)).ScaledBy(da),
|
||||
vp = up.Plus(axis.ScaledBy(dx));
|
||||
|
||||
return (vp.Dot(sbls->normal) > 0);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -643,22 +644,19 @@ typedef struct {
|
|||
// sketch must not contain the axis of revolution as a non-construction line for helix
|
||||
void SShell::MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
|
||||
RgbaColor color, Group *group, double angles,
|
||||
double anglef) {
|
||||
double anglef, double dists, double distf) {
|
||||
int i0 = surface.n; // number of pre-existing surfaces
|
||||
SBezierLoop *sbl;
|
||||
// for testing - hard code the axial distance, and number of sections.
|
||||
// distance will need to be parameters in the future.
|
||||
double dist = 0;
|
||||
double dist = distf - dists;
|
||||
int sections = fabs(anglef - angles) / (PI / 2) + 1;
|
||||
if(sections > 99) {
|
||||
sections = 99;
|
||||
}
|
||||
double wedge = (anglef - angles) / sections;
|
||||
|
||||
double dists = 0; // start distance
|
||||
double distf = dist; // finish distance
|
||||
|
||||
if(CheckNormalAxisRelationship(sbls, pt, axis) ^ (wedge < 0)) {
|
||||
if(CheckNormalAxisRelationship(sbls, pt, axis, anglef-angles, distf-dists)) {
|
||||
swap(angles, anglef);
|
||||
swap(dists, distf);
|
||||
dist = -dist;
|
||||
|
@ -821,7 +819,7 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
|
|||
int i0 = surface.n; // number of pre-existing surfaces
|
||||
SBezierLoop *sbl;
|
||||
|
||||
if(CheckNormalAxisRelationship(sbls, pt, axis)) {
|
||||
if(CheckNormalAxisRelationship(sbls, pt, axis, 1.0, 0.0)) {
|
||||
axis = axis.ScaledBy(-1);
|
||||
}
|
||||
|
||||
|
|
|
@ -382,11 +382,11 @@ public:
|
|||
|
||||
void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1,
|
||||
RgbaColor color);
|
||||
bool CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis);
|
||||
bool CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis, double da, double dx);
|
||||
void MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
|
||||
RgbaColor color, Group *group);
|
||||
void MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color,
|
||||
Group *group, double angles, double anglef);
|
||||
Group *group, double angles, double anglef, double dists, double distf);
|
||||
void MakeFirstOrderRevolvedSurfaces(Vector pt, Vector axis, int i0);
|
||||
void MakeFromUnionOf(SShell *a, SShell *b);
|
||||
void MakeFromDifferenceOf(SShell *a, SShell *b);
|
||||
|
|
|
@ -304,11 +304,14 @@ void TextWindow::ShowGroupInfo() {
|
|||
if(g->type == Group::Type::LATHE) {
|
||||
Printf(true, " %Ftlathe plane sketch");
|
||||
} else if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::ROTATE ||
|
||||
g->type == Group::Type::TRANSLATE || g->type == Group::Type::REVOLVE) {
|
||||
g->type == Group::Type::TRANSLATE || g->type == Group::Type::REVOLVE ||
|
||||
g->type == Group::Type::HELIX) {
|
||||
if(g->type == Group::Type::EXTRUDE) {
|
||||
s = "extrude plane sketch";
|
||||
} else if(g->type == Group::Type::TRANSLATE) {
|
||||
s = "translate original sketch";
|
||||
} else if(g->type == Group::Type::HELIX) {
|
||||
s = "create helical extrusion";
|
||||
} else if(g->type == Group::Type::ROTATE) {
|
||||
s = "rotate original sketch";
|
||||
} else if(g->type == Group::Type::REVOLVE) {
|
||||
|
@ -364,7 +367,8 @@ void TextWindow::ShowGroupInfo() {
|
|||
Printf(false, "");
|
||||
|
||||
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
|
||||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED) {
|
||||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED ||
|
||||
g->type == Group::Type::HELIX) {
|
||||
bool un = (g->meshCombine == Group::CombineAs::UNION);
|
||||
bool diff = (g->meshCombine == Group::CombineAs::DIFFERENCE);
|
||||
bool asy = (g->meshCombine == Group::CombineAs::ASSEMBLE);
|
||||
|
@ -384,7 +388,7 @@ void TextWindow::ShowGroupInfo() {
|
|||
(asy ? RADIO_TRUE : RADIO_FALSE));
|
||||
|
||||
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
|
||||
g->type == Group::Type::REVOLVE) {
|
||||
g->type == Group::Type::REVOLVE || g->type == Group::Type::HELIX) {
|
||||
Printf(false,
|
||||
"%Bd %Ftcolor %E%Bz %Bd (%@, %@, %@) %f%D%Lf%Fl[change]%E",
|
||||
&g->color,
|
||||
|
@ -396,7 +400,8 @@ void TextWindow::ShowGroupInfo() {
|
|||
}
|
||||
|
||||
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
|
||||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED) {
|
||||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED ||
|
||||
g->type == Group::Type::HELIX) {
|
||||
Printf(false, " %Fd%f%LP%s suppress this group's solid model",
|
||||
&TextWindow::ScreenChangeGroupOption,
|
||||
g->suppress ? CHECK_TRUE : CHECK_FALSE);
|
||||
|
|
Loading…
Reference in New Issue