Skip to content

Commit

Permalink
Add JS bindings for triangulation (#393)
Browse files Browse the repository at this point in the history
* js binding for triangulation

* don't use CrossSection class as it alters the order of the vertices

* remove unused code,
rename original Triangulate to TriangulateIdx,
move TriangulateJS from bindings.cpp to polygon.cpp,
rename TrinagulateJS to Triangulate for consistent C++ and JS API,
add optional precision parameter
  • Loading branch information
jirihon authored Apr 4, 2023
1 parent f25d960 commit fbe4cc6
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 9 deletions.
2 changes: 1 addition & 1 deletion bindings/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ add_executable(manifoldjs bindings.cpp)
# make sure that we recompile the wasm when bindings.js is being modified
set_source_files_properties(bindings.cpp OBJECT_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/bindings.js)
target_link_libraries(manifoldjs manifold sdf cross_section)
target_link_libraries(manifoldjs manifold sdf cross_section polygon)
target_compile_options(manifoldjs PRIVATE ${MANIFOLD_FLAGS} -fexceptions)
target_link_options(manifoldjs PUBLIC --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/bindings.js --bind -sALLOW_TABLE_GROWTH=1
-sEXPORTED_RUNTIME_METHODS=addFunction,removeFunction -sMODULARIZE=1 -sEXPORT_ES6=1)
Expand Down
2 changes: 2 additions & 0 deletions bindings/wasm/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using namespace emscripten;

#include <manifold.h>
#include <polygon.h>
#include <sdf.h>

using namespace manifold;
Expand Down Expand Up @@ -266,6 +267,7 @@ EMSCRIPTEN_BINDINGS(whatever) {
function("tetrahedron", &Manifold::Tetrahedron);
function("_Smooth", &Smooth);
function("_Extrude", &Extrude);
function("_Triangulate", &Triangulate);
function("_Revolve", &Revolve);
function("_LevelSet", &LevelSetJs);

Expand Down
7 changes: 7 additions & 0 deletions bindings/wasm/bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ Module.setup = function() {
return result;
};

Module.triangulate = function(polygons, precision = -1) {
const polygonsVec = polygons2vec(polygons);
const result = fromVec(Module._Triangulate(polygonsVec, precision), (x) => [x[0], x[1], x[2]]);
disposePolygons(polygonsVec);
return result;
}

Module.revolve = function(polygons, circularSegments = 0) {
const polygonsVec = polygons2vec(polygons);
const result = Module._Revolve(polygonsVec, circularSegments);
Expand Down
10 changes: 10 additions & 0 deletions bindings/wasm/manifold-encapsulated-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ export function extrude(
crossSection: Polygons, height: number, nDivisions?: number,
twistDegrees?: number, scaleTop?: Vec2): Manifold;

/**
* Triangulates a set of /epsilon-valid polygons.
*
* @param polygons The set of polygons, wound CCW and representing multiple
* polygons and/or holes.
* @param precision The value of epsilon, bounding the uncertainty of the input
* @return The triangles, referencing the original polygon points in order.
*/
export function triangulate(polygons: Polygons, precision?: number): Vec3[];

/**
* Constructs a manifold from a set of polygons by revolving this cross-section
* around its Y-axis and then setting this as the Z-axis of the resulting
Expand Down
1 change: 1 addition & 0 deletions bindings/wasm/manifold.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface ManifoldStatic {
smooth: typeof T.smooth;
tetrahedron: typeof T.tetrahedron;
extrude: typeof T.extrude;
triangulate: typeof T.triangulate;
revolve: typeof T.revolve;
union: typeof T.union;
difference: typeof T.difference;
Expand Down
2 changes: 1 addition & 1 deletion src/manifold/src/constructors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ Manifold Manifold::Extrude(const CrossSection& crossSection, float height,
if (isCone)
for (int j = 0; j < polygons.size(); ++j) // Duplicate vertex for Genus
vertPos.push_back({0.0f, 0.0f, height});
std::vector<glm::ivec3> top = Triangulate(polygonsIndexed);
std::vector<glm::ivec3> top = TriangulateIdx(polygonsIndexed);
for (const glm::ivec3& tri : top) {
triVerts.push_back({tri[0], tri[2], tri[1]});
if (!isCone) triVerts.push_back(tri + nCrossSection * nDivisions);
Expand Down
2 changes: 1 addition & 1 deletion src/manifold/src/face_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge,

const PolygonsIdx polys = Face2Polygons(face, projection, faceEdge);

std::vector<glm::ivec3> newTris = Triangulate(polys, precision_);
std::vector<glm::ivec3> newTris = TriangulateIdx(polys, precision_);

for (auto tri : newTris) {
triVerts.push_back(tri);
Expand Down
7 changes: 5 additions & 2 deletions src/polygon/include/polygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ struct PolyVert {
using SimplePolygonIdx = std::vector<PolyVert>;
using PolygonsIdx = std::vector<SimplePolygonIdx>;

std::vector<glm::ivec3> Triangulate(const PolygonsIdx &polys,
float precision = -1);
std::vector<glm::ivec3> TriangulateIdx(const PolygonsIdx &polys,
float precision = -1);

std::vector<glm::ivec3> Triangulate(
std::vector<std::vector<glm::vec2>> &polygons, float precision = -1);

ExecutionParams &PolygonParams();
/** @} */
Expand Down
26 changes: 25 additions & 1 deletion src/polygon/src/polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,8 @@ namespace manifold {
* @return std::vector<glm::ivec3> The triangles, referencing the original
* vertex indicies.
*/
std::vector<glm::ivec3> Triangulate(const PolygonsIdx &polys, float precision) {
std::vector<glm::ivec3> TriangulateIdx(const PolygonsIdx &polys,
float precision) {
std::vector<glm::ivec3> triangles;
try {
Monotones monotones(polys, precision);
Expand All @@ -1069,6 +1070,29 @@ std::vector<glm::ivec3> Triangulate(const PolygonsIdx &polys, float precision) {
return triangles;
}

/**
* @brief Triangulates a set of /epsilon-valid polygons.
*
* @param polygons The set of polygons, wound CCW and representing multiple
* polygons and/or holes.
* @param precision The value of epsilon, bounding the uncertainty of the input
* @return std::vector<glm::ivec3> The triangles, referencing the original
* polygon points in order.
*/
std::vector<glm::ivec3> Triangulate(
std::vector<std::vector<glm::vec2>> &polygons, float precision) {
int idx = 0;
PolygonsIdx polygonsIndexed;
for (auto &poly : polygons) {
SimplePolygonIdx simpleIndexed;
for (const glm::vec2 &polyVert : poly) {
simpleIndexed.push_back({polyVert, idx++});
}
polygonsIndexed.push_back(simpleIndexed);
}
return TriangulateIdx(polygonsIndexed, precision);
}

ExecutionParams &PolygonParams() { return params; }

} // namespace manifold
6 changes: 3 additions & 3 deletions test/polygon_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ void TestPoly(const PolygonsIdx &polys, int expectedNumTri,
PolygonParams().verbose = options.params.verbose;

std::vector<glm::ivec3> triangles;
EXPECT_NO_THROW(triangles = Triangulate(polys, precision));
EXPECT_NO_THROW(triangles = TriangulateIdx(polys, precision));
EXPECT_EQ(triangles.size(), expectedNumTri) << "Basic";

EXPECT_NO_THROW(triangles = Triangulate(Turn180(polys), precision));
EXPECT_NO_THROW(triangles = TriangulateIdx(Turn180(polys), precision));
EXPECT_EQ(triangles.size(), expectedNumTri) << "Turn 180";

EXPECT_NO_THROW(triangles = Triangulate(Duplicate(polys), precision));
EXPECT_NO_THROW(triangles = TriangulateIdx(Duplicate(polys), precision));
EXPECT_EQ(triangles.size(), 2 * expectedNumTri) << "Duplicate";

PolygonParams().verbose = false;
Expand Down

0 comments on commit fbe4cc6

Please sign in to comment.