diff --git a/build.gradle b/build.gradle
index 0de77cc..5056e87 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,7 +18,7 @@ tasks.withType(Javadoc) {
}
task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') {
- gradleVersion = '3.3'
+ gradleVersion = '4.0'
}
repositories {
@@ -37,7 +37,7 @@ dependencies {
compile group: 'eu.mihosoft.ugshell.ugdist', name: 'ugshell-dist', version: '2016.1.5'
// jcsg library
- compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.2'
- compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.2', classifier: 'sources'
- compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.2', classifier: 'javadoc'
+ compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.5'
+ compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.5', classifier: 'sources'
+ compile group: 'eu.mihosoft.vrl.jcsg', name: 'jcsg', version: '0.5.5', classifier: 'javadoc'
}
diff --git a/gradle/project-info.gradle b/gradle/project-info.gradle
index 4de91ae..f9fb5d4 100644
--- a/gradle/project-info.gradle
+++ b/gradle/project-info.gradle
@@ -3,7 +3,7 @@
// -----------------------------------------------------------------------------
ext.publishing.artifactId = project.name.toLowerCase()
ext.publishing.groupId = 'eu.mihosoft.jcsg.ext.mesh'
-ext.publishing.versionId = '0.4-SNAPSHOT'
+ext.publishing.versionId = '0.4.0'
ext.publishing.developerName = 'Michael Hoffer'
ext.publishing.developerAlias = 'miho'
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index c5dc98a..5f48520 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0cd8e28..677511d 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Feb 04 11:51:45 CET 2017
+#Sun Jun 25 11:33:23 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-bin.zip
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
index 4453cce..cccdd3d
--- a/gradlew
+++ b/gradlew
@@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -155,7 +155,7 @@ if $cygwin ; then
fi
# Escape application args
-save ( ) {
+save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
diff --git a/gradlew.bat b/gradlew.bat
index f955316..e95643d 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,84 +1,84 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/main/java/eu/mihosoft/jcsg/ext/mesh/MeshTools.java b/src/main/java/eu/mihosoft/jcsg/ext/mesh/MeshTools.java
index a2886cf..15b83d5 100644
--- a/src/main/java/eu/mihosoft/jcsg/ext/mesh/MeshTools.java
+++ b/src/main/java/eu/mihosoft/jcsg/ext/mesh/MeshTools.java
@@ -35,12 +35,14 @@
import eu.mihosoft.ugshell.vugshell.Shell;
import eu.mihosoft.jcsg.CSG;
import eu.mihosoft.jcsg.STL;
+import eu.mihosoft.vvecmath.Transform;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
+import java.util.function.Function;
/**
* Mesh tools for optimizing and manipulating csg mesh objects.
@@ -92,19 +94,19 @@ public static CSG optimize(
Path tmpDir = Files.createTempDirectory("jcsgmeshopt");
Path stlFile = Paths.get(tmpDir.toAbsolutePath().toString(),
"csg.stl");
-
- System.out.println("f: " + stlFile);
+
+ System.out.println("mesh-ext: csg file: " + stlFile);
Files.write(stlFile, csg.toStlString().getBytes());
String code = read("optimize-and-repair.lua");
String pathVariable = stlFile.toAbsolutePath().toString();//
-
- if(System.getProperty("os.name").toLowerCase().contains("windows")) {
- pathVariable = pathVariable.replace("\\","\\\\");
+
+ if (System.getProperty("os.name").toLowerCase().contains("windows")) {
+ pathVariable = pathVariable.replace("\\", "\\\\");
}
-
+
code = code.replace("$filename$", "\""
+ pathVariable + "\"");
code = code.replace("$removeDoublesTOL$", "" + tol);
@@ -113,10 +115,9 @@ public static CSG optimize(
code = code.replace("$minEdgeLength$", "" + minEdgeLength);
code = code.replace("$maxEdgeLength$", "" + maxEdgeLength);
code = code.replace("$maxAdjIter$", "" + maxIter);
-
+
// code = code.replace("$edgeApprox$", "" + edgeApprox);
// code = code.replace("$edgeTriangleQuality$", "" + edgeTriangleQuality);
-
Shell.execute(tmpDir.toFile(), code).print().waitFor();
return STL.file(stlFile);
@@ -128,6 +129,103 @@ public static CSG optimize(
}
}
+ /**
+ * Optimizes and repairs the specified csg mesh object.
+ *
+ * Note: the size of the
+ * object during optimization can have a high impact on the overall
+ * optimization quality. Therefore, this method allows the specification of
+ * the size at which the optimization is performed. After the optimization
+ * the object is returned at original size.
+ *
+ * @param csg csg to optimize
+ * @param size object size at which to perform the optimization (minimum
+ * dimension)
+ * @param tol default tolerance
+ * @param maxTol maximum tolerance
+ * @param minEdgeLength minimum edge length
+ * @param maxEdgeLength maximum edge length
+ * @return optimized csg mesh object
+ */
+ public static CSG optimize(
+ CSG csg, double size, double tol,
+ double maxTol,
+ double minEdgeLength,
+ double maxEdgeLength) {
+ return scaleMinDimensionTo(csg, size,
+ (csgObj) -> optimize(
+ csg, tol, maxTol,
+ minEdgeLength, maxEdgeLength,
+ 10, 5.0));
+ }
+
+ /**
+ * Optimizes and repairs the specified csg mesh object.
+ *
+ * Note: the size of the
+ * object during optimization can have a high impact on the overall
+ * optimization quality. Therefore, this method allows the specification of
+ * the size at which the optimization is performed. After the optimization
+ * the object is returned at original size.
+ *
+ * @param csg csg to optimize
+ * @param size object size at which to perform the optimization (minimum
+ * dimension)
+ * @param tol default tolerance
+ * @param maxTol maximum tolerance
+ * @param minEdgeLength minimum edge length
+ * @param maxEdgeLength maximum edge length
+ * @param maxIter number of iterations for edge length adjustment
+ * @param creaseEdgeAngle angle threashold for crease edge marker
+ * @return optimized csg mesh object
+ */
+ public CSG optimize(CSG csg,
+ double size,
+ double tol,
+ double maxTol,
+ double minEdgeLength,
+ double maxEdgeLength,
+ int maxIter,
+ double creaseEdgeAngle) {
+ return scaleMinDimensionTo(csg, size,
+ (csgObj) -> optimize(csgObj, tol, maxTol,
+ minEdgeLength, maxEdgeLength));
+ }
+
+ /**
+ * Scales the minimum CSG dimension to the specified value, invokes the
+ * specified function and rescales the specified CSG object to its original
+ * size.
+ *
+ * @param csg csg to process at specified scale
+ * @param scale scale
+ * @param processF processing function
+ * @return the processed CSG at original scale
+ */
+ private static CSG scaleMinDimensionTo(CSG csg,
+ double scale, Function processF) {
+
+ double w = csg.getBounds().getBounds().getX();
+ double h = csg.getBounds().getBounds().getY();
+ double d = csg.getBounds().getBounds().getZ();
+
+ // find minimum dimension
+ double size = Math.min(w, Math.min(h, d));
+
+ // scale CSG object so its minimum dimension is 100 in size
+ CSG result = csg;
+ double scale1 = 1.0 / size * scale;
+ double scale2 = 1.0 / scale1;
+ result = result.transformed(Transform.unity().scale(scale1));
+
+ result = processF.apply(result);
+
+ // restore original scale
+ result = result.transformed(Transform.unity().scale(scale2));
+
+ return result;
+ }
+
private static String read(String resourceName) {
return new Scanner(MeshTools.class.getResourceAsStream(resourceName),
"UTF-8").useDelimiter("\\A").next();