# How are PShape contours stored?

**URL:** https://discourse.processing.org/t/how-are-pshape-contours-stored/26997
**Category:** Coding Questions
**Created:** [January 12, 2021, 7:12pm UTC](https://discourse.processing.org/t/how-are-pshape-contours-stored/26997 "2021-01-12T19:12:36Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)
#### Post date: [January 12, 2021, 7:12pm UTC](https://discourse.processing.org/t/how-are-pshape-contours-stored/26997/1 "2021-01-12T19:12:36Z")

</div>

![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/7213c563219139d3afd3bf22d26b4c8e01e13a7a.png)

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](https://processing.org/reference/PShape_beginContour_.html).

**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.

---

<div class="post-metadata">

### Author: ![behreajj](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@behreajj](https://discourse.processing.org/u/behreajj)
#### Post date: [January 12, 2021, 7:45pm UTC](https://discourse.processing.org/t/how-are-pshape-contours-stored/26997/2 "2021-01-12T19:45:02Z")

</div>

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](https://discourse.processing.org/t/beziervertex-draws-straight-lines-not-a-curved-line/3139/5) when a shape that should be a `PATH` `family` is assigned the `GEOMETRY` family instead.

[beginContour](https://github.com/processing/processing/blob/94144be998354ecf7a06d5301b7b4fab72df724c/core/src/processing/core/PShape.java#L654) inserts a `BREAK` command into the vertex commands list, so maybe you could use that in conjunction with a [vertex winding algorithm](https://gamedev.stackexchange.com/questions/30537/how-to-determine-counter-clockwise-vertex-winding) 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](https://github.com/behreajj/CamZup/blob/bd01c7a57370ea16956c657f9c59b4704370fab7/src/camzup/pfriendly/Convert.java#L1356) to loop through the commands. The code does _not_ address contours but it may offer a basic outline.

Hope that helps some, Jeremy

---

<div class="post-metadata">

### Author: ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)
#### Post date: [January 12, 2021, 8:38pm UTC](https://discourse.processing.org/t/how-are-pshape-contours-stored/26997/3 "2021-01-12T20:38:13Z")

</div>

Thanks for your reply Jeremy.

After a bit more digging around in `PShape`, I found a block of code [here](https://github.com/processing/processing/blob/master/core/src/processing/core/PShape.java#L1814) that reveals the logic of the vertex codes (for the super class at least). Reversing it is simple:

```auto
	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;
	}

```

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/9/9727ee022308a275b0441680c167c7964e2c47a4.png)
