├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── README.md ├── build └── build.xml ├── license.txt ├── plugin ├── icon.png ├── plugin.xml └── version.properties ├── pom.xml └── src └── org └── ifcopenshell ├── ClientRunner.java ├── IfcGeomServerClient.java ├── IfcGeomServerClientEntity.java ├── IfcOpenShellEngine.java ├── IfcOpenShellEnginePlugin.java ├── IfcOpenShellEntityInstance.java └── IfcOpenShellModel.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /target/ 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | IfcOpenShellPlugin 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.jdt.core.javanature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | encoding/plugin=UTF-8 4 | encoding/src=UTF-8 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 7 | org.eclipse.jdt.core.compiler.release=disabled 8 | org.eclipse.jdt.core.compiler.source=1.8 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | IfcOpenShell-BIMserver-plugin 2 | ============================= 3 | 4 | IfcOpenShell BIMserver plugin 5 | 6 | Occasional problems and solutions 7 | ----------------- 8 | 9 | ### The 3D view does not show anything 10 | If you see `org.bimserver.plugins.renderengine.RenderEngineException: java.io.EOFException` in the geometry generation report, have a look at [BIMserver issue #633](https://github.com/opensourceBIM/BIMserver/issues/633) for a possible reason and [solution](https://github.com/opensourceBIM/BIMserver/issues/633#issuecomment-341644945). Updating gcc and libstdc++ may solve the issue. 11 | 12 | ### Some products are missing from the 3D view 13 | If you see `java.lang.Exception: Missing objects in model` in the geometry generation report, IfcOpenShell was not able to generate geometry for these products. This may happen when you use an older version of IfcOpenShell. In that case it may help to update IfcOpenShell to a newer version through the "build version" (previously "commit sha") plugin setting as described in [BIMserver issue #1207](https://github.com/opensourceBIM/BIMserver/issues/1207#issuecomment-878117652). 14 | -------------------------------------------------------------------------------- /build/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2009-2019 BIMserver.org 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU Affero General Public License as 5 | published by the Free Software Foundation, either version 3 of the 6 | License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU Affero General Public License for more details. 12 | 13 | You should have received a copy of the GNU Affero General Public License 14 | along with this program. If not, see {@literal}. -------------------------------------------------------------------------------- /plugin/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensourceBIM/IfcOpenShell-BIMserver-plugin/e18dd518330518783211e17f93c74fd78bde7c1f/plugin/icon.png -------------------------------------------------------------------------------- /plugin/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.bimserver.plugins.renderengine.RenderEnginePlugin 5 | org.ifcopenshell.IfcOpenShellEnginePlugin 6 | Open source IFC geometry engine visit <a href='http://ifcopenshell.org'>ifcopenshell.org</a> 7 | IfcOpenShell 8 | 9 | -------------------------------------------------------------------------------- /plugin/version.properties: -------------------------------------------------------------------------------- 1 | build.date=${timestamp} -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | org.opensourcebim 5 | ifcopenshellplugin 6 | 0.5.97-SNAPSHOT 7 | IfcOpenShell-BIMserver-plugin 8 | BIMserver plugin that uses IfcOpenShell to generate geometry from IFC files 9 | https://github.com/opensourceBIM/IfcOpenShell-BIMserver-plugin 10 | 11 | OpenSource BIM 12 | opensourcebim.org 13 | 14 | 15 | 16 | GNU Affero General Public License 17 | http://www.gnu.org/licenses/agpl-3.0.en.html 18 | repo 19 | 20 | 21 | 22 | 23 | Ruben de Laat 24 | ruben@logic-labs.nl 25 | 26 | 27 | 28 | scm:git:https://github.com/opensourceBIM/IfcOpenShell-BIMserver-plugin.git 29 | scm:git:https://github.com/opensourceBIM/IfcOpenShell-BIMserver-plugin.git 30 | https://github.com/opensourceBIM/IfcOpenShell-BIMserver-plugin.git 31 | HEAD 32 | 33 | 34 | GitHub 35 | https://github.com/opensourceBIM/IfcOpenShell-BIMserver-plugin/issues 36 | 37 | 38 | 39 | ossrh 40 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 41 | 42 | 43 | ossrh 44 | https://oss.sonatype.org/content/repositories/snapshots 45 | 46 | 47 | 48 | yyyy-MM-dd'T'HH:mm:ssZ 49 | UTF-8 50 | ${maven.build.timestamp} 51 | 52 | 53 | 54 | org.opensourcebim 55 | pluginbase 56 | 1.5.187 57 | 58 | 59 | 60 | 61 | central 62 | https://repo1.maven.org/maven2 63 | 64 | 65 | 66 | src 67 | 68 | 69 | plugin 70 | true 71 | plugin 72 | 73 | 74 | img 75 | img 76 | 77 | 78 | 79 | 80 | org.codehaus.mojo 81 | build-helper-maven-plugin 82 | 3.6.0 83 | 84 | 85 | attach-plugin 86 | package 87 | 88 | attach-artifact 89 | 90 | 91 | 92 | 93 | plugin/plugin.xml 94 | xml 95 | plugin 96 | 97 | 98 | plugin/icon.png 99 | png 100 | icon 101 | 102 | 103 | ${project.build.outputDirectory}/plugin/version.properties 104 | properties 105 | version 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | maven-compiler-plugin 114 | 3.10.1 115 | 116 | 8 117 | 118 | 119 | 120 | org.sonatype.plugins 121 | nexus-staging-maven-plugin 122 | 1.6.3 123 | true 124 | 125 | ossrh 126 | https://oss.sonatype.org/ 127 | false 128 | 129 | 130 | 131 | maven-release-plugin 132 | 2.5.3 133 | 134 | 135 | pom.xml 136 | 137 | false 138 | release 139 | deploy 140 | 141 | 142 | 143 | 144 | 145 | 146 | release 147 | 148 | 149 | 150 | maven-gpg-plugin 151 | 1.5 152 | 153 | 154 | sign-artifacts 155 | verify 156 | 157 | sign 158 | 159 | 160 | 161 | --pinentry-mode 162 | loopback 163 | 164 | ${gpg.keyname} 165 | 166 | 167 | 168 | 169 | 170 | maven-javadoc-plugin 171 | 3.11.2 172 | 173 | 174 | attach-javadocs 175 | 176 | jar 177 | 178 | 179 | 180 | 181 | 182 | maven-source-plugin 183 | 2.4 184 | 185 | 186 | attach-javadocs 187 | 188 | jar 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /src/org/ifcopenshell/ClientRunner.java: -------------------------------------------------------------------------------- 1 | package org.ifcopenshell; 2 | 3 | /****************************************************************************** 4 | * Copyright (C) 2009-2019 BIMserver.org 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see {@literal}. 18 | *****************************************************************************/ 19 | 20 | import java.io.FileInputStream; 21 | import java.io.FileNotFoundException; 22 | 23 | import org.bimserver.plugins.renderengine.RenderEngineException; 24 | import org.bimserver.plugins.renderengine.RenderEngineGeometry; 25 | 26 | public class ClientRunner { 27 | 28 | public static void main(String [] args) 29 | { 30 | try (IfcGeomServerClient client = new IfcGeomServerClient(IfcGeomServerClient.ExecutableSource.S3, IfcOpenShellEnginePlugin.DEFAULT_BUILD_VERSION)) { 31 | try { 32 | client.setCalculateQuantities(true); 33 | } catch (RenderEngineException e1) { 34 | e1.printStackTrace(); 35 | } 36 | try { 37 | client.setApplyLayersets(true); 38 | } catch (RenderEngineException e1) { 39 | e1.printStackTrace(); 40 | } 41 | 42 | try { 43 | client.loadModel(new FileInputStream(args[0])); 44 | } catch (FileNotFoundException | RenderEngineException e) { 45 | e.printStackTrace(); 46 | return; 47 | } 48 | 49 | double t0 = java.lang.System.nanoTime(); 50 | 51 | while (client.hasNext()) { 52 | try { 53 | IfcGeomServerClientEntity instance = client.getNext(); 54 | if (instance == null) { 55 | System.out.println("Internal error"); 56 | return; 57 | } 58 | System.out.println(String.format("%s %s", instance.getType(), instance.getGuid())); 59 | System.out.println(instance.getAllExtendedData().toString()); 60 | RenderEngineGeometry geometry = new RenderEngineGeometry(instance.getIndices(), instance.getPositions(), instance.getNormals(), instance.getColors(), instance.getMaterialIndices()); 61 | System.out.println(String.format("Vertex buffer size: %d", geometry.getNrVertices())); 62 | System.out.println(String.format("Normal buffer size: %d", geometry.getNrNormals())); 63 | System.out.println(String.format("Index buffer size: %d", geometry.getNrIndices())); 64 | System.out.println(String.format("Material buffer size: %d", geometry.getNrMaterials())); 65 | System.out.println(String.format("Material index buffer size: %d", geometry.getNrMaterialIndices())); 66 | } catch (RenderEngineException e) { 67 | e.printStackTrace(); 68 | return; 69 | } 70 | } 71 | 72 | System.out.println(String.format("Conversion took %.2f seconds", (java.lang.System.nanoTime() - t0) / 1.e9)); 73 | 74 | } catch (RenderEngineException e) { 75 | e.printStackTrace(); 76 | return; 77 | } 78 | System.exit(0); 79 | } 80 | } -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcGeomServerClient.java: -------------------------------------------------------------------------------- 1 | package org.ifcopenshell; 2 | 3 | /****************************************************************************** 4 | * Copyright (C) 2009-2019 BIMserver.org 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see {@literal}. 18 | *****************************************************************************/ 19 | 20 | import java.io.ByteArrayInputStream; 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | import java.net.URISyntaxException; 27 | import java.net.URL; 28 | import java.nio.ByteBuffer; 29 | import java.nio.ByteOrder; 30 | import java.nio.DoubleBuffer; 31 | import java.nio.FloatBuffer; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | import java.nio.file.Paths; 35 | import java.nio.file.attribute.FileTime; 36 | import java.nio.file.attribute.PosixFilePermission; 37 | import java.util.GregorianCalendar; 38 | import java.util.HashSet; 39 | import java.util.Set; 40 | import java.util.zip.ZipInputStream; 41 | 42 | import org.apache.commons.io.IOUtils; 43 | import org.apache.http.Header; 44 | import org.apache.http.client.methods.CloseableHttpResponse; 45 | import org.apache.http.client.methods.HttpGet; 46 | import org.apache.http.client.utils.DateUtils; 47 | import org.apache.http.impl.client.CloseableHttpClient; 48 | import org.apache.http.impl.client.HttpClients; 49 | import org.bimserver.plugins.renderengine.RenderEngineException; 50 | import org.bimserver.shared.exceptions.PluginException; 51 | import org.slf4j.Logger; 52 | import org.slf4j.LoggerFactory; 53 | 54 | import com.google.common.base.Charsets; 55 | import com.google.common.io.ByteStreams; 56 | import com.google.common.io.LittleEndianDataInputStream; 57 | import com.google.common.io.LittleEndianDataOutputStream; 58 | 59 | public class IfcGeomServerClient implements AutoCloseable { 60 | private static final Logger LOGGER = LoggerFactory.getLogger(IfcGeomServerClient.class); 61 | 62 | private boolean calculateQuantities = false; 63 | private boolean applyLayersets = false; 64 | private boolean disableOpeningSubtractions = false; 65 | 66 | public boolean doesCalculateQuantities() { 67 | return calculateQuantities; 68 | } 69 | 70 | public void setCalculateQuantities(boolean calculateQuantities) throws RenderEngineException { 71 | if (process != null) { 72 | throw new RenderEngineException("Cannot be changed when running"); 73 | } 74 | this.calculateQuantities = calculateQuantities; 75 | } 76 | 77 | public boolean doesApplyLayersets() { 78 | return applyLayersets; 79 | } 80 | 81 | public void setApplyLayersets(boolean applyLayersets) throws RenderEngineException { 82 | if (process != null) { 83 | throw new RenderEngineException("Cannot be changed when running"); 84 | } 85 | this.applyLayersets = applyLayersets; 86 | } 87 | 88 | public boolean disablesOpeningSubtractions(){ 89 | return disableOpeningSubtractions; 90 | } 91 | 92 | public void setDisableOpeningSubtractions(boolean disableOpeningSubtractions) throws RenderEngineException { 93 | if (process != null) { 94 | throw new RenderEngineException("Cannot be changed when running"); 95 | } 96 | this.disableOpeningSubtractions = disableOpeningSubtractions; 97 | } 98 | 99 | private Process process = null; 100 | private LittleEndianDataInputStream dis = null; 101 | private LittleEndianDataOutputStream dos = null; 102 | private boolean hasMore = false; 103 | 104 | private volatile boolean running = true; 105 | 106 | private Path executableFilename; 107 | 108 | private GregorianCalendar buildDateTime; 109 | 110 | public Path getExecutableFilename() { 111 | return executableFilename; 112 | } 113 | 114 | @Override 115 | public void close() throws RenderEngineException { 116 | running = false; 117 | terminate(); 118 | } 119 | 120 | private static String getOs() throws RenderEngineException { 121 | final String os = System.getProperty("os.name").toLowerCase(); 122 | if (os.contains("windows")) { 123 | return "win"; 124 | } else if (os.contains("osx") || os.contains("os x") || os.contains("darwin") || os.contains("mac")) { 125 | return "osx"; 126 | } else if (os.contains("linux")) { 127 | return "linux"; 128 | } else { 129 | throw new RenderEngineException(String.format("IfcOpenShell is not available on the %s platorm", os)); 130 | } 131 | } 132 | 133 | private static String getExecutableExtension() { 134 | final String os = System.getProperty("os.name").toLowerCase(); 135 | if (os.contains("windows")) { 136 | return ".exe"; 137 | } else { 138 | return ""; 139 | } 140 | } 141 | 142 | public static Path getExecutablePathFromRepo(Path root) throws PluginException { 143 | final String executableName = "IfcGeomServer" + getExecutableExtension(); 144 | final String operatingSystem = getOs(); 145 | final String bitness = operatingSystem.equals("osx") ? "64" : System.getProperty("sun.arch.data.model"); 146 | 147 | return root.resolve("exe").resolve(bitness).resolve(operatingSystem).resolve(executableName); 148 | } 149 | 150 | private Path getSourcePath() throws RenderEngineException { 151 | String name = getClass().getName(); 152 | int lastDot = name.lastIndexOf("."); 153 | name = name.substring(lastDot + 1) + ".class"; 154 | try { 155 | return Paths.get(this.getClass().getResource(name).toURI()).getParent().getParent().getParent().getParent().getParent(); 156 | } catch (URISyntaxException e) { 157 | throw new RenderEngineException(e); 158 | } 159 | } 160 | 161 | public enum ExecutableSource { 162 | REPOSITORY, S3 163 | } 164 | 165 | public IfcGeomServerClient(ExecutableSource source, String buildVersion) throws RenderEngineException { 166 | getExecutable(source, buildVersion, Paths.get(System.getProperty("user.home"))); 167 | } 168 | 169 | public IfcGeomServerClient(ExecutableSource source, String buildVersion, Path homeDir) throws RenderEngineException { 170 | getExecutable(source, buildVersion, homeDir); 171 | } 172 | 173 | private void getExecutable(ExecutableSource source, String buildVersion, Path homeDir) throws RenderEngineException { 174 | if (source == ExecutableSource.REPOSITORY) { 175 | try { 176 | this.executableFilename = getExecutablePathFromRepo(getSourcePath()); 177 | FileTime fileTime = (FileTime) Files.getAttribute(this.executableFilename, "creationTime"); 178 | buildDateTime = new GregorianCalendar(); 179 | buildDateTime.setTimeInMillis(fileTime.toMillis()); 180 | } catch (PluginException e) { 181 | throw new RenderEngineException(e); 182 | } catch (IOException e) { 183 | throw new RenderEngineException(e); 184 | } 185 | } else if (source == ExecutableSource.S3) { 186 | boolean initialized = false; 187 | 188 | String platform = getPlatform(); 189 | try { 190 | String url = "https://s3.amazonaws.com/ifcopenshell-builds/IfcGeomServer-" + buildVersion + "-" + platform + ".zip"; 191 | 192 | String baseName = new File(new URL(url).getPath()).getName(); 193 | baseName = baseName.substring(0, baseName.length() - 4); 194 | baseName += getExecutableExtension(); 195 | this.executableFilename = homeDir.resolve(baseName); 196 | 197 | if (!Files.exists(this.executableFilename)) { 198 | LOGGER.info(String.format("Downloading from %s", url)); 199 | Files.createDirectories(this.executableFilename.getParent()); 200 | LOGGER.info(String.format("Unzipping to %s", this.executableFilename.toString())); 201 | 202 | try (CloseableHttpClient httpClient = HttpClients.createSystem()) { 203 | HttpGet httpGet = new HttpGet(url); 204 | try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { 205 | if (httpResponse.getStatusLine().getStatusCode() == 200) { 206 | Header lastModified = httpResponse.getFirstHeader("Last-Modified"); 207 | LOGGER.info("IfcOpenShell Last Modified: " + lastModified.getValue()); 208 | buildDateTime = new GregorianCalendar(); 209 | buildDateTime.setTime(DateUtils.parseDate(lastModified.getValue())); 210 | 211 | try (ZipInputStream zipInputStream = new ZipInputStream(httpResponse.getEntity().getContent())) { 212 | try (OutputStream fos = Files.newOutputStream(this.executableFilename)) { 213 | // tfk: assume single entry 214 | zipInputStream.getNextEntry(); 215 | ByteStreams.copy(zipInputStream, fos); 216 | } 217 | } 218 | 219 | Files.setAttribute(this.executableFilename, "creationTime", FileTime.fromMillis(buildDateTime.getTimeInMillis())); 220 | } else { 221 | LOGGER.error(httpResponse.getStatusLine().toString()); 222 | LOGGER.error("File not found " + url); 223 | throw new RenderEngineException("File not found " + url); 224 | } 225 | } 226 | } 227 | 228 | try { 229 | Set permissions = new HashSet<>(); 230 | permissions.add(PosixFilePermission.OWNER_EXECUTE); 231 | permissions.add(PosixFilePermission.OWNER_READ); 232 | permissions.add(PosixFilePermission.OWNER_WRITE); 233 | Files.setPosixFilePermissions(this.executableFilename, permissions); 234 | } catch (Exception e) {} 235 | } else { 236 | FileTime fileTime = (FileTime) Files.getAttribute(this.executableFilename, "creationTime"); 237 | buildDateTime = new GregorianCalendar(); 238 | buildDateTime.setTimeInMillis(fileTime.toMillis()); 239 | } 240 | 241 | initialized = true; 242 | } catch (IOException | PluginException e) { 243 | throw new RenderEngineException(e); 244 | } 245 | if (!initialized) { 246 | throw new RenderEngineException("No IfcGeomServer executable found for platform '" + platform + "'"); 247 | } 248 | } 249 | } 250 | 251 | public IfcGeomServerClient(Path executableFilename) throws RenderEngineException { 252 | this.executableFilename = executableFilename; 253 | } 254 | 255 | public void initialize() throws RenderEngineException { 256 | try { 257 | process = Runtime.getRuntime().exec(new String[]{this.executableFilename.toAbsolutePath().toString()}); 258 | dos = new LittleEndianDataOutputStream(process.getOutputStream()); 259 | dis = new LittleEndianDataInputStream(process.getInputStream()); 260 | 261 | if (dis.readInt() != HELLO) { 262 | LOGGER.error("Invalid welcome message received"); 263 | terminate(); 264 | return; 265 | } 266 | 267 | Hello h = new Hello(); 268 | h.read(dis); 269 | 270 | boolean isV070 = h.getString().startsWith("IfcOpenShell-v0.7.0"); // https://github.com/IfcOpenShell/IfcOpenShell/commit/ff73f82798a8e744a0b7e2aaa353252df0a2934c 271 | new Setting(Setting.SettingId.CALCULATE_QUANTITITES, calculateQuantities).write(dos); 272 | new Setting(isV070 ? Setting.SettingId.APPLY_LAYERSETS_V070 : Setting.SettingId.APPLY_LAYERSETS, applyLayersets).write(dos); 273 | new Setting(isV070 ? Setting.SettingId.DISABLE_OPENING_SUBTRACTION_V070 : Setting.SettingId.DISABLE_OPENING_SUBTRACTION, disableOpeningSubtractions).write(dos); 274 | } catch (IOException e) { 275 | throw new RenderEngineException(e); 276 | } 277 | } 278 | 279 | public void loadModel(InputStream inputStream) throws RenderEngineException { 280 | if (process == null) { 281 | initialize(); 282 | } 283 | 284 | IfcModel m = new IfcModel(inputStream); 285 | try { 286 | m.write(dos); 287 | askForMore(); 288 | } catch (IOException e) { 289 | close(); 290 | } 291 | } 292 | 293 | public void loadModel(InputStream inputStream, long length) throws RenderEngineException { 294 | if (process == null) { 295 | initialize(); 296 | } 297 | 298 | IfcModel m = new IfcModel(inputStream, length); 299 | try { 300 | m.write(dos); 301 | askForMore(); 302 | } catch (IOException e) { 303 | close(); 304 | } 305 | } 306 | 307 | private static final int HELLO = 0xff00; 308 | private static final int IFC_MODEL = HELLO + 1; 309 | private static final int GET = IFC_MODEL + 1; 310 | private static final int ENTITY = GET + 1; 311 | private static final int MORE = ENTITY + 1; 312 | private static final int NEXT = MORE + 1; 313 | private static final int BYE = NEXT + 1; 314 | private static final int GET_LOG = BYE + 1; 315 | private static final int LOG = GET_LOG + 1; 316 | private static final int DEFLECTION = LOG + 1; 317 | private static final int SETTING = DEFLECTION + 1; 318 | 319 | private static final String PROTOCOL_VERSION = "IfcOpenShell-0.6.0b0-0"; 320 | 321 | abstract static class Command { 322 | abstract void read_contents(LittleEndianDataInputStream s) throws IOException; 323 | 324 | abstract void write_contents(LittleEndianDataOutputStream s) throws IOException; 325 | 326 | int iden; 327 | int len; 328 | 329 | void read(LittleEndianDataInputStream s) throws IOException { 330 | len = s.readInt(); 331 | read_contents(s); 332 | } 333 | 334 | void write(LittleEndianDataOutputStream s) throws IOException { 335 | s.writeInt(iden); 336 | ByteArrayOutputStream oss = new ByteArrayOutputStream(); 337 | write_contents(new LittleEndianDataOutputStream(oss)); 338 | 339 | // Comment Ruben: It seems redundant to send the size twice (when 340 | // sending a String, LittleEndianness should not change the size I 341 | // think) 342 | // Also storing the intermediate results in another buffer can be 343 | // avoided I think, why not send the original s variable to 344 | // write_contents? 345 | s.writeInt(oss.size()); 346 | s.write(oss.toByteArray()); 347 | s.flush(); 348 | } 349 | 350 | Command(int iden) { 351 | this.iden = iden; 352 | } 353 | 354 | protected String readString(LittleEndianDataInputStream s) throws IOException { 355 | int len = s.readInt(); 356 | byte[] b = new byte[len]; 357 | s.readFully(b); 358 | String str = new String(b); 359 | while (len++ % 4 != 0) 360 | s.read(); 361 | return str; 362 | } 363 | 364 | protected float[] readFloatArray(LittleEndianDataInputStream s) throws IOException { 365 | int len = s.readInt() / 4; 366 | float[] fs = new float[len]; 367 | for (int i = 0; i < len; ++i) { 368 | fs[i] = s.readFloat(); 369 | } 370 | return fs; 371 | } 372 | 373 | protected double[] readDoubleArray(LittleEndianDataInputStream s) throws IOException { 374 | int len = s.readInt() / 8; 375 | double[] fs = new double[len]; 376 | for (int i = 0; i < len; ++i) { 377 | fs[i] = s.readDouble(); 378 | } 379 | return fs; 380 | } 381 | 382 | protected ByteBuffer readByteBuffer(LittleEndianDataInputStream s) throws IOException { 383 | int byteLength = s.readInt(); 384 | byte[] buffer = new byte[byteLength]; 385 | s.readFully(buffer); 386 | return ByteBuffer.wrap(buffer); 387 | } 388 | 389 | // This method can be removed as soon as the binaries have been updated 390 | protected ByteBuffer readByteFloatToDoubleBuffer(LittleEndianDataInputStream s) throws IOException { 391 | int byteLength = s.readInt(); 392 | byte[] buffer = new byte[byteLength]; 393 | s.readFully(buffer); 394 | ByteBuffer byteBuffer = ByteBuffer.wrap(buffer); 395 | ByteBuffer newBuffer = ByteBuffer.allocate(buffer.length * 2); 396 | FloatBuffer floatBuffer = byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); 397 | DoubleBuffer doubleBuffer = newBuffer.order(ByteOrder.LITTLE_ENDIAN).asDoubleBuffer(); 398 | int capacity = floatBuffer.capacity(); 399 | for (int i=0; i 0) { 713 | LOGGER.info("\n" + log); 714 | } 715 | 716 | Bye b = new Bye(); 717 | b.write(dos); 718 | 719 | if (dis.readInt() != BYE) { 720 | LOGGER.error("Invalid command sequence encountered"); 721 | throw new IOException(); 722 | } 723 | b.read(dis); 724 | } catch (Throwable e) { 725 | } 726 | 727 | try { 728 | // Give the executable some time to terminate by itself or kill 729 | // it after 2 seconds have passed 730 | for (int n = 0;;) { 731 | try { 732 | if (process.exitValue() != 0) { 733 | // LOGGER.error(String.format("Exited with non-zero exit 734 | // code: %d", process.exitValue())); 735 | throw new RenderEngineException(String.format("Exited with non-zero exit code: %d", process.exitValue())); 736 | } 737 | break; 738 | } catch (IllegalThreadStateException e) { 739 | if (n++ == 20) { 740 | process.destroy(); 741 | LOGGER.error("Forcefully terminated IfcOpenShell process"); 742 | break; 743 | } 744 | } 745 | try { 746 | Thread.sleep(100); 747 | } catch (InterruptedException e) { 748 | } 749 | } 750 | } finally { 751 | process.destroyForcibly(); 752 | } 753 | 754 | dis = null; 755 | dos = null; 756 | process = null; 757 | } 758 | 759 | private void askForMore() throws IOException { 760 | hasMore = false; 761 | if (dis.readInt() != MORE) { 762 | LOGGER.error("Invalid command sequence encountered"); 763 | throw new IOException(); 764 | } 765 | 766 | More mr = new More(); 767 | mr.read(dis); 768 | 769 | hasMore = mr.hasMore(); 770 | } 771 | 772 | public IfcGeomServerClientEntity getNext() throws RenderEngineException { 773 | try { 774 | Get g = new Get(); 775 | g.write(dos); 776 | 777 | if (dis.readInt() != ENTITY) { 778 | LOGGER.error("Invalid command sequence encountered"); 779 | throw new IOException(); 780 | } 781 | Entity e = new Entity(); 782 | e.read(dis); 783 | 784 | Next n = new Next(); 785 | n.write(dos); 786 | 787 | askForMore(); 788 | 789 | return e.getEntity(); 790 | } catch (IOException e) { 791 | terminate(); 792 | return null; 793 | } 794 | } 795 | 796 | public boolean isRunning() { 797 | return running; 798 | } 799 | 800 | public boolean hasNext() { 801 | return hasMore; 802 | } 803 | 804 | public String getProtocolVersion() { 805 | return PROTOCOL_VERSION; 806 | } 807 | 808 | public GregorianCalendar getBuildDateTime() { 809 | return buildDateTime; 810 | } 811 | 812 | public String getPlatform() throws RenderEngineException { 813 | String platform = "unknown"; 814 | String os = getOs(); 815 | 816 | if (os == "osx") { 817 | platform = "macos64"; 818 | } else { 819 | platform = os.toLowerCase() + System.getProperty("sun.arch.data.model"); 820 | } 821 | 822 | return platform; 823 | } 824 | } -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcGeomServerClientEntity.java: -------------------------------------------------------------------------------- 1 | package org.ifcopenshell; 2 | 3 | /****************************************************************************** 4 | * Copyright (C) 2009-2019 BIMserver.org 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see {@literal}. 18 | *****************************************************************************/ 19 | 20 | import java.io.IOException; 21 | import java.nio.ByteBuffer; 22 | 23 | /****************************************************************************** 24 | * Copyright (C) 2009-2018 BIMserver.org 25 | * 26 | * This program is free software: you can redistribute it and/or modify 27 | * it under the terms of the GNU Affero General Public License as 28 | * published by the Free Software Foundation, either version 3 of the 29 | * License, or (at your option) any later version. 30 | * 31 | * This program is distributed in the hope that it will be useful, 32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | * GNU Affero General Public License for more details. 35 | * 36 | * You should have received a copy of the GNU Affero General Public License 37 | * along with this program. If not, see {@literal}. 38 | *****************************************************************************/ 39 | 40 | import org.bimserver.geometry.Matrix; 41 | import org.bimserver.plugins.renderengine.RenderEngineException; 42 | 43 | import com.fasterxml.jackson.databind.ObjectMapper; 44 | import com.fasterxml.jackson.databind.node.ObjectNode; 45 | 46 | public class IfcGeomServerClientEntity { 47 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 48 | private long id; 49 | private String guid; 50 | private String name; 51 | private String type; 52 | private long parentId; 53 | private double[] matrix; 54 | private int repId; 55 | private ByteBuffer positions; 56 | private ByteBuffer normals; 57 | private ByteBuffer indices; 58 | private ByteBuffer colors; 59 | private ByteBuffer materialIndices; 60 | private ObjectNode extendedData; 61 | 62 | public IfcGeomServerClientEntity(long id, String guid, String name, 63 | String type, long parentId, double[] matrix, int repId, 64 | ByteBuffer positions, ByteBuffer normals, ByteBuffer indices, ByteBuffer colors, 65 | ByteBuffer materialIndices, String messageRemainder) { 66 | super(); 67 | this.id = id; 68 | this.guid = guid; 69 | this.name = name; 70 | this.type = type; 71 | this.parentId = parentId; 72 | this.matrix = Matrix.changeOrientation(matrix); 73 | this.repId = repId; 74 | this.positions = positions; 75 | this.normals = normals; 76 | this.indices = indices; 77 | this.colors = colors; 78 | this.materialIndices = materialIndices; 79 | 80 | if (messageRemainder != null && messageRemainder.length() > 0) { 81 | // un-pad string 82 | try { 83 | this.extendedData = OBJECT_MAPPER.readValue(messageRemainder.trim(), ObjectNode.class); 84 | } catch (IOException e) { 85 | e.printStackTrace(); 86 | } 87 | } 88 | } 89 | 90 | public long getId() { 91 | return id; 92 | } 93 | 94 | public String getGuid() { 95 | return guid; 96 | } 97 | 98 | public String getName() { 99 | return name; 100 | } 101 | 102 | public String getType() { 103 | return type; 104 | } 105 | 106 | public long getParentId() { 107 | return parentId; 108 | } 109 | 110 | public double[] getMatrix() { 111 | return matrix; 112 | } 113 | 114 | public int getRepId() { 115 | return repId; 116 | } 117 | 118 | public ByteBuffer getPositions() { 119 | return positions; 120 | } 121 | 122 | public ByteBuffer getNormals() { 123 | return normals; 124 | } 125 | 126 | public ByteBuffer getIndices() { 127 | return indices; 128 | } 129 | 130 | public ByteBuffer getColors() { 131 | return colors; 132 | } 133 | 134 | public ByteBuffer getMaterialIndices() { 135 | return materialIndices; 136 | } 137 | 138 | public ObjectNode getAllExtendedData() throws RenderEngineException { 139 | return this.extendedData; 140 | } 141 | } -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcOpenShellEngine.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * * 3 | * This file is part of IfcOpenShell. * 4 | * * 5 | * IfcOpenShell is free software: you can redistribute it and/or modify * 6 | * it under the terms of the Lesser GNU General Public License as published by * 7 | * the Free Software Foundation, either version 3.0 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * IfcOpenShell is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * Lesser GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the Lesser GNU General Public License * 16 | * along with this program. If not, see . * 17 | * * 18 | ********************************************************************************/ 19 | 20 | /******************************************************************************* 21 | * * 22 | * An intermediate between the Plugin implementation and the Model * 23 | * implementation, nothing fancy going on here. * 24 | * * 25 | ********************************************************************************/ 26 | 27 | package org.ifcopenshell; 28 | 29 | /****************************************************************************** 30 | * Copyright (C) 2009-2019 BIMserver.org 31 | * 32 | * This program is free software: you can redistribute it and/or modify 33 | * it under the terms of the GNU Affero General Public License as 34 | * published by the Free Software Foundation, either version 3 of the 35 | * License, or (at your option) any later version. 36 | * 37 | * This program is distributed in the hope that it will be useful, 38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 40 | * GNU Affero General Public License for more details. 41 | * 42 | * You should have received a copy of the GNU Affero General Public License 43 | * along with this program. If not, see {@literal}. 44 | *****************************************************************************/ 45 | 46 | import java.io.IOException; 47 | import java.io.InputStream; 48 | import java.nio.file.Path; 49 | 50 | import org.bimserver.plugins.renderengine.Metrics; 51 | import org.bimserver.plugins.renderengine.RenderEngine; 52 | import org.bimserver.plugins.renderengine.RenderEngineException; 53 | import org.bimserver.plugins.renderengine.RenderEngineModel; 54 | import org.slf4j.Logger; 55 | import org.slf4j.LoggerFactory; 56 | 57 | public class IfcOpenShellEngine implements RenderEngine { 58 | private static final Logger LOGGER = LoggerFactory.getLogger(IfcOpenShellEngine.class); 59 | private Path executableFilename; 60 | 61 | private IfcGeomServerClient client; 62 | private boolean calculateQuantities; 63 | private boolean applyLayerSets; 64 | private boolean disableOpeningSubtractions; 65 | 66 | public IfcOpenShellEngine(Path executableFilename, boolean calculateQuantities, boolean applyLayerSets, boolean disableOpeningSubtractions) throws IOException { 67 | this.executableFilename = executableFilename; 68 | this.setCalculateQuantities(calculateQuantities); 69 | this.setApplyLayerSets(applyLayerSets); 70 | this.setDisableOpeningSubtractions(disableOpeningSubtractions); 71 | } 72 | 73 | @Override 74 | public void init() throws RenderEngineException { 75 | LOGGER.debug("Initializing IfcOpenShell engine"); 76 | 77 | client = new IfcGeomServerClient(executableFilename); 78 | client.setCalculateQuantities(isCalculateQuantities()); 79 | client.setApplyLayersets(isApplyLayerSets()); 80 | client.setDisableOpeningSubtractions(isDisableOpeningSubtractions()); 81 | } 82 | 83 | @Override 84 | public void close() throws RenderEngineException { 85 | LOGGER.debug("Closing IfcOpenShell engine"); 86 | if (client.isRunning()) { 87 | client.close(); 88 | } 89 | } 90 | 91 | @Override 92 | public RenderEngineModel openModel(InputStream inputStream, long size) throws RenderEngineException { 93 | if (!client.isRunning()) { 94 | client = new IfcGeomServerClient(executableFilename); 95 | } 96 | try { 97 | return new IfcOpenShellModel(client, inputStream, size); 98 | } catch (IOException e) { 99 | throw new RenderEngineException(e); 100 | } 101 | } 102 | 103 | @Override 104 | public RenderEngineModel openModel(InputStream inputStream) throws RenderEngineException { 105 | if (!client.isRunning()) { 106 | client = new IfcGeomServerClient(executableFilename); 107 | } 108 | try { 109 | return new IfcOpenShellModel(client, inputStream); 110 | } catch (IOException e) { 111 | throw new RenderEngineException(e); 112 | } 113 | } 114 | 115 | public boolean isCalculateQuantities() { 116 | return calculateQuantities; 117 | } 118 | 119 | public void setCalculateQuantities(boolean calculateQuantities) { 120 | this.calculateQuantities = calculateQuantities; 121 | } 122 | 123 | public boolean isApplyLayerSets() { 124 | return applyLayerSets; 125 | } 126 | 127 | public void setApplyLayerSets(boolean applyLayerSets) { 128 | this.applyLayerSets = applyLayerSets; 129 | } 130 | 131 | public boolean isDisableOpeningSubtractions(){ 132 | return disableOpeningSubtractions; 133 | } 134 | public void setDisableOpeningSubtractions(boolean disableOpeningSubtractions) { 135 | this.disableOpeningSubtractions = disableOpeningSubtractions; 136 | } 137 | 138 | 139 | 140 | @Override 141 | public Metrics getMetrics() { 142 | return null; 143 | } 144 | } -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcOpenShellEnginePlugin.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * * 3 | * This file is part of IfcOpenShell. * 4 | * * 5 | * IfcOpenShell is free software: you can redistribute it and/or modify * 6 | * it under the terms of the Lesser GNU General Public License as published by * 7 | * the Free Software Foundation, either version 3.0 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * IfcOpenShell is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * Lesser GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the Lesser GNU General Public License * 16 | * along with this program. If not, see . * 17 | * * 18 | ********************************************************************************/ 19 | 20 | /******************************************************************************* 21 | * * 22 | * This class ensures that a valid binary is available for the platform the * 23 | * code is running on. * 24 | * * 25 | ********************************************************************************/ 26 | 27 | package org.ifcopenshell; 28 | 29 | /****************************************************************************** 30 | * Copyright (C) 2009-2019 BIMserver.org 31 | * 32 | * This program is free software: you can redistribute it and/or modify 33 | * it under the terms of the GNU Affero General Public License as 34 | * published by the Free Software Foundation, either version 3 of the 35 | * License, or (at your option) any later version. 36 | * 37 | * This program is distributed in the hope that it will be useful, 38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 40 | * GNU Affero General Public License for more details. 41 | * 42 | * You should have received a copy of the GNU Affero General Public License 43 | * along with this program. If not, see {@literal}. 44 | *****************************************************************************/ 45 | 46 | import java.io.IOException; 47 | import java.nio.file.Path; 48 | 49 | import org.bimserver.models.store.BooleanType; 50 | import org.bimserver.models.store.ObjectDefinition; 51 | import org.bimserver.models.store.ParameterDefinition; 52 | import org.bimserver.models.store.PrimitiveDefinition; 53 | import org.bimserver.models.store.PrimitiveEnum; 54 | import org.bimserver.models.store.StoreFactory; 55 | import org.bimserver.models.store.StringType; 56 | import org.bimserver.plugins.PluginConfiguration; 57 | import org.bimserver.plugins.PluginContext; 58 | import org.bimserver.plugins.renderengine.RenderEngine; 59 | import org.bimserver.plugins.renderengine.RenderEngineException; 60 | import org.bimserver.plugins.renderengine.RenderEnginePlugin; 61 | import org.bimserver.plugins.renderengine.VersionInfo; 62 | import org.bimserver.shared.exceptions.PluginException; 63 | import org.slf4j.Logger; 64 | import org.slf4j.LoggerFactory; 65 | 66 | public class IfcOpenShellEnginePlugin implements RenderEnginePlugin { 67 | private static final Logger LOGGER = LoggerFactory.getLogger(IfcOpenShellEnginePlugin.class); 68 | public static final String DEFAULT_BUILD_VERSION = "v0.7.0-c7830e9"; // last v0.7.0 version, from 30.05.2024 69 | private static final String BUILD_VERSION = "buildversion"; 70 | private static final String CALCULATE_QUANTITIES_SETTING = "calculatequantities"; 71 | private static final String APPLY_LAYER_SETS = "applylayersets"; 72 | private static final String DISABLE_OPENING_SUBTRACTIONS = "disableopeningsubtrations"; 73 | private Path executableFilename; 74 | private VersionInfo versionInfo; 75 | private boolean calculateQuantities = true; 76 | private boolean applyLayerSets = true; 77 | private boolean disableOpeningSubtractions = false; 78 | 79 | @Override 80 | public RenderEngine createRenderEngine(PluginConfiguration pluginConfiguration, String schema) throws RenderEngineException { 81 | try { 82 | return new IfcOpenShellEngine(executableFilename, calculateQuantities, applyLayerSets, disableOpeningSubtractions); 83 | } catch (IOException e) { 84 | throw new RenderEngineException(e); 85 | } 86 | } 87 | 88 | @Override 89 | public void init(PluginContext pluginContext, PluginConfiguration systemSettings) throws PluginException { 90 | // Make sure an executable is downloaded before invoking the plug-in using multiple threads. 91 | // This also checks whether the version of the executable matches the java source. 92 | 93 | if (systemSettings != null) { 94 | calculateQuantities = systemSettings.getBoolean(CALCULATE_QUANTITIES_SETTING, true); 95 | applyLayerSets = systemSettings.getBoolean(APPLY_LAYER_SETS, true); 96 | disableOpeningSubtractions = systemSettings.getBoolean(DISABLE_OPENING_SUBTRACTIONS, false); 97 | } 98 | 99 | String buildVersion = DEFAULT_BUILD_VERSION; 100 | if (systemSettings != null && systemSettings.getString(BUILD_VERSION) != null && !systemSettings.getString(BUILD_VERSION).trim().contentEquals("")) { 101 | // Overruled by system settings 102 | buildVersion = systemSettings.getString(BUILD_VERSION); 103 | LOGGER.info("Using overruled system setting for build version"); 104 | } 105 | 106 | try (IfcGeomServerClient test = new IfcGeomServerClient(IfcGeomServerClient.ExecutableSource.S3, buildVersion, pluginContext.getTempDir())) { 107 | executableFilename = test.getExecutableFilename(); 108 | versionInfo = new VersionInfo(buildVersion, test.getProtocolVersion(), test.getBuildDateTime(), test.getPlatform()); 109 | } 110 | 111 | LOGGER.info("Using " + executableFilename); 112 | } 113 | 114 | @Override 115 | public ObjectDefinition getUserSettingsDefinition() { 116 | return null; 117 | } 118 | 119 | @Override 120 | public ObjectDefinition getSystemSettingsDefinition() { 121 | ObjectDefinition settings = StoreFactory.eINSTANCE.createObjectDefinition(); 122 | 123 | PrimitiveDefinition stringType = StoreFactory.eINSTANCE.createPrimitiveDefinition(); 124 | stringType.setType(PrimitiveEnum.STRING); 125 | 126 | PrimitiveDefinition booleanType = StoreFactory.eINSTANCE.createPrimitiveDefinition(); 127 | booleanType.setType(PrimitiveEnum.BOOLEAN); 128 | 129 | StringType defaultBuildVersion = StoreFactory.eINSTANCE.createStringType(); 130 | defaultBuildVersion.setValue(DEFAULT_BUILD_VERSION); 131 | 132 | BooleanType defaultTrue = StoreFactory.eINSTANCE.createBooleanType(); 133 | defaultTrue.setValue(true); 134 | 135 | BooleanType defaultFalse = StoreFactory.eINSTANCE.createBooleanType(); 136 | defaultFalse.setValue(false); 137 | 138 | ParameterDefinition buildVersionParameter = StoreFactory.eINSTANCE.createParameterDefinition(); 139 | buildVersionParameter.setIdentifier(BUILD_VERSION); 140 | buildVersionParameter.setName("Build version"); 141 | buildVersionParameter.setDescription("Build version of IfcOpenShell binary, usually consisting of version number and commit SHA. This overrules the default for the currently installed IfcOpenShell plugin"); 142 | buildVersionParameter.setType(stringType); 143 | buildVersionParameter.setRequired(false); 144 | buildVersionParameter.setDefaultValue(defaultBuildVersion); 145 | 146 | ParameterDefinition calculateQuantities = StoreFactory.eINSTANCE.createParameterDefinition(); 147 | calculateQuantities.setIdentifier(CALCULATE_QUANTITIES_SETTING); 148 | calculateQuantities.setName("Calculate Quantities"); 149 | calculateQuantities.setDescription("Calculates volumes and areas, Takes a bit more time (about 15%)"); 150 | calculateQuantities.setType(booleanType); 151 | calculateQuantities.setRequired(false); 152 | calculateQuantities.setDefaultValue(defaultTrue); 153 | 154 | ParameterDefinition applyLayerSets = StoreFactory.eINSTANCE.createParameterDefinition(); 155 | applyLayerSets.setIdentifier(APPLY_LAYER_SETS); 156 | applyLayerSets.setName("Apply Layer Sets"); 157 | applyLayerSets.setDescription("Splits certain objects into several layers, depending on the model can take about 10x more processing time, and results in more geometry"); 158 | applyLayerSets.setType(booleanType); 159 | applyLayerSets.setRequired(false); 160 | applyLayerSets.setDefaultValue(defaultTrue); 161 | 162 | ParameterDefinition disableOpeningSubtractions = StoreFactory.eINSTANCE.createParameterDefinition(); 163 | disableOpeningSubtractions.setIdentifier(DISABLE_OPENING_SUBTRACTIONS); 164 | disableOpeningSubtractions.setName("Disable Opening Subtractions"); 165 | disableOpeningSubtractions.setDescription("Omits subtractions of voiding opening elements form the voided elements."); 166 | disableOpeningSubtractions.setType(booleanType); 167 | disableOpeningSubtractions.setRequired(false); 168 | disableOpeningSubtractions.setDefaultValue(defaultFalse); 169 | 170 | settings.getParameters().add(buildVersionParameter); 171 | settings.getParameters().add(calculateQuantities); 172 | settings.getParameters().add(applyLayerSets); 173 | settings.getParameters().add(disableOpeningSubtractions); 174 | return settings; 175 | } 176 | 177 | public VersionInfo getVersionInfo() { 178 | return versionInfo; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcOpenShellEntityInstance.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * * 3 | * This file is part of IfcOpenShell. * 4 | * * 5 | * IfcOpenShell is free software: you can redistribute it and/or modify * 6 | * it under the terms of the Lesser GNU General Public License as published by * 7 | * the Free Software Foundation, either version 3.0 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * IfcOpenShell is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * Lesser GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the Lesser GNU General Public License * 16 | * along with this program. If not, see . * 17 | * * 18 | ********************************************************************************/ 19 | 20 | package org.ifcopenshell; 21 | 22 | /****************************************************************************** 23 | * Copyright (C) 2009-2019 BIMserver.org 24 | * 25 | * This program is free software: you can redistribute it and/or modify 26 | * it under the terms of the GNU Affero General Public License as 27 | * published by the Free Software Foundation, either version 3 of the 28 | * License, or (at your option) any later version. 29 | * 30 | * This program is distributed in the hope that it will be useful, 31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | * GNU Affero General Public License for more details. 34 | * 35 | * You should have received a copy of the GNU Affero General Public License 36 | * along with this program. If not, see {@literal}. 37 | *****************************************************************************/ 38 | 39 | import org.bimserver.plugins.renderengine.RenderEngineException; 40 | import org.bimserver.plugins.renderengine.RenderEngineGeometry; 41 | import org.bimserver.plugins.renderengine.RenderEngineInstance; 42 | 43 | import com.fasterxml.jackson.databind.node.ObjectNode; 44 | 45 | public class IfcOpenShellEntityInstance implements RenderEngineInstance { 46 | private IfcGeomServerClientEntity entity; 47 | 48 | public IfcOpenShellEntityInstance(IfcGeomServerClientEntity entity) { 49 | this.entity = entity; 50 | } 51 | 52 | @Override 53 | public double[] getTransformationMatrix() { 54 | return entity.getMatrix(); 55 | } 56 | 57 | @Override 58 | public RenderEngineGeometry generateGeometry() { 59 | if (entity == null) { 60 | return null; 61 | } 62 | return new RenderEngineGeometry(entity.getIndices(), entity.getPositions(), entity.getNormals(), entity.getColors(), entity.getMaterialIndices()); 63 | } 64 | 65 | public ObjectNode getAdditionalData() throws RenderEngineException { 66 | return entity.getAllExtendedData(); 67 | } 68 | } -------------------------------------------------------------------------------- /src/org/ifcopenshell/IfcOpenShellModel.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * * 3 | * This file is part of IfcOpenShell. * 4 | * * 5 | * IfcOpenShell is free software: you can redistribute it and/or modify * 6 | * it under the terms of the Lesser GNU General Public License as published by * 7 | * the Free Software Foundation, either version 3.0 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * IfcOpenShell is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * Lesser GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the Lesser GNU General Public License * 16 | * along with this program. If not, see . * 17 | * * 18 | ********************************************************************************/ 19 | 20 | /******************************************************************************* 21 | * * 22 | * This class communicates with the JNI wrapper of IfcOpenShell. Note that, * 23 | * contrary to the Bonsma IFC engine, if the wrapper crashes it will take the * 24 | * BIMserver down with her. Since loading the wrapper involves loading a * 25 | * considerable binary into memory, it would have been better to make the * 26 | * System.load() call somewhere in IfcOpenShellEngine.java. * 27 | * * 28 | ********************************************************************************/ 29 | 30 | package org.ifcopenshell; 31 | 32 | /****************************************************************************** 33 | * Copyright (C) 2009-2019 BIMserver.org 34 | * 35 | * This program is free software: you can redistribute it and/or modify 36 | * it under the terms of the GNU Affero General Public License as 37 | * published by the Free Software Foundation, either version 3 of the 38 | * License, or (at your option) any later version. 39 | * 40 | * This program is distributed in the hope that it will be useful, 41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 | * GNU Affero General Public License for more details. 44 | * 45 | * You should have received a copy of the GNU Affero General Public License 46 | * along with this program. If not, see {@literal}. 47 | *****************************************************************************/ 48 | 49 | import java.io.IOException; 50 | import java.io.InputStream; 51 | import java.util.Collection; 52 | import java.util.HashMap; 53 | import java.util.Map; 54 | 55 | import org.bimserver.plugins.renderengine.EntityNotFoundException; 56 | import org.bimserver.plugins.renderengine.RenderEngineException; 57 | import org.bimserver.plugins.renderengine.RenderEngineFilter; 58 | import org.bimserver.plugins.renderengine.RenderEngineInstance; 59 | import org.bimserver.plugins.renderengine.RenderEngineModel; 60 | import org.bimserver.plugins.renderengine.RenderEngineSettings; 61 | import org.slf4j.Logger; 62 | import org.slf4j.LoggerFactory; 63 | 64 | public class IfcOpenShellModel implements RenderEngineModel { 65 | private static final Logger LOGGER = LoggerFactory.getLogger(IfcOpenShellModel.class); 66 | 67 | private InputStream ifcInputStream; 68 | 69 | private Map instancesById; 70 | 71 | private IfcGeomServerClient client; 72 | 73 | public IfcOpenShellModel(IfcGeomServerClient client, InputStream ifcInputStream) throws RenderEngineException, IOException { 74 | this.client = client; 75 | this.ifcInputStream = ifcInputStream; 76 | 77 | client.loadModel(ifcInputStream); 78 | } 79 | 80 | public IfcOpenShellModel(IfcGeomServerClient client, InputStream ifcInputStream, long length) throws RenderEngineException, IOException { 81 | this.client = client; 82 | this.ifcInputStream = ifcInputStream; 83 | 84 | client.loadModel(ifcInputStream, length); 85 | } 86 | 87 | @Override 88 | public void close() throws RenderEngineException { 89 | if (instancesById != null) { 90 | instancesById.clear(); 91 | } 92 | try { 93 | ifcInputStream.close(); 94 | } catch (IOException e) { 95 | LOGGER.error("", e); 96 | } 97 | } 98 | 99 | @Override 100 | public void generateGeneralGeometry() throws RenderEngineException { 101 | // We keep track of instances ourselves 102 | instancesById = new HashMap(); 103 | 104 | final double t0 = (double) System.nanoTime(); 105 | 106 | while (client.hasNext()) { 107 | IfcGeomServerClientEntity next = client.getNext(); 108 | // Store the instance in our dictionary 109 | IfcOpenShellEntityInstance instance = new IfcOpenShellEntityInstance(next); 110 | instancesById.put(next.getId(), instance); 111 | } 112 | 113 | final double t1 = (double) System.nanoTime(); 114 | 115 | LOGGER.debug(String.format("Took %.2f seconds to obtain representations for %d entities", (t1-t0) / 1.E9, instancesById.size())); 116 | } 117 | 118 | @Override 119 | public RenderEngineInstance getInstanceFromExpressId(long expressId) throws RenderEngineException { 120 | if (instancesById.containsKey(expressId)) { 121 | return instancesById.get(expressId); 122 | } else { 123 | // Probably something went wrong with the processing of this element in 124 | // the IfcOpenShell binary, as it has not been included in the enumerated 125 | // set of elements with geometry. 126 | throw new EntityNotFoundException("Entity " + expressId + " not found in model"); 127 | } 128 | } 129 | 130 | @Override 131 | public void setFormat(int format, int mask) throws RenderEngineException { 132 | } 133 | 134 | @Override 135 | public void setSettings(RenderEngineSettings settings) throws RenderEngineException { 136 | } 137 | 138 | @Override 139 | public void setFilter(RenderEngineFilter renderEngineFilter) { 140 | } 141 | 142 | @Override 143 | public Collection listInstances() throws RenderEngineException { 144 | return null; 145 | } 146 | } --------------------------------------------------------------------------------