Skip to content

Commit 8aa7318

Browse files
authored
Merge pull request #26 from FezVrasta/feat/view-picker-tolerance
feat(View): pointerSize property
2 parents b41817b + d370e94 commit 8aa7318

File tree

1 file changed

+67
-29
lines changed

1 file changed

+67
-29
lines changed

src/core/View.js

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,14 @@ export default class View extends Component {
209209
if (this.props.pickingModes.indexOf('click') === -1) {
210210
return;
211211
}
212-
const selection = this.pick(x, y, x, y);
212+
const tolerance = this.getPointerSizeTolerance();
213+
const selection = this.pick(
214+
Math.floor(x - tolerance),
215+
Math.floor(y - tolerance),
216+
Math.ceil(x + tolerance),
217+
Math.ceil(y + tolerance),
218+
false
219+
);
213220

214221
// Share the selection with the rest of the world
215222
if (this.props.onClick) {
@@ -225,7 +232,15 @@ export default class View extends Component {
225232
if (this.props.pickingModes.indexOf('hover') === -1) {
226233
return;
227234
}
228-
const selection = this.pick(x, y, x, y);
235+
236+
const tolerance = this.getPointerSizeTolerance();
237+
const selection = this.pick(
238+
Math.floor(x - tolerance),
239+
Math.floor(y - tolerance),
240+
Math.ceil(x + tolerance),
241+
Math.ceil(y + tolerance),
242+
false
243+
);
229244

230245
// Guard against trigger of empty selection
231246
if (this.lastSelection.length === 0 && selection.length === 0) {
@@ -248,7 +263,7 @@ export default class View extends Component {
248263
return;
249264
}
250265
const [x1, x2, y1, y2] = selection;
251-
const pickResult = this.pick(x1, y1, x2, y2);
266+
const pickResult = this.pick(x1, y1, x2, y2, true);
252267

253268
// Share the selection with the rest of the world
254269
if (this.props.onSelect) {
@@ -287,6 +302,10 @@ export default class View extends Component {
287302
);
288303
}
289304

305+
getPointerSizeTolerance() {
306+
return this.props.pointerSize / 2;
307+
}
308+
290309
getScreenEventPositionFor(source) {
291310
const bounds = this.containerRef.current.getBoundingClientRect();
292311
const [canvasWidth, canvasHeight] = this.openglRenderWindow.getSize();
@@ -476,12 +495,12 @@ export default class View extends Component {
476495
this.renderWindow.render();
477496
}
478497

479-
pick(x1, y1, x2, y2) {
498+
pick(x1, y1, x2, y2, useFrustrum = false) {
480499
this.selector.setArea(x1, y1, x2, y2);
481500
this.previousSelectedData = null;
482501
if (this.selector.captureBuffers()) {
483502
this.selections = this.selector.generateSelection(x1, y1, x2, y2) || [];
484-
if (x1 !== x2 || y1 !== y2) {
503+
if (useFrustrum) {
485504
const frustrum = [
486505
Array.from(
487506
this.openglRenderWindow.displayToWorld(x1, y1, 0, this.renderer)
@@ -511,7 +530,8 @@ export default class View extends Component {
511530
const representationIds = [];
512531
this.selections.forEach((v) => {
513532
const { prop } = v.getProperties();
514-
const representationId = prop?.get('representationId').representationId;
533+
const representationId =
534+
prop?.get('representationId').representationId;
515535
if (representationId) {
516536
representationIds.push(representationId);
517537
}
@@ -520,33 +540,45 @@ export default class View extends Component {
520540
}
521541
const ray = [
522542
Array.from(
523-
this.openglRenderWindow.displayToWorld(x1, y1, 0, this.renderer)
543+
this.openglRenderWindow.displayToWorld(
544+
Math.round((x1 + x2) / 2),
545+
Math.round((y1 + y2) / 2),
546+
0,
547+
this.renderer
548+
)
524549
),
525550
Array.from(
526-
this.openglRenderWindow.displayToWorld(x1, y1, 1, this.renderer)
551+
this.openglRenderWindow.displayToWorld(
552+
Math.round((x1 + x2) / 2),
553+
Math.round((y1 + y2) / 2),
554+
1,
555+
this.renderer
556+
)
527557
),
528558
];
529-
return this.selections.map((v) => {
530-
const { prop, compositeID, displayPosition } = v.getProperties();
531-
532-
// Return false to mark this item for removal
533-
if (prop == null) return false;
534-
535-
return {
536-
worldPosition: Array.from(
537-
this.openglRenderWindow.displayToWorld(
538-
displayPosition[0],
539-
displayPosition[1],
540-
displayPosition[2],
541-
this.renderer
542-
)
543-
),
544-
displayPosition,
545-
compositeID, // Not yet useful unless GlyphRepresentation
546-
...prop.get('representationId'),
547-
ray,
548-
};
549-
}).filter(Boolean);
559+
return this.selections
560+
.map((v) => {
561+
const { prop, compositeID, displayPosition } = v.getProperties();
562+
563+
// Return false to mark this item for removal
564+
if (prop == null) return false;
565+
566+
return {
567+
worldPosition: Array.from(
568+
this.openglRenderWindow.displayToWorld(
569+
displayPosition[0],
570+
displayPosition[1],
571+
displayPosition[2],
572+
this.renderer
573+
)
574+
),
575+
displayPosition,
576+
compositeID, // Not yet useful unless GlyphRepresentation
577+
...prop.get('representationId'),
578+
ray,
579+
};
580+
})
581+
.filter(Boolean);
550582
}
551583
return [];
552584
}
@@ -602,6 +634,7 @@ View.defaultProps = {
602634
interactive: true,
603635
pickingModes: [],
604636
showCubeAxes: false,
637+
pointerSize: 0,
605638
};
606639

607640
View.propTypes = {
@@ -710,6 +743,11 @@ View.propTypes = {
710743
*/
711744
selectInfo: PropTypes.object,
712745

746+
/**
747+
* Defines the tolerance of the click and hover selection.
748+
*/
749+
pointerSize: PropTypes.number,
750+
713751
/**
714752
* Show/Hide Cube Axes for the given representation
715753
*/

0 commit comments

Comments
 (0)