Take the PShape above. Clearly it must know that the vertices of the inner region are not to be joined with the other vertices of the edge and represent a region that is “cut-out” from the shape. Processing calls such regions contours.
Is there a way to get this info from a PShape? i.e. which contour group each vertex belongs to?
Now there’s a method getVertexCodes()
which looked promising but the array it returns has less length than the number of vertices a shape has, so I wonder whether this refers to what I want and whether it’s possible to get this info from it.
1 Like
Hi @micycle ,
The vertex codes will not match the number of vertices. For a cubic Bezier vertex, there will be 3 pairs (6 floats) in vertices per command; for a quadratic Bezier vertex 2 pairs (4 floats) in vertices per command. That’s why this happens when a shape that should be a PATH
family
is assigned the GEOMETRY
family instead.
beginContour inserts a BREAK
command into the vertex commands list, so maybe you could use that in conjunction with a vertex winding algorithm to get what you’re looking for.
(Also, beware of implementation differences between a super-class PShape
and its sub-classes, for example PShapeOpenGL
).
EDIT: When I wanted to convert between a PShape and my own 2D curve class, I used this routine to loop through the commands. The code does not address contours but it may offer a basic outline.
Hope that helps some, Jeremy
1 Like
Thanks for your reply Jeremy.
After a bit more digging around in PShape
, I found a block of code here that reveals the logic of the vertex codes (for the super class at least). Reversing it is simple:
static int[] getContourGroups(int[] vertexCodes) {
int group = 0;
ArrayList<Integer> groups = new ArrayList<>(vertexCodes.length * 2);
for (int vertexCode : vertexCodes) {
switch (vertexCode) {
case VERTEX:
groups.add(group);
break;
case QUADRATIC_VERTEX:
groups.add(group);
groups.add(group);
break;
case BEZIER_VERTEX:
groups.add(group);
groups.add(group);
groups.add(group);
break;
case CURVE_VERTEX:
groups.add(group);
break;
case BREAK:
/*
* Marks beginning/end of new contour, and should be proceeded by a VERTEX
*/
group++;
break;
}
}
final int[] vertexGroups = new int[groups.size()];
Arrays.setAll(vertexGroups, groups::get);
return vertexGroups;
}
2 Likes