use of org.bimserver.shared.AbstractHashMapVirtualObject in project BIMserver by opensourceBIM.
the class GeometryAccellerator method generateOctree.
private Octree generateOctree(OctreeKey key) {
LOGGER.info("Generating octree: " + key);
Long start = System.nanoTime();
try (DatabaseSession databaseSession = bimServer.getDatabase().createSession(OperationType.READ_ONLY)) {
Bounds totalBounds = new Bounds();
for (long roid : key.getRoids()) {
Revision revision = databaseSession.get(roid, OldQuery.getDefault());
totalBounds.integrate(revision.getBoundsMm());
}
Octree octree = new Octree(totalBounds, 9);
// Assuming all given roids are of projects that all have the same
// schema
Revision revision = databaseSession.get(key.getRoids().iterator().next(), OldQuery.getDefault());
PackageMetaData packageMetaData = bimServer.getMetaDataManager().getPackageMetaData(revision.getProject().getSchema());
Set<EClass> excluded = new HashSet<>();
if (key.getExcludedClasses() != null) {
for (String exclude : key.getExcludedClasses()) {
excluded.add(packageMetaData.getEClass(exclude));
}
}
Query query = new Query(packageMetaData);
QueryPart queryPart = query.createQueryPart();
queryPart.addType(packageMetaData.getEClass("IfcProduct"), true, excluded);
Include product = queryPart.createInclude();
product.addType(packageMetaData.getEClass("IfcProduct"), true);
product.addFieldDirect("geometry");
Include geometryInfo = product.createInclude();
geometryInfo.addType(GeometryPackage.eINSTANCE.getGeometryInfo(), false);
geometryInfo.addFieldDirect("data");
geometryInfo.addFieldDirect("boundsMm");
Include boundsInclude = geometryInfo.createInclude();
boundsInclude.addType(GeometryPackage.eINSTANCE.getBounds(), false);
boundsInclude.addFieldDirect("min");
boundsInclude.addFieldDirect("max");
Include dataInclude = geometryInfo.createInclude();
dataInclude.addType(GeometryPackage.eINSTANCE.getGeometryData(), false);
dataInclude.addFieldDirect("boundsMm");
Include dataBoundsInclude = dataInclude.createInclude();
dataBoundsInclude.addType(GeometryPackage.eINSTANCE.getBounds(), false);
dataBoundsInclude.addFieldDirect("min");
dataBoundsInclude.addFieldDirect("max");
QueryObjectProvider queryObjectProvider = new QueryObjectProvider(databaseSession, bimServer, query, key.getRoids(), packageMetaData);
HashMapVirtualObject next = queryObjectProvider.next();
Map<Long, GeometryDataObject> map = new HashMap<>();
while (next != null) {
AbstractHashMapVirtualObject geometry = next.getDirectFeature(packageMetaData.getEReference("IfcProduct", "geometry"));
if (geometry != null) {
float density = (float) geometry.get("density");
long geometryDataId = (long) geometry.get("data");
AbstractHashMapVirtualObject boundsMm = geometry.getDirectFeature(GeometryPackage.eINSTANCE.getGeometryInfo_BoundsMm());
GeometryDataObject geometryDataObject = null;
if (key.getGeometryIdsToReuse().contains(geometryDataId)) {
// Special case, we now have to use the complete
// bounding box of all reused objects, instead of using
// the object's aabb
HashMapVirtualObject geometryData = (HashMapVirtualObject) geometry.getDirectFeature(GeometryPackage.eINSTANCE.getGeometryInfo_Data());
boundsMm = geometryData.getDirectFeature(GeometryPackage.eINSTANCE.getGeometryData_BoundsMm());
geometryDataObject = map.get(geometryData.getOid());
if (geometryDataObject == null) {
geometryDataObject = new GeometryDataObject(geometryData);
map.put(geometryData.getOid(), geometryDataObject);
}
}
if (boundsMm != null) {
AbstractHashMapVirtualObject min = boundsMm.getDirectFeature(GeometryPackage.eINSTANCE.getBounds_Min());
AbstractHashMapVirtualObject max = boundsMm.getDirectFeature(GeometryPackage.eINSTANCE.getBounds_Max());
HashMapVirtualObject geometryData = (HashMapVirtualObject) geometry.getDirectFeature(GeometryPackage.eINSTANCE.getGeometryInfo_Data());
int saveableTriangles = (int) geometryData.get("saveableTriangles");
int reused = (int) geometryData.get("reused");
int triangles = (int) geometryData.get("nrIndices") / 3;
org.bimserver.database.queries.Bounds objectBounds = new org.bimserver.database.queries.Bounds((double) min.get("x"), (double) min.get("y"), (double) min.get("z"), (double) max.get("x"), (double) max.get("y"), (double) max.get("z"));
GeometryObject geometryObject = new GeometryObject(next.getOid(), next.eClass(), next.getCroid(), saveableTriangles, reused, triangles, density, objectBounds);
Node node = octree.add(geometryObject);
geometryObject.setTileId(node.getId());
geometryObject.setTileLevel(node.getLevel());
geometryObject.setGeometryDataObject(geometryDataObject);
}
}
next = queryObjectProvider.next();
}
AtomicLong totalTriangles = new AtomicLong();
octree.traverseBreathFirst(new Traverser() {
@Override
public void traverse(Node node) {
for (GeometryObject geometryObject : node.getValues()) {
totalTriangles.addAndGet(geometryObject.getTriangles());
}
}
});
LOGGER.info("Total triangles: " + totalTriangles);
octree.moveGeometryDown(new MoveGeometryDownDecider() {
@Override
public boolean shouldMoveDown(GeometryObject geometryObject) {
GeometryDataObject geometryDataObject = geometryObject.getGeometryDataObject();
if (geometryDataObject == null) {
// It's not reused at all
return false;
}
return false;
}
});
octree.moveUp(new MoveUpDecider() {
@Override
public boolean moveUp(Node node) {
// TODO use more heuristics
int totalTriangles = 0;
for (GeometryObject geometryObject : node.getValues()) {
totalTriangles += geometryObject.getTriangles();
}
if (totalTriangles < 1200) {
return true;
}
return false;
}
});
long end = System.nanoTime();
LOGGER.info("Octree generated in " + ((end - start) / 1000000) + " ms");
return octree;
} catch (BimserverDatabaseException e) {
LOGGER.error("", e);
} catch (IOException e) {
LOGGER.error("", e);
} catch (QueryException e) {
LOGGER.error("", e);
}
return null;
}
Aggregations