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(rightDown) {
|
||||
middleDown = true;
|
||||
shiftDown = true;
|
||||
shiftDown = !shiftDown;
|
||||
}
|
||||
|
||||
Point2d mp = { x, y };
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
if(dogd.drawing) {
|
||||
// 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);
|
||||
glxVertex3v(a);
|
||||
glxVertex3v(b);
|
||||
|
@ -132,6 +132,41 @@ bool Entity::IsVisible(void) {
|
|||
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) {
|
||||
// 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.
|
||||
|
@ -301,18 +336,7 @@ void Entity::DrawOrGetDistance(void) {
|
|||
Vector p1 = SS.GetEntity(point[1])->PointGetNum();
|
||||
Vector p2 = SS.GetEntity(point[2])->PointGetNum();
|
||||
Vector p3 = SS.GetEntity(point[3])->PointGetNum();
|
||||
int i, n = (int)(15/sqrt(SS.meshTol));
|
||||
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;
|
||||
}
|
||||
BezierPwl(0, 1, p0, p1, p2, p3);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
18
mesh.cpp
18
mesh.cpp
|
@ -244,15 +244,17 @@ bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
|
|||
// Now we have a list of all the triangles (or fragments thereof) from
|
||||
// A that lie inside B, or vice versa. That's the interference, and
|
||||
// we report it so that it can be flagged.
|
||||
|
||||
// For the actual output, take the union.
|
||||
flipNormal = false;
|
||||
keepCoplanar = false;
|
||||
AddAgainstBsp(srcb, bspa);
|
||||
|
||||
flipNormal = false;
|
||||
keepCoplanar = true;
|
||||
AddAgainstBsp(srca, bspb);
|
||||
|
||||
// But as far as the actual model, we just copy everything over.
|
||||
int i;
|
||||
for(i = 0; i < srca->l.n; i++) {
|
||||
AddTriangle(&(srca->l.elem[i]));
|
||||
}
|
||||
for(i = 0; i < srcb->l.n; i++) {
|
||||
AddTriangle(&(srcb->l.elem[i]));
|
||||
}
|
||||
// And we're successful if the intersection was empty.
|
||||
return (error->l.n == 0);
|
||||
}
|
||||
|
||||
|
|
4
sketch.h
4
sketch.h
|
@ -393,6 +393,10 @@ public:
|
|||
void LineDrawOrGetDistanceOrEdge(Vector a, Vector b);
|
||||
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);
|
||||
void Draw(void);
|
||||
double GetDistance(Point2d mp);
|
||||
|
|
|
@ -23,8 +23,8 @@ void SolveSpace::Init(char *cmdLine) {
|
|||
lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" );
|
||||
lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" );
|
||||
lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" );
|
||||
// Mesh tolerance
|
||||
meshTol = CnfThawFloat(1.0f, "MeshTolerance");
|
||||
// Chord tolerance
|
||||
chordTol = CnfThawFloat(2.0f, "ChordTolerance");
|
||||
// View units
|
||||
viewUnits = (Unit)CnfThawDWORD((DWORD)UNIT_MM, "ViewUnits");
|
||||
// Camera tangent (determines perspective)
|
||||
|
@ -79,8 +79,8 @@ void SolveSpace::Exit(void) {
|
|||
CnfFreezeFloat((float)lightDir[1].x, "LightDir_1_Right");
|
||||
CnfFreezeFloat((float)lightDir[1].y, "LightDir_1_Up");
|
||||
CnfFreezeFloat((float)lightDir[1].z, "LightDir_1_Forward");
|
||||
// Mesh tolerance
|
||||
CnfFreezeFloat((float)meshTol, "MeshTolerance");
|
||||
// Chord tolerance
|
||||
CnfFreezeFloat((float)chordTol, "ChordTolerance");
|
||||
// Display/entry units
|
||||
CnfFreezeDWORD((DWORD)viewUnits, "ViewUnits");
|
||||
// Camera tangent (determines perspective)
|
||||
|
@ -100,8 +100,22 @@ void SolveSpace::DoLater(void) {
|
|||
}
|
||||
|
||||
int SolveSpace::CircleSides(double r) {
|
||||
int s = 7 + (int)(sqrt(r*SS.GW.scale/meshTol));
|
||||
return min(s, 40);
|
||||
// Let the pwl segment be symmetric about the x axis; then the curve
|
||||
// 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) {
|
||||
|
|
|
@ -290,6 +290,8 @@ public:
|
|||
Vector TransformIntPoint(int x, int y);
|
||||
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 BezierPwl(double ta, double tb, Vector p0, Vector p1, Vector p2);
|
||||
Vector BezierEval(double t, Vector p0, Vector p1, Vector p2);
|
||||
};
|
||||
|
||||
class TtfFontList {
|
||||
|
@ -354,7 +356,7 @@ public:
|
|||
int modelColor[MODEL_COLORS];
|
||||
Vector lightDir[2];
|
||||
double lightIntensity[2];
|
||||
double meshTol;
|
||||
double chordTol;
|
||||
double cameraTangent;
|
||||
DWORD edgeColor;
|
||||
float exportScale;
|
||||
|
|
|
@ -541,11 +541,11 @@ void TextWindow::ScreenChangeColor(int link, DWORD v) {
|
|||
SS.TW.edit.meaning = EDIT_COLOR;
|
||||
SS.TW.edit.i = v;
|
||||
}
|
||||
void TextWindow::ScreenChangeMeshTolerance(int link, DWORD v) {
|
||||
void TextWindow::ScreenChangeChordTolerance(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.2f", SS.meshTol);
|
||||
sprintf(str, "%.2f", SS.chordTol);
|
||||
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) {
|
||||
char str[1024];
|
||||
|
@ -594,10 +594,10 @@ void TextWindow::ShowConfiguration(void) {
|
|||
}
|
||||
|
||||
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",
|
||||
SS.meshTol,
|
||||
&ScreenChangeMeshTolerance, 0,
|
||||
SS.chordTol,
|
||||
&ScreenChangeChordTolerance, 0,
|
||||
SS.GetGroup(SS.GW.activeGroup)->runningMesh.l.n);
|
||||
|
||||
Printf(false, "");
|
||||
|
@ -702,8 +702,8 @@ void TextWindow::EditControlDone(char *s) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case EDIT_MESH_TOLERANCE: {
|
||||
SS.meshTol = min(10, max(0.1, atof(s)));
|
||||
case EDIT_CHORD_TOLERANCE: {
|
||||
SS.chordTol = min(10, max(0.1, atof(s)));
|
||||
SS.GenerateAll(0, INT_MAX);
|
||||
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));
|
||||
}
|
||||
|
||||
void TtfFont::Bezier(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
Entity *e = SS.GetEntity(entity);
|
||||
Vector TtfFont::BezierEval(double t, Vector p0, Vector p1, Vector p2) {
|
||||
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),
|
||||
p1 = TransformIntPoint(x1, y1),
|
||||
p2 = TransformIntPoint(x2, y2);
|
||||
|
||||
int i, n = max(2, (int)(4/sqrt(SS.meshTol)));
|
||||
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;
|
||||
}
|
||||
BezierPwl(0, 1, p0, p1, p2);
|
||||
}
|
||||
|
||||
|
|
4
ui.h
4
ui.h
|
@ -62,7 +62,7 @@ public:
|
|||
static const int EDIT_LIGHT_DIRECTION = 3;
|
||||
static const int EDIT_LIGHT_INTENSITY = 4;
|
||||
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_EDGE_COLOR = 8;
|
||||
static const int EDIT_EXPORT_SCALE = 9;
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
static void ScreenChangeLightDirection(int link, DWORD v);
|
||||
static void ScreenChangeLightIntensity(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 ScreenChangeEdgeColor(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
|
||||
remove back button in browser?
|
||||
auto-generate circles and faces when lathing
|
||||
|
|
Loading…
Reference in New Issue
Block a user