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
at top of the scene: is the final result of extruding
at bottom: separated subshapes, one hole related to another polygon
edit: i dig into three.js code and figured out that is a bug of ShapePath.toShapes method.
the part of code with detection of correct hole target is bugged. case when one area enclosed my another (countour hierarchy) is not handled properly
the part of code with detection of correct hole target is bugged. case when one area enclosed my another (countour hierarchy) is not handled properly
Can you please link to the mentioned code section? Besides, what would you do different?
https://github.com/mrdoob/three.js/blob/dev/src/extras/core/ShapePath.js
Scroll down source to last return statement.
Look at the value of return variable, in my case it contains two shapes, one with hole from another. Code above is trying to resolve the relations between shapes and holes, but..
Pasting the path from the fiddle into webgl_geometry_extrude_shapes2.html
produces this:
@strangerintheq What is your intended visual output?
I mean can you please specify the expected visual output with a screenshot? TBH, i don't understand what you are trying to achieve...
@Mugen87 here is expected result fiddle
it achieved by manual managing of svg path subpaths sequence
What does "manual managing" mean?
@WestLangley original svg path is the external input data for my app, in fiddle above i took last subpath and moved it to place after second subpath (1 2 3 4 5 -> 1 2 5 3 4)
moved it to place after second subpath (1 2 3 4 5 -> 1 2 5 3 4)
Why do you think that worked?
Are your subpaths clockwise or counterclockwise or both?
It seems that all my paths and sub paths is always clockwise
I was fixed bug in my case by adding following code at the end of:
https://github.com/mrdoob/three.js/blob/dev/src/extras/core/ShapePath.js
it is not an optimal solution, but it enough for me, and it handles more complex shapes that in my example...
Thanks for fast response guys!
return fixShapesHoles(shapes);
function fixShapesHoles(shapes) {
if (shapes.length > 1) {
var holesToShapeMap = [];
var allHoles = shapes.reduce(function (acc, shape) {
acc.holes = acc.holes.concat(shape.holes)
return acc;
}).holes;
shapes.forEach(function (shape) {
shape.holes = [];
});
allHoles.forEach(function (hole, i) {
holesToShapeMap[i] = findEnclosingShapes(hole, shapes)
});
holesToShapeMap.forEach(function (shapes, i) {
var targetShapeIndex = shapes.length === 1 ? 0 :
findLastInnerShapeIndex(shapes);
shapes[targetShapeIndex].holes.push(allHoles[i]);
});
}
return shapes;
}
function findEnclosingShapes(hole, shapes) {
return shapes.filter(function (shape) {
return isPointInsidePolygon(hole.currentPoint, shape.getPoints());
});
}
function findAllInnerShapes(shape, possibleInnerShapes) {
return possibleInnerShapes.filter(function (s) {
return isPointInsidePolygon(s.getPoints()[0], shape.getPoints());
});
}
function findLastInnerShapeIndex(shapes) {
return shapes.map (function (shape, i) {
var copy = shapes.slice(0);
copy.splice(copy.indexOf(shape), 1);
return {
index: i,
shapes: findAllInnerShapes(shape, copy)
};
}).find(function (item) {
return item.shapes.length === 0;
}).index;
}
PS: let me know if you interesting in pull request
It seems that all my paths and sub paths is always clockwise
By default, paths should be clockwise; holes counterclockwise. Please try it.
@WestLangley but how? it is a input data for me, i cant determine where is shape or hole to reverse hole path
By default, paths should be clockwise; holes counterclockwise. Please try it.
is this a three-js define? or svg spec?
See this SVG fill-rule property demo.
I think we can close this issue. Like @WestLangley mentioned, input paths should be clockwise, holes counterclockwise. Users have to ensure that their data corresponds to this standard.
input paths should be clockwise, holes counterclockwise. Users have to ensure that their data corresponds to this standard.
I would call it an SVG option, set by the SVG fill-rule
property.
It is a three.js standard, however -- subject to the value of the toShapes()
argument isCCW
.
Note that three.js fills by triangulation, while SVG fills per pixel.
Maybe this is something that SVGLoader
will be able to handle. Still early days though... #13478
I get same issue when fill-rule is evenodd.
All paths and holes are clockwise.
@whatisor can you share the file?
Here you are
google_PNG19642.svg.zip
It is generated by potrace library
So, I believe it is same issue to support evenodd rule:
https://github.com/iPlug2/iPlug2/issues/135
Most helpful comment
I would call it an SVG option, set by the SVG
fill-rule
property.It is a three.js standard, however -- subject to the value of the
toShapes()
argumentisCCW
.Note that three.js fills by triangulation, while SVG fills per pixel.