Three.js: Hole in a shape and extrude it, this "Probably Hole outside Shape!" (found but not solved)

Created on 15 Aug 2017  路  14Comments  路  Source: mrdoob/three.js

Description of the problem

While drilling a hole in a shape and extrude it, this line is called:
console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" );

Beause this lines fail:
if ( ( inExcludeAdjacentSegs ) &&
( ( perpSeg1 === 0 ) || ( Math) === Math. ) ) ) return [];

The values are equal! Almost :-/
The last digits of the float values are slightly differnt.
This happends if the points of the shapes do have a lot of digits after the dot. ThreeJS will calculate with them, loosing the last details. I often heard the rule: Don't compare floats with "equals"!

I changed the line, adding "floor" and it worked:
( ( perpSeg1 === 0 ) || ( Math.floor(perpSeg1) === Math.floor(limit) ) ) ) return [];

That is an guly patch and no solution. I don't have the expirience to find one.
It did not solve all my problems. There are more lines in Three.js alike coded.
Se more below!

Three.js version
  • [ ] r83 and r86
Browser
  • [?] All of them
  • [ x] Firefox
OS
  • [?] All of them
  • [x] macOS
Hardware Requirements (graphics card, VR Device, ...)

NO

#

That's the code you may test it with:

var FAR = 10000

var points = []
points.push( new THREE.Vector2( +FAR,+FAR ))
points.push( new THREE.Vector2( +FAR,-FAR ))
points.push( new THREE.Vector2( -FAR,-FAR ))
points.push( new THREE.Vector2( -FAR,+FAR ))
points.push( new THREE.Vector2( +FAR,+FAR ))
var shape = new THREE.Shape( points )
points = []
var ts0 = 0// (lastLoadEx-lastLoadx)(tileDistMax+0)
var ts1 = 0// (lastLoadz-lastLoadEz)
(tileDistMax+1)
ts0=744.31 //.3099999999//.3162744867122
ts1=992.4 //.4078465743082//.4078465743082
points.push( new THREE.Vector2( -ts0,+ts0 ))
points.push( new THREE.Vector2( -ts0,-ts1 ))
points.push( new THREE.Vector2( +ts1,-ts1 ))
points.push( new THREE.Vector2( +ts1,+ts0 ))
points.push( new THREE.Vector2( -ts0,+ts0 ))
shape.holes.push(new THREE.Shape( points ))
var geometry = new THREE.ShapeGeometry(shape)
var mate = new THREE.MeshLambertMaterial( {color: 0x00ff00, side: THREE.DoubleSide} )
var lowBox = new THREE.Mesh(geometry,mate)

var l = geometry.faces.length
console.log(l)
if(l!=8) alert(l)

#

History:

I am writing a 3D renderer for OSM data: www.OSMgo.org
Many buildings do have "holes", some triangulate fine, some not:
The walls are ok but much roofs are missing holes.
As descripted abow it is clear why, isn't it?

To catch the problem, I reduced the code to the example abowe.
I run it with different values and got good and bad results.
Then I debugged and compared the way, the code did run
and found that patched line as the relevant difference.

I hope someone will find a propper solution for all cases.
May be all float compares have to be don with a little "tolerance".

-karlos-

Bug

Most helpful comment

Can you reproduce this using Earcut?

Earcut appears to work in this case.

fiddle using Earcut: http://jsfiddle.net/x6mfqch3/4/

@WestLangley I'm considering replacing the current triangulation code with Earcut.

That seems like a good idea to me.

All 14 comments

fiddle: jsfiddle.net/x6mfqch3/

EDIT: use this fiddle instead: http://jsfiddle.net/x6mfqch3/3/

Yes, if you use smaler numbers, the error is gone:
var FAR = 1000; // changed - was 10000
But that isn't a solution, is it?

I created the fidde for you simply to demonstrate the issue.

Thanks.
Just to clarify it:
To reproduche the problem, you have to use the larger number

This will show the square withOUT the hole:
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.set( 0, 0, 30000 );

Seems now I know how to handle it. With Error:
http://jsfiddle.net/DerKarlos/kcqvf4ja/

Can you reproduce this using Earcut?
https://threejs.org/examples/webgl_geometry_text_earcut.html#00FF19111#Earcut

@WestLangley I'm considering replacing the current triangulation code with Earcut.

Can you reproduce this using Earcut?

Earcut appears to work in this case.

fiddle using Earcut: http://jsfiddle.net/x6mfqch3/4/

@WestLangley I'm considering replacing the current triangulation code with Earcut.

That seems like a good idea to me.

@mrdoob How would the integration of Earcut would look like? Add the project as a new dependency to package.json?

@mrdoob How would the integration of Earcut would look like? Add the project as a new dependency to package.json?

Not sure... Maybe directly copying to /src/third-party/...?

I would prefer to manage project dependencies over npm. Makes everything easier. And we don't clutter the /src directory with source code that uses different code style and naming conventions.

I would prefer to manage project dependencies over npm. Makes everything easier. And we don't clutter the /src directory with source code that uses different code style and naming conventions.

That sure is tempting...

Had a similar problem, after hours of debugging and rewriting my code, the Earcut was the solution :sweat_smile: , Thanks for the issue.

+1 for integrating Earcut.

This should be fixed in r.89dev. The implementation is now based on earcut.

Hi!
Problem description:
I have a svg path with holes and i want to extrude geometry from it, everything is fine except usecase where i have a isolated inner figure in source svg path

here is a fiddle with example of problem

dev-branch fiddle

at top of the scene: is the final result of extruding

at bottom: separated subshapes, one hole related to another polygon

is this bug related to three.js or d3-three code?

@strangerintheq Please open a new issue for this.

Was this page helpful?
0 / 5 - 0 ratings