forked from ieskudero/three-dxf-viewer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ibon eskudero
committed
Jun 12, 2023
1 parent
ba4a4c5
commit aa0800d
Showing
4 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#loading { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
background-color: black; | ||
color: white; | ||
opacity: 50%; | ||
font-size: 5vh; | ||
text-align: center; | ||
padding-top: 15vh; | ||
z-index: 1000; | ||
display: none; | ||
} | ||
|
||
#headerTitle{ | ||
font-size: 25px; | ||
font-weight: bold; | ||
color: white; | ||
text-align: center; | ||
position: fixed; | ||
top: 0; | ||
top: 1vh; | ||
left: 50%; | ||
width: 24vh; | ||
margin-left: -12vh; | ||
z-index: 1; | ||
} | ||
|
||
/*set footer bottom centered*/ | ||
#footer { | ||
position: fixed; | ||
bottom: 20px; | ||
left: 0; | ||
right: 0; | ||
margin-left: -12vh; | ||
z-index: 1; | ||
font-size: 21px; | ||
color: white; | ||
text-align: center; | ||
opacity: 0.25; | ||
} | ||
|
||
#file{ | ||
position: fixed; | ||
top: 1vh; | ||
left: 1vh; | ||
color: white; | ||
font-size: 1.5vh; | ||
z-index: 2; | ||
} | ||
|
||
#canvas3d { | ||
position: fixed; | ||
top: 0; | ||
bottom: 0; | ||
right: 0; | ||
left: 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<title>Select example</title> | ||
<style type="text/css"> | ||
html, | ||
body { | ||
margin: 0; | ||
padding: 0; | ||
overflow: hidden | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div id="headerTitle"> Drop or Paste File </div> | ||
<div id="footer"> Select single entity with mouse left click. If Ctrl is pressed it can select multiple entities that are inside the selection box </div> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { DXFViewer } from '../../src/dxfViewer.js'; | ||
import { Boilerplate } from '../boilerplate.js'; | ||
import { Select } from '../../src/utils/select.js'; | ||
|
||
//global variables | ||
const font = 'fonts/helvetiker_regular.typeface.json'; | ||
const viewer = new DXFViewer(); | ||
|
||
//init html | ||
let html = new Boilerplate(); | ||
html.onLoad = async ( file ) => { | ||
html.three.clear(); | ||
|
||
let dxf = await viewer.getFromFile( file, font ); | ||
if( dxf ) { | ||
|
||
new Select( html.three.renderer.domElement, html.three.camera, dxf ); | ||
|
||
html.three.scene.add( dxf ); | ||
html.three.centerCamera(); | ||
} | ||
}; | ||
|
||
html.init(); | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
import { Box3, Vector3 } from 'three'; | ||
import { Raycaster } from '../tools/raycaster'; | ||
|
||
export class Select extends Raycaster { | ||
constructor( container, camera, dxf, raycasting = null ) { | ||
|
||
super(); | ||
this.container = container; | ||
this.camera = camera; | ||
this.dxf = dxf; | ||
|
||
//init raycasting | ||
this._initRaycasting( container, camera, dxf, raycasting ); | ||
|
||
//create orange hover material that will be seeen above all other materials | ||
this._setMaterial( 0x0000ff ); | ||
|
||
this.selecteds = []; | ||
this._boxHelpers = { | ||
start3dpoint: new Vector3(), | ||
end3dpoint: new Vector3(), | ||
boxMin : new Vector3(), | ||
boxMax : new Vector3(), | ||
}; | ||
|
||
this.container.addEventListener( 'pointerdown', async( e ) => await this._onPointerDown( e ), false ); | ||
this.container.addEventListener( 'pointerup', async( e ) => await this._onPointerUp( e ), false ); | ||
this.container.addEventListener( 'pointermove', async( e ) => await this._onPointerMove( e ), false ); | ||
} | ||
|
||
async _onPointerDown( event ) { | ||
|
||
//if control is pushed start selection box | ||
if( event.ctrlKey && event.button !== 2 ) { | ||
this._onSelectionBox = { | ||
start: { x: event.clientX, y: event.clientY }, | ||
end: { x: event.clientX, y: event.clientY } | ||
}; | ||
return; | ||
} | ||
} | ||
|
||
async _onPointerUp( event ) { | ||
//if mouse right button return | ||
if( event.button === 2 ) return; | ||
if( this._moving ) { this._moving = false; return; } | ||
|
||
event.preventDefault(); | ||
|
||
this._deselectAll(); | ||
|
||
|
||
//TRY TO SELECT USING SELECTION BOX | ||
let ss = null; | ||
if( this._onSelectionBox ) { | ||
const objs = this._getEntitiesUnderSelectionBox( this._onSelectionBox.start, this._onSelectionBox.end ); | ||
if( objs ) ss = objs; | ||
} else { | ||
|
||
//SELECT BY RAYCASTING | ||
this.pointer.x = ( event.clientX / this.container.clientWidth ) * 2 - 1; | ||
this.pointer.y = - ( event.clientY / this.container.clientHeight ) * 2 + 1; | ||
|
||
const intersected = await this.raycast.raycast( this.pointer ); | ||
if( intersected ) ss = intersected.object.parent; | ||
} | ||
|
||
if( ss ) this._select( ss ); | ||
|
||
//CLEAN UP | ||
this._removeSelectionBox(); | ||
this._onSelectionBox = null; | ||
} | ||
|
||
async _onPointerMove( event ) { | ||
if( this._onSelectionBox ) { | ||
this._onSelectionBox.end = { x: event.clientX, y: event.clientY }; | ||
this.drawSelectionBox( this._onSelectionBox.start, this._onSelectionBox.end ); | ||
return; | ||
} | ||
} | ||
|
||
drawSelectionBox( start, end ) { | ||
this._removeSelectionBox(); | ||
|
||
const width = Math.max( start.x, end.x ) - Math.min( start.x, end.x ); | ||
const height = Math.max( start.y, end.y ) - Math.min( start.y, end.y ); | ||
|
||
this._selectionBox = document.createElement( 'div' ); | ||
//STYLE | ||
this._selectionBox.style.position = 'absolute'; | ||
this._selectionBox.style.border = '1px solid white'; | ||
this._selectionBox.style.left = Math.min( start.x, end.x ) + 'px'; | ||
this._selectionBox.style.top = Math.min( start.y, end.y ) + 'px'; | ||
this._selectionBox.style.width = width + 'px'; | ||
this._selectionBox.style.height = height + 'px'; | ||
this._selectionBox.style.pointerEvents = 'none'; this._selectionBox.style.background= 'blue'; | ||
this._selectionBox.style.opacity = 0.25; | ||
|
||
document.body.appendChild( this._selectionBox ); | ||
} | ||
|
||
_removeSelectionBox() { | ||
if( this._selectionBox ) { | ||
document.body.removeChild( this._selectionBox ); | ||
this._selectionBox = null; | ||
} | ||
} | ||
|
||
_getEntitiesUnderSelectionBox( start, end ) { | ||
|
||
//transform screen coordinates to 3d coordinates | ||
start.x = ( start.x / this.container.clientWidth ) * 2 - 1; | ||
start.y = - ( start.y / this.container.clientHeight ) * 2 + 1; | ||
end.x = ( end.x / this.container.clientWidth ) * 2 - 1; | ||
end.y = - ( end.y / this.container.clientHeight ) * 2 + 1; | ||
this._boxHelpers.start3dpoint = new Vector3( start.x, start.y, 0 ).unproject( this.camera ); | ||
this._boxHelpers.end3dpoint = new Vector3( end.x, end.y, 0 ).unproject( this.camera ); | ||
|
||
//get box min and max | ||
this._boxHelpers.boxMin.set( | ||
Math.min( this._boxHelpers.start3dpoint.x, this._boxHelpers.end3dpoint.x ), | ||
Math.min( this._boxHelpers.start3dpoint.y, this._boxHelpers.end3dpoint.y ), | ||
0 | ||
); | ||
this._boxHelpers.boxMax.set( | ||
Math.max( this._boxHelpers.start3dpoint.x, this._boxHelpers.end3dpoint.x ), | ||
Math.max( this._boxHelpers.start3dpoint.y, this._boxHelpers.end3dpoint.y ), | ||
0 | ||
); | ||
|
||
const box = new Box3( this._boxHelpers.boxMin, this._boxHelpers.boxMax ); | ||
|
||
const blocks = this._getBlocksUnderBox( box, this.dxf ); | ||
|
||
return blocks.length > 0 ? blocks : null; | ||
} | ||
|
||
_getBlocksUnderBox( box, root ) { | ||
|
||
const blocks = []; | ||
if( !root || !root.children ) return blocks; | ||
|
||
if( root.name !== '' && this._fitInsideBox( box, root ) ) { | ||
blocks.push( root ); | ||
} else { | ||
for( let i = 0; i < root.children.length; i++ ) { | ||
const child = root.children[ i ]; | ||
const b = this._getBlocksUnderBox( box, child ); | ||
if( b.length > 0 ) blocks.push( ...b ); | ||
} | ||
} | ||
|
||
return blocks; | ||
} | ||
|
||
_fitInsideBox( box, root ) { | ||
let b = new Box3().setFromObject( root ); | ||
|
||
return box.containsBox( b ); | ||
} | ||
|
||
|
||
_select( obj ) { | ||
const objs = obj instanceof Array ? obj : [ obj ]; | ||
objs.forEach( o => { | ||
const clone = this._clone( o ); | ||
clone.traverse( c => { if ( c.material ) c.material = this._material; } ); | ||
o.parent.add( clone ); | ||
this.selecteds.push( clone ); | ||
} ); | ||
} | ||
|
||
_deselectAll() { | ||
if( this.selecteds ) { | ||
this.selecteds.forEach( s => s.parent.remove( s ) ); | ||
this.selecteds.length = 0; | ||
} | ||
} | ||
} |