Check entity bounding box before hit testing edges.
parent
b054b9682a
commit
e99eedd7a3
|
@ -336,7 +336,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
d = e->GetDistance(mp);
|
d = e->GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < SELECTION_RADIUS && d < dmin) {
|
||||||
s = {};
|
s = {};
|
||||||
s.entity = e->h;
|
s.entity = e->h;
|
||||||
dmin = d;
|
dmin = d;
|
||||||
|
@ -348,7 +348,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
// Constraints
|
// Constraints
|
||||||
for(i = 0; i < SK.constraint.n; i++) {
|
for(i = 0; i < SK.constraint.n; i++) {
|
||||||
d = SK.constraint.elem[i].GetDistance(mp);
|
d = SK.constraint.elem[i].GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < SELECTION_RADIUS && d < dmin) {
|
||||||
s = {};
|
s = {};
|
||||||
s.constraint = SK.constraint.elem[i].h;
|
s.constraint = SK.constraint.elem[i].h;
|
||||||
dmin = d;
|
dmin = d;
|
||||||
|
|
|
@ -152,6 +152,37 @@ SEdgeList *Entity::GetOrGenerateEdges() {
|
||||||
return &edges;
|
return &edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BBox Entity::GetScreenBBox(bool *hasBBox) {
|
||||||
|
SBezierList *sbl = GetOrGenerateBezierCurves();
|
||||||
|
|
||||||
|
// We don't bother with bounding boxes for normals, workplanes, etc.
|
||||||
|
*hasBBox = (IsPoint() || sbl->l.n > 0);
|
||||||
|
if(!*hasBBox) return {};
|
||||||
|
|
||||||
|
BBox result = {};
|
||||||
|
if(IsPoint()) {
|
||||||
|
Vector proj = SS.GW.ProjectPoint3(PointGetNum());
|
||||||
|
result = BBox::From(proj, proj);
|
||||||
|
} else if(sbl->l.n > 0) {
|
||||||
|
Vector first = SS.GW.ProjectPoint3(sbl->l.elem[0].ctrl[0]);
|
||||||
|
result = BBox::From(first, first);
|
||||||
|
for(int i = 0; i < sbl->l.n; i++) {
|
||||||
|
SBezier *sb = &sbl->l.elem[i];
|
||||||
|
for(int i = 0; i <= sb->deg; i++) {
|
||||||
|
result.Include(SS.GW.ProjectPoint3(sb->ctrl[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else oops();
|
||||||
|
|
||||||
|
// Enlarge the bounding box to consider selection radius.
|
||||||
|
result.minp.x -= SELECTION_RADIUS;
|
||||||
|
result.minp.y -= SELECTION_RADIUS;
|
||||||
|
result.maxp.x += SELECTION_RADIUS;
|
||||||
|
result.maxp.y += SELECTION_RADIUS;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
double Entity::GetDistance(Point2d mp) {
|
double Entity::GetDistance(Point2d mp) {
|
||||||
dogd.drawing = false;
|
dogd.drawing = false;
|
||||||
dogd.mp = mp;
|
dogd.mp = mp;
|
||||||
|
@ -473,6 +504,15 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::DrawOrGetDistance(void) {
|
void Entity::DrawOrGetDistance(void) {
|
||||||
|
// If we're about to perform hit testing on an entity, consider
|
||||||
|
// whether the pointer is inside its bounding box first.
|
||||||
|
if(!dogd.drawing) {
|
||||||
|
bool hasBBox;
|
||||||
|
BBox box = GetScreenBBox(&hasBBox);
|
||||||
|
if(hasBBox && !box.Contains(dogd.mp))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!IsVisible()) return;
|
if(!IsVisible()) return;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
|
|
@ -513,6 +513,7 @@ public:
|
||||||
|
|
||||||
void Include(const Vector &v, double r = 0.0);
|
void Include(const Vector &v, double r = 0.0);
|
||||||
bool Overlaps(BBox &b1);
|
bool Overlaps(BBox &b1);
|
||||||
|
bool Contains(const Point2d &p);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -509,6 +509,7 @@ public:
|
||||||
|
|
||||||
SBezierList *GetOrGenerateBezierCurves();
|
SBezierList *GetOrGenerateBezierCurves();
|
||||||
SEdgeList *GetOrGenerateEdges();
|
SEdgeList *GetOrGenerateEdges();
|
||||||
|
BBox GetScreenBBox(bool *hasBBox);
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
beziers.l.Clear();
|
beziers.l.Clear();
|
||||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -328,6 +328,8 @@ public:
|
||||||
void EditControlDone(const char *s);
|
void EditControlDone(const char *s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SELECTION_RADIUS 10.0
|
||||||
|
|
||||||
class GraphicsWindow {
|
class GraphicsWindow {
|
||||||
public:
|
public:
|
||||||
void Init(void);
|
void Init(void);
|
||||||
|
|
|
@ -1047,3 +1047,7 @@ bool BBox::Overlaps(BBox &b1) {
|
||||||
|
|
||||||
return fabs(t.x) < e.x && fabs(t.y) < e.y && fabs(t.z) < e.z;
|
return fabs(t.x) < e.x && fabs(t.y) < e.y && fabs(t.z) < e.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BBox::Contains(const Point2d &p) {
|
||||||
|
return p.x >= minp.x && p.y >= minp.y && p.x <= maxp.x && p.y <= maxp.y;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue