@@ -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
607640View . 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