Make the piecewise linear stuff for cubics and quadratics adaptive,
based on a chord tolerance. And rewrite the pwl circles to work against a chord tolerance too (which they really were doing before, but in funny units). Also make "assemble" combine type do a union after interference checking; was previously just copying, which meant that coplanar faces could break subsequent operations. And make right-clicking effectively toggle shift key, instead of forcing it on; so you can pan or rotate with either right or middle button. [git-p4: depot-paths = "//depot/solvespace/": change = 1829]
This commit is contained in:
parent
6852b4134f
commit
7622534b2a
2
draw.cpp
2
draw.cpp
|
@ -22,7 +22,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
if(GraphicsEditControlIsVisible()) return;
|
if(GraphicsEditControlIsVisible()) return;
|
||||||
if(rightDown) {
|
if(rightDown) {
|
||||||
middleDown = true;
|
middleDown = true;
|
||||||
shiftDown = true;
|
shiftDown = !shiftDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point2d mp = { x, y };
|
Point2d mp = { x, y };
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
// Draw lines from active group in front of those from previous
|
// Draw lines from active group in front of those from previous
|
||||||
glxDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 2);
|
glxDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 3);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
glxVertex3v(a);
|
glxVertex3v(a);
|
||||||
glxVertex3v(b);
|
glxVertex3v(b);
|
||||||
|
@ -132,6 +132,41 @@ bool Entity::IsVisible(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector Entity::BezierEval(double t, Vector p0, Vector p1, Vector p2, Vector p3)
|
||||||
|
{
|
||||||
|
return (p0.ScaledBy((1 - t)*(1 - t)*(1 - t))).Plus(
|
||||||
|
(p1.ScaledBy(3*t*(1 - t)*(1 - t))).Plus(
|
||||||
|
(p2.ScaledBy(3*t*t*(1 - t))).Plus(
|
||||||
|
(p3.ScaledBy(t*t*t)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::BezierPwl(double ta, double tb,
|
||||||
|
Vector p0, Vector p1, Vector p2, Vector p3)
|
||||||
|
{
|
||||||
|
Vector pa = BezierEval(ta, p0, p1, p2, p3);
|
||||||
|
Vector pb = BezierEval(tb, p0, p1, p2, p3);
|
||||||
|
|
||||||
|
double tm1 = (2*ta + tb) / 3;
|
||||||
|
double tm2 = (ta + 2*tb) / 3;
|
||||||
|
|
||||||
|
Vector pm1 = BezierEval(tm1, p0, p1, p2, p3);
|
||||||
|
Vector pm2 = BezierEval(tm2, p0, p1, p2, p3);
|
||||||
|
|
||||||
|
double d = max(pm1.DistanceToLine(pa, pb.Minus(pa)),
|
||||||
|
pm2.DistanceToLine(pa, pb.Minus(pa)));
|
||||||
|
|
||||||
|
double tol = 0.5*SS.chordTol/SS.GW.scale;
|
||||||
|
|
||||||
|
if((tb - ta) < 0.05 || d < tol) {
|
||||||
|
LineDrawOrGetDistanceOrEdge(pa, pb);
|
||||||
|
} else {
|
||||||
|
double tm = (ta + tb) / 2;
|
||||||
|
BezierPwl(ta, tm, p0, p1, p2, p3);
|
||||||
|
BezierPwl(tm, tb, p0, p1, p2, p3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Entity::DrawOrGetDistance(void) {
|
void Entity::DrawOrGetDistance(void) {
|
||||||
// If an entity is invisible, then it doesn't get shown, and it doesn't
|
// If an entity is invisible, then it doesn't get shown, and it doesn't
|
||||||
// contribute a distance for the selection, but it still generates edges.
|
// contribute a distance for the selection, but it still generates edges.
|
||||||
|
@ -301,18 +336,7 @@ void Entity::DrawOrGetDistance(void) {
|
||||||
Vector p1 = SS.GetEntity(point[1])->PointGetNum();
|
Vector p1 = SS.GetEntity(point[1])->PointGetNum();
|
||||||
Vector p2 = SS.GetEntity(point[2])->PointGetNum();
|
Vector p2 = SS.GetEntity(point[2])->PointGetNum();
|
||||||
Vector p3 = SS.GetEntity(point[3])->PointGetNum();
|
Vector p3 = SS.GetEntity(point[3])->PointGetNum();
|
||||||
int i, n = (int)(15/sqrt(SS.meshTol));
|
BezierPwl(0, 1, p0, p1, p2, p3);
|
||||||
Vector prev = p0;
|
|
||||||
for(i = 1; i <= n; i++) {
|
|
||||||
double t = ((double)i)/n;
|
|
||||||
Vector p =
|
|
||||||
(p0.ScaledBy((1 - t)*(1 - t)*(1 - t))).Plus(
|
|
||||||
(p1.ScaledBy(3*t*(1 - t)*(1 - t))).Plus(
|
|
||||||
(p2.ScaledBy(3*t*t*(1 - t))).Plus(
|
|
||||||
(p3.ScaledBy(t*t*t)))));
|
|
||||||
LineDrawOrGetDistanceOrEdge(prev, p);
|
|
||||||
prev = p;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
mesh.cpp
18
mesh.cpp
|
@ -245,14 +245,16 @@ bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
|
||||||
// A that lie inside B, or vice versa. That's the interference, and
|
// A that lie inside B, or vice versa. That's the interference, and
|
||||||
// we report it so that it can be flagged.
|
// we report it so that it can be flagged.
|
||||||
|
|
||||||
// But as far as the actual model, we just copy everything over.
|
// For the actual output, take the union.
|
||||||
int i;
|
flipNormal = false;
|
||||||
for(i = 0; i < srca->l.n; i++) {
|
keepCoplanar = false;
|
||||||
AddTriangle(&(srca->l.elem[i]));
|
AddAgainstBsp(srcb, bspa);
|
||||||
}
|
|
||||||
for(i = 0; i < srcb->l.n; i++) {
|
flipNormal = false;
|
||||||
AddTriangle(&(srcb->l.elem[i]));
|
keepCoplanar = true;
|
||||||
}
|
AddAgainstBsp(srca, bspb);
|
||||||
|
|
||||||
|
// And we're successful if the intersection was empty.
|
||||||
return (error->l.n == 0);
|
return (error->l.n == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
sketch.h
4
sketch.h
|
@ -393,6 +393,10 @@ public:
|
||||||
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
|
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
|
||||||
void DrawOrGetDistance(void);
|
void DrawOrGetDistance(void);
|
||||||
|
|
||||||
|
void BezierPwl(double ta, double tb,
|
||||||
|
Vector p0, Vector p1, Vector p2, Vector p3);
|
||||||
|
Vector BezierEval(double t, Vector p0, Vector p1, Vector p2, Vector p3);
|
||||||
|
|
||||||
static void DrawAll(void);
|
static void DrawAll(void);
|
||||||
void Draw(void);
|
void Draw(void);
|
||||||
double GetDistance(Point2d mp);
|
double GetDistance(Point2d mp);
|
||||||
|
|
|
@ -23,8 +23,8 @@ void SolveSpace::Init(char *cmdLine) {
|
||||||
lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" );
|
lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" );
|
||||||
lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" );
|
lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" );
|
||||||
lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" );
|
lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" );
|
||||||
// Mesh tolerance
|
// Chord tolerance
|
||||||
meshTol = CnfThawFloat(1.0f, "MeshTolerance");
|
chordTol = CnfThawFloat(2.0f, "ChordTolerance");
|
||||||
// View units
|
// View units
|
||||||
viewUnits = (Unit)CnfThawDWORD((DWORD)UNIT_MM, "ViewUnits");
|
viewUnits = (Unit)CnfThawDWORD((DWORD)UNIT_MM, "ViewUnits");
|
||||||
// Camera tangent (determines perspective)
|
// Camera tangent (determines perspective)
|
||||||
|
@ -79,8 +79,8 @@ void SolveSpace::Exit(void) {
|
||||||
CnfFreezeFloat((float)lightDir[1].x, "LightDir_1_Right");
|
CnfFreezeFloat((float)lightDir[1].x, "LightDir_1_Right");
|
||||||
CnfFreezeFloat((float)lightDir[1].y, "LightDir_1_Up");
|
CnfFreezeFloat((float)lightDir[1].y, "LightDir_1_Up");
|
||||||
CnfFreezeFloat((float)lightDir[1].z, "LightDir_1_Forward");
|
CnfFreezeFloat((float)lightDir[1].z, "LightDir_1_Forward");
|
||||||
// Mesh tolerance
|
// Chord tolerance
|
||||||
CnfFreezeFloat((float)meshTol, "MeshTolerance");
|
CnfFreezeFloat((float)chordTol, "ChordTolerance");
|
||||||
// Display/entry units
|
// Display/entry units
|
||||||
CnfFreezeDWORD((DWORD)viewUnits, "ViewUnits");
|
CnfFreezeDWORD((DWORD)viewUnits, "ViewUnits");
|
||||||
// Camera tangent (determines perspective)
|
// Camera tangent (determines perspective)
|
||||||
|
@ -100,8 +100,22 @@ void SolveSpace::DoLater(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int SolveSpace::CircleSides(double r) {
|
int SolveSpace::CircleSides(double r) {
|
||||||
int s = 7 + (int)(sqrt(r*SS.GW.scale/meshTol));
|
// Let the pwl segment be symmetric about the x axis; then the curve
|
||||||
return min(s, 40);
|
// goes out to r, and if there's n segments, then the endpoints are
|
||||||
|
// at +/- (2pi/n)/2 = +/- pi/n. So the chord goes to x = r cos pi/n,
|
||||||
|
// from x = r, so it's
|
||||||
|
// tol = r - r cos pi/n
|
||||||
|
// tol = r(1 - cos pi/n)
|
||||||
|
// tol ~ r(1 - (1 - (pi/n)^2/2)) (Taylor expansion)
|
||||||
|
// tol = r((pi/n)^2/2)
|
||||||
|
// 2*tol/r = (pi/n)^2
|
||||||
|
// sqrt(2*tol/r) = pi/n
|
||||||
|
// n = pi/sqrt(2*tol/r);
|
||||||
|
|
||||||
|
double tol = chordTol/GW.scale;
|
||||||
|
int n = 3 + (int)(PI/sqrt(2*tol/r));
|
||||||
|
|
||||||
|
return max(7, min(n, 40));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *SolveSpace::MmToString(double v) {
|
char *SolveSpace::MmToString(double v) {
|
||||||
|
|
|
@ -290,6 +290,8 @@ public:
|
||||||
Vector TransformIntPoint(int x, int y);
|
Vector TransformIntPoint(int x, int y);
|
||||||
void LineSegment(int x0, int y0, int x1, int y1);
|
void LineSegment(int x0, int y0, int x1, int y1);
|
||||||
void Bezier(int x0, int y0, int x1, int y1, int x2, int y2);
|
void Bezier(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||||
|
void BezierPwl(double ta, double tb, Vector p0, Vector p1, Vector p2);
|
||||||
|
Vector BezierEval(double t, Vector p0, Vector p1, Vector p2);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TtfFontList {
|
class TtfFontList {
|
||||||
|
@ -354,7 +356,7 @@ public:
|
||||||
int modelColor[MODEL_COLORS];
|
int modelColor[MODEL_COLORS];
|
||||||
Vector lightDir[2];
|
Vector lightDir[2];
|
||||||
double lightIntensity[2];
|
double lightIntensity[2];
|
||||||
double meshTol;
|
double chordTol;
|
||||||
double cameraTangent;
|
double cameraTangent;
|
||||||
DWORD edgeColor;
|
DWORD edgeColor;
|
||||||
float exportScale;
|
float exportScale;
|
||||||
|
|
|
@ -541,11 +541,11 @@ void TextWindow::ScreenChangeColor(int link, DWORD v) {
|
||||||
SS.TW.edit.meaning = EDIT_COLOR;
|
SS.TW.edit.meaning = EDIT_COLOR;
|
||||||
SS.TW.edit.i = v;
|
SS.TW.edit.i = v;
|
||||||
}
|
}
|
||||||
void TextWindow::ScreenChangeMeshTolerance(int link, DWORD v) {
|
void TextWindow::ScreenChangeChordTolerance(int link, DWORD v) {
|
||||||
char str[1024];
|
char str[1024];
|
||||||
sprintf(str, "%.2f", SS.meshTol);
|
sprintf(str, "%.2f", SS.chordTol);
|
||||||
ShowTextEditControl(37, 3, str);
|
ShowTextEditControl(37, 3, str);
|
||||||
SS.TW.edit.meaning = EDIT_MESH_TOLERANCE;
|
SS.TW.edit.meaning = EDIT_CHORD_TOLERANCE;
|
||||||
}
|
}
|
||||||
void TextWindow::ScreenChangeCameraTangent(int link, DWORD v) {
|
void TextWindow::ScreenChangeCameraTangent(int link, DWORD v) {
|
||||||
char str[1024];
|
char str[1024];
|
||||||
|
@ -594,10 +594,10 @@ void TextWindow::ShowConfiguration(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf(false, "");
|
Printf(false, "");
|
||||||
Printf(false, "%Ft mesh tolerance (smaller is finer)%E");
|
Printf(false, "%Ft chord tolerance (in screen pixels)%E");
|
||||||
Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles",
|
Printf(false, "%Ba %2 %Fl%Ll%f%D[change]%E; now %d triangles",
|
||||||
SS.meshTol,
|
SS.chordTol,
|
||||||
&ScreenChangeMeshTolerance, 0,
|
&ScreenChangeChordTolerance, 0,
|
||||||
SS.GetGroup(SS.GW.activeGroup)->runningMesh.l.n);
|
SS.GetGroup(SS.GW.activeGroup)->runningMesh.l.n);
|
||||||
|
|
||||||
Printf(false, "");
|
Printf(false, "");
|
||||||
|
@ -702,8 +702,8 @@ void TextWindow::EditControlDone(char *s) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EDIT_MESH_TOLERANCE: {
|
case EDIT_CHORD_TOLERANCE: {
|
||||||
SS.meshTol = min(10, max(0.1, atof(s)));
|
SS.chordTol = min(10, max(0.1, atof(s)));
|
||||||
SS.GenerateAll(0, INT_MAX);
|
SS.GenerateAll(0, INT_MAX);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
39
ttf.cpp
39
ttf.cpp
|
@ -690,23 +690,36 @@ void TtfFont::LineSegment(int x0, int y0, int x1, int y1) {
|
||||||
TransformIntPoint(x1, y1));
|
TransformIntPoint(x1, y1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TtfFont::Bezier(int x0, int y0, int x1, int y1, int x2, int y2) {
|
Vector TtfFont::BezierEval(double t, Vector p0, Vector p1, Vector p2) {
|
||||||
Entity *e = SS.GetEntity(entity);
|
return (p0.ScaledBy((1 - t)*(1 - t))).Plus(
|
||||||
|
(p1.ScaledBy(2*t*(1 - t))).Plus(
|
||||||
|
(p2.ScaledBy(t*t))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TtfFont::BezierPwl(double ta, double tb, Vector p0, Vector p1, Vector p2) {
|
||||||
|
Vector pa = BezierEval(ta, p0, p1, p2);
|
||||||
|
Vector pb = BezierEval(tb, p0, p1, p2);
|
||||||
|
|
||||||
|
double tm = (ta + tb) / 2;
|
||||||
|
|
||||||
|
Vector pm = BezierEval(tm, p0, p1, p2);
|
||||||
|
|
||||||
|
double tol = 0.5*SS.chordTol/SS.GW.scale;
|
||||||
|
|
||||||
|
if((tb - ta) < 0.05 || pm.DistanceToLine(pa, pb.Minus(pa)) < tol) {
|
||||||
|
Entity *e = SS.GetEntity(entity);
|
||||||
|
e->LineDrawOrGetDistanceOrEdge(pa, pb);
|
||||||
|
} else {
|
||||||
|
BezierPwl(ta, tm, p0, p1, p2);
|
||||||
|
BezierPwl(tm, tb, p0, p1, p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TtfFont::Bezier(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||||
Vector p0 = TransformIntPoint(x0, y0),
|
Vector p0 = TransformIntPoint(x0, y0),
|
||||||
p1 = TransformIntPoint(x1, y1),
|
p1 = TransformIntPoint(x1, y1),
|
||||||
p2 = TransformIntPoint(x2, y2);
|
p2 = TransformIntPoint(x2, y2);
|
||||||
|
|
||||||
int i, n = max(2, (int)(4/sqrt(SS.meshTol)));
|
BezierPwl(0, 1, p0, p1, p2);
|
||||||
Vector prev = p0;
|
|
||||||
for(i = 1; i <= n; i++) {
|
|
||||||
double t = ((double)i)/n;
|
|
||||||
Vector p =
|
|
||||||
(p0.ScaledBy((1 - t)*(1 - t))).Plus(
|
|
||||||
(p1.ScaledBy(2*t*(1 - t))).Plus(
|
|
||||||
(p2.ScaledBy(t*t))));
|
|
||||||
e->LineDrawOrGetDistanceOrEdge(prev, p);
|
|
||||||
prev = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
ui.h
4
ui.h
|
@ -62,7 +62,7 @@ public:
|
||||||
static const int EDIT_LIGHT_DIRECTION = 3;
|
static const int EDIT_LIGHT_DIRECTION = 3;
|
||||||
static const int EDIT_LIGHT_INTENSITY = 4;
|
static const int EDIT_LIGHT_INTENSITY = 4;
|
||||||
static const int EDIT_COLOR = 5;
|
static const int EDIT_COLOR = 5;
|
||||||
static const int EDIT_MESH_TOLERANCE = 6;
|
static const int EDIT_CHORD_TOLERANCE = 6;
|
||||||
static const int EDIT_CAMERA_TANGENT = 7;
|
static const int EDIT_CAMERA_TANGENT = 7;
|
||||||
static const int EDIT_EDGE_COLOR = 8;
|
static const int EDIT_EDGE_COLOR = 8;
|
||||||
static const int EDIT_EXPORT_SCALE = 9;
|
static const int EDIT_EXPORT_SCALE = 9;
|
||||||
|
@ -129,7 +129,7 @@ public:
|
||||||
static void ScreenChangeLightDirection(int link, DWORD v);
|
static void ScreenChangeLightDirection(int link, DWORD v);
|
||||||
static void ScreenChangeLightIntensity(int link, DWORD v);
|
static void ScreenChangeLightIntensity(int link, DWORD v);
|
||||||
static void ScreenChangeColor(int link, DWORD v);
|
static void ScreenChangeColor(int link, DWORD v);
|
||||||
static void ScreenChangeMeshTolerance(int link, DWORD v);
|
static void ScreenChangeChordTolerance(int link, DWORD v);
|
||||||
static void ScreenChangeCameraTangent(int link, DWORD v);
|
static void ScreenChangeCameraTangent(int link, DWORD v);
|
||||||
static void ScreenChangeEdgeColor(int link, DWORD v);
|
static void ScreenChangeEdgeColor(int link, DWORD v);
|
||||||
static void ScreenChangeExportScale(int link, DWORD v);
|
static void ScreenChangeExportScale(int link, DWORD v);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
adaptive pwl for polynomial curves
|
|
||||||
some kind of rounding / chamfer
|
some kind of rounding / chamfer
|
||||||
remove back button in browser?
|
remove back button in browser?
|
||||||
auto-generate circles and faces when lathing
|
auto-generate circles and faces when lathing
|
||||||
|
|
Loading…
Reference in New Issue
Block a user