Also consider constraints when zooming to fit.

Before this commit, when working on convex sketches, zooming to fit
was guaranteed to clip most or even all constraints, making it quite
useless.
This commit is contained in:
whitequark 2016-08-01 14:00:00 +00:00
parent 8e7d2eaa84
commit f2633e4a57
3 changed files with 42 additions and 20 deletions

View File

@ -13,6 +13,7 @@ Other new features:
"Analyze → Measure Perimeter".
* New link to match the on-screen size of the sketch with its actual size,
"view → set to full scale".
* When zooming to fit, constraints are also considered.
2.2
---

View File

@ -313,11 +313,11 @@ void GraphicsWindow::HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *p
*wmin = min(*wmin, w);
}
void GraphicsWindow::LoopOverPoints(const std::vector<Entity *> &entities,
const std::vector<Constraint *> &constraints,
const std::vector<hEntity> &faces,
Point2d *pmax, Point2d *pmin, double *wmin,
bool usePerspective, bool includeMesh) {
int i, j;
for(Entity *e : entities) {
if(e->IsPoint()) {
HandlePointForZoomToFit(e->PointGetNum(), pmax, pmin, wmin, usePerspective);
@ -329,7 +329,7 @@ void GraphicsWindow::LoopOverPoints(const std::vector<Entity *> &entities,
double r = e->CircleGetRadiusNum();
Vector c = SK.GetEntity(e->point[0])->PointGetNum();
Quaternion q = SK.GetEntity(e->normal)->NormalGetNum();
for(j = 0; j < 4; j++) {
for(int j = 0; j < 4; j++) {
Vector p = (j == 0) ? (c.Plus(q.RotationU().ScaledBy( r))) :
(j == 1) ? (c.Plus(q.RotationU().ScaledBy(-r))) :
(j == 2) ? (c.Plus(q.RotationV().ScaledBy( r))) :
@ -346,11 +346,19 @@ void GraphicsWindow::LoopOverPoints(const std::vector<Entity *> &entities,
}
}
for(Constraint *c : constraints) {
std::vector<Vector> refs;
c->GetReferencePoints(GetCamera(), &refs);
for(Vector p : refs) {
HandlePointForZoomToFit(p, pmax, pmin, wmin, usePerspective);
}
}
if(!includeMesh && faces.empty()) return;
Group *g = SK.GetGroup(activeGroup);
g->GenerateDisplayItems();
for(i = 0; i < g->displayMesh.l.n; i++) {
for(int i = 0; i < g->displayMesh.l.n; i++) {
STriangle *tr = &(g->displayMesh.l.elem[i]);
if(!includeMesh) {
bool found = false;
@ -366,21 +374,22 @@ void GraphicsWindow::LoopOverPoints(const std::vector<Entity *> &entities,
HandlePointForZoomToFit(tr->c, pmax, pmin, wmin, usePerspective);
}
if(!includeMesh) return;
for(i = 0; i < g->polyLoops.l.n; i++) {
for(int i = 0; i < g->polyLoops.l.n; i++) {
SContour *sc = &(g->polyLoops.l.elem[i]);
for(j = 0; j < sc->l.n; j++) {
for(int j = 0; j < sc->l.n; j++) {
HandlePointForZoomToFit(sc->l.elem[j].p, pmax, pmin, wmin, usePerspective);
}
}
}
void GraphicsWindow::ZoomToFit(bool includingInvisibles, bool useSelection) {
std::vector<Entity *> entities;
std::vector<Constraint *> constraints;
std::vector<hEntity> faces;
if(useSelection) {
for(int i = 0; i < selection.n; i++) {
Selection *s = &selection.elem[i];
if(s->entity.v == 0) continue;
if(s->entity.v != 0) {
Entity *e = SK.entity.FindById(s->entity);
if(e->IsFace()) {
faces.push_back(e->h);
@ -388,24 +397,33 @@ void GraphicsWindow::ZoomToFit(bool includingInvisibles, bool useSelection) {
}
entities.push_back(e);
}
if(s->constraint.v != 0) {
Constraint *c = SK.constraint.FindById(s->constraint);
constraints.push_back(c);
}
}
}
bool selectionUsed = !entities.empty() || !faces.empty();
bool selectionUsed = !entities.empty() || !constraints.empty() || !faces.empty();
if(!selectionUsed) {
for(int i = 0; i<SK.entity.n; i++) {
Entity *e = &(SK.entity.elem[i]);
for(Entity &e : SK.entity) {
// we don't want to handle separate points, because we will iterate them inside entities.
if(e->IsPoint()) continue;
if(!includingInvisibles && !e->IsVisible()) continue;
entities.push_back(e);
if(e.IsPoint()) continue;
if(!includingInvisibles && !e.IsVisible()) continue;
entities.push_back(&e);
}
for(Constraint &c : SK.constraint) {
if(!c.IsVisible()) continue;
constraints.push_back(&c);
}
}
// On the first run, ignore perspective.
Point2d pmax = { -1e12, -1e12 }, pmin = { 1e12, 1e12 };
double wmin = 1;
LoopOverPoints(entities, faces, &pmax, &pmin, &wmin,
LoopOverPoints(entities, constraints, faces, &pmax, &pmin, &wmin,
/*usePerspective=*/false, /*includeMesh=*/!selectionUsed);
double xm = (pmax.x + pmin.x)/2, ym = (pmax.y + pmin.y)/2;
@ -431,7 +449,7 @@ void GraphicsWindow::ZoomToFit(bool includingInvisibles, bool useSelection) {
pmax.x = -1e12; pmax.y = -1e12;
pmin.x = 1e12; pmin.y = 1e12;
wmin = 1;
LoopOverPoints(entities, faces, &pmax, &pmin, &wmin,
LoopOverPoints(entities, constraints, faces, &pmax, &pmin, &wmin,
/*usePerspective=*/true, /*includeMesh=*/!selectionUsed);
// Adjust the scale so that no points are behind the camera

View File

@ -559,7 +559,10 @@ public:
Vector VectorFromProjs(Vector rightUpForward);
void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin,
double *wmin, bool usePerspective);
void LoopOverPoints(const std::vector<Entity *> &entity, const std::vector<hEntity> &faces, Point2d *pmax, Point2d *pmin,
void LoopOverPoints(const std::vector<Entity *> &entities,
const std::vector<Constraint *> &constraints,
const std::vector<hEntity> &faces,
Point2d *pmax, Point2d *pmin,
double *wmin, bool usePerspective, bool includeMesh);
void ZoomToFit(bool includingInvisibles, bool useSelection = false);