3535import eu .mihosoft .ugshell .vugshell .Shell ;
3636import eu .mihosoft .jcsg .CSG ;
3737import eu .mihosoft .jcsg .STL ;
38+ import eu .mihosoft .vvecmath .Transform ;
3839
3940import java .io .IOException ;
4041import java .nio .file .Files ;
4142import java .nio .file .Path ;
4243import java .nio .file .Paths ;
4344import java .util .Scanner ;
45+ import java .util .function .Function ;
4446
4547/**
4648 * Mesh tools for optimizing and manipulating csg mesh objects.
@@ -92,19 +94,19 @@ public static CSG optimize(
9294 Path tmpDir = Files .createTempDirectory ("jcsgmeshopt" );
9395 Path stlFile = Paths .get (tmpDir .toAbsolutePath ().toString (),
9496 "csg.stl" );
95-
96- System .out .println ("f : " + stlFile );
97+
98+ System .out .println ("mesh-ext: csg file : " + stlFile );
9799
98100 Files .write (stlFile , csg .toStlString ().getBytes ());
99101
100102 String code = read ("optimize-and-repair.lua" );
101103
102104 String pathVariable = stlFile .toAbsolutePath ().toString ();//
103-
104- if (System .getProperty ("os.name" ).toLowerCase ().contains ("windows" )) {
105- pathVariable = pathVariable .replace ("\\ " ,"\\ \\ " );
105+
106+ if (System .getProperty ("os.name" ).toLowerCase ().contains ("windows" )) {
107+ pathVariable = pathVariable .replace ("\\ " , "\\ \\ " );
106108 }
107-
109+
108110 code = code .replace ("$filename$" , "\" "
109111 + pathVariable + "\" " );
110112 code = code .replace ("$removeDoublesTOL$" , "" + tol );
@@ -113,10 +115,9 @@ public static CSG optimize(
113115 code = code .replace ("$minEdgeLength$" , "" + minEdgeLength );
114116 code = code .replace ("$maxEdgeLength$" , "" + maxEdgeLength );
115117 code = code .replace ("$maxAdjIter$" , "" + maxIter );
116-
118+
117119// code = code.replace("$edgeApprox$", "" + edgeApprox);
118120// code = code.replace("$edgeTriangleQuality$", "" + edgeTriangleQuality);
119-
120121 Shell .execute (tmpDir .toFile (), code ).print ().waitFor ();
121122
122123 return STL .file (stlFile );
@@ -128,6 +129,103 @@ public static CSG optimize(
128129 }
129130 }
130131
132+ /**
133+ * Optimizes and repairs the specified csg mesh object.
134+ *
135+ * <b>Note: </b>the size of the
136+ * object during optimization can have a high impact on the overall
137+ * optimization quality. Therefore, this method allows the specification of
138+ * the size at which the optimization is performed. After the optimization
139+ * the object is returned at original size.
140+ *
141+ * @param csg csg to optimize
142+ * @param size object size at which to perform the optimization (minimum
143+ * dimension)
144+ * @param tol default tolerance
145+ * @param maxTol maximum tolerance
146+ * @param minEdgeLength minimum edge length
147+ * @param maxEdgeLength maximum edge length
148+ * @return optimized csg mesh object
149+ */
150+ public static CSG optimize (
151+ CSG csg , double size , double tol ,
152+ double maxTol ,
153+ double minEdgeLength ,
154+ double maxEdgeLength ) {
155+ return scaleMinDimensionTo (csg , size ,
156+ (csgObj ) -> optimize (
157+ csg , tol , maxTol ,
158+ minEdgeLength , maxEdgeLength ,
159+ 10 , 5.0 ));
160+ }
161+
162+ /**
163+ * Optimizes and repairs the specified csg mesh object.
164+ *
165+ * <b>Note: </b>the size of the
166+ * object during optimization can have a high impact on the overall
167+ * optimization quality. Therefore, this method allows the specification of
168+ * the size at which the optimization is performed. After the optimization
169+ * the object is returned at original size.
170+ *
171+ * @param csg csg to optimize
172+ * @param size object size at which to perform the optimization (minimum
173+ * dimension)
174+ * @param tol default tolerance
175+ * @param maxTol maximum tolerance
176+ * @param minEdgeLength minimum edge length
177+ * @param maxEdgeLength maximum edge length
178+ * @param maxIter number of iterations for edge length adjustment
179+ * @param creaseEdgeAngle angle threashold for crease edge marker
180+ * @return optimized csg mesh object
181+ */
182+ public CSG optimize (CSG csg ,
183+ double size ,
184+ double tol ,
185+ double maxTol ,
186+ double minEdgeLength ,
187+ double maxEdgeLength ,
188+ int maxIter ,
189+ double creaseEdgeAngle ) {
190+ return scaleMinDimensionTo (csg , size ,
191+ (csgObj ) -> optimize (csgObj , tol , maxTol ,
192+ minEdgeLength , maxEdgeLength ));
193+ }
194+
195+ /**
196+ * Scales the minimum CSG dimension to the specified value, invokes the
197+ * specified function and rescales the specified CSG object to its original
198+ * size.
199+ *
200+ * @param csg csg to process at specified scale
201+ * @param scale scale
202+ * @param processF processing function
203+ * @return the processed CSG at original scale
204+ */
205+ private static CSG scaleMinDimensionTo (CSG csg ,
206+ double scale , Function <CSG , CSG > processF ) {
207+
208+ double w = csg .getBounds ().getBounds ().getX ();
209+ double h = csg .getBounds ().getBounds ().getY ();
210+ double d = csg .getBounds ().getBounds ().getZ ();
211+
212+ // find minimum dimension
213+ double size = Math .min (w , Math .min (h , d ));
214+
215+ // scale CSG object so its minimum dimension is 100 in size
216+ CSG result = csg ;
217+ double scale1 = 1.0 / size * scale ;
218+ double scale2 = 1.0 / scale1 ;
219+ result = result .transformed (Transform .unity ().scale (scale1 ));
220+
221+ result = processF .apply (result );
222+
223+ // restore original scale
224+ result = result .transformed (Transform .unity ().scale (scale2 ));
225+
226+ return result ;
227+ }
228+
131229 private static String read (String resourceName ) {
132230 return new Scanner (MeshTools .class .getResourceAsStream (resourceName ),
133231 "UTF-8" ).useDelimiter ("\\ A" ).next ();
0 commit comments