diff --git a/src/io/parser/BIMtoOSMParser.java b/src/io/parser/BIMtoOSMParser.java index c5d2e10..7bd11bb 100644 --- a/src/io/parser/BIMtoOSMParser.java +++ b/src/io/parser/BIMtoOSMParser.java @@ -97,21 +97,14 @@ public boolean parse(String filepath) { // extract important data and put them into internal data structure FilteredRawBIMData filteredRawBIMData = BIMtoOSMUtility.extractMajorBIMData(ifcModel); - // for preparation of filtered BIM data find Id of BIM root IFCLOCALPLACEMENT element (kept in IFCSITE flag) - int bimFileRootId = BIMtoOSMUtility.getIfcLocalPlacementRootObject(filteredRawBIMData); - if (bimFileRootId == -1) { - showParsingErrorView(filepath, "Could not import IFC file.\nIFC file does not contains IFCSITE element.", true); - return false; - } - // prepare filtered BIM data - find global object coordinates and other attributes like object height, width etc. ArrayList preparedBIMData = new ArrayList<>(); - preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcSlab, filteredRawBIMData.getAreaObjects())); - preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcWall, filteredRawBIMData.getWallObjects())); - preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcColumn, filteredRawBIMData.getColumnObjects())); -// preparedBIMData.addAll(BIMtoOSMHelper.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcDoor, filteredRawBIMData.getDoorObjects())); -// preparedBIMData.addAll(BIMtoOSMHelper.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcWindow, filteredRawBIMData.getWindowObjects())); - preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, bimFileRootId, BIMtoOSMCatalog.BIMObject.IfcStair, filteredRawBIMData.getStairObjects())); + preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcSlab, filteredRawBIMData.getAreaObjects())); + preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcWall, filteredRawBIMData.getWallObjects())); + preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcColumn, filteredRawBIMData.getColumnObjects())); +// preparedBIMData.addAll(BIMtoOSMHelper.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcDoor, filteredRawBIMData.getDoorObjects())); +// preparedBIMData.addAll(BIMtoOSMHelper.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcWindow, filteredRawBIMData.getWindowObjects())); + preparedBIMData.addAll(BIMtoOSMUtility.prepareBIMObjects(ifcModel, BIMtoOSMCatalog.BIMObject.IfcStair, filteredRawBIMData.getStairObjects())); // set units setUnits(); diff --git a/src/io/parser/data/math/Vector3D.java b/src/io/parser/data/math/Vector3D.java index 82ed175..dbf2c17 100644 --- a/src/io/parser/data/math/Vector3D.java +++ b/src/io/parser/data/math/Vector3D.java @@ -153,11 +153,6 @@ public double angleBetween(Vector3D vector){ double b_abs; double r; if (this.getZ() == 0.0 && vector.getZ() == 0.0) { -// ab = vector1[0] * vector2[0] + vector1[1] * vector2[1]; -// a_abs = Math.sqrt(Math.pow(vector1[0], 2.0) + Math.pow(vector1[1], 2.0)); -// b_abs = Math.sqrt(Math.pow(vector2[0], 2.0) + Math.pow(vector2[1], 2.0)); -// r = ab / (a_abs + b_abs); -// if(result2DWithSign < 0 && Math.acos(r) > 0) return -(Math.acos(r)); return result2DWithSign; } else{ ab = this.getX() * vector.getX() + this.getY() * vector.getY() + this.getZ() * vector.getZ(); diff --git a/src/io/parser/helper/BIMtoOSMUtility.java b/src/io/parser/helper/BIMtoOSMUtility.java index 42a729b..de0ec5c 100644 --- a/src/io/parser/helper/BIMtoOSMUtility.java +++ b/src/io/parser/helper/BIMtoOSMUtility.java @@ -81,31 +81,15 @@ public static FilteredRawBIMData extractMajorBIMData(ModelPopulation ifcModel) { return bimData; } - /** - * Gets the LOCALPLACEMENT root element of IFC file - * - * @param filteredBIMData Data including IFCSITE flag of IFC file - * @return Root LOCALPLACEMENT element of IFC file - */ - public static int getIfcLocalPlacementRootObject(FilteredRawBIMData filteredBIMData) { - try { - return filteredBIMData.getIfcSite().getAttributeValueBNasEntityInstance("ObjectPlacement").getId(); - } catch (NullPointerException e) { - return -1; - } - } - /** * Prepares BIM objects for further operations. Extracts OSM relevant information and puts it into {@link BIMObject3D} * - * @param ifcModel ifcModel - * @param bimFileRootId Root IFCLOCALPLACEMENT element of BIM file - * @param objectType relating BIMtoOSMCatalog.BIMObject - * @param bimObjects All BIM objects of objectType + * @param ifcModel ifcModel + * @param objectType relating BIMtoOSMCatalog.BIMObject + * @param bimObjects All BIM objects of objectType * @return Prepared BIM objects */ - public static List prepareBIMObjects(ModelPopulation ifcModel, int bimFileRootId, BIMtoOSMCatalog.BIMObject objectType, Vector bimObjects) { - // TODO - WIP: Improve object placement determination + public static List prepareBIMObjects(ModelPopulation ifcModel, BIMtoOSMCatalog.BIMObject objectType, Vector bimObjects) { ArrayList preparedObjects = new ArrayList<>(); for (EntityInstance objectEntity : bimObjects) { @@ -117,7 +101,7 @@ public static List prepareBIMObjects(ModelPopulation ifcModel, int // get IFCLOCALPLACEMENT of object (origin of object) Vector3D cartesianOrigin = object.getTranslation(); // get rotation matrix of object - Matrix3D rotMatrix = getObjectRotationMatrix(bimFileRootId, objectEntity); + Matrix3D rotMatrix = getObjectRotationMatrix(objectEntity); // get local points representing shape of object ArrayList shapeDataOfObject = (ArrayList) getShapeDataOfObject(ifcModel, objectEntity); @@ -125,11 +109,7 @@ public static List prepareBIMObjects(ModelPopulation ifcModel, int // create PreparedBIMObject3D and save if (cartesianOrigin != null && rotMatrix != null && (shapeDataOfObject != null && !shapeDataOfObject.isEmpty())) { // transform points - for (Vector3D point : shapeDataOfObject) { - if (point.equalsVector(IfcRepresentationExtractor.defaultPoint)) continue; // for workaround - rotMatrix.transform(point); - point.add(object.getTranslation()); - } + transformPoints(shapeDataOfObject, rotMatrix, cartesianOrigin); object.setCartesianShapeCoordinates(shapeDataOfObject); // Check if data includes IFCShapeDataExtractor.defaultPoint. IFCShapeDataExtractor.defaultPoint got added @@ -140,20 +120,11 @@ public static List prepareBIMObjects(ModelPopulation ifcModel, int } // Workaround: Check data set for closed loops (separated by defaultPoint). If closed loop in data set, extract and add as own way - ArrayList loop = new ArrayList<>(); - for (Vector3D point : shapeDataOfObject) { - if (point.equalsVector(IfcRepresentationExtractor.defaultPoint) && !loop.isEmpty()) { - object.setCartesianShapeCoordinates(loop); - preparedObjects.add(object); - loop = new ArrayList<>(); - } else if (!point.equalsVector(IfcRepresentationExtractor.defaultPoint)) { - loop.add(point); - } - if (shapeDataOfObject.indexOf(point) == shapeDataOfObject.size() - 1 && !loop.isEmpty()) { - object.setCartesianShapeCoordinates(loop); - preparedObjects.add(object); - } - } + List> loops = splitClosedLoopsInDataSet(shapeDataOfObject); + loops.forEach(l -> { + object.setCartesianShapeCoordinates(l); + preparedObjects.add(object); + }); } } @@ -308,17 +279,16 @@ public static IfcRepresentation getRepresentationSpecificObjectType( /** * Gets rotation matrix for ifc object * - * @param bimFileRootId root IFCLOCALPLACEMENT element of BIM file - * @param object to get rotation matrix for + * @param object to get rotation matrix for * @return rotation matrix */ @SuppressWarnings("unchecked") - private static Matrix3D getObjectRotationMatrix(int bimFileRootId, EntityInstance object) { + private static Matrix3D getObjectRotationMatrix(EntityInstance object) { // get objects IFCLOCALPLACEMENT entity EntityInstance objectIFCLP = object.getAttributeValueBNasEntityInstance("ObjectPlacement"); // get all RELATIVEPLACEMENTs to root - ArrayList objectRP = getRelativePlacementsToRoot(bimFileRootId, objectIFCLP, new ArrayList<>()); + ArrayList objectRP = getRelativePlacementsToRoot(objectIFCLP, new ArrayList<>()); double rotAngleX = 0.0; // in rad double rotAngleZ = 0.0; // in rad @@ -339,16 +309,15 @@ private static Matrix3D getObjectRotationMatrix(int bimFileRootId, EntityInstanc } Vector3D xAxis = stringVectorToVector3D(xDirectionRatios); - if (xAxis == null ) return null; + if (xAxis == null) return null; Vector3D zAxis = stringVectorToVector3D(zDirectionRatios); - if (zAxis == null ) return null; + if (zAxis == null) return null; xAxis = retrieveXAxis(zAxis, xAxis); // get x-axis rotation angle if (parentXVector != null) { rotAngleX += parentXVector.angleBetween(xAxis); - } - else{ + } else { parentXVector = new Vector3D(); } // update parent vector @@ -359,8 +328,7 @@ private static Matrix3D getObjectRotationMatrix(int bimFileRootId, EntityInstanc // get z-axis rotation angle if (parentZVector != null) { rotAngleZ += parentZVector.angleBetween(zAxis); - } - else{ + } else { parentZVector = new Vector3D(); } // update parent vector @@ -376,32 +344,15 @@ private static Matrix3D getObjectRotationMatrix(int bimFileRootId, EntityInstanc return xMatrix; } - /** - * Gets the actual x-axis vector from reference system - * - * @param zAxis of IfcAxis2Placement3D - * @param refDirection of IfcAxis2Placement3D - * @return actual x-axis vector - */ - private static Vector3D retrieveXAxis(Vector3D zAxis, Vector3D refDirection) { - double d = refDirection.dot(zAxis) / zAxis.lengthSquared(); - Vector3D xAxis = new Vector3D(refDirection); - Vector3D refZ = new Vector3D(zAxis); - refZ.scale(d); - xAxis.sub(refZ); - return xAxis; - } - /** * Method recursive walks thru IFC file and collects the RELATIVEPLACEMENT EntityInstances from start entity to root entity * - * @param bimFileRootId of root IFCLOCALPLACEMENT element of BIMFile * @param entity you want to collect the RELATIVEPLACEMENT from * @param relativePlacementsToRoot empty list at beginning, needed for recursive iteration * @return List with EntityInstances of RELATIVEPLACEMENTs */ - private static ArrayList getRelativePlacementsToRoot(int bimFileRootId, EntityInstance entity, ArrayList relativePlacementsToRoot) { - if (entity.getId() == bimFileRootId) return relativePlacementsToRoot; + private static ArrayList getRelativePlacementsToRoot(EntityInstance entity, ArrayList relativePlacementsToRoot) { + if (entity == null) return relativePlacementsToRoot; // get objects IFCRELATIVEPLACEMENT entity EntityInstance relativePlacement = entity.getAttributeValueBNasEntityInstance("RelativePlacement"); @@ -409,7 +360,7 @@ private static ArrayList getRelativePlacementsToRoot(int bimFile // get id of placement relative to this (PLACEMENTRELTO) EntityInstance placementRelTo = entity.getAttributeValueBNasEntityInstance("PlacementRelTo"); - getRelativePlacementsToRoot(bimFileRootId, placementRelTo, relativePlacementsToRoot); + getRelativePlacementsToRoot(placementRelTo, relativePlacementsToRoot); return relativePlacementsToRoot; } @@ -452,5 +403,57 @@ public static List identifyRepresentationsOfObject(EntityInst return repObjectIdentities; } + /** + * Transforms the list of points using the given rotation matrix and translation vector + * + * @param points to transform + * @param rotation matrix + * @param translation vector + */ + private static void transformPoints(ArrayList points, Matrix3D rotation, Vector3D translation) { + points.forEach(p -> { + rotation.transform(p); + p.add(translation); + }); + } + + /** + * Gets the actual x-axis vector from reference system + * + * @param zAxis of IfcAxis2Placement3D + * @param refDirection of IfcAxis2Placement3D + * @return actual x-axis vector + */ + private static Vector3D retrieveXAxis(Vector3D zAxis, Vector3D refDirection) { + double d = refDirection.dot(zAxis) / zAxis.lengthSquared(); + Vector3D xAxis = new Vector3D(refDirection); + Vector3D refZ = new Vector3D(zAxis); + refZ.scale(d); + xAxis.sub(refZ); + return xAxis; + } + + /** + * Method finds and slips loops in data set + * + * @param data to check for loops + * @return list with data for each loop + */ + private static List> splitClosedLoopsInDataSet(List data) { + List> loops = new ArrayList<>(); + ArrayList loop = new ArrayList<>(); + for (Vector3D point : data) { + if (point.equalsVector(IfcRepresentationExtractor.defaultPoint) && !loop.isEmpty()) { + loops.add(loop); + loop = new ArrayList<>(); + } else if (!point.equalsVector(IfcRepresentationExtractor.defaultPoint)) { + loop.add(point); + } + if (data.indexOf(point) == data.size() - 1 && !loop.isEmpty()) { + loops.add(loop); + } + } + return loops; + } }