Creating a shape defined by dynamically added vertices

Hello!

I’m trying to implement a feature to a piece of software where users can essentially ‘draw’ an area and that area would be enclosed and colored.

I made a short video which should better explain what I’m trying to do:

As for now, it works perfectly with a triangular shape, but as soon as more vertices are added, the area is not filled entirely and it gets very messy.

In the video I’m laying down markers with a left click and cancel adding a new marker with a right click.

In the the end I’d like the entire area to be colored only in the inside.

The idea is that I create the mesh once in the constructor and then later as the user adds points/markers, the geometry of that mesh is updated accordingly and a new mesh is rendered with updated vertices.

In the constructor:

this.positions = new Float32Array( 500 * 3 ); 
this.fill = this.createFill()
this.add(this.fill)

Instance method:

createFill() {
    const geometry = new THREE.BufferGeometry();
    geometry.setAttribute( 'position', new THREE.BufferAttribute(this.positions, 3));

    let mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
        color: "red",
        side: THREE.DoubleSide,
	    transparent: true,
	    opacity: .3
    }));

    return mesh
}

The following lines are all in the update/render method. this.points refers to markers the user has added.

The idea is that I loop over all of the markers/points, push them to a temp array and then create a new geometry based on these points. The reason I do this in the update method, is so that if the user moves any of the markers or adds a new one, the location of that point is updated immediately.

let verts = []

for (let i = 0; i <= this.points.length - 1; i++) {
    let point = this.points[i];

    verts.push(new THREE.Vector3(
        point.position.x, 
	    point.position.y, 
	    point.position.z
	));
}

this.positions = verts
this.fill.geometry.setFromPoints(verts)

this.fill.geometry.attributes.position.needsUpdate = true
this.fill.geometry.computeBoundingBox();
this.fill.geometry.computeBoundingSphere();

I believe I’m more or less on the right track, but I’m obviously doing something wrong as so far it only works with a triangular shape. How could I make it work with any shape?

I also tried this solution but couldn’t get it to work with the update method - it did create the desired shape but it wasn’t “responsive”. With every new marker added, the old coloring remained and the new overlapped the old one.

If you have any ideas whatsoever, please let me know, it’s driving me insane.

Thank you!

The problem you’re trying to address is called “polygon triangulation” and has extensive coverage in the literature. Basically it’s about decomposing an arbitrarily shaped polygon into a set of triangles.There can be a number of complications:

  • polygons can be non-convex, meaning: a rubber band tied around the contour doesn’t touch all vertices.
  • polygons may also contain “holes”.

Google: “polygon triangulation” and look at the images and you’ll get the idea, where your “mess” may be coming from.

Once you’ve figured out how to triangulate a polygon, you’re still not set:

If yo want to do it dynamically on your website, adding one more points to an existing polygon may very well result in an entirely(!) different triangulation (set of triangles). So you’ll have to discard the previous result (set of triangles) and re-create based on the new triangulation.

Maybe you can use some of my examples?

Construction of frames with contour/profile

Addon for triangulation of implicit surfaces/ forms with holes

forms with holes star at bottom

When generating the star with the star-shaped holes, there may be malfunctions. The algorithm sometimes fails with corners that are too sharp and fine in relation to the given size of the triangles used for triangulation.