Add sin and cos to the expression entry (for dimensions etc.), with
the same precedence as sqrt. Add the code to find naked edges, and draw them highlighted on the model. And make the direction of trim curves consistent, always ccw with normal toward viewer; so there's no need to fix the directions before triangulating. [git-p4: depot-paths = "//depot/solvespace/": change = 1903]solver
parent
bb4b767e99
commit
2e4ec6dd04
11
draw.cpp
11
draw.cpp
|
@ -1021,6 +1021,17 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
|
// And the naked edges, if the user did Analyze -> Show Naked Edges.
|
||||||
|
glLineWidth(7);
|
||||||
|
glEnable(GL_LINE_STIPPLE);
|
||||||
|
glLineStipple(4, 0x5555);
|
||||||
|
glColor3d(1, 0, 0);
|
||||||
|
glxDrawEdges(&(SS.nakedEdges));
|
||||||
|
glLineStipple(4, 0xaaaa);
|
||||||
|
glColor3d(0, 0, 0);
|
||||||
|
glxDrawEdges(&(SS.nakedEdges));
|
||||||
|
glDisable(GL_LINE_STIPPLE);
|
||||||
|
|
||||||
// Then redraw whatever the mouse is hovering over, highlighted.
|
// Then redraw whatever the mouse is hovering over, highlighted.
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glxLockColorTo(1, 1, 0);
|
glxLockColorTo(1, 1, 0);
|
||||||
|
|
|
@ -88,7 +88,7 @@ void SolveSpace::ExportSectionTo(char *filename) {
|
||||||
SKdNode *root = SKdNode::From(&m);
|
SKdNode *root = SKdNode::From(&m);
|
||||||
SEdgeList el;
|
SEdgeList el;
|
||||||
ZERO(&el);
|
ZERO(&el);
|
||||||
root->MakeCertainEdgesInto(&el, false);
|
root->MakeNakedEdgesInto(&el);
|
||||||
// Assemble those edges into a polygon, and clear the edge list
|
// Assemble those edges into a polygon, and clear the edge list
|
||||||
el.AssemblePolygon(&sp, NULL);
|
el.AssemblePolygon(&sp, NULL);
|
||||||
el.Clear();
|
el.Clear();
|
||||||
|
|
12
expr.cpp
12
expr.cpp
|
@ -598,7 +598,9 @@ int Expr::Precedence(Expr *e) {
|
||||||
if(e->op != BINARY_OP && e->op != UNARY_OP) oops();
|
if(e->op != BINARY_OP && e->op != UNARY_OP) oops();
|
||||||
|
|
||||||
switch(e->x.c) {
|
switch(e->x.c) {
|
||||||
|
case 'q':
|
||||||
case 's':
|
case 's':
|
||||||
|
case 'c':
|
||||||
case 'n': return 30;
|
case 'n': return 30;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
|
@ -629,7 +631,9 @@ c:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': n = PopOperand()->Negate(); break;
|
case 'n': n = PopOperand()->Negate(); break;
|
||||||
case 's': n = PopOperand()->Sqrt(); break;
|
case 'q': n = PopOperand()->Sqrt(); break;
|
||||||
|
case 's': n = (PopOperand()->Times(Expr::From(PI/180)))->Sin(); break;
|
||||||
|
case 'c': n = (PopOperand()->Times(Expr::From(PI/180)))->Cos(); break;
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
|
@ -721,6 +725,12 @@ void Expr::Lex(char *in) {
|
||||||
|
|
||||||
Expr *e = AllocExpr();
|
Expr *e = AllocExpr();
|
||||||
if(strcmp(name, "sqrt")==0) {
|
if(strcmp(name, "sqrt")==0) {
|
||||||
|
e->op = UNARY_OP;
|
||||||
|
e->x.c = 'q';
|
||||||
|
} else if(strcmp(name, "cos")==0) {
|
||||||
|
e->op = UNARY_OP;
|
||||||
|
e->x.c = 'c';
|
||||||
|
} else if(strcmp(name, "sin")==0) {
|
||||||
e->op = UNARY_OP;
|
e->op = UNARY_OP;
|
||||||
e->x.c = 's';
|
e->x.c = 's';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -295,14 +295,9 @@ void glxDebugPolygon(SPolygon *p)
|
||||||
|
|
||||||
void glxDrawEdges(SEdgeList *el)
|
void glxDrawEdges(SEdgeList *el)
|
||||||
{
|
{
|
||||||
int i;
|
SEdge *se;
|
||||||
glLineWidth(1);
|
|
||||||
glxDepthRangeOffset(2);
|
|
||||||
glxColor3d(REDf(SS.edgeColor), GREENf(SS.edgeColor), BLUEf(SS.edgeColor));
|
|
||||||
|
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
for(i = 0; i < el->l.n; i++) {
|
for(se = el->l.First(); se; se = el->l.NextAfter(se)) {
|
||||||
SEdge *se = &(el->l.elem[i]);
|
|
||||||
glxVertex3v(se->a);
|
glxVertex3v(se->a);
|
||||||
glxVertex3v(se->b);
|
glxVertex3v(se->b);
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,6 +558,7 @@ void GraphicsWindow::MenuEdit(int id) {
|
||||||
}
|
}
|
||||||
SS.GW.ClearSuper();
|
SS.GW.ClearSuper();
|
||||||
HideTextEditControl();
|
HideTextEditControl();
|
||||||
|
SS.nakedEdges.Clear();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MNU_DELETE: {
|
case MNU_DELETE: {
|
||||||
|
|
|
@ -87,7 +87,6 @@ void Group::GenerateShellForStepAndRepeat(void) {
|
||||||
|
|
||||||
void Group::GenerateShellAndMesh(void) {
|
void Group::GenerateShellAndMesh(void) {
|
||||||
thisShell.Clear();
|
thisShell.Clear();
|
||||||
STriMeta meta = { 0, color };
|
|
||||||
|
|
||||||
if(type == TRANSLATE || type == ROTATE) {
|
if(type == TRANSLATE || type == ROTATE) {
|
||||||
GenerateShellForStepAndRepeat();
|
GenerateShellForStepAndRepeat();
|
||||||
|
@ -105,7 +104,7 @@ void Group::GenerateShellAndMesh(void) {
|
||||||
tbot = translate.ScaledBy(-1); ttop = translate.ScaledBy(1);
|
tbot = translate.ScaledBy(-1); ttop = translate.ScaledBy(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
thisShell.MakeFromExtrusionOf(&(src->bezierLoopSet), tbot, ttop);
|
thisShell.MakeFromExtrusionOf(&(src->bezierLoopSet), tbot, ttop, color);
|
||||||
} else if(type == LATHE) {
|
} else if(type == LATHE) {
|
||||||
Group *src = SS.GetGroup(opA);
|
Group *src = SS.GetGroup(opA);
|
||||||
|
|
||||||
|
@ -223,6 +222,11 @@ void Group::Draw(void) {
|
||||||
glxFillMesh(specColor, &runningMesh, mh, ms1, ms2);
|
glxFillMesh(specColor, &runningMesh, mh, ms1, ms2);
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glLineWidth(1);
|
||||||
|
glxDepthRangeOffset(2);
|
||||||
|
glxColor3d(REDf (SS.edgeColor),
|
||||||
|
GREENf(SS.edgeColor),
|
||||||
|
BLUEf (SS.edgeColor));
|
||||||
glxDrawEdges(&emphEdges);
|
glxDrawEdges(&emphEdges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
58
mesh.cpp
58
mesh.cpp
|
@ -476,21 +476,19 @@ void SKdNode::MakeMeshInto(SMesh *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int *nOther,
|
void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int cnt) {
|
||||||
STriMeta m, int cnt)
|
|
||||||
{
|
|
||||||
if(gt && lt) {
|
if(gt && lt) {
|
||||||
double ac = a.Element(which),
|
double ac = a.Element(which),
|
||||||
bc = b.Element(which);
|
bc = b.Element(which);
|
||||||
if(ac < c + KDTREE_EPS ||
|
if(ac < c + KDTREE_EPS ||
|
||||||
bc < c + KDTREE_EPS)
|
bc < c + KDTREE_EPS)
|
||||||
{
|
{
|
||||||
lt->FindEdgeOn(a, b, n, nOther, m, cnt);
|
lt->FindEdgeOn(a, b, n, cnt);
|
||||||
}
|
}
|
||||||
if(ac > c - KDTREE_EPS ||
|
if(ac > c - KDTREE_EPS ||
|
||||||
bc > c - KDTREE_EPS)
|
bc > c - KDTREE_EPS)
|
||||||
{
|
{
|
||||||
gt->FindEdgeOn(a, b, n, nOther, m, cnt);
|
gt->FindEdgeOn(a, b, n, cnt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
STriangleLl *ll;
|
STriangleLl *ll;
|
||||||
|
@ -499,43 +497,20 @@ void SKdNode::FindEdgeOn(Vector a, Vector b, int *n, int *nOther,
|
||||||
|
|
||||||
if(tr->tag == cnt) continue;
|
if(tr->tag == cnt) continue;
|
||||||
|
|
||||||
if((a.Equals(tr->b, KDTREE_EPS) && b.Equals(tr->a, KDTREE_EPS)) ||
|
if((a.Equals(tr->b) && b.Equals(tr->a)) ||
|
||||||
(a.Equals(tr->c, KDTREE_EPS) && b.Equals(tr->b, KDTREE_EPS)) ||
|
(a.Equals(tr->c) && b.Equals(tr->b)) ||
|
||||||
(a.Equals(tr->a, KDTREE_EPS) && b.Equals(tr->c, KDTREE_EPS)))
|
(a.Equals(tr->a) && b.Equals(tr->c)))
|
||||||
{
|
{
|
||||||
(*n)++;
|
(*n)++;
|
||||||
if(tr->meta.face != m.face) {
|
|
||||||
if(tr->meta.color == m.color &&
|
|
||||||
tr->meta.face != 0 && m.face != 0)
|
|
||||||
{
|
|
||||||
hEntity hf0 = { tr->meta.face },
|
|
||||||
hf1 = { m.face };
|
|
||||||
Entity *f0 = SS.GetEntity(hf0),
|
|
||||||
*f1 = SS.GetEntity(hf1);
|
|
||||||
|
|
||||||
Vector n0 = f0->FaceGetNormalNum().WithMagnitude(1),
|
|
||||||
n1 = f1->FaceGetNormalNum().WithMagnitude(1);
|
|
||||||
|
|
||||||
if(n0.Equals(n1) || n0.Equals(n1.ScaledBy(-1))) {
|
|
||||||
// faces are coincident, skip
|
|
||||||
// (If the planes are parallel, and the edge
|
|
||||||
// lies in both planes, then they're also
|
|
||||||
// coincident.)
|
|
||||||
} else {
|
|
||||||
(*nOther)++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(*nOther)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Ensure that we don't count this triangle twice if it appears
|
||||||
|
// in two buckets of the kd tree.
|
||||||
tr->tag = cnt;
|
tr->tag = cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SKdNode::MakeCertainEdgesInto(SEdgeList *sel, bool emphasized) {
|
void SKdNode::MakeNakedEdgesInto(SEdgeList *sel) {
|
||||||
SMesh m;
|
SMesh m;
|
||||||
ZERO(&m);
|
ZERO(&m);
|
||||||
ClearTags();
|
ClearTags();
|
||||||
|
@ -551,20 +526,11 @@ void SKdNode::MakeCertainEdgesInto(SEdgeList *sel, bool emphasized) {
|
||||||
Vector b = (j == 0) ? tr->b : ((j == 1) ? tr->c : tr->a);
|
Vector b = (j == 0) ? tr->b : ((j == 1) ? tr->c : tr->a);
|
||||||
|
|
||||||
int n = 0, nOther = 0;
|
int n = 0, nOther = 0;
|
||||||
FindEdgeOn(a, b, &n, &nOther, tr->meta, cnt++);
|
FindEdgeOn(a, b, &n, cnt);
|
||||||
if(n != 1) {
|
if(n != 1) {
|
||||||
if(!emphasized) {
|
sel->AddEdge(a, b);
|
||||||
if(n == 0 && (a.Minus(b).Magnitude()) > KDTREE_EPS) {
|
|
||||||
sel->AddEdge(a, b);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// dbp("hanging: n=%d (%.3f %.3f %.3f) (%.3f %.3f %.3f)",
|
|
||||||
// n, CO(a), CO(b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(nOther > 0) {
|
|
||||||
if(emphasized) sel->AddEdge(a, b);
|
|
||||||
}
|
}
|
||||||
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
polygon.cpp
14
polygon.cpp
|
@ -68,8 +68,8 @@ void SEdgeList::AddEdge(Vector a, Vector b) {
|
||||||
l.Add(&e);
|
l.Add(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SEdgeList::AssembleContour(Vector first, Vector last,
|
bool SEdgeList::AssembleContour(Vector first, Vector last, SContour *dest,
|
||||||
SContour *dest, SEdge *errorAt)
|
SEdge *errorAt, bool keepDir)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -87,7 +87,8 @@ bool SEdgeList::AssembleContour(Vector first, Vector last,
|
||||||
se->tag = 1;
|
se->tag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(se->b.Equals(last)) {
|
// Don't allow backwards edges if keepDir is true.
|
||||||
|
if(!keepDir && se->b.Equals(last)) {
|
||||||
dest->AddPoint(se->a);
|
dest->AddPoint(se->a);
|
||||||
last = se->a;
|
last = se->a;
|
||||||
se->tag = 1;
|
se->tag = 1;
|
||||||
|
@ -108,7 +109,7 @@ bool SEdgeList::AssembleContour(Vector first, Vector last,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt) {
|
bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt, bool keepDir) {
|
||||||
dest->Clear();
|
dest->Clear();
|
||||||
|
|
||||||
bool allClosed = true;
|
bool allClosed = true;
|
||||||
|
@ -130,8 +131,11 @@ bool SEdgeList::AssemblePolygon(SPolygon *dest, SEdge *errorAt) {
|
||||||
// Create a new empty contour in our polygon, and finish assembling
|
// Create a new empty contour in our polygon, and finish assembling
|
||||||
// into that contour.
|
// into that contour.
|
||||||
dest->AddEmptyContour();
|
dest->AddEmptyContour();
|
||||||
if(!AssembleContour(first, last, &(dest->l.elem[dest->l.n-1]), errorAt))
|
if(!AssembleContour(first, last, &(dest->l.elem[dest->l.n-1]),
|
||||||
|
errorAt, keepDir))
|
||||||
|
{
|
||||||
allClosed = false;
|
allClosed = false;
|
||||||
|
}
|
||||||
// But continue assembling, even if some of the contours are open
|
// But continue assembling, even if some of the contours are open
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ public:
|
||||||
|
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
void AddEdge(Vector a, Vector b);
|
void AddEdge(Vector a, Vector b);
|
||||||
bool AssemblePolygon(SPolygon *dest, SEdge *errorAt);
|
bool AssemblePolygon(SPolygon *dest, SEdge *errorAt, bool keepDir=false);
|
||||||
bool AssembleContour(Vector first, Vector last, SContour *dest,
|
bool AssembleContour(Vector first, Vector last, SContour *dest,
|
||||||
SEdge *errorAt);
|
SEdge *errorAt, bool keepDir);
|
||||||
int AnyEdgeCrossings(Vector a, Vector b, Vector *pi=NULL);
|
int AnyEdgeCrossings(Vector a, Vector b, Vector *pi=NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,9 +218,8 @@ public:
|
||||||
void MakeMeshInto(SMesh *m);
|
void MakeMeshInto(SMesh *m);
|
||||||
void ClearTags(void);
|
void ClearTags(void);
|
||||||
|
|
||||||
void FindEdgeOn(Vector a, Vector b, int *n, int *nOther,
|
void FindEdgeOn(Vector a, Vector b, int *n, int cnt);
|
||||||
STriMeta m, int cnt);
|
void MakeNakedEdgesInto(SEdgeList *sel);
|
||||||
void MakeCertainEdgesInto(SEdgeList *sel, bool emphasized);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -183,6 +183,8 @@ void SolveSpace::AfterNewFile(void) {
|
||||||
// Clear out the traced point, which is no longer valid
|
// Clear out the traced point, which is no longer valid
|
||||||
traced.point = Entity::NO_ENTITY;
|
traced.point = Entity::NO_ENTITY;
|
||||||
traced.path.l.Clear();
|
traced.path.l.Clear();
|
||||||
|
// and the naked edges
|
||||||
|
nakedEdges.Clear();
|
||||||
|
|
||||||
ReloadAllImported();
|
ReloadAllImported();
|
||||||
GenerateAll(-1, -1);
|
GenerateAll(-1, -1);
|
||||||
|
@ -400,6 +402,20 @@ void SolveSpace::MenuAnalyze(int id) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GraphicsWindow::MNU_NAKED_EDGES: {
|
case GraphicsWindow::MNU_NAKED_EDGES: {
|
||||||
|
SS.nakedEdges.Clear();
|
||||||
|
|
||||||
|
SMesh *m = &(SS.GetGroup(SS.GW.activeGroup)->runningMesh);
|
||||||
|
SKdNode *root = SKdNode::From(m);
|
||||||
|
root->MakeNakedEdgesInto(&(SS.nakedEdges));
|
||||||
|
InvalidateGraphics();
|
||||||
|
|
||||||
|
if(SS.nakedEdges.l.n == 0) {
|
||||||
|
Error("Zero naked edges; the model is watertight. "
|
||||||
|
"An exported STL file will be valid.");
|
||||||
|
} else {
|
||||||
|
Error("Found %d naked edges, now highlighted.",
|
||||||
|
SS.nakedEdges.l.n);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -471,6 +471,7 @@ public:
|
||||||
SContour path;
|
SContour path;
|
||||||
hEntity point;
|
hEntity point;
|
||||||
} traced;
|
} traced;
|
||||||
|
SEdgeList nakedEdges;
|
||||||
|
|
||||||
void MarkGroupDirty(hGroup hg);
|
void MarkGroupDirty(hGroup hg);
|
||||||
void MarkGroupDirtyByEntity(hEntity he);
|
void MarkGroupDirtyByEntity(hEntity he);
|
||||||
|
|
|
@ -320,13 +320,21 @@ void SCurve::Clear(void) {
|
||||||
pts.Clear();
|
pts.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc) {
|
STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool backwards) {
|
||||||
STrimBy stb;
|
STrimBy stb;
|
||||||
ZERO(&stb);
|
ZERO(&stb);
|
||||||
stb.curve = hsc;
|
stb.curve = hsc;
|
||||||
SCurve *sc = shell->curve.FindById(hsc);
|
SCurve *sc = shell->curve.FindById(hsc);
|
||||||
stb.start = sc->pts.elem[0];
|
|
||||||
stb.finish = sc->pts.elem[sc->pts.n - 1];
|
if(backwards) {
|
||||||
|
stb.finish = sc->pts.elem[0];
|
||||||
|
stb.start = sc->pts.elem[sc->pts.n - 1];
|
||||||
|
stb.backwards = true;
|
||||||
|
} else {
|
||||||
|
stb.start = sc->pts.elem[0];
|
||||||
|
stb.finish = sc->pts.elem[sc->pts.n - 1];
|
||||||
|
stb.backwards = false;
|
||||||
|
}
|
||||||
|
|
||||||
return stb;
|
return stb;
|
||||||
}
|
}
|
||||||
|
@ -377,6 +385,8 @@ SSurface SSurface::FromTransformationOf(SSurface *a, Vector t, Quaternion q,
|
||||||
ZERO(&ret);
|
ZERO(&ret);
|
||||||
|
|
||||||
ret.h = a->h;
|
ret.h = a->h;
|
||||||
|
ret.color = a->color;
|
||||||
|
ret.face = a->face;
|
||||||
|
|
||||||
ret.degm = a->degm;
|
ret.degm = a->degm;
|
||||||
ret.degn = a->degn;
|
ret.degn = a->degn;
|
||||||
|
@ -511,9 +521,20 @@ void SSurface::MakeEdgesInto(SShell *shell, SEdgeList *sel, bool asUv) {
|
||||||
|
|
||||||
Vector prev, prevuv, ptuv;
|
Vector prev, prevuv, ptuv;
|
||||||
bool inCurve = false;
|
bool inCurve = false;
|
||||||
Vector *pt;
|
|
||||||
double u = 0, v = 0;
|
double u = 0, v = 0;
|
||||||
for(pt = sc->pts.First(); pt; pt = sc->pts.NextAfter(pt)) {
|
|
||||||
|
int i, first, last, increment;
|
||||||
|
if(stb->backwards) {
|
||||||
|
first = sc->pts.n - 1;
|
||||||
|
last = 0;
|
||||||
|
increment = -1;
|
||||||
|
} else {
|
||||||
|
first = 0;
|
||||||
|
last = sc->pts.n - 1;
|
||||||
|
increment = 1;
|
||||||
|
}
|
||||||
|
for(i = first; i != (last + increment); i += increment) {
|
||||||
|
Vector *pt = &(sc->pts.elem[i]);
|
||||||
if(asUv) {
|
if(asUv) {
|
||||||
ClosestPointTo(*pt, &u, &v);
|
ClosestPointTo(*pt, &u, &v);
|
||||||
ptuv = Vector::From(u, v, 0);
|
ptuv = Vector::From(u, v, 0);
|
||||||
|
@ -542,14 +563,14 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
|
||||||
|
|
||||||
SPolygon poly;
|
SPolygon poly;
|
||||||
ZERO(&poly);
|
ZERO(&poly);
|
||||||
if(!el.AssemblePolygon(&poly, NULL)) {
|
if(!el.AssemblePolygon(&poly, NULL, true)) {
|
||||||
dbp("failed to assemble polygon to trim nurbs surface in uv space");
|
dbp("failed to assemble polygon to trim nurbs surface in uv space");
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, start = sm->l.n;
|
int i, start = sm->l.n;
|
||||||
poly.UvTriangulateInto(sm);
|
poly.UvTriangulateInto(sm);
|
||||||
|
|
||||||
STriMeta meta = { 0, 0x888888 };
|
STriMeta meta = { face, color };
|
||||||
for(i = start; i < sm->l.n; i++) {
|
for(i = start; i < sm->l.n; i++) {
|
||||||
STriangle *st = &(sm->l.elem[i]);
|
STriangle *st = &(sm->l.elem[i]);
|
||||||
st->meta = meta;
|
st->meta = meta;
|
||||||
|
@ -559,10 +580,9 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
|
||||||
st->a = PointAt(st->a.x, st->a.y);
|
st->a = PointAt(st->a.x, st->a.y);
|
||||||
st->b = PointAt(st->b.x, st->b.y);
|
st->b = PointAt(st->b.x, st->b.y);
|
||||||
st->c = PointAt(st->c.x, st->c.y);
|
st->c = PointAt(st->c.x, st->c.y);
|
||||||
if((st->Normal()).Dot(st->an) < 0) {
|
// Works out that my chosen contour direction is inconsistent with
|
||||||
// Have to get the vertices in the right order
|
// the triangle direction, sigh.
|
||||||
st->FlipNormal();
|
st->FlipNormal();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
el.Clear();
|
el.Clear();
|
||||||
|
@ -573,7 +593,9 @@ void SSurface::Clear(void) {
|
||||||
trim.Clear();
|
trim.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1,
|
||||||
|
int color)
|
||||||
|
{
|
||||||
ZERO(this);
|
ZERO(this);
|
||||||
|
|
||||||
// Make the extrusion direction consistent with respect to the normal
|
// Make the extrusion direction consistent with respect to the normal
|
||||||
|
@ -586,7 +608,9 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
// planes.
|
// planes.
|
||||||
SSurface s0, s1;
|
SSurface s0, s1;
|
||||||
s0 = SSurface::FromPlane(sbls->point.Plus(t0), sbls->normal.ScaledBy(-1));
|
s0 = SSurface::FromPlane(sbls->point.Plus(t0), sbls->normal.ScaledBy(-1));
|
||||||
|
s0.color = color;
|
||||||
s1 = SSurface::FromPlane(sbls->point.Plus(t1), sbls->normal.ScaledBy( 1));
|
s1 = SSurface::FromPlane(sbls->point.Plus(t1), sbls->normal.ScaledBy( 1));
|
||||||
|
s1.color = color;
|
||||||
hSSurface hs0 = surface.AddAndAssignId(&s0),
|
hSSurface hs0 = surface.AddAndAssignId(&s0),
|
||||||
hs1 = surface.AddAndAssignId(&s1);
|
hs1 = surface.AddAndAssignId(&s1);
|
||||||
|
|
||||||
|
@ -598,7 +622,7 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
SBezier *sb;
|
SBezier *sb;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
STrimBy trim;
|
hSCurve hc;
|
||||||
hSSurface hs;
|
hSSurface hs;
|
||||||
} TrimLine;
|
} TrimLine;
|
||||||
List<TrimLine> trimLines;
|
List<TrimLine> trimLines;
|
||||||
|
@ -608,6 +632,7 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
// Generate the surface of extrusion of this curve, and add
|
// Generate the surface of extrusion of this curve, and add
|
||||||
// it to the list
|
// it to the list
|
||||||
SSurface ss = SSurface::FromExtrusionOf(sb, t0, t1);
|
SSurface ss = SSurface::FromExtrusionOf(sb, t0, t1);
|
||||||
|
ss.color = color;
|
||||||
hSSurface hsext = surface.AddAndAssignId(&ss);
|
hSSurface hsext = surface.AddAndAssignId(&ss);
|
||||||
|
|
||||||
// Translate the curve by t0 and t1 to produce two trim curves
|
// Translate the curve by t0 and t1 to produce two trim curves
|
||||||
|
@ -615,19 +640,21 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
ZERO(&sc);
|
ZERO(&sc);
|
||||||
sb->MakePwlInto(&(sc.pts), t0);
|
sb->MakePwlInto(&(sc.pts), t0);
|
||||||
hSCurve hc0 = curve.AddAndAssignId(&sc);
|
hSCurve hc0 = curve.AddAndAssignId(&sc);
|
||||||
STrimBy stb0 = STrimBy::EntireCurve(this, hc0);
|
STrimBy stb0 = STrimBy::EntireCurve(this, hc0, false);
|
||||||
|
|
||||||
ZERO(&sc);
|
ZERO(&sc);
|
||||||
sb->MakePwlInto(&(sc.pts), t1);
|
sb->MakePwlInto(&(sc.pts), t1);
|
||||||
hSCurve hc1 = curve.AddAndAssignId(&sc);
|
hSCurve hc1 = curve.AddAndAssignId(&sc);
|
||||||
STrimBy stb1 = STrimBy::EntireCurve(this, hc1);
|
STrimBy stb1 = STrimBy::EntireCurve(this, hc1, true);
|
||||||
|
|
||||||
// The translated curves trim the flat top and bottom surfaces.
|
// The translated curves trim the flat top and bottom surfaces.
|
||||||
(surface.FindById(hs0))->trim.Add(&stb0);
|
(surface.FindById(hs0))->trim.Add(&stb0);
|
||||||
(surface.FindById(hs1))->trim.Add(&stb1);
|
(surface.FindById(hs1))->trim.Add(&stb1);
|
||||||
|
|
||||||
// The translated curves also trim the surface of extrusion.
|
// The translated curves also trim the surface of extrusion.
|
||||||
|
stb0 = STrimBy::EntireCurve(this, hc0, true);
|
||||||
(surface.FindById(hsext))->trim.Add(&stb0);
|
(surface.FindById(hsext))->trim.Add(&stb0);
|
||||||
|
stb1 = STrimBy::EntireCurve(this, hc1, false);
|
||||||
(surface.FindById(hsext))->trim.Add(&stb1);
|
(surface.FindById(hsext))->trim.Add(&stb1);
|
||||||
|
|
||||||
// And form the trim line
|
// And form the trim line
|
||||||
|
@ -639,7 +666,7 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
hSCurve hl = curve.AddAndAssignId(&sc);
|
hSCurve hl = curve.AddAndAssignId(&sc);
|
||||||
// save this for later
|
// save this for later
|
||||||
TrimLine tl;
|
TrimLine tl;
|
||||||
tl.trim = STrimBy::EntireCurve(this, hl);
|
tl.hc = hl;
|
||||||
tl.hs = hsext;
|
tl.hs = hsext;
|
||||||
trimLines.Add(&tl);
|
trimLines.Add(&tl);
|
||||||
}
|
}
|
||||||
|
@ -651,8 +678,11 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1) {
|
||||||
|
|
||||||
TrimLine *tlp = &(trimLines.elem[WRAP(i-1, trimLines.n)]);
|
TrimLine *tlp = &(trimLines.elem[WRAP(i-1, trimLines.n)]);
|
||||||
|
|
||||||
ss->trim.Add(&(tl->trim));
|
STrimBy stb;
|
||||||
ss->trim.Add(&(tlp->trim));
|
stb = STrimBy::EntireCurve(this, tl->hc, true);
|
||||||
|
ss->trim.Add(&stb);
|
||||||
|
stb = STrimBy::EntireCurve(this, tlp->hc, false);
|
||||||
|
ss->trim.Add(&stb);
|
||||||
}
|
}
|
||||||
trimLines.Clear();
|
trimLines.Clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,11 +97,14 @@ public:
|
||||||
class STrimBy {
|
class STrimBy {
|
||||||
public:
|
public:
|
||||||
hSCurve curve;
|
hSCurve curve;
|
||||||
|
bool backwards;
|
||||||
|
// If a trim runs backwards, then start and finish still correspond to
|
||||||
|
// the actual start and finish, but they appear in reverse order in
|
||||||
|
// the referenced curve.
|
||||||
Vector start;
|
Vector start;
|
||||||
Vector finish;
|
Vector finish;
|
||||||
Vector out;
|
|
||||||
|
|
||||||
static STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc);
|
static STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool bkwds);
|
||||||
};
|
};
|
||||||
|
|
||||||
// A rational polynomial surface in Bezier form.
|
// A rational polynomial surface in Bezier form.
|
||||||
|
@ -109,6 +112,9 @@ class SSurface {
|
||||||
public:
|
public:
|
||||||
hSSurface h;
|
hSSurface h;
|
||||||
|
|
||||||
|
int color;
|
||||||
|
DWORD face;
|
||||||
|
|
||||||
int degm, degn;
|
int degm, degn;
|
||||||
Vector ctrl[4][4];
|
Vector ctrl[4][4];
|
||||||
double weight[4][4];
|
double weight[4][4];
|
||||||
|
@ -136,7 +142,8 @@ public:
|
||||||
IdList<SCurve,hSCurve> curve;
|
IdList<SCurve,hSCurve> curve;
|
||||||
IdList<SSurface,hSSurface> surface;
|
IdList<SSurface,hSSurface> surface;
|
||||||
|
|
||||||
void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1);
|
void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1,
|
||||||
|
int color);
|
||||||
void MakeFromUnionOf(SShell *a, SShell *b);
|
void MakeFromUnionOf(SShell *a, SShell *b);
|
||||||
void MakeFromDifferenceOf(SShell *a, SShell *b);
|
void MakeFromDifferenceOf(SShell *a, SShell *b);
|
||||||
void MakeFromCopyOf(SShell *a);
|
void MakeFromCopyOf(SShell *a);
|
||||||
|
|
|
@ -51,7 +51,7 @@ void SPolygon::UvTriangulateInto(SMesh *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbp("finished finding holes: %d ms", GetMilliseconds() - in);
|
// dbp("finished finding holes: %d ms", GetMilliseconds() - in);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
double xmin = 1e10;
|
double xmin = 1e10;
|
||||||
SContour *scmin = NULL;
|
SContour *scmin = NULL;
|
||||||
|
@ -70,13 +70,13 @@ void SPolygon::UvTriangulateInto(SMesh *m) {
|
||||||
dbp("couldn't merge our hole");
|
dbp("couldn't merge our hole");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dbp(" bridged to contour: %d ms", GetMilliseconds() - in);
|
// dbp(" bridged to contour: %d ms", GetMilliseconds() - in);
|
||||||
scmin->tag = 3;
|
scmin->tag = 3;
|
||||||
}
|
}
|
||||||
dbp("finished merging holes: %d ms", GetMilliseconds() - in);
|
// dbp("finished merging holes: %d ms", GetMilliseconds() - in);
|
||||||
|
|
||||||
merged.UvTriangulateInto(m);
|
merged.UvTriangulateInto(m);
|
||||||
dbp("finished ear clippping: %d ms", GetMilliseconds() - in);
|
// dbp("finished ear clippping: %d ms", GetMilliseconds() - in);
|
||||||
merged.l.Clear();
|
merged.l.Clear();
|
||||||
el.Clear();
|
el.Clear();
|
||||||
vl.Clear();
|
vl.Clear();
|
||||||
|
|
Loading…
Reference in New Issue