Generate primitives for lathe groups.

The primitives that are generated are circles from points and
faces from axis-perpendicular line segments.
pull/4/head
EvilSpirit 2015-10-31 14:22:26 +06:00 committed by whitequark
parent 9c4d1cb9b0
commit 6dced8052b
7 changed files with 130 additions and 5 deletions

View File

@ -366,6 +366,7 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) {
Vector a = SK.GetEntity(point[0])->PointGetNum();
Vector b = SK.GetEntity(point[1])->PointGetNum();
sb = SBezier::From(a, b);
sb.entity = h.v;
sbl->l.Add(&sb);
break;
}

View File

@ -283,7 +283,7 @@ std::string Group::DescriptionString(void) {
}
void Group::Activate(void) {
if(type == EXTRUDE || type == IMPORTED) {
if(type == EXTRUDE || type == IMPORTED || type == LATHE || type == TRANSLATE || type == ROTATE) {
SS.GW.showFaces = true;
} else {
SS.GW.showFaces = false;
@ -390,6 +390,43 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
}
case LATHE: {
Vector axis_pos = SK.GetEntity(predef.origin)->PointGetNum();
Vector axis_dir = SK.GetEntity(predef.entityB)->VectorGetNum();
AddParam(param, h.param(0), axis_dir.x);
AddParam(param, h.param(1), axis_dir.y);
AddParam(param, h.param(2), axis_dir.z);
// Remapped entity index.
int ai = 1;
for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v) continue;
e->CalculateNumerical(false);
hEntity he = e->h;
// As soon as I call CopyEntity, e may become invalid! That
// adds entities, which may cause a realloc.
CopyEntity(entity, SK.GetEntity(predef.origin), 0, ai,
h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true, false);
CopyEntity(entity, SK.GetEntity(he), 0, REMAP_LATHE_START,
h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true, false);
CopyEntity(entity, SK.GetEntity(he), 0, REMAP_LATHE_END,
h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true, false);
MakeLatheCircles(entity, param, he, axis_pos, axis_dir, ai);
ai++;
}
break;
}
@ -600,6 +637,78 @@ void Group::MakeExtrusionLines(IdList<Entity,hEntity> *el, hEntity in) {
}
}
void Group::MakeLatheCircles(IdList<Entity,hEntity> *el, IdList<Param,hParam> *param, hEntity in, Vector pt, Vector axis, int ai) {
Entity *ep = SK.GetEntity(in);
Entity en = {};
if(ep->IsPoint()) {
// A point gets revolved to form an arc.
en.point[0] = Remap(predef.origin, ai);
en.point[1] = Remap(ep->h, REMAP_LATHE_START);
en.point[2] = Remap(ep->h, REMAP_LATHE_END);
// Get arc center and point on arc.
Entity *pc = SK.GetEntity(en.point[0]);
Entity *pp = SK.GetEntity(en.point[1]);
// Project arc point to the revolution axis and use it for arc center.
double k = pp->numPoint.Minus(pt).Dot(axis) / axis.Dot(axis);
pc->numPoint = pt.Plus(axis.ScaledBy(k));
// Create arc entity.
en.group = h;
en.construction = ep->construction;
en.style = ep->style;
en.h = Remap(ep->h, REMAP_PT_TO_ARC);
en.type = Entity::ARC_OF_CIRCLE;
// Generate a normal.
Entity n = {};
n.workplane = en.workplane;
n.h = Remap(ep->h, REMAP_PT_TO_NORMAL);
n.group = en.group;
n.style = en.style;
n.type = Entity::NORMAL_N_COPY;
// Create basis for the normal.
Vector nu = pp->numPoint.Minus(pc->numPoint).WithMagnitude(1.0);
Vector nv = nu.Cross(axis).WithMagnitude(1.0);
n.numNormal = Quaternion::From(nv, nu);
// The point determines where the normal gets displayed on-screen;
// it's entirely cosmetic.
n.point[0] = en.point[0];
el->Add(&n);
en.normal = n.h;
el->Add(&en);
} else if(ep->type == Entity::LINE_SEGMENT) {
// An axis-perpendicular line gets revolved to form a face.
Vector a = SK.GetEntity(ep->point[0])->PointGetNum();
Vector b = SK.GetEntity(ep->point[1])->PointGetNum();
Vector u = b.Minus(a).WithMagnitude(1.0);
// Check for perpendicularity: calculate cosine of the angle
// between axis and line direction and check that
// cos(angle) == 0 <-> angle == +-90 deg.
if(fabs(u.Dot(axis) / axis.Magnitude()) < ANGLE_COS_EPS) {
en.param[0] = h.param(0);
en.param[1] = h.param(1);
en.param[2] = h.param(2);
Vector v = axis.Cross(u).WithMagnitude(1.0);
Vector n = u.Cross(v);
en.numNormal = Quaternion::From(0, n.x, n.y, n.z);
en.group = h;
en.construction = ep->construction;
en.style = ep->style;
en.h = Remap(ep->h, REMAP_LINE_TO_FACE);
en.type = Entity::FACE_NORMAL_PT;
en.point[0] = ep->point[0];
el->Add(&en);
}
}
}
void Group::MakeExtrusionTopBottomFaces(IdList<Entity,hEntity> *el, hEntity pt)
{
if(pt.v == 0) return;

View File

@ -283,7 +283,7 @@ void Group::GenerateShellAndMesh(void) {
SBezierLoopSetSet *sblss = &(src->bezierLoops);
SBezierLoopSet *sbls;
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
thisShell.MakeFromRevolutionOf(sbls, pt, axis, color);
thisShell.MakeFromRevolutionOf(sbls, pt, axis, color, this);
}
} else if(type == IMPORTED) {
// The imported shell or mesh are copied over, with the appropriate

View File

@ -214,10 +214,15 @@ public:
REMAP_TOP = 1001,
REMAP_BOTTOM = 1002,
REMAP_PT_TO_LINE = 1003,
REMAP_LINE_TO_FACE = 1004
REMAP_LINE_TO_FACE = 1004,
REMAP_LATHE_START = 1006,
REMAP_LATHE_END = 1007,
REMAP_PT_TO_ARC = 1008,
REMAP_PT_TO_NORMAL = 1009,
};
hEntity Remap(hEntity in, int copyNumber);
void MakeExtrusionLines(EntityList *el, hEntity in);
void MakeLatheCircles(IdList<Entity,hEntity> *el, IdList<Param,hParam> *param, hEntity in, Vector pt, Vector axis, int ai);
void MakeExtrusionTopBottomFaces(EntityList *el, hEntity pt);
void CopyEntity(EntityList *el,
Entity *ep, int timesApplied, int remap,

View File

@ -94,6 +94,7 @@ inline double ffabs(double v) { return (v > 0) ? v : (-v); }
#define CO(v) (v).x, (v).y, (v).z
#define ANGLE_COS_EPS (1e-6)
#define LENGTH_EPS (1e-6)
#define VERY_POSITIVE (1e10)
#define VERY_NEGATIVE (-1e10)

View File

@ -600,7 +600,7 @@ typedef struct {
hSSurface d[4];
} Revolved;
void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color)
void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color, Group *group)
{
SBezierLoop *sbl;
@ -654,6 +654,14 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
(PI/2)*j,
(PI/2)*(j+1));
ss.color = color;
if(sb->entity != 0) {
hEntity he;
he.v = sb->entity;
hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
if(SK.entity.FindByIdNoOops(hface) != NULL) {
ss.face = hface.v;
}
}
revs.d[j] = surface.AddAndAssignId(&ss);
}
}

View File

@ -77,6 +77,7 @@ public:
int deg;
Vector ctrl[4];
double weight[4];
uint32_t entity;
Vector PointAt(double t);
Vector TangentAt(double t);
@ -363,7 +364,7 @@ public:
void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1,
RgbaColor color);
void MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
RgbaColor color);
RgbaColor color, Group *group);
void MakeFromUnionOf(SShell *a, SShell *b);
void MakeFromDifferenceOf(SShell *a, SShell *b);