@@ -160,21 +160,84 @@ std::vector<std::vector<int>> map_mesh(
160160 return pattern_polygonal_faces;
161161}
162162
163- // Create the nanobind module
164- NB_MODULE (_mapping, m) {
165- // Bind std::vector<std::vector<int>> type for Python interoperability
166- nb::bind_vector<std::vector<int >>(m, " VectorInt" );
167- nb::bind_vector<std::vector<std::vector<int >>>(m, " VectorVectorInt" );
163+ std::vector<std::vector<int >> map_mesh_with_automatic_parameterization (
164+ Eigen::Ref<const compas::RowMatrixXd> target_v,
165+ Eigen::Ref<const compas::RowMatrixXi> target_f,
166+ Eigen::Ref<compas::RowMatrixXd> pattern_v,
167+ Eigen::Ref<const compas::RowMatrixXi> pattern_f)
168+ {
169+ // Compute target mesh UV parameterization using LSCM
170+ Eigen::MatrixXd target_uv;
171+
172+ // Find the open boundary
173+ Eigen::VectorXi B;
174+ igl::boundary_loop (target_f, B);
175+
176+ // Fix two points on the boundary
177+ Eigen::VectorXi fixed (2 , 1 );
178+ fixed (0 ) = B (0 );
179+ fixed (1 ) = B (B.size () / 2 );
180+
181+ Eigen::MatrixXd fixed_uv (2 , 2 );
182+ fixed_uv << 0 , 0 , 1 , 0 ;
183+
184+ // LSCM parametrization
185+ igl::lscm (target_v, target_f, fixed, fixed_uv, target_uv);
186+
187+ // Rescale target UV coordinates
188+ // Find min and max values for normalization
189+ Eigen::Vector2d min_coeff = target_uv.colwise ().minCoeff ();
190+ Eigen::Vector2d max_coeff = target_uv.colwise ().maxCoeff ();
191+
192+ // Compute the size of the bounding box
193+ Eigen::Vector2d size = max_coeff - min_coeff;
194+
195+ // Translate UV coordinates so minimum is at the origin
196+ target_uv.col (0 ) = target_uv.col (0 ).array () - min_coeff (0 );
197+ target_uv.col (1 ) = target_uv.col (1 ).array () - min_coeff (1 );
198+
199+ // Scale to fit in a 0-1 box while maintaining aspect ratio
200+ double scale_factor = 1.0 / std::max (size (0 ), size (1 ));
201+ target_uv *= scale_factor;
202+
203+ // Compute pattern mesh UV parameterization using simple method
204+ Eigen::MatrixXd pattern_uv = pattern_v.leftCols (2 ); // Use the first two columns (X and Y coordinates)
168205
206+ // Rescale pattern UV coordinates
207+ min_coeff = pattern_uv.colwise ().minCoeff ();
208+ max_coeff = pattern_uv.colwise ().maxCoeff ();
209+
210+ size = max_coeff - min_coeff;
211+
212+ pattern_uv.col (0 ) = pattern_uv.col (0 ).array () - min_coeff (0 );
213+ pattern_uv.col (1 ) = pattern_uv.col (1 ).array () - min_coeff (1 );
214+
215+ scale_factor = 1.0 / std::max (size (0 ), size (1 ));
216+ pattern_uv *= scale_factor;
217+
218+ // Now perform the mapping using the computed UV parameterizations
219+ return map_mesh (target_v, target_f, target_uv, pattern_v, pattern_f, pattern_uv);
220+ }
221+
222+ NB_MODULE (_mapping, m)
223+ {
169224 m.def (
170225 " map_mesh" ,
171226 &map_mesh,
172- " Map a 2D pattern mesh onto a 3D target mesh using simple UV parameterization " ,
173- " v " _a,
174- " f " _a,
175- " uv " _a,
227+ " Map a 2D pattern mesh onto a 3D target mesh. " ,
228+ " target_v " _a,
229+ " target_f " _a,
230+ " target_uv " _a,
176231 " pattern_v" _a,
177232 " pattern_f" _a,
178- " pattern_uv" _a
179- );
180- }
233+ " pattern_uv" _a);
234+
235+ m.def (
236+ " map_mesh_with_automatic_parameterization" ,
237+ &map_mesh_with_automatic_parameterization,
238+ " Map a 2D pattern mesh onto a 3D target mesh with automatic parameterization." ,
239+ " target_v" _a,
240+ " target_f" _a,
241+ " pattern_v" _a,
242+ " pattern_f" _a);
243+ }
0 commit comments