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);
|
||||
if(d < 10 && d < dmin) {
|
||||
if(d < SELECTION_RADIUS && d < dmin) {
|
||||
s = {};
|
||||
s.entity = e->h;
|
||||
dmin = d;
|
||||
|
@ -348,7 +348,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
|||
// Constraints
|
||||
for(i = 0; i < SK.constraint.n; i++) {
|
||||
d = SK.constraint.elem[i].GetDistance(mp);
|
||||
if(d < 10 && d < dmin) {
|
||||
if(d < SELECTION_RADIUS && d < dmin) {
|
||||
s = {};
|
||||
s.constraint = SK.constraint.elem[i].h;
|
||||
dmin = d;
|
||||
|
|
|
@ -152,6 +152,37 @@ SEdgeList *Entity::GetOrGenerateEdges() {
|
|||
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) {
|
||||
dogd.drawing = false;
|
||||
dogd.mp = mp;
|
||||
|
@ -473,6 +504,15 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
switch(type) {
|
||||
|
|
|
@ -513,6 +513,7 @@ public:
|
|||
|
||||
void Include(const Vector &v, double r = 0.0);
|
||||
bool Overlaps(BBox &b1);
|
||||
bool Contains(const Point2d &p);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -509,6 +509,7 @@ public:
|
|||
|
||||
SBezierList *GetOrGenerateBezierCurves();
|
||||
SEdgeList *GetOrGenerateEdges();
|
||||
BBox GetScreenBBox(bool *hasBBox);
|
||||
|
||||
void Clear() {
|
||||
beziers.l.Clear();
|
||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -328,6 +328,8 @@ public:
|
|||
void EditControlDone(const char *s);
|
||||
};
|
||||
|
||||
#define SELECTION_RADIUS 10.0
|
||||
|
||||
class GraphicsWindow {
|
||||
public:
|
||||
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;
|
||||
}
|
||||
|
||||
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