mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-02 01:46:27 +00:00
Merge developments from master into the python_wrapper branch
This commit is contained in:
@@ -1,2 +1,5 @@
|
||||
ADD_EXECUTABLE(IfcParseExamples IfcParseExamples.cpp)
|
||||
TARGET_LINK_LIBRARIES (IfcParseExamples IfcParse)
|
||||
TARGET_LINK_LIBRARIES (IfcParseExamples IfcParse)
|
||||
|
||||
ADD_EXECUTABLE(IfcOpenHouse IfcOpenHouse.cpp)
|
||||
TARGET_LINK_LIBRARIES (IfcOpenHouse IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet)
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <TColgp_Array2OfPnt.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcHierarchyHelper.h"
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
// Some convenience typedefs and definitions.
|
||||
typedef std::string S;
|
||||
typedef IfcWrite::IfcGuidHelper guid;
|
||||
typedef std::pair<double, double> XY;
|
||||
boost::none_t const null = (static_cast<boost::none_t>(0));
|
||||
|
||||
// The creation of Nurbs-surface for the IfcSite mesh, to be implemented lateron
|
||||
void createGroundShape(TopoDS_Shape& shape);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// The IfcHierarchyHelper is a subclass of the regular IfcFile that provides several
|
||||
// convenience functions for working with geometry in IFC files.
|
||||
IfcHierarchyHelper file;
|
||||
file.filename("IfcOpenHouse.ifc");
|
||||
|
||||
// Start by adding a wall to the file, initially leaving most attributes blank.
|
||||
IfcSchema::IfcWallStandardCase* south_wall = new IfcSchema::IfcWallStandardCase(
|
||||
guid(), // GlobalId
|
||||
0, // OwnerHistory
|
||||
S("South wall"), // Name
|
||||
null, // Description
|
||||
null, // ObjectType
|
||||
0, // ObjectPlacement
|
||||
0, // Representation
|
||||
null // Tag
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
|
||||
#endif
|
||||
);
|
||||
file.addBuildingProduct(south_wall);
|
||||
|
||||
// By adding a wall, a hierarchy has been automatically created that consists of the following
|
||||
// structure: IfcProject > IfcSite > IfcBuilding > IfcBuildingStorey > IfcWall
|
||||
|
||||
// Lateron changing the name of the IfcProject can be done by obtaining a reference to the
|
||||
// project, which has been created automatically.
|
||||
file.getSingle<IfcSchema::IfcProject>()->setName("IfcOpenHouse");
|
||||
|
||||
// An IfcOwnerHistory has been initialized as well, which should be assigned to the wall.
|
||||
south_wall->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
// The wall will be shaped as a box, with the dimensions specified in millimeters.
|
||||
IfcSchema::IfcProductDefinitionShape* south_wall_shape = file.addBox(10000, 360, 3000);
|
||||
|
||||
// The shape has to be assigned to the representation of the wall and is placed at the origin
|
||||
// of the coordinate system.
|
||||
south_wall->setRepresentation(south_wall_shape);
|
||||
south_wall->setObjectPlacement(file.addLocalPlacement());
|
||||
|
||||
// A pale white colour is assigned to the wall.
|
||||
IfcSchema::IfcPresentationStyleAssignment* wall_colour = file.setSurfaceColour(
|
||||
south_wall->Representation(), 0.75, 0.73, 0.68);
|
||||
|
||||
// Now create a footing for the wall to rest on.
|
||||
IfcSchema::IfcFooting* footing = new IfcSchema::IfcFooting(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
S("Footing"), null, null, 0, 0, null, IfcSchema::IfcFootingTypeEnum::IfcFootingType_STRIP_FOOTING);
|
||||
|
||||
file.addBuildingProduct(footing);
|
||||
|
||||
// The footing will span the entire floor plan of our building. The IfcRepresentationContext is
|
||||
// something that has been created automatically as well, but representations could have been
|
||||
// assigned to a specific context, for example to add a two dimensional plan representation as well.
|
||||
footing->setRepresentation(file.addBox(10100, 5460, 2000, 0, 0, 0, file.getSingle<IfcSchema::IfcRepresentationContext>()));
|
||||
footing->setObjectPlacement(file.addLocalPlacement(0, 2500, -2000));
|
||||
// The footing will have a dark gray colour
|
||||
IfcSchema::IfcPresentationStyleAssignment* footing_colour = file.setSurfaceColour(footing->Representation(), 0.26, 0.22, 0.18);
|
||||
|
||||
// IFC has two ways to apply boolean operations to geometry. IfcBooleanResults are commonly used
|
||||
// to clip geometry to a surface, for example to a slanted roof. For openings that are filled
|
||||
// with another element, for example a door or a window, an IfcOpeningElement is used instead.
|
||||
// An opening element is created with rectangular geometry
|
||||
IfcSchema::IfcOpeningElement* west_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, file.addLocalPlacement(-2500, 0, 400),
|
||||
file.addBox(6000, 3630, 1600, 0, 0, 0, file.getSingle<IfcSchema::IfcRepresentationContext>()), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(west_opening);
|
||||
|
||||
// Relate the opening element to the wall.
|
||||
IfcSchema::IfcRelVoidsElement* void_element = new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, south_wall, west_opening);
|
||||
file.AddEntity(void_element);
|
||||
|
||||
// Now create an additional opening
|
||||
IfcSchema::IfcOpeningElement* south_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, file.addLocalPlacement(3000, 0, 400),
|
||||
file.addBox(1860, 3000, 1600, 0, 0, 0, file.getSingle<IfcSchema::IfcRepresentationContext>()), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(south_opening);
|
||||
file.AddEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, south_wall, south_opening));
|
||||
|
||||
// Create a roof element
|
||||
IfcSchema::IfcRoof* south_roof = new IfcSchema::IfcRoof(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("South roof"), null, null,
|
||||
0, 0, null, IfcSchema::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
|
||||
|
||||
// The roof geometry is slanted 45 degrees by specifying a direction for the box extrusion
|
||||
south_roof->setRepresentation(file.addBox(10200, 360, sqrt(2.0*2900*2900), 0, file.addPlacement3d(0, 0, 0, 0, 1, 0),
|
||||
file.addTriplet<IfcSchema::IfcDirection>(0, -sqrt(0.5), sqrt(0.5)), file.getSingle<IfcSchema::IfcRepresentationContext>()));
|
||||
south_roof->setObjectPlacement(file.addLocalPlacement(0, -400, 2700));
|
||||
file.addBuildingProduct(south_roof);
|
||||
|
||||
// The same roof geometry is re-used on the north side of the roof, by inverting the X-axis of
|
||||
// the local placement the roof is rotated 180 degrees around the Z-axis
|
||||
IfcSchema::IfcRoof* north_roof = new IfcSchema::IfcRoof(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("North roof"),
|
||||
null, null, 0, 0, null, IfcSchema::IfcRoofTypeEnum::IfcRoofType_GABLE_ROOF);
|
||||
north_roof->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
north_roof->setRepresentation(south_roof->Representation());
|
||||
north_roof->setObjectPlacement(file.addLocalPlacement(0, 5400, 2700, 0, 0, 1, -1, 0, 0));
|
||||
file.addBuildingProduct(north_roof);
|
||||
|
||||
// By specifying a surface style for the south part of the roof, it gets assigned to the other
|
||||
// roof part as well, because they share the same representation.
|
||||
file.setSurfaceColour(south_roof->Representation(), 0.24, 0.08, 0.04);
|
||||
|
||||
// Copy the south wall to the north
|
||||
file.addBuildingProduct(new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), S("North wall"),
|
||||
null, null, file.addLocalPlacement(0, 5000, 0), south_wall->Representation(), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
|
||||
#endif
|
||||
));
|
||||
|
||||
// Now create a wall on the east of the building, again starting with just a box shape
|
||||
IfcSchema::IfcWallStandardCase* east_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
S("East wall"), null, null, file.addLocalPlacement(4820, 2500, 0, 0, 0, 1, 0, 1, 0), file.addBox(5000, 360, 6000), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
|
||||
#endif
|
||||
);
|
||||
file.addBuildingProduct(east_wall);
|
||||
|
||||
// The east wall geometry is clipped using two IfcHalfSpaceSolids, created from an
|
||||
// 'axis 3d placement' that specifies the plane against which the geometry is clipped.
|
||||
file.clipRepresentation(east_wall->Representation(), file.addPlacement3d(-2500, 0, 3000, -1, 0, 1), false);
|
||||
file.clipRepresentation(east_wall->Representation(), file.addPlacement3d(2500, 0, 3000, 1, 0, 1), false);
|
||||
|
||||
file.setSurfaceColour(east_wall->Representation(), wall_colour);
|
||||
|
||||
// The east wall is copied to the west location of the house
|
||||
IfcSchema::IfcWallStandardCase* west_wall = new IfcSchema::IfcWallStandardCase(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
S("West wall"), null, null, file.addLocalPlacement(-4820, 2500, 0, 0, 0, 1, 0, -1, 0), east_wall->Representation(), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcWallTypeEnum::IfcWallType_STANDARD
|
||||
#endif
|
||||
);
|
||||
file.addBuildingProduct(west_wall);
|
||||
|
||||
// The west wall is assigned an opening element we created for the south wall, opening elements are
|
||||
// not shared accross building elements, even if they share the same representation. Hence, the east
|
||||
// wall will not feature this opening.
|
||||
// NB: an Opening Element can only be used to create a single void within a single Element, as per:
|
||||
// http://www.buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcproductextension/lexical/ifcfeatureelementsubtraction.htm
|
||||
IfcSchema::IfcOpeningElement* west_opening_copy = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, west_opening->ObjectPlacement(), west_opening->Representation(), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(west_opening_copy);
|
||||
file.AddEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, west_wall, west_opening_copy));
|
||||
|
||||
// Up until now we have only used simple extrusions for the creation of the geometry. For the
|
||||
// ground mesh of the IfcSite we will use a Nurbs surface created in Open Cascade. The surface
|
||||
// will be tesselated using the deflection specified.
|
||||
TopoDS_Shape shape;
|
||||
createGroundShape(shape);
|
||||
IfcEntities geometrical_entities(new IfcEntityList());
|
||||
IfcSchema::IfcProductDefinitionShape* ground_representation = IfcGeom::tesselate(shape, 100., geometrical_entities);
|
||||
file.getSingle<IfcSchema::IfcSite>()->setRepresentation(ground_representation);
|
||||
file.AddEntities(geometrical_entities);
|
||||
IfcSchema::IfcShapeRepresentation::list ground_reps = geometrical_entities->as<IfcSchema::IfcShapeRepresentation>();
|
||||
for (IfcSchema::IfcShapeRepresentation::it it = ground_reps->begin(); it != ground_reps->end(); ++it) {
|
||||
(*it)->setContextOfItems(file.getSingle<IfcSchema::IfcRepresentationContext>());
|
||||
}
|
||||
file.setSurfaceColour(ground_representation, 0.15, 0.25, 0.05);
|
||||
|
||||
// According to the Ifc2x3 schema an IfcWallStandardCase needs to have an IfcMaterialLayerSet
|
||||
// assigned. Note that this material definition is independent of the surface styles we have
|
||||
// been assigning to the walls already. The surface styles determine the colour in the
|
||||
// '3D viewport' of most applications.
|
||||
// Some BIM authoring applications, such as Autodesk Revit, ignore the geometrical representation
|
||||
// by and large and construct native walls using the layer thickness and reference line offset
|
||||
// provided here.
|
||||
#ifdef USE_IFC4
|
||||
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick", null, null);
|
||||
#else
|
||||
IfcSchema::IfcMaterial* material = new IfcSchema::IfcMaterial("Brick");
|
||||
#endif
|
||||
IfcSchema::IfcMaterialLayer* layer = new IfcSchema::IfcMaterialLayer(
|
||||
material,
|
||||
360,
|
||||
null
|
||||
#ifdef USE_IFC4
|
||||
, null
|
||||
, null
|
||||
, null
|
||||
, null
|
||||
#endif
|
||||
);
|
||||
IfcSchema::IfcMaterialLayer::list layers (new IfcTemplatedEntityList<IfcSchema::IfcMaterialLayer>());
|
||||
layers->push(layer);
|
||||
IfcSchema::IfcMaterialLayerSet* layer_set = new IfcSchema::IfcMaterialLayerSet(
|
||||
layers,
|
||||
S("Wall")
|
||||
#ifdef USE_IFC4
|
||||
, null
|
||||
#endif
|
||||
);
|
||||
IfcSchema::IfcMaterialLayerSetUsage* layer_usage = new IfcSchema::IfcMaterialLayerSetUsage(
|
||||
layer_set,
|
||||
IfcSchema::IfcLayerSetDirectionEnum::IfcLayerSetDirection_AXIS2,
|
||||
IfcSchema::IfcDirectionSenseEnum::IfcDirectionSense_POSITIVE,
|
||||
-180
|
||||
#ifdef USE_IFC4
|
||||
, null
|
||||
#endif
|
||||
);
|
||||
|
||||
IfcSchema::IfcRelAssociatesMaterial* associates_material = new IfcSchema::IfcRelAssociatesMaterial(
|
||||
guid(),
|
||||
file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null,
|
||||
null,
|
||||
#ifdef USE_IFC4
|
||||
file.EntitiesByType<IfcSchema::IfcWallStandardCase>()->generalize(),
|
||||
#else
|
||||
file.EntitiesByType<IfcSchema::IfcWallStandardCase>()->as<IfcSchema::IfcRoot>(),
|
||||
#endif
|
||||
layer_usage);
|
||||
|
||||
file.AddEntity(material);
|
||||
file.AddEntity(layer);
|
||||
file.AddEntity(layer_set);
|
||||
file.AddEntity(layer_usage);
|
||||
file.AddEntity(associates_material);
|
||||
|
||||
// In addition, another common way to represent geometry in IFC files is to use extrusions of
|
||||
// planar areas bounded by a polygon.
|
||||
std::vector<XY> stair_points;
|
||||
stair_points.push_back(XY( 0, 0));
|
||||
stair_points.push_back(XY(250, 0));
|
||||
stair_points.push_back(XY(250, 200));
|
||||
stair_points.push_back(XY(500, 200));
|
||||
stair_points.push_back(XY(500, 400));
|
||||
stair_points.push_back(XY( 0, 400));
|
||||
IfcSchema::IfcStairFlight* stair = new IfcSchema::IfcStairFlight(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, file.addLocalPlacement(5050, 1000, 0, 0, 1, 0, 1, 0, 0),
|
||||
file.addExtrudedPolyline(stair_points, 1200), null, 2, 2, 0.2, 0.25
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcStairFlightTypeEnum::IfcStairFlightType_STRAIGHT
|
||||
#endif
|
||||
);
|
||||
|
||||
file.addBuildingProduct(stair);
|
||||
file.setSurfaceColour(stair->Representation(), footing_colour);
|
||||
|
||||
IfcSchema::IfcOpeningElement* door_opening = new IfcSchema::IfcOpeningElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, file.addLocalPlacement(5000-180, 2500-900, 0), file.addBox(1000, 1000, 2200), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcOpeningElementTypeEnum::IfcOpeningElementType_OPENING
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(door_opening);
|
||||
file.AddEntity(new IfcSchema::IfcRelVoidsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, east_wall, door_opening));
|
||||
|
||||
// A single shape representation can contain multiple representiation items. This way a product
|
||||
// can be a composition of multiple solids. The following door will be composed of four boxes
|
||||
// which constitute the door and its frame.
|
||||
IfcSchema::IfcDoor* door = new IfcSchema::IfcDoor(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, null,
|
||||
file.addLocalPlacement(4800, 1600, 0, 0, 0, 1, 0, 1, 0), 0, null, 2200, 1000
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcDoorTypeEnum::IfcDoorType_DOOR
|
||||
, IfcSchema::IfcDoorTypeOperationEnum::IfcDoorTypeOperation_SINGLE_SWING_LEFT
|
||||
, null
|
||||
#endif
|
||||
);
|
||||
door->setRepresentation(file.addBox(80, 80, 2120, 0, file.addPlacement3d(460, 0, 0)));
|
||||
IfcSchema::IfcRepresentation::list door_representations = door->Representation()->Representations();
|
||||
IfcSchema::IfcShapeRepresentation* door_body = 0;
|
||||
for (IfcSchema::IfcRepresentation::it i = door_representations->begin(); i != door_representations->end(); ++i) {
|
||||
IfcSchema::IfcRepresentation* rep = *i;
|
||||
if (rep->is(IfcSchema::Type::IfcShapeRepresentation) && rep->RepresentationIdentifier() == "Body") {
|
||||
door_body = (IfcSchema::IfcShapeRepresentation*) rep;
|
||||
}
|
||||
}
|
||||
file.addBox(door_body, 80, 80, 2120, 0, file.addPlacement3d(-460, 0, 0));
|
||||
file.addBox(door_body, 1000, 80, 80, 0, file.addPlacement3d( 0, 0, 2120));
|
||||
file.addBox(door_body, 860, 30, 2120);
|
||||
file.addBuildingProduct(door);
|
||||
file.setSurfaceColour(door->Representation(), 0.9, 0.9, 0.9);
|
||||
file.AddEntity(new IfcSchema::IfcRelFillsElement(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null, null, door_opening, door));
|
||||
|
||||
// Surface styles are assigned to representation items, hence there is no real limitation to
|
||||
// assign different colours within the same representation. However, some viewers have
|
||||
// difficulties rendering products with representation items with different surface styles.
|
||||
// Therefore we will construct the window as a decomposition of beams and a plate, in which
|
||||
// only the plate will have a transparent material assigned.
|
||||
|
||||
// The window frame will consists of four seperate beams.
|
||||
// AutoCAD Architecture will create an internal window type for the IfcWindow created.
|
||||
// Therefore the OverallWidth and OverallHeight of the window attributes will need to
|
||||
// match the bounding box of the representation. Furthermore, the window placement needs
|
||||
// to align with the lowerleft corner of the constituent parts.
|
||||
IfcSchema::IfcProductDefinitionShape::list frame_representations (new IfcTemplatedEntityList<IfcSchema::IfcProductDefinitionShape>());
|
||||
frame_representations->push(file.addBox(1860, 90, 90));
|
||||
frame_representations->push(*frame_representations->begin()); // Add a reference to the shape created above
|
||||
frame_representations->push(file.addBox(90, 90, 1420));
|
||||
frame_representations->push(*(frame_representations->end()-1)); // Add a reference to the shape created above
|
||||
|
||||
// The beams all have the same surface style assigned
|
||||
IfcSchema::IfcPresentationStyleAssignment* frame_style = 0;
|
||||
for (IfcSchema::IfcProductDefinitionShape::it i = frame_representations->begin(); i != frame_representations->end(); ++i) {
|
||||
if (frame_style) {
|
||||
file.setSurfaceColour(*i, frame_style);
|
||||
} else {
|
||||
frame_style = file.setSurfaceColour(*i, 0.5, 0.4, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
// This window will be placed at five locations within the building. A list of placements is
|
||||
// created and is iterated over to create all window instances.
|
||||
IfcSchema::IfcLocalPlacement::list window_placements (new IfcTemplatedEntityList<IfcSchema::IfcLocalPlacement>());
|
||||
window_placements->push(file.addLocalPlacement(2*-1770-430-930, -45, 400));
|
||||
window_placements->push(file.addLocalPlacement( -1770-430-930, -45, 400));
|
||||
window_placements->push(file.addLocalPlacement( -430-930, -45, 400));
|
||||
window_placements->push(file.addLocalPlacement( 3000-930, -45, 400));
|
||||
window_placements->push(file.addLocalPlacement( -4855+45, 885-930, 400, 0, 0, 1, 0, 1, 0));
|
||||
|
||||
for (IfcSchema::IfcLocalPlacement::it it = window_placements->begin(); it != window_placements->end(); ++it) {
|
||||
|
||||
// Create the window at the current location
|
||||
IfcSchema::IfcLocalPlacement* place = *it;
|
||||
IfcSchema::IfcWindow* window = new IfcSchema::IfcWindow(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, place, 0, null, 1600, 1860
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcWindowTypeEnum::IfcWindowType_WINDOW
|
||||
, IfcSchema::IfcWindowTypePartitioningEnum::IfcWindowTypePartitioning_SINGLE_PANEL
|
||||
, null
|
||||
#endif
|
||||
);
|
||||
file.addBuildingProduct(window);
|
||||
|
||||
// Initalize a list of parts for the window to be composed of
|
||||
IfcSchema::IfcObjectDefinition::list window_parts(new IfcTemplatedEntityList<IfcSchema::IfcObjectDefinition>());
|
||||
|
||||
// The placements for the beams are not shared accross the different windows because every
|
||||
// beam is placed relative to its parent window entity.
|
||||
IfcSchema::IfcLocalPlacement::list frame_placements (new IfcTemplatedEntityList<IfcSchema::IfcLocalPlacement>());
|
||||
frame_placements->push(file.addLocalPlacement( 930,45));
|
||||
frame_placements->push(file.addLocalPlacement( 930, 45, 1510));
|
||||
frame_placements->push(file.addLocalPlacement(-885+930, 45, 90));
|
||||
frame_placements->push(file.addLocalPlacement( 885+930, 45, 90));
|
||||
|
||||
// Now iterate over the placements and representations of the beam and add them to list of parts
|
||||
IfcSchema::IfcLocalPlacement::it frame_placement;
|
||||
IfcSchema::IfcProductDefinitionShape::it frame_representation;
|
||||
for (frame_placement = frame_placements->begin(), frame_representation = frame_representations->begin();
|
||||
frame_placement != frame_placements->end() && frame_representation != frame_representations->end();
|
||||
++frame_placement, ++frame_representation)
|
||||
{
|
||||
IfcSchema::IfcMember* frame_part = new IfcSchema::IfcMember(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, null, *frame_placement, *frame_representation, null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcMemberTypeEnum::IfcMemberType_MULLION
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(frame_part);
|
||||
window_parts->push(frame_part);
|
||||
file.relatePlacements(window, frame_part);
|
||||
}
|
||||
|
||||
// Add the glass plate to the list of parts
|
||||
IfcSchema::IfcPlate* glass_part = new IfcSchema::IfcPlate(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(), null,
|
||||
null, null, file.addLocalPlacement(930, 45, 90), file.addBox(1680, 10, 1420), null
|
||||
#ifdef USE_IFC4
|
||||
, IfcSchema::IfcPlateTypeEnum::IfcPlateType_SHEET
|
||||
#endif
|
||||
);
|
||||
file.AddEntity(glass_part);
|
||||
window_parts->push(glass_part);
|
||||
file.relatePlacements(window, glass_part);
|
||||
file.setSurfaceColour(glass_part->Representation(), 0.6, 0.7, 0.75, 0.1);
|
||||
|
||||
// Now create a decomposition relation between the window and the parts. Most viewers and authoring
|
||||
// tools will consider the window a single entity that can be selected as a whole.
|
||||
IfcSchema::IfcRelDecomposes* decomposition = new IfcSchema::IfcRelAggregates(guid(), file.getSingle<IfcSchema::IfcOwnerHistory>(),
|
||||
null, null, window, window_parts);
|
||||
file.AddEntity(decomposition);
|
||||
}
|
||||
|
||||
// Finally create a file stream for our output and write the IFC file to it.
|
||||
std::ofstream f("IfcOpenHouse.ifc");
|
||||
f << file;
|
||||
}
|
||||
|
||||
void createGroundShape(TopoDS_Shape& shape) {
|
||||
TColgp_Array2OfPnt cv (0, 4, 0, 4);
|
||||
cv.SetValue(0, 0, gp_Pnt(-10000, -10000, -4130));
|
||||
cv.SetValue(0, 1, gp_Pnt(-10000, -4330, -4130));
|
||||
cv.SetValue(0, 2, gp_Pnt(-10000, 0, -5130));
|
||||
cv.SetValue(0, 3, gp_Pnt(-10000, 4330, -7130));
|
||||
cv.SetValue(0, 4, gp_Pnt(-10000, 10000, -7130));
|
||||
cv.SetValue(1, 0, gp_Pnt( -3330, -10000, -5130));
|
||||
cv.SetValue(1, 1, gp_Pnt( -7670, -3670, 5000));
|
||||
cv.SetValue(1, 2, gp_Pnt( -9000, 0, 1000));
|
||||
cv.SetValue(1, 3, gp_Pnt( -7670, 7670, 6000));
|
||||
cv.SetValue(1, 4, gp_Pnt( -3330, 10000, -4130));
|
||||
cv.SetValue(2, 0, gp_Pnt( 0, -10000, -5530));
|
||||
cv.SetValue(2, 1, gp_Pnt( 0, -3670, 3000));
|
||||
cv.SetValue(2, 2, gp_Pnt( 0, 0, -12000));
|
||||
cv.SetValue(2, 3, gp_Pnt( 0, 7670, 1500));
|
||||
cv.SetValue(2, 4, gp_Pnt( 0, 10000, -4130));
|
||||
cv.SetValue(3, 0, gp_Pnt( 3330, -10000, -6130));
|
||||
cv.SetValue(3, 1, gp_Pnt( 7670, -3670, 6000));
|
||||
cv.SetValue(3, 2, gp_Pnt( 9000, 0, 5000));
|
||||
cv.SetValue(3, 3, gp_Pnt( 7670, 9000, 7000));
|
||||
cv.SetValue(3, 4, gp_Pnt( 3330, 10000, -4130));
|
||||
cv.SetValue(4, 0, gp_Pnt( 10000, -10000, -6130));
|
||||
cv.SetValue(4, 1, gp_Pnt( 10000, -4330, -5130));
|
||||
cv.SetValue(4, 2, gp_Pnt( 10000, 0, -4130));
|
||||
cv.SetValue(4, 3, gp_Pnt( 10000, 4330, -4130));
|
||||
cv.SetValue(4, 4, gp_Pnt( 10000, 10000, -8130));
|
||||
TColStd_Array1OfReal knots(0, 1);
|
||||
knots(0) = 0;
|
||||
knots(1) = 1;
|
||||
TColStd_Array1OfInteger mult(0, 1);
|
||||
mult(0) = 5;
|
||||
mult(1) = 5;
|
||||
Handle(Geom_BSplineSurface) surf = new Geom_BSplineSurface(cv, knots, knots, mult, mult, 4, 4);
|
||||
#if OCC_VERSION_HEX < 0x60502
|
||||
shape = BRepBuilderAPI_MakeFace(surf);
|
||||
#else
|
||||
shape = BRepBuilderAPI_MakeFace(surf, 1);
|
||||
#endif
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
using namespace Ifc2x3;
|
||||
using namespace IfcSchema;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ColladaSerializer.h"
|
||||
|
||||
std::string collada_id(const std::string& s) {
|
||||
std::string id;
|
||||
id.reserve(s.size());
|
||||
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
|
||||
const std::string::value_type c = *it;
|
||||
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_')) {
|
||||
id.push_back(c);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<float>& floats, const char* coords /* = "XYZ" */) {
|
||||
COLLADASW::FloatSource source(mSW);
|
||||
source.setId(mesh_id + suffix);
|
||||
source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX);
|
||||
source.setAccessorStride(strlen(coords));
|
||||
source.setAccessorCount(floats.size() / 3);
|
||||
for (unsigned int i = 0; i < source.getAccessorStride(); ++i) {
|
||||
source.getParameterNameList().push_back(std::string(1, coords[i]));
|
||||
}
|
||||
source.prepareToAppendValues();
|
||||
for (std::vector<float>::const_iterator it = floats.begin(); it != floats.end(); ++it) {
|
||||
source.appendValues(*it);
|
||||
}
|
||||
source.finish();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeomObjects::Material>& materials) {
|
||||
openMesh(mesh_id);
|
||||
|
||||
// The normals vector can be empty for example when the WELD_VERTICES setting is used.
|
||||
// IfcOpenShell does not provide them with multiple face normals collapsed into a single vertex.
|
||||
const bool has_normals = !normals.empty();
|
||||
|
||||
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions);
|
||||
if (has_normals) {
|
||||
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, normals);
|
||||
}
|
||||
|
||||
COLLADASW::VerticesElement vertices(mSW);
|
||||
vertices.setId(mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX );
|
||||
vertices.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::POSITION, "#" + mesh_id + COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX));
|
||||
vertices.add();
|
||||
|
||||
std::vector<int>::const_iterator index_range_start = indices.begin();
|
||||
std::vector<int>::const_iterator material_it = material_ids.begin();
|
||||
int previous_material_id = -2;
|
||||
for (std::vector<int>::const_iterator it = indices.begin(); ; it += 3) {
|
||||
const int current_material_id = material_it == material_ids.end()
|
||||
? -3
|
||||
: *(material_it++);
|
||||
const int num_triangles = std::distance(index_range_start, it) / 3;
|
||||
if ((previous_material_id != current_material_id && num_triangles > 0) || (it == indices.end())) {
|
||||
COLLADASW::Triangles triangles(mSW);
|
||||
triangles.setMaterial(collada_id(previous_material_id < 0
|
||||
? default_material_name
|
||||
: materials[previous_material_id].name()));
|
||||
triangles.setCount(num_triangles);
|
||||
int offset = 0;
|
||||
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) );
|
||||
if (has_normals) {
|
||||
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++ ) );
|
||||
}
|
||||
triangles.prepareToAppendValues();
|
||||
for (std::vector<int>::const_iterator jt = index_range_start; jt != it; ++jt) {
|
||||
const int idx = *jt;
|
||||
if (has_normals) {
|
||||
triangles.appendValues(idx, idx);
|
||||
} else {
|
||||
triangles.appendValues(idx);
|
||||
}
|
||||
}
|
||||
triangles.finish();
|
||||
index_range_start = it;
|
||||
}
|
||||
previous_material_id = current_material_id;
|
||||
if (it == indices.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closeMesh();
|
||||
closeGeometry();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaGeometries::close() {
|
||||
closeLibrary();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<float>& matrix) {
|
||||
if (!scene_opened) {
|
||||
openVisualScene(scene_id);
|
||||
scene_opened = true;
|
||||
}
|
||||
|
||||
COLLADASW::Node node(mSW);
|
||||
node.setNodeId(node_id);
|
||||
node.setNodeName(node_name);
|
||||
node.setType(COLLADASW::Node::NODE);
|
||||
|
||||
// The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement.
|
||||
// Note that this placement is absolute, ie it is multiplied with all parent placements.
|
||||
double matrix_array[4][4] = {
|
||||
{matrix[0], matrix[3], matrix[6], matrix[ 9]},
|
||||
{matrix[1], matrix[4], matrix[7], matrix[10]},
|
||||
{matrix[2], matrix[5], matrix[8], matrix[11]},
|
||||
{ 0, 0, 0, 1}
|
||||
};
|
||||
|
||||
node.start();
|
||||
node.addMatrix(matrix_array);
|
||||
COLLADASW::InstanceGeometry instanceGeometry(mSW);
|
||||
instanceGeometry.setUrl ("#" + geom_name);
|
||||
for (std::vector<std::string>::const_iterator it = material_ids.begin(); it != material_ids.end(); ++it) {
|
||||
COLLADASW::InstanceMaterial material (*it, "#" + *it);
|
||||
instanceGeometry.getBindMaterial().getInstanceMaterialList().push_back(material);
|
||||
}
|
||||
instanceGeometry.add();
|
||||
node.end();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaScene::write() {
|
||||
if (scene_opened) {
|
||||
closeVisualScene();
|
||||
closeLibrary();
|
||||
|
||||
COLLADASW::Scene scene (mSW, COLLADASW::URI ("#" + scene_id));
|
||||
scene.add();
|
||||
}
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeomObjects::Material& material) {
|
||||
openEffect(collada_id(material.name()) + "-fx");
|
||||
COLLADASW::EffectProfile effect(mSW);
|
||||
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
|
||||
if (material.hasDiffuse()) {
|
||||
const double* diffuse = material.diffuse();
|
||||
effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(diffuse[0],diffuse[1],diffuse[2])));
|
||||
}
|
||||
if (material.hasSpecular()) {
|
||||
const double* specular = material.specular();
|
||||
effect.setSpecular(COLLADASW::ColorOrTexture(COLLADASW::Color(specular[0],specular[1],specular[2])));
|
||||
}
|
||||
if (material.hasSpecularity()) {
|
||||
effect.setShininess(material.specularity());
|
||||
}
|
||||
if (material.hasTransparency()) {
|
||||
const double transparency = material.transparency();
|
||||
if (transparency > 0) {
|
||||
// The default opacity mode for Collada is A_ONE, which apparently indicates a
|
||||
// transparency value of 1 to be fully opaque. Hence transparency is inverted.
|
||||
effect.setTransparency(1.0 - transparency);
|
||||
}
|
||||
}
|
||||
addEffectProfile(effect);
|
||||
closeEffect();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close() {
|
||||
closeLibrary();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeomObjects::Material& material) {
|
||||
if (!contains(material)) {
|
||||
effects.write(material);
|
||||
materials.push_back(material);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeomObjects::Material& material) {
|
||||
return std::find(materials.begin(), materials.end(), material) != materials.end();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
|
||||
effects.close();
|
||||
for (std::vector<IfcGeomObjects::Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
|
||||
const std::string& material_name = collada_id((*it).name());
|
||||
openMaterial(material_name);
|
||||
addInstanceEffect("#" + material_name + "-fx");
|
||||
closeMaterial();
|
||||
}
|
||||
closeLibrary();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_name, float unit_magnitude) {
|
||||
stream.startDocument();
|
||||
|
||||
COLLADASW::Asset asset(&stream);
|
||||
asset.getContributor().mAuthoringTool = std::string("IfcOpenShell ") + IFCOPENSHELL_VERSION;
|
||||
asset.setUnit(unit_name, unit_magnitude);
|
||||
asset.setUpAxisType(COLLADASW::Asset::Z_UP);
|
||||
asset.add();
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeomObjects::Material>& _materials) {
|
||||
const IfcGeomObjects::Material default_for_type = IfcGeomObjects::Material(IfcGeom::get_default_style(type));
|
||||
std::vector<std::string> material_references;
|
||||
const bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end();
|
||||
if (needs_default) {
|
||||
if (!materials.contains(default_for_type)) {
|
||||
materials.add(default_for_type);
|
||||
}
|
||||
material_references.push_back(collada_id(default_for_type.name()));
|
||||
}
|
||||
for (std::vector<IfcGeomObjects::Material>::const_iterator it = _materials.begin(); it != _materials.end(); ++it) {
|
||||
const IfcGeomObjects::Material& material = *it;
|
||||
if (!materials.contains(material)) {
|
||||
materials.add(material);
|
||||
}
|
||||
material_references.push_back(collada_id(material.name()));
|
||||
}
|
||||
deferreds.push_back(DeferredObject(guid, name, type, obj_id, matrix, vertices, normals, indices, material_ids, _materials, material_references));
|
||||
}
|
||||
|
||||
const std::string ColladaSerializer::ColladaExporter::DeferredObject::Name() const {
|
||||
std::stringstream ss;
|
||||
if (!this->name.empty()) {
|
||||
ss << this->obj_id << "_" << this->name;
|
||||
} else {
|
||||
ss << this->guid;
|
||||
}
|
||||
return collada_id(ss.str());
|
||||
}
|
||||
|
||||
void ColladaSerializer::ColladaExporter::endDocument() {
|
||||
// In fact due the XML based nature of Collada and its dependency on library nodes,
|
||||
// only at this point all objects are written to the stream.
|
||||
materials.write();
|
||||
for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
|
||||
const std::string object_name = it->Name();
|
||||
geometries.write(object_name, it->type, it->vertices, it->normals, it->indices, it->material_ids, it->materials);
|
||||
}
|
||||
geometries.close();
|
||||
for (std::vector<DeferredObject>::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
|
||||
const std::string object_name = it->Name();
|
||||
scene.add(object_name, object_name, object_name, it->material_references, it->matrix);
|
||||
}
|
||||
scene.write();
|
||||
stream.endDocument();
|
||||
}
|
||||
|
||||
bool ColladaSerializer::ready() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ColladaSerializer::writeHeader() {
|
||||
exporter.startDocument(unit_name, unit_magnitude);
|
||||
}
|
||||
|
||||
void ColladaSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
|
||||
const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh();
|
||||
exporter.writeTesselated(o->guid(), o->name(), o->type(), o->id(), o->matrix(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.material_ids(), mesh.materials());
|
||||
}
|
||||
|
||||
void ColladaSerializer::finalize() {
|
||||
exporter.endDocument();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
|
||||
#ifndef COLLADASERIALIZER_H
|
||||
#define COLLADASERIALIZER_H
|
||||
|
||||
#include <COLLADASWStreamWriter.h>
|
||||
#include <COLLADASWPrimitves.h>
|
||||
#include <COLLADASWLibraryGeometries.h>
|
||||
#include <COLLADASWSource.h>
|
||||
#include <COLLADASWScene.h>
|
||||
#include <COLLADASWNode.h>
|
||||
#include <COLLADASWInstanceGeometry.h>
|
||||
#include <COLLADASWLibraryVisualScenes.h>
|
||||
#include <COLLADASWLibraryEffects.h>
|
||||
#include <COLLADASWLibraryMaterials.h>
|
||||
#include <COLLADASWBaseInputElement.h>
|
||||
#include <COLLADASWAsset.h>
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
#include "../ifcconvert/GeometrySerializer.h"
|
||||
|
||||
class ColladaSerializer : public GeometrySerializer
|
||||
{
|
||||
private:
|
||||
class ColladaExporter
|
||||
{
|
||||
private:
|
||||
class ColladaGeometries : public COLLADASW::LibraryGeometries
|
||||
{
|
||||
public:
|
||||
explicit ColladaGeometries(COLLADASW::StreamWriter& stream)
|
||||
: COLLADASW::LibraryGeometries(&stream)
|
||||
{}
|
||||
void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<float>& floats, const char* coords = "XYZ");
|
||||
void write(const std::string mesh_id, const std::string& default_material_name, const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int> material_ids, const std::vector<IfcGeomObjects::Material>& materials);
|
||||
void close();
|
||||
};
|
||||
class ColladaScene : public COLLADASW::LibraryVisualScenes
|
||||
{
|
||||
private:
|
||||
const std::string scene_id;
|
||||
bool scene_opened;
|
||||
public:
|
||||
ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream)
|
||||
: COLLADASW::LibraryVisualScenes(&stream)
|
||||
, scene_id(scene_id)
|
||||
, scene_opened(false)
|
||||
{}
|
||||
void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<float>& matrix);
|
||||
void write();
|
||||
};
|
||||
class ColladaMaterials : public COLLADASW::LibraryMaterials
|
||||
{
|
||||
private:
|
||||
class ColladaEffects : public COLLADASW::LibraryEffects
|
||||
{
|
||||
public:
|
||||
explicit ColladaEffects(COLLADASW::StreamWriter& stream)
|
||||
: COLLADASW::LibraryEffects(&stream)
|
||||
{}
|
||||
void write(const IfcGeomObjects::Material& material);
|
||||
void close();
|
||||
};
|
||||
std::vector<IfcGeomObjects::Material> materials;
|
||||
ColladaEffects effects;
|
||||
public:
|
||||
explicit ColladaMaterials(COLLADASW::StreamWriter& stream)
|
||||
: COLLADASW::LibraryMaterials(&stream)
|
||||
, effects(stream)
|
||||
{}
|
||||
void add(const IfcGeomObjects::Material& material);
|
||||
bool contains(const IfcGeomObjects::Material& material);
|
||||
void write();
|
||||
};
|
||||
class DeferredObject {
|
||||
public:
|
||||
std::string guid, name, type;
|
||||
int obj_id;
|
||||
std::vector<float> matrix;
|
||||
std::vector<float> vertices;
|
||||
std::vector<float> normals;
|
||||
std::vector<int> indices;
|
||||
std::vector<int> material_ids;
|
||||
std::vector<IfcGeomObjects::Material> materials;
|
||||
std::vector<std::string> material_references;
|
||||
DeferredObject(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices,
|
||||
const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids,
|
||||
const std::vector<IfcGeomObjects::Material>& materials, const std::vector<std::string>& material_references)
|
||||
: guid(guid)
|
||||
, name(name)
|
||||
, type(type)
|
||||
, obj_id(obj_id)
|
||||
, matrix(matrix)
|
||||
, vertices(vertices)
|
||||
, normals(normals)
|
||||
, indices(indices)
|
||||
, material_ids(material_ids)
|
||||
, materials(materials)
|
||||
, material_references(material_references)
|
||||
{}
|
||||
const std::string Name() const;
|
||||
};
|
||||
COLLADABU::NativeString filename;
|
||||
COLLADASW::StreamWriter stream;
|
||||
ColladaGeometries geometries;
|
||||
ColladaScene scene;
|
||||
ColladaMaterials materials;
|
||||
public:
|
||||
ColladaExporter(const std::string& scene_name, const std::string& fn)
|
||||
: filename(fn.c_str())
|
||||
, stream(filename)
|
||||
, geometries(stream)
|
||||
, scene(scene_name, stream)
|
||||
, materials(stream)
|
||||
{}
|
||||
std::vector<DeferredObject> deferreds;
|
||||
virtual ~ColladaExporter() {}
|
||||
void startDocument(const std::string& unit_name, float unit_magnitude);
|
||||
void writeTesselated(const std::string& guid, const std::string& name, const std::string& type, int obj_id, const std::vector<float>& matrix, const std::vector<float>& vertices, const std::vector<float>& normals, const std::vector<int>& indices, const std::vector<int>& material_ids, const std::vector<IfcGeomObjects::Material>& materials);
|
||||
void endDocument();
|
||||
};
|
||||
ColladaExporter exporter;
|
||||
std::string unit_name;
|
||||
float unit_magnitude;
|
||||
public:
|
||||
ColladaSerializer(const std::string& dae_filename)
|
||||
: GeometrySerializer()
|
||||
, exporter("IfcOpenShell", dae_filename)
|
||||
{}
|
||||
bool ready();
|
||||
void writeHeader();
|
||||
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o);
|
||||
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
|
||||
void finalize();
|
||||
bool isTesselated() const { return true; }
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
|
||||
unit_name = name;
|
||||
unit_magnitude = magnitude;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef GEOMETRYSERIALIZER_H
|
||||
#define GEOMETRYSERIALIZER_H
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
class GeometrySerializer {
|
||||
public:
|
||||
virtual bool ready() = 0;
|
||||
virtual void writeHeader() = 0;
|
||||
virtual void finalize() = 0;
|
||||
virtual bool isTesselated() const = 0;
|
||||
virtual ~GeometrySerializer() {}
|
||||
virtual void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) = 0;
|
||||
virtual void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) = 0;
|
||||
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,299 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This started as a brief example of how IfcOpenShell can be interfaced from *
|
||||
* within a C++ context, it has since then evolved into a fullfledged command *
|
||||
* line application that is able to convert geometry in an IFC files into *
|
||||
* several tesselated and topological output formats. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
#include "../ifcconvert/ColladaSerializer.h"
|
||||
#include "../ifcconvert/IgesSerializer.h"
|
||||
#include "../ifcconvert/StepSerializer.h"
|
||||
#include "../ifcconvert/WavefrontObjSerializer.h"
|
||||
|
||||
void printVersion() {
|
||||
std::cerr << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
|
||||
}
|
||||
|
||||
void printUsage(const boost::program_options::options_description& generic_options, const boost::program_options::options_description& geom_options) {
|
||||
printVersion();
|
||||
std::cerr << "Usage: IfcConvert [options] <input.ifc> [<output>]" << std::endl
|
||||
<< std::endl
|
||||
<< "Converts the geometry in an IFC file into one of the following formats:" << std::endl
|
||||
<< " .obj WaveFront OBJ (a .mtl file is also created)" << std::endl;
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
std::cerr << " .dae Collada Digital Assets Exchange" << std::endl;
|
||||
#endif
|
||||
std::cerr << " .stp STEP Standard for the Exchange of Product Data" << std::endl
|
||||
<< " .igs IGES Initial Graphics Exchange Specification" << std::endl
|
||||
<< std::endl
|
||||
<< "Command line options" << std::endl << generic_options << std::endl
|
||||
<< "Advanced options" << std::endl << geom_options << std::endl;
|
||||
}
|
||||
|
||||
std::string change_extension(const std::string& fn, const std::string& ext) {
|
||||
std::string::size_type dot = fn.find_last_of('.');
|
||||
if (dot != std::string::npos) {
|
||||
return fn.substr(0,dot+1) + ext;
|
||||
} else {
|
||||
return fn + "." + ext;
|
||||
}
|
||||
}
|
||||
|
||||
static std::stringstream log_stream;
|
||||
void write_log();
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
boost::program_options::options_description generic_options;
|
||||
generic_options.add_options()
|
||||
("help", "display usage information")
|
||||
("version", "display version information")
|
||||
("verbose,v", "more verbose output");
|
||||
|
||||
boost::program_options::options_description fileio_options;
|
||||
fileio_options.add_options()
|
||||
("input-file", boost::program_options::value<std::string>(), "input IFC file")
|
||||
("output-file", boost::program_options::value<std::string>(), "output geometry file");
|
||||
|
||||
std::vector<std::string> ignore_types_vector;
|
||||
boost::program_options::options_description geom_options;
|
||||
geom_options.add_options()
|
||||
("weld-vertices", "Specifies whether vertices are welded, meaning that the coordinates "
|
||||
"vector will only contain unique xyz-triplets. This results in a "
|
||||
"manifold mesh which is useful for modelling applications, but might "
|
||||
"result in unwanted shading artifacts in rendering applications.")
|
||||
("use-world-coords", "Specifies whether to apply the local placements of building elements "
|
||||
"directly to the coordinates of the representation mesh rather than "
|
||||
"to represent the local placement in the 4x3 matrix, which will in that "
|
||||
"case be the identity matrix.")
|
||||
("convert-back-units", "Specifies whether to convert back geometrical output back to the "
|
||||
"unit of measure in which it is defined in the IFC file. Default is "
|
||||
"to use meters.")
|
||||
("sew-shells", "Specifies whether to sew the faces of IfcConnectedFaceSets together. This is a "
|
||||
"potentially time consuming operation, but guarantees a consistent orientation "
|
||||
"of surface normals, even if the faces are not properly oriented in the IFC file.")
|
||||
("merge-boolean-operands", "Specifies whether to merge all IfcOpeningElement operands into a single "
|
||||
"operand before applying the subtraction operation. This may "
|
||||
"introduce a performance improvement at the risk of failing, in "
|
||||
"which case the subtraction is applied one-by-one.")
|
||||
("force-ccw-face-orientation", "Recompute topological face normals using Newell's Method to "
|
||||
"guarantee that face vertices are defined in a Counter Clock "
|
||||
"Wise order, even if the faces are not part of a closed shell.")
|
||||
("disable-opening-subtractions", "Specifies whether to disable the boolean subtraction of "
|
||||
"IfcOpeningElement Representations from their RelatingElements.")
|
||||
("ignore-types", boost::program_options::value< std::vector<std::string> >(&ignore_types_vector)->multitoken(),
|
||||
"A list of IFC datatype keywords that should not be included in the geometrical output. "
|
||||
"Defaults to IfcOpeningElement and IfcSpace");
|
||||
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(fileio_options).add(geom_options);
|
||||
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("input-file", 1);
|
||||
positional_options.add("output-file", 1);
|
||||
|
||||
boost::program_options::variables_map vmap;
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
|
||||
options(cmdline_options).positional(positional_options).run(), vmap);
|
||||
boost::program_options::notify(vmap);
|
||||
|
||||
if (vmap.count("version")) {
|
||||
printVersion();
|
||||
return 1;
|
||||
} else if (vmap.count("help") || !vmap.count("input-file")) {
|
||||
printUsage(generic_options, geom_options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const bool verbose = vmap.count("verbose") != 0;
|
||||
const bool weld_vertices = vmap.count("weld-vertices") != 0;
|
||||
const bool use_world_coords = vmap.count("use-world-coords") != 0;
|
||||
const bool convert_back_units = vmap.count("convert-back-units") != 0;
|
||||
const bool sew_shells = vmap.count("sew-shells") != 0;
|
||||
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
|
||||
const bool force_ccw_face_orientation = vmap.count("force-ccw-face-orientation") != 0;
|
||||
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
|
||||
|
||||
// Gets the set ifc types to be ignored from the command line.
|
||||
std::set<std::string> ignore_types;
|
||||
for (std::vector<std::string>::const_iterator it = ignore_types_vector.begin(); it != ignore_types_vector.end(); ++it) {
|
||||
std::string lowercase_type = *it;
|
||||
for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) {
|
||||
*c = tolower(*c);
|
||||
}
|
||||
ignore_types.insert(lowercase_type);
|
||||
}
|
||||
// If none are specified these are the defaults to skip from output
|
||||
if (ignore_types_vector.empty()) {
|
||||
ignore_types.insert("ifcopeningelement");
|
||||
ignore_types.insert("ifcspace");
|
||||
}
|
||||
|
||||
const std::string input_filename = vmap["input-file"].as<std::string>();
|
||||
// If no output filename is specified a Wavefront OBJ file will be output
|
||||
// to maintain backwards compatibility with the obsolete IfcObj executable.
|
||||
const std::string output_filename = vmap.count("output-file") == 1
|
||||
? vmap["output-file"].as<std::string>()
|
||||
: change_extension(input_filename, "obj");
|
||||
|
||||
if (output_filename.size() < 5) {
|
||||
printUsage(generic_options, geom_options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, use_world_coords);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES, weld_vertices);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS, sew_shells);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::CONVERT_BACK_UNITS, convert_back_units);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::FASTER_BOOLEANS, merge_boolean_operands);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION, force_ccw_face_orientation);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
|
||||
|
||||
std::string output_extension = output_filename.substr(output_filename.size()-4);
|
||||
for (std::string::iterator c = output_extension.begin(); c != output_extension.end(); ++c) {
|
||||
*c = tolower(*c);
|
||||
}
|
||||
|
||||
Logger::SetOutput(&std::cout, &log_stream);
|
||||
|
||||
GeometrySerializer* serializer;
|
||||
if (output_extension == ".obj") {
|
||||
const std::string mtl_filename = output_filename.substr(0,output_filename.size()-3) + "mtl";
|
||||
if (!use_world_coords) {
|
||||
Logger::Message(Logger::LOG_NOTICE, "Using world coords when writing WaveFront OBJ files");
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, true);
|
||||
}
|
||||
serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename);
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
} else if (output_extension == ".dae") {
|
||||
serializer = new ColladaSerializer(output_filename);
|
||||
#endif
|
||||
} else if (output_extension == ".stp") {
|
||||
serializer = new StepSerializer(output_filename);
|
||||
} else if (output_extension == ".igs") {
|
||||
// Not sure why this is needed, but it is.
|
||||
// See: http://tracker.dev.opencascade.org/view.php?id=23679
|
||||
IGESControl_Controller::Init();
|
||||
serializer = new IgesSerializer(output_filename);
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unknown output filename extension");
|
||||
write_log();
|
||||
printUsage(generic_options, geom_options);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
|
||||
|
||||
if (!serializer->ready()) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unable to open output file for writing");
|
||||
write_log();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!serializer->isTesselated()) {
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_TRIANGULATION, true);
|
||||
if (weld_vertices) {
|
||||
Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing STEP or IGES files");
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the file supplied in argv[1]. Returns true on succes.
|
||||
if ( ! IfcGeomObjects::Init(input_filename, &std::cout, &log_stream) ) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file or no geometrical entities found");
|
||||
write_log();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (convert_back_units) {
|
||||
serializer->setUnitNameAndMagnitude(IfcGeomObjects::GetUnitName(), IfcGeomObjects::GetUnitMagnitude());
|
||||
} else {
|
||||
serializer->setUnitNameAndMagnitude("METER", 1.0f);
|
||||
}
|
||||
|
||||
serializer->writeHeader();
|
||||
|
||||
std::set<std::string> materials;
|
||||
|
||||
time_t start,end;
|
||||
time(&start);
|
||||
int old_progress = -1;
|
||||
Logger::Status("Creating geometry...");
|
||||
|
||||
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
|
||||
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcGeomObjects.h for definition)
|
||||
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
|
||||
do {
|
||||
const IfcGeomObjects::IfcObject* geom_object;
|
||||
|
||||
if (serializer->isTesselated()) {
|
||||
geom_object = IfcGeomObjects::Get();
|
||||
} else {
|
||||
geom_object = IfcGeomObjects::GetShapeModel();
|
||||
}
|
||||
|
||||
std::string lowercase_type = geom_object->type();
|
||||
for (std::string::iterator c = lowercase_type.begin(); c != lowercase_type.end(); ++c) {
|
||||
*c = tolower(*c);
|
||||
}
|
||||
if (ignore_types.find(lowercase_type) != ignore_types.end()) continue;
|
||||
|
||||
if (serializer->isTesselated()) {
|
||||
serializer->writeTesselated(static_cast<const IfcGeomObjects::IfcGeomObject*>(geom_object));
|
||||
} else {
|
||||
serializer->writeShapeModel(static_cast<const IfcGeomObjects::IfcGeomShapeModelObject*>(geom_object));
|
||||
}
|
||||
|
||||
const int progress = IfcGeomObjects::Progress() / 2;
|
||||
if ( old_progress!= progress ) Logger::ProgressBar(progress);
|
||||
old_progress = progress;
|
||||
|
||||
} while ( IfcGeomObjects::Next() );
|
||||
|
||||
serializer->finalize();
|
||||
delete serializer;
|
||||
|
||||
Logger::Status("\rDone creating geometry ");
|
||||
|
||||
write_log();
|
||||
|
||||
time(&end);
|
||||
int dif = (int) difftime (end,start);
|
||||
printf ("\nConversion took %d seconds\n", dif );
|
||||
}
|
||||
|
||||
void write_log() {
|
||||
std::string log = log_stream.str();
|
||||
if (!log.empty()) {
|
||||
std::cerr << std::endl << "Log:" << std::endl;
|
||||
std::cerr << log << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IGESSERIALIZER_H
|
||||
#define IGESSERIALIZER_H
|
||||
|
||||
#include <IGESControl_Controller.hxx>
|
||||
#include <IGESControl_Writer.hxx>
|
||||
#include <Interface_Static.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
#include "../ifcconvert/OpenCascadeBasedSerializer.h"
|
||||
|
||||
class IgesSerializer : public OpenCascadeBasedSerializer
|
||||
{
|
||||
private:
|
||||
IGESControl_Writer writer;
|
||||
public:
|
||||
explicit IgesSerializer(const std::string& out_filename)
|
||||
: OpenCascadeBasedSerializer(out_filename)
|
||||
{}
|
||||
virtual ~IgesSerializer() {}
|
||||
void writeShape(const TopoDS_Shape& shape) {
|
||||
writer.AddShape(shape);
|
||||
}
|
||||
void finalize() {
|
||||
writer.Write(out_filename.c_str());
|
||||
}
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
|
||||
const char* symbol = getSymbolForUnitMagnitude(magnitude);
|
||||
if (symbol) {
|
||||
Interface_Static::SetCVal("write.iges.unit", symbol);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
|
||||
#include "OpenCascadeBasedSerializer.h"
|
||||
|
||||
bool OpenCascadeBasedSerializer::ready() {
|
||||
std::ofstream test_file(out_filename.c_str(), std::ios_base::binary);
|
||||
bool succeeded = test_file.is_open();
|
||||
test_file.close();
|
||||
remove(out_filename.c_str());
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void OpenCascadeBasedSerializer::writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {
|
||||
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = o->mesh().begin(); it != o->mesh().end(); ++ it) {
|
||||
gp_GTrsf gtrsf = it->Placement();
|
||||
|
||||
// TODO:
|
||||
gp_GTrsf o_trsf;
|
||||
int k = 0;
|
||||
for( int i = 1; i < 5; ++ i )
|
||||
for ( int j = 1; j < 4; ++ j )
|
||||
o_trsf.SetValue(j, i, o->matrix()[k++]);
|
||||
|
||||
gtrsf.PreMultiply(o_trsf);
|
||||
const TopoDS_Shape& s = it->Shape();
|
||||
|
||||
bool trsf_valid = false;
|
||||
gp_Trsf trsf;
|
||||
try {
|
||||
trsf = gtrsf.Trsf();
|
||||
trsf_valid = true;
|
||||
} catch (...) {}
|
||||
|
||||
const TopoDS_Shape moved_shape = trsf_valid
|
||||
? BRepBuilderAPI_Transform(s, trsf, true).Shape()
|
||||
: BRepBuilderAPI_GTransform(s, gtrsf, true).Shape();
|
||||
|
||||
writeShape(moved_shape);
|
||||
}
|
||||
}
|
||||
|
||||
#define RATHER_SMALL (1e-3)
|
||||
#define ALMOST_THE_SAME(a,b) (fabs(a-b) < RATHER_SMALL)
|
||||
|
||||
const char* OpenCascadeBasedSerializer::getSymbolForUnitMagnitude(float mag) {
|
||||
if (ALMOST_THE_SAME(mag, 0.001f)) {
|
||||
return "MM";
|
||||
} else if (ALMOST_THE_SAME(mag, 0.01f)) {
|
||||
return "CM";
|
||||
} else if (ALMOST_THE_SAME(mag, 1.0f)) {
|
||||
return "M";
|
||||
} else if (ALMOST_THE_SAME(mag, 0.3048f)) {
|
||||
return "FT";
|
||||
} else if (ALMOST_THE_SAME(mag, 0.0254f)) {
|
||||
return "INCH";
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef OPENCASCADEBASEDSERIALIZER_H
|
||||
#define OPENCASCADEBASEDSERIALIZER_H
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
#include "../ifcconvert/GeometrySerializer.h"
|
||||
|
||||
class OpenCascadeBasedSerializer : public GeometrySerializer {
|
||||
protected:
|
||||
const std::string& out_filename;
|
||||
const char* getSymbolForUnitMagnitude(float mag);
|
||||
public:
|
||||
explicit OpenCascadeBasedSerializer(const std::string& out_filename)
|
||||
: GeometrySerializer()
|
||||
, out_filename(out_filename)
|
||||
{}
|
||||
virtual ~OpenCascadeBasedSerializer() {}
|
||||
void writeHeader() {}
|
||||
void writeMaterial(const IfcGeom::SurfaceStyle& style) {}
|
||||
bool ready();
|
||||
virtual void writeShape(const TopoDS_Shape& shape) = 0;
|
||||
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {}
|
||||
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o);
|
||||
bool isTesselated() const { return false; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef STEPSERIALIZER_H
|
||||
#define STEPSERIALIZER_H
|
||||
|
||||
#include <STEPControl_Controller.hxx>
|
||||
#include <STEPControl_Writer.hxx>
|
||||
#include <Interface_Static.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
#include "../ifcconvert/OpenCascadeBasedSerializer.h"
|
||||
|
||||
class StepSerializer : public OpenCascadeBasedSerializer
|
||||
{
|
||||
private:
|
||||
STEPControl_Writer writer;
|
||||
public:
|
||||
explicit StepSerializer(const std::string& out_filename)
|
||||
: OpenCascadeBasedSerializer(out_filename)
|
||||
{}
|
||||
virtual ~StepSerializer() {}
|
||||
void writeShape(const TopoDS_Shape& shape) {
|
||||
std::stringstream ss;
|
||||
std::streambuf *sb = std::cout.rdbuf(ss.rdbuf());
|
||||
writer.Transfer(shape, STEPControl_AsIs);
|
||||
std::cout.rdbuf(sb);
|
||||
}
|
||||
void finalize() {
|
||||
std::stringstream ss;
|
||||
std::streambuf *sb = std::cout.rdbuf(ss.rdbuf());
|
||||
writer.Write(out_filename.c_str());
|
||||
std::cout.rdbuf(sb);
|
||||
}
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
|
||||
const char* symbol = getSymbolForUnitMagnitude(magnitude);
|
||||
if (symbol) {
|
||||
Interface_Static::SetCVal("write.step.unit", symbol);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file defines default materials for several IFC datatypes *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef SURFACESTYLE_H
|
||||
#define SURFACESTYLE_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <array>
|
||||
|
||||
class SurfaceStyle {
|
||||
public:
|
||||
class ColorComponent {
|
||||
private:
|
||||
std::array<double, 3> data;
|
||||
public:
|
||||
ColorComponent(double r, double g, double b) {
|
||||
data[0] = r; data[1] = g; data[2] = b;
|
||||
}
|
||||
const double& R() const { return data[0]; }
|
||||
const double& G() const { return data[1]; }
|
||||
const double& B() const { return data[2]; }
|
||||
double& R() { return data[0]; }
|
||||
double& G() { return data[1]; }
|
||||
double& B() { return data[2]; }
|
||||
};
|
||||
private:
|
||||
std::string name;
|
||||
ColorComponent diffuse, specular, ambient;
|
||||
double transparency;
|
||||
double specularity;
|
||||
public:
|
||||
SurfaceStyle(const std::string& name,
|
||||
double dr = 0.7, double dg = 0.7, double db = 0.7,
|
||||
double sr = 0.2, double sg = 0.2, double sb = 0.2,
|
||||
double ar = 0.1, double ag = 0.1, double ab = 0.1,
|
||||
double Ns = 10.0, double Tr = 1.0)
|
||||
: name(name)
|
||||
, diffuse(dr, dg, db)
|
||||
, specular(sr, sg, sb)
|
||||
, ambient(ar, ag, ab)
|
||||
, transparency(Tr)
|
||||
, specularity(Ns)
|
||||
{}
|
||||
const std::string& Name() const { return name; }
|
||||
const ColorComponent& Diffuse() const { return diffuse; }
|
||||
const ColorComponent& Specular() const { return specular; }
|
||||
const ColorComponent& Ambient() const { return ambient; }
|
||||
double Transparency() const { return transparency; }
|
||||
double Specularity() const { return specularity; }
|
||||
};
|
||||
|
||||
SurfaceStyle GetDefaultMaterial(const std::string& s);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
||||
|
||||
#include "WavefrontObjSerializer.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
bool WaveFrontOBJSerializer::ready() {
|
||||
return obj_stream.is_open() && mtl_stream.is_open();
|
||||
}
|
||||
|
||||
void WaveFrontOBJSerializer::writeHeader() {
|
||||
obj_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
|
||||
#ifdef WIN32
|
||||
const char dir_separator = '\\';
|
||||
#else
|
||||
const char dir_separator = '/';
|
||||
#endif
|
||||
std::string mtl_basename = mtl_filename;
|
||||
std::string::size_type slash = mtl_basename.find_last_of(dir_separator);
|
||||
if (slash != std::string::npos) {
|
||||
mtl_basename = mtl_basename.substr(slash+1);
|
||||
}
|
||||
obj_stream << "mtllib " << mtl_basename << std::endl;
|
||||
mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
|
||||
}
|
||||
|
||||
void WaveFrontOBJSerializer::writeMaterial(const IfcGeomObjects::Material& style) {
|
||||
mtl_stream << "newmtl " << style.name() << std::endl;
|
||||
if (style.hasDiffuse()) {
|
||||
const double* diffuse = style.diffuse();
|
||||
mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << std::endl;
|
||||
}
|
||||
if (style.hasSpecular()) {
|
||||
const double* specular = style.specular();
|
||||
mtl_stream << "Ks " << specular[0] << " " << specular[1] << " " << specular[2] << std::endl;
|
||||
}
|
||||
if (style.hasSpecularity()) {
|
||||
mtl_stream << "Ns " << style.specularity() << std::endl;
|
||||
}
|
||||
if (style.hasTransparency()) {
|
||||
const double transparency = 1.0 - style.transparency();
|
||||
if (transparency < 1) {
|
||||
mtl_stream << "Tr " << transparency << std::endl;
|
||||
mtl_stream << "d " << transparency << std::endl;
|
||||
mtl_stream << "D " << transparency << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
|
||||
|
||||
std::string tmp = o->name().empty() ? o->guid() : o->name();
|
||||
|
||||
std::replace( tmp.begin(), tmp.end(), ' ', '_');
|
||||
const std::string name = tmp;
|
||||
obj_stream << "g " << name << std::endl;
|
||||
obj_stream << "s 1" << std::endl;
|
||||
|
||||
const IfcGeomObjects::IfcRepresentationTriangulation& mesh = o->mesh();
|
||||
|
||||
const int vcount = mesh.verts().size() / 3;
|
||||
for ( std::vector<float>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
|
||||
const double x = *(it++);
|
||||
const double y = *(it++);
|
||||
const double z = *(it++);
|
||||
obj_stream << "v " << x << " " << y << " " << z << std::endl;
|
||||
}
|
||||
for ( std::vector<float>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) {
|
||||
const double x = *(it++);
|
||||
const double y = *(it++);
|
||||
const double z = *(it++);
|
||||
obj_stream << "vn " << x << " " << y << " " << z << std::endl;
|
||||
}
|
||||
|
||||
int previous_material_id = -2;
|
||||
std::vector<int>::const_iterator material_it = mesh.material_ids().begin();
|
||||
|
||||
for ( std::vector<int>::const_iterator it = mesh.faces().begin(); it != mesh.faces().end(); ) {
|
||||
|
||||
const int material_id = *(material_it++);
|
||||
if (material_id != previous_material_id) {
|
||||
IfcGeomObjects::Material material(0);
|
||||
if (material_id >= 0) {
|
||||
material = mesh.materials()[material_id];
|
||||
} else {
|
||||
material = IfcGeomObjects::Material(IfcGeom::get_default_style(o->type()));
|
||||
}
|
||||
const std::string material_name = material.name();
|
||||
obj_stream << "usemtl " << material_name << std::endl;
|
||||
if (materials.find(material_name) == materials.end()) {
|
||||
writeMaterial(material);
|
||||
materials.insert(material_name);
|
||||
}
|
||||
previous_material_id = material_id;
|
||||
}
|
||||
|
||||
const int v1 = *(it++)+vcount_total;
|
||||
const int v2 = *(it++)+vcount_total;
|
||||
const int v3 = *(it++)+vcount_total;
|
||||
obj_stream << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << std::endl;
|
||||
}
|
||||
vcount_total += vcount;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef WAVEFRONTOBJSERIALIZER_H
|
||||
#define WAVEFRONTOBJSERIALIZER_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "../ifcconvert/GeometrySerializer.h"
|
||||
|
||||
class WaveFrontOBJSerializer : public GeometrySerializer {
|
||||
private:
|
||||
const std::string mtl_filename;
|
||||
std::ofstream obj_stream;
|
||||
std::ofstream mtl_stream;
|
||||
unsigned int vcount_total;
|
||||
std::set<std::string> materials;
|
||||
public:
|
||||
WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename)
|
||||
: GeometrySerializer()
|
||||
, obj_stream(obj_filename.c_str())
|
||||
, mtl_filename(mtl_filename)
|
||||
, mtl_stream(mtl_filename.c_str())
|
||||
, vcount_total(1)
|
||||
{}
|
||||
virtual ~WaveFrontOBJSerializer() {}
|
||||
bool ready();
|
||||
void writeHeader();
|
||||
void writeMaterial(const IfcGeomObjects::Material& style);
|
||||
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o);
|
||||
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
|
||||
void finalize() {}
|
||||
bool isTesselated() const { return true; }
|
||||
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
This folder contains Python code to generate C++ type information based on an
|
||||
Express schema. In particular is has only been tested using recent version of
|
||||
the IFC schema and will most likely fail on any other Express schema.
|
||||
|
||||
The code can be invoked in the following way and results in two header files
|
||||
and a single implementation file named according to the schema name in the
|
||||
Express file. A python 3 interpreter with the pyparsing library is required.
|
||||
|
||||
$ python bootstrap.py express.bnf > express_parser.py && python express_parser.py IFC2X3_TC1.exp
|
||||
@@ -0,0 +1,193 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import sys
|
||||
import string
|
||||
from pyparsing import *
|
||||
|
||||
class Expression:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
def __repr__(self):
|
||||
if self.op is None: return repr(self.contents)
|
||||
c = [isinstance(c,str) and c or str(c) for c in self.contents]
|
||||
if "%s" in self.op: return self.op % (" ".join(c))
|
||||
else: return "(%s)" % (" %s "%self.op).join(c)
|
||||
def __iter__(self):
|
||||
return self.contents.__iter__()
|
||||
|
||||
class Union(Expression):
|
||||
op = "|"
|
||||
|
||||
class Concat(Expression):
|
||||
op = "+"
|
||||
|
||||
class Optional(Expression):
|
||||
op = "Optional(%s)"
|
||||
|
||||
class Repeated(Expression):
|
||||
op = "ZeroOrMore(%s)"
|
||||
|
||||
class Term(Expression):
|
||||
op = None
|
||||
|
||||
class Keyword:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
def __repr__(self):
|
||||
return self.contents
|
||||
|
||||
class Terminal:
|
||||
def __init__(self, contents):
|
||||
self.contents = contents[0]
|
||||
def __repr__(self):
|
||||
s = self.contents
|
||||
is_keyword = len(s) >= 4 and s[0::len(s)-1] == '""' and \
|
||||
all(c in alphanums+"_" for c in s[1:-1])
|
||||
ty = "CaselessKeyword" if is_keyword else "CaselessLiteral"
|
||||
return "%s(%s)" % (ty, s)
|
||||
|
||||
|
||||
LPAREN = Suppress("(")
|
||||
RPAREN = Suppress(")")
|
||||
LBRACK = Suppress("[")
|
||||
RBRACK = Suppress("]")
|
||||
LBRACE = Suppress("{")
|
||||
RBRACE = Suppress("}")
|
||||
EQUALS = Suppress("=")
|
||||
VBAR = Suppress("|")
|
||||
PERIOD = Suppress(".")
|
||||
HASH = Suppress("#")
|
||||
|
||||
identifier = Word(alphanums+"_")
|
||||
keyword = Word(alphanums+"_").setParseAction(Keyword)
|
||||
expression = Forward()
|
||||
optional = Group(LBRACK + expression + RBRACK).setParseAction(Optional)
|
||||
repeated = Group(LBRACE + expression + RBRACE).setParseAction(Repeated)
|
||||
terminal = quotedString.setParseAction(Terminal)
|
||||
term = (keyword | terminal | optional | repeated | (LPAREN + expression + RPAREN)).setParseAction(Term)
|
||||
concat = Group(term + OneOrMore(term)).setParseAction(Concat)
|
||||
factor = concat | term
|
||||
union = Group(factor + OneOrMore(VBAR + factor)).setParseAction(Union)
|
||||
rule = identifier + EQUALS + expression + PERIOD
|
||||
|
||||
expression << (union | factor)
|
||||
|
||||
grammar = OneOrMore(Group(rule))
|
||||
grammar.ignore(HASH + restOfLine)
|
||||
|
||||
express = grammar.parseFile(sys.argv[1])
|
||||
|
||||
def find_keywords(expr, li = None):
|
||||
if li is None: li = []
|
||||
if isinstance(expr, Term):
|
||||
expr = expr.contents
|
||||
if isinstance(expr, Keyword):
|
||||
li.append(repr(expr))
|
||||
return li
|
||||
elif isinstance(expr, Expression):
|
||||
for term in expr:
|
||||
find_keywords(term, li)
|
||||
return set(li)
|
||||
|
||||
actions = {
|
||||
'type_decl' : "lambda t: TypeDeclaration(t)",
|
||||
'entity_decl' : "lambda t: EntityDeclaration(t)",
|
||||
'underlying_type' : "lambda t: UnderlyingType(t)",
|
||||
'enumeration_type' : "lambda t: EnumerationType(t)",
|
||||
'aggregation_types' : "lambda t: AggregationType(t)",
|
||||
'general_aggregation_types' : "lambda t: AggregationType(t)",
|
||||
'select_type' : "lambda t: SelectType(t)",
|
||||
'binary_type' : "lambda t: BinaryType(t)",
|
||||
'subtype_declaration' : "lambda t: SubtypeExpression(t)",
|
||||
'derive_clause' : "lambda t: AttributeList('derive', t)",
|
||||
'derived_attr' : "lambda t: DerivedAttribute(t)",
|
||||
'inverse_clause' : "lambda t: AttributeList('inverse', t)",
|
||||
'inverse_attr' : "lambda t: InverseAttribute(t)",
|
||||
'bound_spec' : "lambda t: BoundSpecification(t)",
|
||||
'explicit_attr' : "lambda t: ExplicitAttribute(t)",
|
||||
}
|
||||
|
||||
to_emit = set(id for id, expr in express)
|
||||
emitted = set()
|
||||
to_combine = set(["simple_id"])
|
||||
to_ignore = set(["where_clause", "supertype_constraint", "unique_clause"])
|
||||
statements = []
|
||||
|
||||
while True:
|
||||
emitted_in_loop = set()
|
||||
for id, expr in express:
|
||||
kws = find_keywords(expr)
|
||||
found = [k in emitted for k in kws]
|
||||
if id in to_emit and all(found):
|
||||
emitted_in_loop.add(id)
|
||||
emitted.add(id)
|
||||
stmt = "(%s)" % expr
|
||||
if id in to_combine:
|
||||
stmt = "originalTextFor(Combine%s)" % stmt
|
||||
if id in actions:
|
||||
stmt = "%s.setParseAction(%s)" % (stmt, actions[id])
|
||||
statements.append("%s = %s" % (id, stmt))
|
||||
to_emit -= emitted_in_loop
|
||||
if not emitted_in_loop: break
|
||||
|
||||
for id in to_emit:
|
||||
action = ".setParseAction(%s)" % actions[id] if id in actions else ""
|
||||
statements.append("%s = Forward()%s" % (id, action))
|
||||
|
||||
for id in to_emit:
|
||||
expr = [e for k, e in express if k == id][0]
|
||||
stmt = "(%s)" % expr
|
||||
if id in to_combine:
|
||||
stmt = "Suppress%s" % stmt
|
||||
statements.append("%s << %s" % (id, stmt))
|
||||
|
||||
print ("""import sys
|
||||
from pyparsing import *
|
||||
from nodes import *
|
||||
|
||||
%s
|
||||
|
||||
import schema
|
||||
import mapping
|
||||
|
||||
import header
|
||||
import enum_header
|
||||
import implementation
|
||||
import rt_header
|
||||
import rt_implementation
|
||||
|
||||
syntax.ignore(Regex(r"\((?:\*(?:[^*]*\*+)+?\))"))
|
||||
ast = syntax.parseFile(sys.argv[1])
|
||||
schema = schema.Schema(ast)
|
||||
mapping = mapping.Mapping(schema)
|
||||
|
||||
header.Header(mapping).emit()
|
||||
enum_header.EnumHeader(mapping).emit()
|
||||
implementation.Implementation(mapping).emit()
|
||||
rt_header.RuntimeTypingHeader(mapping).emit()
|
||||
rt_implementation.RuntimeTypingImplementation(mapping).emit()
|
||||
|
||||
def retry():
|
||||
import imp
|
||||
imp.reload(rt_header)
|
||||
imp.reload(rt_implementation)
|
||||
rt_header.RuntimeTypingHeader(mapping).emit()
|
||||
rt_implementation.RuntimeTypingImplementation(mapping).emit()
|
||||
"""%('\n'.join(statements)))
|
||||
@@ -0,0 +1,70 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# #
|
||||
# This files uses the documentation files from buildingSMART to generate #
|
||||
# descriptions from EXPRESS names that are suitable for comments in the C++ #
|
||||
# code. The .csv files used by this file are generated from the MS Office #
|
||||
# Access database, which in turn has been generated from the IFC baseline #
|
||||
# documentation by the IFCDOC utility provided by buildingSMART. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import re,csv
|
||||
import csv
|
||||
try: from html.entities import entitydefs
|
||||
except: from htmlentitydefs import entitydefs
|
||||
|
||||
name_to_oid = {}
|
||||
oid_to_desc = {}
|
||||
oid_to_name = {}
|
||||
oid_to_pid = {}
|
||||
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' ']))
|
||||
|
||||
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
|
||||
for fn in definition_files:
|
||||
with open(fn) as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
name_to_oid[name] = oid
|
||||
oid_to_name[oid] = name
|
||||
oid_to_desc[oid] = desc
|
||||
|
||||
with open('DocEntityAttributes.csv') as f:
|
||||
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
oid_to_pid[oid] = pid
|
||||
|
||||
with open('DocAttribute.csv') as f:
|
||||
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
|
||||
pid = oid_to_pid[oid]
|
||||
pname = oid_to_name[pid]
|
||||
name_to_oid[(pname, name)] = oid
|
||||
oid_to_desc[oid] = desc
|
||||
|
||||
def description(item):
|
||||
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
|
||||
oid = name_to_oid.get(item,0)
|
||||
desc = oid_to_desc.get(oid, None)
|
||||
if desc:
|
||||
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
|
||||
desc = desc.replace("\r","")
|
||||
for r,s in regices: desc = r.sub(s,desc)
|
||||
desc = desc.strip()
|
||||
return desc.split("\n")
|
||||
else: return []
|
||||
@@ -0,0 +1,38 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import templates
|
||||
|
||||
class EnumHeader:
|
||||
def __init__(self, mapping):
|
||||
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
|
||||
|
||||
self.str = templates.enum_header % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize(),
|
||||
'types' : ', '.join(enumerable_types)
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
def emit(self):
|
||||
f = open('%senum.h'%self.schema_name, 'w', encoding='utf-8')
|
||||
f.write(str(self))
|
||||
f.close()
|
||||
@@ -0,0 +1,344 @@
|
||||
# Taken from http://sourceforge.net/p/exp-engine/expresso/ci/master/tree/docs/iso-10303-11--2004.bnf
|
||||
|
||||
ABS = "abs" .
|
||||
ABSTRACT = "abstract" .
|
||||
ACOS = "acos" .
|
||||
AGGREGATE = "aggregate" .
|
||||
ALIAS = "alias" .
|
||||
AND = "and" .
|
||||
ANDOR = "andor" .
|
||||
ARRAY = "array" .
|
||||
AS = "as" .
|
||||
ASIN = "asin" .
|
||||
ATAN = "atan" .
|
||||
BAG = "bag" .
|
||||
BASED_ON = "based_on" .
|
||||
BEGIN = "begin" .
|
||||
BINARY = "binary" .
|
||||
BLENGTH = "blength" .
|
||||
BOOLEAN = "boolean" .
|
||||
BY = "by" .
|
||||
CASE = "case" .
|
||||
CONSTANT = "constant" .
|
||||
CONST_E = "const_e" .
|
||||
COS = "cos" .
|
||||
DERIVE = "derive" .
|
||||
DIV = "div" .
|
||||
ELSE = "else" .
|
||||
END = "end" .
|
||||
END_ALIAS = "end_alias" .
|
||||
END_CASE = "end_case" .
|
||||
END_CONSTANT = "end_constant" .
|
||||
END_ENTITY = "end_entity" .
|
||||
END_FUNCTION = "end_function" .
|
||||
END_IF = "end_if" .
|
||||
END_LOCAL = "end_local" .
|
||||
END_PROCEDURE = "end_procedure" .
|
||||
END_REPEAT = "end_repeat" .
|
||||
END_RULE = "end_rule" .
|
||||
END_SCHEMA = "end_schema" .
|
||||
END_SUBTYPE_CONSTRAINT = "end_subtype_constraint" .
|
||||
END_TYPE = "end_type" .
|
||||
ENTITY = "entity" .
|
||||
ENUMERATION = "enumeration" .
|
||||
ESCAPE = "escape" .
|
||||
EXISTS = "exists" .
|
||||
EXTENSIBLE = "extensible" .
|
||||
EXP = "exp" .
|
||||
FALSE = "false" .
|
||||
FIXED = "fixed" .
|
||||
FOR = "for" .
|
||||
FORMAT = "format" .
|
||||
FROM = "from" .
|
||||
FUNCTION = "function" .
|
||||
GENERIC = "generic" .
|
||||
GENERIC_ENTITY = "generic_entity" .
|
||||
HIBOUND = "hibound" .
|
||||
HIINDEX = "hiindex" .
|
||||
IF = "if" .
|
||||
IN = "in" .
|
||||
INSERT = "insert" .
|
||||
INTEGER = "integer" .
|
||||
INVERSE = "inverse" .
|
||||
LENGTH = "length" .
|
||||
LIKE = "like" .
|
||||
LIST = "list" .
|
||||
LOBOUND = "lobound" .
|
||||
LOCAL = "local" .
|
||||
LOG = "log" .
|
||||
LOG10 = "log10" .
|
||||
LOG2 = "log2" .
|
||||
LOGICAL = "logical" .
|
||||
LOINDEX = "loindex" .
|
||||
MOD = "mod" .
|
||||
NOT = "not" .
|
||||
NUMBER = "number" .
|
||||
NVL = "nvl" .
|
||||
ODD = "odd" .
|
||||
OF = "of" .
|
||||
ONEOF = "oneof" .
|
||||
OPTIONAL = "optional" .
|
||||
OR = "or" .
|
||||
OTHERWISE = "otherwise" .
|
||||
PI = "pi" .
|
||||
PROCEDURE = "procedure" .
|
||||
QUERY = "query" .
|
||||
REAL = "real" .
|
||||
REFERENCE = "reference" .
|
||||
REMOVE = "remove" .
|
||||
RENAMED = "renamed" .
|
||||
REPEAT = "repeat" .
|
||||
RETURN = "return" .
|
||||
ROLESOF = "rolesof" .
|
||||
RULE = "rule" .
|
||||
SCHEMA = "schema" .
|
||||
SELECT = "select" .
|
||||
SELF = "self" .
|
||||
SET = "set" .
|
||||
SIN = "sin" .
|
||||
SIZEOF = "sizeof" .
|
||||
SKIP = "skip" .
|
||||
SQRT = "sqrt" .
|
||||
STRING = "string" .
|
||||
SUBTYPE = "subtype" .
|
||||
SUBTYPE_CONSTRAINT = "subtype_constraint" .
|
||||
SUPERTYPE = "supertype" .
|
||||
TAN = "tan" .
|
||||
THEN = "then" .
|
||||
TO = "to" .
|
||||
TOTAL_OVER = "total_over" .
|
||||
TRUE = "true" .
|
||||
TYPE = "type" .
|
||||
TYPEOF = "typeof" .
|
||||
UNIQUE = "unique" .
|
||||
UNKNOWN = "unknown" .
|
||||
UNTIL = "until" .
|
||||
USE = "use" .
|
||||
USEDIN = "usedin" .
|
||||
VALUE = "value" .
|
||||
VALUE_IN = "value_in" .
|
||||
VALUE_UNIQUE = "value_unique" .
|
||||
VAR = "var" .
|
||||
WHERE = "where" .
|
||||
WHILE = "while" .
|
||||
WITH = "with" .
|
||||
XOR = "xor" .
|
||||
bit = "0" | "1" .
|
||||
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
|
||||
digits = digit { digit } .
|
||||
encoded_character = octet octet octet octet .
|
||||
hex_digit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
|
||||
letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" .
|
||||
lparen_then_not_lparen_star = "(" { "(" } not_lparen_star { not_lparen_star } .
|
||||
not_lparen_star = not_paren_star | ")" .
|
||||
not_paren_star = letter | digit | not_paren_star_special .
|
||||
not_paren_star_quote_special = "!" | "#" | "$" | "%" | "&" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "[" | "\\" | "]" | "^" | "_" | "{" | "|" | "}" | "~" .
|
||||
not_paren_star_special = not_paren_star_quote_special | "\"\"" .
|
||||
not_quote = not_paren_star_quote_special | letter | digit | "(" | ")" | "*" .
|
||||
not_rparen_star = not_paren_star | "(" .
|
||||
octet = hex_digit hex_digit .
|
||||
special = not_paren_star_quote_special | "(" | ")" | "*" | "\"\"" .
|
||||
not_rparen_star_then_rparen = not_rparen_star { not_rparen_star } ")" { ")" } .
|
||||
binary_literal = "%" bit { bit } .
|
||||
encoded_string_literal = "\"" encoded_character { encoded_character } "\"" .
|
||||
integer_literal = digits .
|
||||
real_literal = ( digits "." [ digits ] [ "e" [ sign ] digits ] ) | integer_literal .
|
||||
simple_id = letter { letter | digit | "_" } .
|
||||
simple_string_literal = "'" { ( "'" "'" ) | not_quote } "'" .
|
||||
embedded_remark = "(*" [ remark_tag ] { ( not_paren_star { not_paren_star } ) | lparen_then_not_lparen_star | ( "*" { "*" } ) | not_rparen_star_then_rparen | embedded_remark } "*)" .
|
||||
remark = embedded_remark | tail_remark .
|
||||
remark_tag = "\"" remark_ref { "." remark_ref } "\"" .
|
||||
remark_ref = attribute_ref | constant_ref | entity_ref | enumeration_ref | function_ref | parameter_ref | procedure_ref | rule_label_ref | rule_ref | schema_ref | subtype_constraint_ref | type_label_ref | type_ref | variable_ref .
|
||||
tail_remark = "--" [ remark_tag ] .
|
||||
attribute_ref = attribute_id .
|
||||
constant_ref = constant_id .
|
||||
entity_ref = entity_id .
|
||||
enumeration_ref = enumeration_id .
|
||||
function_ref = function_id .
|
||||
parameter_ref = parameter_id .
|
||||
procedure_ref = procedure_id .
|
||||
rule_label_ref = rule_label_id .
|
||||
rule_ref = rule_id .
|
||||
schema_ref = schema_id .
|
||||
subtype_constraint_ref = subtype_constraint_id .
|
||||
type_label_ref = type_label_id .
|
||||
type_ref = type_id .
|
||||
variable_ref = variable_id .
|
||||
abstract_entity_declaration = ABSTRACT .
|
||||
abstract_supertype = ABSTRACT SUPERTYPE ";" .
|
||||
abstract_supertype_declaration = ABSTRACT SUPERTYPE [ subtype_constraint ] .
|
||||
actual_parameter_list = "(" [ parameter ] { "," parameter } ")" .
|
||||
add_like_op = "+" | "-" | OR | XOR .
|
||||
aggregate_initializer = "[" [ element { "," element } ] "]" .
|
||||
aggregate_source = simple_expression .
|
||||
aggregate_type = AGGREGATE [ ":" type_label ] OF parameter_type .
|
||||
aggregation_types = array_type | bag_type | list_type | set_type .
|
||||
algorithm_head = { declaration } [ constant_decl ] [ local_decl ] .
|
||||
alias_stmt = ALIAS variable_id FOR general_ref { qualifier } ";" stmt { stmt } END_ALIAS ";" .
|
||||
array_type = ARRAY bound_spec OF [ OPTIONAL ] [ UNIQUE ] instantiable_type .
|
||||
assignment_stmt = general_ref { qualifier } ":=" expression ";" .
|
||||
attribute_decl = redeclared_attribute | attribute_id .
|
||||
attribute_id = simple_id .
|
||||
attribute_qualifier = "." attribute_ref .
|
||||
bag_type = BAG [ bound_spec ] OF instantiable_type .
|
||||
binary_type = BINARY [ width_spec ] .
|
||||
boolean_type = BOOLEAN .
|
||||
bound_1 = numeric_expression .
|
||||
bound_2 = numeric_expression .
|
||||
bound_spec = "[" bound_1 ":" bound_2 "]" .
|
||||
built_in_constant = CONST_E | PI | SELF | "?" .
|
||||
built_in_function = ABS | ACOS | ASIN | ATAN | BLENGTH | COS | EXISTS | EXP | FORMAT | HIBOUND | HIINDEX | LENGTH | LOBOUND | LOINDEX | LOG | LOG2 | LOG10 | NVL | ODD | ROLESOF | SIN | SIZEOF | SQRT | TAN | TYPEOF | USEDIN | VALUE | VALUE_IN | VALUE_UNIQUE .
|
||||
built_in_procedure = INSERT | REMOVE .
|
||||
case_action = case_label { "," case_label } ":" stmt .
|
||||
case_label = expression .
|
||||
case_stmt = CASE selector OF { case_action } [ OTHERWISE ":" stmt ] END_CASE ";" .
|
||||
compound_stmt = BEGIN stmt { stmt } END ";" .
|
||||
concrete_types = aggregation_types | simple_types | type_ref .
|
||||
constant_body = constant_id ":" instantiable_type ":=" expression ";" .
|
||||
constant_decl = CONSTANT constant_body { constant_body } END_CONSTANT ";" .
|
||||
constant_factor = built_in_constant | constant_ref .
|
||||
constant_id = simple_id .
|
||||
constructed_types = enumeration_type | select_type .
|
||||
declaration = entity_decl | function_decl | procedure_decl | subtype_constraint_decl | type_decl .
|
||||
derived_attr = attribute_decl ":" parameter_type ":=" expression ";" .
|
||||
derive_clause = DERIVE derived_attr { derived_attr } .
|
||||
domain_rule = rule_label_id ":" expression .
|
||||
element = expression [ ":" repetition ] .
|
||||
entity_body = { explicit_attr } [ derive_clause ] [ inverse_clause ] [ unique_clause ] [ where_clause ] .
|
||||
entity_constructor = entity_ref "(" [ expression { "," expression } ] ")" .
|
||||
entity_decl = entity_head entity_body END_ENTITY ";" .
|
||||
entity_head = ENTITY entity_id subsuper ";" .
|
||||
entity_id = simple_id .
|
||||
enumeration_extension = BASED_ON type_ref [ WITH enumeration_items ] .
|
||||
enumeration_id = simple_id .
|
||||
enumeration_items = "(" enumeration_id { "," enumeration_id } ")" .
|
||||
enumeration_reference = [ type_ref "." ] enumeration_ref .
|
||||
enumeration_type = [ EXTENSIBLE ] ENUMERATION [ ( OF enumeration_items ) | enumeration_extension ] .
|
||||
escape_stmt = ESCAPE ";" .
|
||||
explicit_attr = attribute_decl { "," attribute_decl } ":" [ OPTIONAL ] parameter_type ";" .
|
||||
expression = simple_expression [ rel_op_extended simple_expression ] .
|
||||
factor = simple_factor [ "**" simple_factor ] .
|
||||
formal_parameter = parameter_id { "," parameter_id } ":" parameter_type .
|
||||
function_call = ( built_in_function | function_ref ) actual_parameter_list .
|
||||
function_decl = function_head algorithm_head stmt { stmt } END_FUNCTION ";" .
|
||||
function_head = FUNCTION function_id [ "(" formal_parameter { ";" formal_parameter } ")" ] ":" parameter_type ";" .
|
||||
function_id = simple_id .
|
||||
generalized_types = aggregate_type | general_aggregation_types | generic_entity_type | generic_type .
|
||||
general_aggregation_types = general_array_type | general_bag_type | general_list_type | general_set_type .
|
||||
general_array_type = ARRAY [ bound_spec ] OF [ OPTIONAL ] [ UNIQUE ] parameter_type .
|
||||
general_bag_type = BAG [ bound_spec ] OF parameter_type .
|
||||
general_list_type = LIST [ bound_spec ] OF [ UNIQUE ] parameter_type .
|
||||
general_ref = parameter_ref | variable_ref .
|
||||
general_set_type = SET [ bound_spec ] OF parameter_type .
|
||||
generic_entity_type = GENERIC_ENTITY [ ":" type_label ] .
|
||||
generic_type = GENERIC [ ":" type_label ] .
|
||||
group_qualifier = "\\" entity_ref .
|
||||
if_stmt = IF logical_expression THEN stmt { stmt } [ ELSE stmt { stmt } ] END_IF ";" .
|
||||
increment = numeric_expression .
|
||||
increment_control = variable_id ":=" bound_1 TO bound_2 [ BY increment ] .
|
||||
index = numeric_expression .
|
||||
index_1 = index .
|
||||
index_2 = index .
|
||||
index_qualifier = "[" index_1 [ ":" index_2 ] "]" .
|
||||
instantiable_type = concrete_types | entity_ref .
|
||||
integer_type = INTEGER .
|
||||
interface_specification = reference_clause | use_clause .
|
||||
interval = "{" interval_low interval_op interval_item interval_op interval_high "}" .
|
||||
interval_high = simple_expression .
|
||||
interval_item = simple_expression .
|
||||
interval_low = simple_expression .
|
||||
interval_op = "<=" | "<" .
|
||||
inverse_attr = attribute_decl ":" [ ( SET | BAG ) [ bound_spec ] OF ] entity_ref FOR [ entity_ref "." ] attribute_ref ";" .
|
||||
inverse_clause = INVERSE inverse_attr { inverse_attr } .
|
||||
list_type = LIST [ bound_spec ] OF [ UNIQUE ] instantiable_type .
|
||||
literal = binary_literal | logical_literal | real_literal | string_literal .
|
||||
local_decl = LOCAL local_variable { local_variable } END_LOCAL ";" .
|
||||
local_variable = variable_id { "," variable_id } ":" parameter_type [ ":=" expression ] ";" .
|
||||
logical_expression = expression .
|
||||
logical_literal = FALSE | TRUE | UNKNOWN .
|
||||
logical_type = LOGICAL .
|
||||
multiplication_like_op = "*" | "/" | DIV | MOD | AND | "||" .
|
||||
named_types = entity_ref | type_ref .
|
||||
named_type_or_rename = named_types [ AS ( entity_id | type_id ) ] .
|
||||
null_stmt = ";" .
|
||||
number_type = NUMBER .
|
||||
numeric_expression = simple_expression .
|
||||
one_of = ONEOF "(" supertype_expression { "," supertype_expression } ")" .
|
||||
parameter = expression .
|
||||
parameter_id = simple_id .
|
||||
parameter_type = generalized_types | simple_types | named_types .
|
||||
population = entity_ref .
|
||||
precision_spec = numeric_expression .
|
||||
primary = literal | ( qualifiable_factor { qualifier } ) .
|
||||
procedure_call_stmt = ( built_in_procedure | procedure_ref ) actual_parameter_list ";" .
|
||||
procedure_decl = procedure_head algorithm_head { stmt } END_PROCEDURE ";" .
|
||||
procedure_head = PROCEDURE procedure_id [ "(" [ VAR ] formal_parameter { ";" [ VAR ] formal_parameter } ")" ] ";" .
|
||||
procedure_id = simple_id .
|
||||
qualifiable_factor = function_call | attribute_ref | constant_factor | general_ref | population .
|
||||
qualified_attribute = SELF group_qualifier attribute_qualifier .
|
||||
qualifier = attribute_qualifier | group_qualifier | index_qualifier .
|
||||
query_expression = QUERY "(" variable_id "<*" aggregate_source "|" logical_expression ")" .
|
||||
real_type = REAL [ "(" precision_spec ")" ] .
|
||||
redeclared_attribute = qualified_attribute [ RENAMED attribute_id ] .
|
||||
referenced_attribute = attribute_ref | qualified_attribute .
|
||||
reference_clause = REFERENCE FROM schema_ref [ "(" resource_or_rename { "," resource_or_rename } ")" ] ";" .
|
||||
rel_op = "<=" | ">=" | "<>" | "=" | ":<>:" | ":=:" | "<" | ">" .
|
||||
rel_op_extended = rel_op | IN | LIKE .
|
||||
rename_id = constant_id | entity_id | function_id | procedure_id | type_id .
|
||||
repeat_control = [ increment_control ] [ while_control ] [ until_control ] .
|
||||
repeat_stmt = REPEAT repeat_control ";" stmt { stmt } END_REPEAT ";" .
|
||||
repetition = numeric_expression .
|
||||
resource_or_rename = resource_ref [ AS rename_id ] .
|
||||
resource_ref = constant_ref | entity_ref | function_ref | procedure_ref | type_ref .
|
||||
return_stmt = RETURN [ "(" expression ")" ] ";" .
|
||||
rule_decl = rule_head algorithm_head { stmt } where_clause END_RULE ";" .
|
||||
rule_head = RULE rule_id FOR "(" entity_ref { "," entity_ref } ")" ";" .
|
||||
rule_id = simple_id .
|
||||
rule_label_id = simple_id .
|
||||
schema_body = { interface_specification } [ constant_decl ] { declaration | rule_decl } .
|
||||
schema_decl = SCHEMA schema_id [ schema_version_id ] ";" schema_body END_SCHEMA ";" .
|
||||
schema_id = simple_id .
|
||||
schema_version_id = string_literal .
|
||||
selector = expression .
|
||||
select_extension = BASED_ON type_ref [ WITH select_list ] .
|
||||
select_list = "(" named_types { "," named_types } ")" .
|
||||
select_type = [ EXTENSIBLE [ GENERIC_ENTITY ] ] SELECT [ select_list | select_extension ] .
|
||||
set_type = SET [ bound_spec ] OF instantiable_type .
|
||||
sign = "+" | "-" .
|
||||
simple_expression = term { add_like_op term } .
|
||||
simple_factor = aggregate_initializer | interval | query_expression | ( [ unary_op ] ( "(" expression ")" | primary ) ) | entity_constructor | enumeration_reference .
|
||||
simple_types = binary_type | boolean_type | integer_type | logical_type | number_type | real_type | string_type .
|
||||
skip_stmt = SKIP ";" .
|
||||
stmt = alias_stmt | assignment_stmt | case_stmt | compound_stmt | escape_stmt | if_stmt | null_stmt | procedure_call_stmt | repeat_stmt | return_stmt | skip_stmt .
|
||||
string_literal = simple_string_literal | encoded_string_literal .
|
||||
string_type = STRING [ width_spec ] .
|
||||
subsuper = [ supertype_constraint ] [ subtype_declaration ] .
|
||||
subtype_constraint = OF "(" supertype_expression ")" .
|
||||
subtype_constraint_body = [ abstract_supertype ] [ total_over ] [ supertype_expression ";" ] .
|
||||
subtype_constraint_decl = subtype_constraint_head subtype_constraint_body END_SUBTYPE_CONSTRAINT ";" .
|
||||
subtype_constraint_head = SUBTYPE_CONSTRAINT subtype_constraint_id FOR entity_ref ";" .
|
||||
subtype_constraint_id = simple_id .
|
||||
subtype_declaration = SUBTYPE OF "(" entity_ref { "," entity_ref } ")" .
|
||||
supertype_constraint = abstract_supertype_declaration | abstract_entity_declaration | supertype_rule .
|
||||
supertype_expression = supertype_factor { ANDOR supertype_factor } .
|
||||
supertype_factor = supertype_term { AND supertype_term } .
|
||||
supertype_rule = SUPERTYPE subtype_constraint .
|
||||
supertype_term = one_of | "(" supertype_expression ")" | entity_ref .
|
||||
syntax = schema_decl { schema_decl } .
|
||||
term = factor { multiplication_like_op factor } .
|
||||
total_over = TOTAL_OVER "(" entity_ref { "," entity_ref } ")" ";" .
|
||||
type_decl = TYPE type_id "=" underlying_type ";" [ where_clause ] END_TYPE ";" .
|
||||
type_id = simple_id .
|
||||
type_label = type_label_id | type_label_ref .
|
||||
type_label_id = simple_id .
|
||||
unary_op = "+" | "-" | NOT .
|
||||
underlying_type = constructed_types | concrete_types .
|
||||
unique_clause = UNIQUE unique_rule ";" { unique_rule ";" } .
|
||||
unique_rule = rule_label_id ":" referenced_attribute { "," referenced_attribute } .
|
||||
until_control = UNTIL logical_expression .
|
||||
use_clause = USE FROM schema_ref [ "(" named_type_or_rename { "," named_type_or_rename } ")" ] ";" .
|
||||
variable_id = simple_id .
|
||||
where_clause = WHERE domain_rule ";" { domain_rule ";" } .
|
||||
while_control = WHILE logical_expression .
|
||||
width = numeric_expression .
|
||||
width_spec = "(" width ")" [ FIXED ] .
|
||||
@@ -0,0 +1,127 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import templates
|
||||
import documentation
|
||||
|
||||
class Header:
|
||||
def __init__(self, mapping):
|
||||
emitted_types = set(mapping.express_to_cpp_typemapping.values())
|
||||
declarations = []
|
||||
|
||||
write = lambda str, **kwargs: declarations.append(str%dict({
|
||||
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
|
||||
|
||||
for name, type in mapping.schema.simpletypes.items():
|
||||
type_str = mapping.make_type_string(type)
|
||||
type_dep = mapping.get_type_dep(type)
|
||||
if type_dep in emitted_types:
|
||||
write(templates.simpletype, name=name, type=type_str)
|
||||
emitted_types.add(name)
|
||||
|
||||
for name, type in mapping.schema.selects.items():
|
||||
write(templates.select, name=name)
|
||||
emitted_types.add(name)
|
||||
|
||||
for name, type in mapping.schema.simpletypes.items():
|
||||
if name not in emitted_types:
|
||||
type_str = mapping.make_type_string(type)
|
||||
write(templates.simpletype, name=name, type=type_str)
|
||||
emitted_types.add(name)
|
||||
|
||||
for name, type in mapping.schema.enumerations.items():
|
||||
short_name = name[:-4] if name.endswith("Enum") else name
|
||||
write(templates.enumeration, name=name, values=", ".join(["%s_%s"%(short_name, v) for v in type.values]))
|
||||
|
||||
forward_definitions = "".join(["class %s; "%n for n in mapping.schema.entities.keys()])
|
||||
|
||||
class_definitions = []
|
||||
|
||||
write = lambda str, **kwargs: class_definitions.append(str%dict({
|
||||
'documentation': templates.multi_line_comment(documentation.description(kwargs['name']))}, **kwargs))
|
||||
|
||||
emitted_entities = set()
|
||||
while len(emitted_entities) < len(mapping.schema.entities):
|
||||
for name, type in mapping.schema.entities.items():
|
||||
if name in emitted_entities: continue
|
||||
if len(type.supertypes) == 0 or set(type.supertypes) < emitted_entities:
|
||||
attr_lines = []
|
||||
def write_method(attr):
|
||||
if attr.optional:
|
||||
attr_lines.append(templates.optional_attribute_description % (attr.name, name))
|
||||
attr_lines.append("bool has%s();"%(attr.name))
|
||||
attr_lines.extend(["/// %s"%d for d in documentation.description((name, attr.name))])
|
||||
type_str = mapping.get_parameter_type(attr, allow_optional=False, allow_entities=False)
|
||||
if mapping.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN":
|
||||
attr_lines.append("%s %s();"%(type_str, attr.name))
|
||||
attr_lines.append("void set%s(%s v);"%(attr.name, type_str))
|
||||
|
||||
[write_method(attr) for attr in type.attributes]
|
||||
|
||||
inv_lines = []
|
||||
def write_inverse(attr):
|
||||
inv_lines.append(templates.inverse_attr%{'name':attr.name, 'entity':attr.entity, 'attribute':attr.attribute})
|
||||
|
||||
if type.inverse:
|
||||
[write_inverse(attr) for attr in type.inverse.elements]
|
||||
|
||||
attributes = "\n".join(["%s%s"%(' '*4, a) for a in attr_lines])
|
||||
if len(attributes): attributes += '\n'
|
||||
|
||||
inverse = "\n".join(["%s%s"%(' '*4, a) for a in inv_lines])
|
||||
if len(inverse): inverse += '\n'
|
||||
|
||||
supertypes = type.supertypes if len(type.supertypes) else ['IfcUtil::IfcBaseEntity']
|
||||
superclass = ": %s "%(", ".join(["public %s"%c for c in supertypes]))
|
||||
|
||||
argument_count = mapping.argument_count(type)
|
||||
|
||||
argument_start = argument_count - len(type.attributes)
|
||||
|
||||
argument_name_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return "%s"; '%(i+argument_start, attr.name) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
|
||||
argument_name_function_body_tail = (" return %s::getArgumentName(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
|
||||
|
||||
argument_name_function_body = argument_name_function_body_switch_stmt + argument_name_function_body_tail
|
||||
|
||||
argument_type_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_type(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
|
||||
argument_type_function_body_tail = (" return %s::getArgumentType(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
|
||||
|
||||
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
|
||||
|
||||
constructor_arguments = ", ".join("%(full_type)s v%(index)d_%(name)s"%a for a in mapping.get_assignable_arguments(type))
|
||||
|
||||
write(templates.entity, **locals())
|
||||
emitted_entities.add(name)
|
||||
|
||||
self.str = templates.header % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize(),
|
||||
'declarations' : ''.join(declarations),
|
||||
'forward_definitions' : forward_definitions,
|
||||
'class_definitions' : ''.join(class_definitions)
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
def emit(self):
|
||||
f = open('%s.h'%self.schema_name, 'w', encoding='utf-8')
|
||||
f.write(str(self))
|
||||
f.close()
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import templates
|
||||
|
||||
class Implementation:
|
||||
def __init__(self, mapping):
|
||||
enumeration_functions = []
|
||||
entity_implementations = []
|
||||
schema_entity_statements = []
|
||||
|
||||
schema_name = mapping.schema.name.capitalize()
|
||||
|
||||
stringify = lambda s: '"%s"'%s
|
||||
cat = lambda vs: "".join(vs)
|
||||
catc = lambda vs: ", ".join(vs)
|
||||
catnl = lambda vs: "\n".join(vs)
|
||||
cator = lambda vs: " || ".join(vs)
|
||||
nl = lambda s: "%s\n"%s if len(s) else s
|
||||
|
||||
write = lambda str, **kwargs: enumeration_functions.append(str%kwargs)
|
||||
|
||||
for name, enum in mapping.schema.enumerations.items():
|
||||
short_name = name[:-4] if name.endswith("Enum") else name
|
||||
context = locals()
|
||||
write(
|
||||
templates.enumeration_function,
|
||||
max_id = len(enum.values),
|
||||
name = name,
|
||||
values = catc(map(stringify, enum.values)),
|
||||
from_string_statements = catnl(templates.enum_from_string_stmt%dict(context,**locals()) for value in enum.values)
|
||||
)
|
||||
|
||||
write = lambda str, **kwargs: entity_implementations.append(str%kwargs)
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
parent_type_test = "" if not type.supertypes or len(type.supertypes) != 1 \
|
||||
else templates.parent_type_test%(type.supertypes[0])
|
||||
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
|
||||
constructor_arguments_str = catc("%(full_type)s v%(index)d_%(name)s"%a for a in constructor_arguments if not a['is_derived'])
|
||||
attributes = []
|
||||
constructor_implementations = []
|
||||
write_attr = lambda str, **kwargs: attributes.append(str%kwargs)
|
||||
for arg in constructor_arguments:
|
||||
if not arg['is_inherited'] and not arg['is_derived']:
|
||||
if arg['is_optional']:
|
||||
write_attr(
|
||||
templates.function,
|
||||
class_name = name,
|
||||
name = 'has%s'%arg['name'],
|
||||
arguments = '',
|
||||
return_type = 'bool',
|
||||
body = templates.optional_attr_stmt % {'index':arg['index']-1}
|
||||
)
|
||||
|
||||
tmpl = templates.get_attr_stmt_enum if arg['is_enum'] else templates.get_attr_stmt_array if arg['is_array'] and not mapping.schema.is_simpletype(arg['list_instance_type']) and arg['list_instance_type'] not in mapping.express_to_cpp_typemapping else templates.get_attr_stmt_entity if arg['non_optional_type'].endswith('*') else templates.get_attr_stmt
|
||||
write_attr(
|
||||
templates.function,
|
||||
class_name = name,
|
||||
name = arg['name'],
|
||||
arguments = '',
|
||||
return_type = arg['non_optional_type'],
|
||||
body = tmpl % {'index': arg['index']-1,
|
||||
'type' : arg['non_optional_type'].split('::')[0],
|
||||
'list_instance_type' : arg['list_instance_type']}
|
||||
)
|
||||
|
||||
tmpl = templates.set_attr_stmt_enum if arg['is_enum'] else templates.set_attr_stmt_array if arg['is_array'] and not mapping.schema.is_simpletype(arg['list_instance_type']) and arg['list_instance_type'] not in mapping.express_to_cpp_typemapping else templates.set_attr_stmt
|
||||
write_attr(
|
||||
templates.function,
|
||||
class_name = name,
|
||||
name = 'set%s'%arg['name'],
|
||||
arguments = '%s v'%arg['non_optional_type'],
|
||||
return_type = 'void',
|
||||
body = tmpl % {'index': arg['index']-1,
|
||||
'type' : arg['non_optional_type'].split('::')[0]}
|
||||
)
|
||||
|
||||
if arg['is_derived']:
|
||||
constructor_implementations.append(templates.constructor_stmt_derived % {'index' : arg['index']-1})
|
||||
else:
|
||||
is_optional_non_naked_ptr = arg['is_optional'] and not arg['non_optional_type'].endswith('*')
|
||||
arg_name = "v%(index)d_%(name)s"%arg
|
||||
deref_name = ("*%s"%arg_name) if is_optional_non_naked_ptr else arg_name
|
||||
|
||||
tmpl = templates.constructor_stmt_array if arg['is_templated_list'] \
|
||||
else templates.constructor_stmt_enum if arg['is_enum'] \
|
||||
else templates.constructor_stmt
|
||||
impl = tmpl % {'name' : deref_name,
|
||||
'index' : arg['index']-1,
|
||||
'type' : arg['non_optional_type'].split('::')[0]}
|
||||
if is_optional_non_naked_ptr:
|
||||
impl = templates.constructor_stmt_optional%{'name' : arg_name,
|
||||
'index' : arg['index']-1,
|
||||
'stmt' : impl}
|
||||
constructor_implementations.append(impl)
|
||||
|
||||
inverse = [templates.function % {
|
||||
'class_name' : name,
|
||||
'name' : i.name,
|
||||
'arguments' : '',
|
||||
'return_type' : '%s::list' % i.entity,
|
||||
'body' : templates.get_inverse % {'type': i.entity}
|
||||
} for i in (type.inverse.elements if type.inverse else [])]
|
||||
|
||||
superclass = "%s((IfcAbstractEntityPtr)0)" % type.supertypes[0] if len(type.supertypes) == 1 else 'IfcUtil::IfcBaseEntity()'
|
||||
|
||||
write(
|
||||
templates.entity_implementation,
|
||||
name = name,
|
||||
parent_type_test = parent_type_test,
|
||||
constructor_arguments = constructor_arguments_str,
|
||||
constructor_implementation = cat(constructor_implementations),
|
||||
attributes = nl(catnl(attributes)),
|
||||
inverse = nl(catnl(inverse)),
|
||||
superclass = superclass
|
||||
)
|
||||
|
||||
selectable_simple_types = sorted(set(sum([b.values for a,b in mapping.schema.selects.items()], [])) & set(mapping.schema.types.keys()))
|
||||
schema_entity_statements += [templates.schema_simple_stmt%locals() for name in selectable_simple_types]
|
||||
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.entities.items()]
|
||||
|
||||
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
|
||||
max_len = max(map(len, enumerable_types))
|
||||
type_name_strings = catc(map(stringify, enumerable_types))
|
||||
string_map_statements = [templates.string_map_statement % {
|
||||
'uppercase_name' : name.upper(),
|
||||
'name' : name,
|
||||
'padding' : ' ' * (max_len - len(name))
|
||||
} for name in enumerable_types]
|
||||
|
||||
parent_type_statements = [templates.parent_type_stmt % {
|
||||
'name' : name,
|
||||
'parent' : type.supertypes[0],
|
||||
'padding' : ' ' * (max_len - len(name))
|
||||
} for name, type in mapping.schema.entities.items() if type.supertypes and len(type.supertypes) == 1]
|
||||
|
||||
max_id = len(enumerable_types)
|
||||
|
||||
simple_type_statements = cator("v == Type::%s"%name for name in selectable_simple_types)
|
||||
|
||||
self.str = templates.implementation % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize(),
|
||||
'max_id' : max_id,
|
||||
'enumeration_functions' : cat(enumeration_functions),
|
||||
'schema_entity_statements' : catnl(schema_entity_statements),
|
||||
'type_name_strings' : type_name_strings,
|
||||
'string_map_statements' : catnl(string_map_statements),
|
||||
'simple_type_statement' : simple_type_statements,
|
||||
'parent_type_statements' : catnl(parent_type_statements),
|
||||
'entity_implementations' : catnl(entity_implementations)
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
def emit(self):
|
||||
f = open('%s.cpp'%self.schema_name, 'w', encoding='utf-8')
|
||||
f.write(str(self))
|
||||
f.close()
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import nodes
|
||||
import templates
|
||||
|
||||
class Mapping:
|
||||
|
||||
express_to_cpp_typemapping = {
|
||||
'boolean' : 'bool',
|
||||
'logical' : 'bool',
|
||||
'integer' : 'int',
|
||||
'real' : 'double',
|
||||
'number' : 'double',
|
||||
'string' : 'std::string'
|
||||
}
|
||||
|
||||
def __init__(self, schema):
|
||||
self.schema = schema
|
||||
|
||||
def make_type_string(self, type):
|
||||
if isinstance(type, str):
|
||||
return self.express_to_cpp_typemapping.get(type, type)
|
||||
else:
|
||||
is_list = self.schema.is_entity(type.type)
|
||||
tmpl = templates.list_type if is_list else templates.array_type
|
||||
return tmpl % {
|
||||
'instance_type' : self.make_type_string(type.type),
|
||||
'lower' : type.bounds.lower,
|
||||
'upper' : type.bounds.upper,
|
||||
}
|
||||
|
||||
def is_array(self, type):
|
||||
if isinstance(type, nodes.AggregationType):
|
||||
return True
|
||||
elif isinstance(type, str) and self.schema.is_type(type):
|
||||
return self.is_array(self.schema.types[type].type.type)
|
||||
else:
|
||||
return False
|
||||
|
||||
def make_argument_type(self, attr):
|
||||
def _make_argument_type(type):
|
||||
if type in self.express_to_cpp_typemapping:
|
||||
return self.express_to_cpp_typemapping.get(type, type).split('::')[-1].upper()
|
||||
elif self.schema.is_entity(type):
|
||||
return "ENTITY"
|
||||
elif self.schema.is_type(type):
|
||||
return _make_argument_type(self.schema.types[type].type.type)
|
||||
elif isinstance(type, nodes.BinaryType):
|
||||
return "UNKNOWN"
|
||||
elif isinstance(type, nodes.EnumerationType):
|
||||
return "ENUMERATION"
|
||||
elif isinstance(type, nodes.SelectType):
|
||||
return "ENTITY"
|
||||
elif isinstance(type, nodes.AggregationType):
|
||||
ty = _make_argument_type(type.type)
|
||||
if ty == "UNKNOWN": return "UNKNOWN"
|
||||
return "ENTITY_LIST" if ty == "ENTITY" else ("VECTOR_%s"%ty)
|
||||
else: raise ValueError
|
||||
supported = {'INT', 'BOOL', 'DOUBLE', 'STRING', 'VECTOR_INT', 'VECTOR_DOUBLE', 'VECTOR_STRING', 'ENTITY', 'ENTITY_LIST', 'ENUMERATION'}
|
||||
ty = _make_argument_type(attr.type)
|
||||
if ty not in supported: ty = 'UNKNOWN'
|
||||
return "IfcUtil::Argument_%s" % ty
|
||||
|
||||
def get_type_dep(self, type):
|
||||
if isinstance(type, str):
|
||||
return self.express_to_cpp_typemapping.get(type, type)
|
||||
else:
|
||||
return self.get_type_dep(type.type)
|
||||
|
||||
def get_parameter_type(self, attr, allow_optional, allow_entities, allow_pointer = True):
|
||||
type_str = self.express_to_cpp_typemapping.get(str(attr.type), attr.type)
|
||||
is_ptr = False
|
||||
if self.schema.is_enumeration(attr.type):
|
||||
type_str = '%s::%s'%(attr.type, attr.type)
|
||||
elif isinstance(type_str, nodes.AggregationType):
|
||||
ty = self.get_parameter_type(attr.type, False, allow_entities, allow_pointer=False)
|
||||
if allow_entities and self.schema.is_select(attr.type.type):
|
||||
type_str = templates.untyped_list
|
||||
elif self.schema.is_simpletype(ty) or ty in self.express_to_cpp_typemapping.values():
|
||||
type_str = templates.array_type % {
|
||||
'instance_type' : ty,
|
||||
'lower' : attr.type.bounds.lower,
|
||||
'upper' : attr.type.bounds.upper
|
||||
}
|
||||
else:
|
||||
type_str = templates.list_type % {
|
||||
'instance_type': ty
|
||||
}
|
||||
elif allow_pointer and self.schema.is_entity(type_str):
|
||||
type_str += '*'
|
||||
is_ptr = True
|
||||
elif not allow_pointer and self.schema.is_select(type_str):
|
||||
type_str = "IfcUtil::IfcAbstractSelect"
|
||||
is_ptr = True
|
||||
if allow_optional and attr.optional and not is_ptr:
|
||||
type_str = "boost::optional< %s >"%type_str
|
||||
return type_str
|
||||
|
||||
def argument_count(self, t):
|
||||
c = sum([self.argument_count(self.schema.entities[s]) for s in t.supertypes])
|
||||
return c + len(t.attributes)
|
||||
|
||||
def arguments(self, t):
|
||||
c = sum([self.arguments(self.schema.entities[s]) for s in t.supertypes], [])
|
||||
return c + t.attributes
|
||||
|
||||
def derived_in_supertype(self, t):
|
||||
c = sum([self.derived_in_supertype(self.schema.entities[s]) for s in t.supertypes], [])
|
||||
return c + ([str(s) for s in t.derive.elements] if t.derive else [])
|
||||
|
||||
def list_instance_type(self, attr):
|
||||
f = lambda v : 'IfcUtil::IfcAbstractSelect' if self.schema.is_select(v) else v
|
||||
if self.is_array(attr.type) and not isinstance(attr.type, str):
|
||||
return f(attr.type.type)
|
||||
elif self.is_array(attr.type) and isinstance(attr.type, str):
|
||||
return f(attr.type)
|
||||
else: return None
|
||||
|
||||
def is_templated_list(self, attr):
|
||||
ty = self.list_instance_type(attr)
|
||||
arr = self.is_array(attr.type)
|
||||
simple = self.schema.is_simpletype(ty)
|
||||
express = ty in self.express_to_cpp_typemapping
|
||||
select = ty == 'IfcUtil::IfcAbstractSelect'
|
||||
return arr and not simple and not express and not select
|
||||
|
||||
def get_assignable_arguments(self, t, include_derived = False):
|
||||
count = self.argument_count(t)
|
||||
num_inherited = count - len(t.attributes)
|
||||
derived = set(self.derived_in_supertype(t))
|
||||
attrs = enumerate(self.arguments(t))
|
||||
|
||||
def include(attr):
|
||||
not_derived = include_derived or (attr.name not in derived)
|
||||
supported = self.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN"
|
||||
return not_derived and supported
|
||||
|
||||
return [{
|
||||
'index' : i+1,
|
||||
'name' : attr.name,
|
||||
'full_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=True),
|
||||
'specialized_type' : self.get_parameter_type(attr, allow_optional=True, allow_entities=False),
|
||||
'non_optional_type' : self.get_parameter_type(attr, allow_optional=False, allow_entities=False),
|
||||
'list_instance_type' : self.list_instance_type(attr),
|
||||
'is_optional' : attr.optional,
|
||||
'is_inherited' : i < num_inherited,
|
||||
'is_enum' : attr.type in self.schema.enumerations,
|
||||
'is_array' : self.is_array(attr.type),
|
||||
'is_derived' : attr.name in derived,
|
||||
'is_templated_list' : self.is_templated_list(attr),
|
||||
'argument_type_enum' : self.make_argument_type(attr),
|
||||
'argument_type' : attr.type
|
||||
} for i, attr in attrs if include(attr)]
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import string
|
||||
import collections
|
||||
|
||||
class Node:
|
||||
def __init__(self, tokens):
|
||||
self.tokens = tokens
|
||||
self.init()
|
||||
def tokens_of_type(self, cls):
|
||||
return [t for t in self.tokens if isinstance(t, cls)]
|
||||
def single_token_of_type(self, cls, k = None, v = None):
|
||||
ts = [t for t in self.tokens if isinstance(t, cls) and (k is None or getattr(t, k) == v)]
|
||||
return ts[0] if len(ts) == 1 else None
|
||||
|
||||
|
||||
class TypeDeclaration(Node):
|
||||
name = property(lambda self: self.tokens[1])
|
||||
type = property(lambda self: self.tokens[3])
|
||||
def init(self):
|
||||
assert self.tokens[0] == 'type'
|
||||
assert isinstance(self.type, UnderlyingType)
|
||||
def __repr__(self):
|
||||
return "%s = TypeDeclaration(%s)" % (self.name, self.type)
|
||||
|
||||
|
||||
class EntityDeclaration(Node):
|
||||
name = property(lambda self: self.tokens[1])
|
||||
attributes = property(lambda self: self.tokens_of_type(ExplicitAttribute))
|
||||
def init(self):
|
||||
assert self.tokens[0] == 'entity'
|
||||
s = self.single_token_of_type(SubtypeExpression)
|
||||
self.inverse = self.single_token_of_type(AttributeList, 'type', 'inverse')
|
||||
self.derive = self.single_token_of_type(AttributeList, 'type', 'derive')
|
||||
self.supertypes = s.types if s else []
|
||||
def __repr__(self):
|
||||
builder = ""
|
||||
builder += "Entity(%s)" % (self.name)
|
||||
if len(self.supertypes):
|
||||
builder += "\n Supertypes: %s"%(",".join(self.supertypes))
|
||||
if len(self.attributes):
|
||||
builder += "\n Attributes: %s"%("".join(["\n %s"%a for a in self.attributes]))
|
||||
if self.derive:
|
||||
builder += "\n Derive:"
|
||||
builder += str(self.derive)
|
||||
if self.inverse:
|
||||
builder += "\n Inverse:"
|
||||
builder += str(self.inverse)
|
||||
builder += "\n"
|
||||
return builder
|
||||
|
||||
|
||||
class UnderlyingType(Node):
|
||||
type = property(lambda self: self.tokens[0])
|
||||
def init(self):
|
||||
pass
|
||||
def __repr__(self):
|
||||
return repr(self.type)
|
||||
|
||||
|
||||
class EnumerationType(Node):
|
||||
type = property(lambda self: self.tokens[0])
|
||||
values = property(lambda self: self.tokens[3::2])
|
||||
def init(self):
|
||||
assert self.type == 'enumeration'
|
||||
def __repr__(self):
|
||||
return ",".join(self.values)
|
||||
|
||||
|
||||
class AggregationType(Node):
|
||||
aggregate_type = property(lambda self: self.tokens[0])
|
||||
bounds = property(lambda self: None if self.tokens[1] == 'of' else self.tokens[1])
|
||||
type = property(lambda self: self.tokens[-1])
|
||||
def init(self):
|
||||
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
|
||||
def __repr__(self):
|
||||
return "%s%s of %s"%(self.aggregate_type, self.bounds, self.type)
|
||||
|
||||
|
||||
class SelectType(Node):
|
||||
type = property(lambda self: self.tokens[0])
|
||||
values = property(lambda self: self.tokens[2::2])
|
||||
def init(self):
|
||||
assert self.type == 'select'
|
||||
def __repr__(self):
|
||||
return ",".join(self.values)
|
||||
|
||||
|
||||
class SubSuperTypeExpression(Node):
|
||||
type = property(lambda self: self.tokens[0])
|
||||
types = property(lambda self: self.tokens[3::2])
|
||||
def init(self):
|
||||
assert self.type == self.class_type
|
||||
|
||||
|
||||
class SubtypeExpression(SubSuperTypeExpression):
|
||||
class_type = 'subtype'
|
||||
|
||||
|
||||
class AttributeList(Node):
|
||||
elements = property(lambda self: self.tokens[1:])
|
||||
def __init__(self, ty, toks):
|
||||
self.type = ty
|
||||
Node.__init__(self, toks)
|
||||
def init(self):
|
||||
assert self.type == self.tokens[0]
|
||||
def __repr__(self):
|
||||
return "".join(["\n %s"%s for s in self.elements])
|
||||
|
||||
|
||||
class InverseAttribute(Node):
|
||||
name = property(lambda self: self.tokens[0])
|
||||
type = property(lambda self: self.tokens[2])
|
||||
bounds = property(lambda self: None if len(self.tokens) == 6 else self.tokens[3])
|
||||
entity = property(lambda self: self.tokens[-4])
|
||||
attribute = property(lambda self: self.tokens[-2])
|
||||
def init(self):
|
||||
assert self.bounds is None or isinstance(self.bounds, BoundSpecification)
|
||||
def __repr__(self):
|
||||
return "%s = %s.%s (%s%s)"%(self.name, self.entity, self.attribute, self.type, self.bounds or "")
|
||||
|
||||
|
||||
class DerivedAttribute(Node):
|
||||
def init(self):
|
||||
name_index = list(self.tokens).index(':') - 1
|
||||
self.name = self.tokens[name_index]
|
||||
def __repr__(self):
|
||||
return str(self.name)
|
||||
|
||||
|
||||
class BinaryType(Node):
|
||||
def init(self):
|
||||
pass
|
||||
def __repr__(self):
|
||||
return "BINARY"
|
||||
|
||||
|
||||
class BoundSpecification(Node):
|
||||
lower = property(lambda self: self.tokens[1])
|
||||
upper = property(lambda self: self.tokens[3])
|
||||
def init(self):
|
||||
# assert self.lower in string.digits or self.lower == '?'
|
||||
# assert self.upper in string.digits or self.upper == '?'
|
||||
pass
|
||||
def __repr__(self):
|
||||
return "[%s:%s]"%(self.lower, self.upper)
|
||||
|
||||
|
||||
class ExplicitAttribute(Node):
|
||||
name = property(lambda self: self.tokens[0])
|
||||
type = property(lambda self: self.tokens[-2])
|
||||
optional = property(lambda self: len(self.tokens) == 5 and self.tokens[-3] == 'optional')
|
||||
def init(self):
|
||||
# NB: This assumes a single name per attribute
|
||||
# definition, which is not necessarily the case.
|
||||
assert self.tokens[1] == ':'
|
||||
def __repr__(self):
|
||||
return "%s : %s%s" % (self.name, self.type, " ?" if self.optional else "")
|
||||
@@ -0,0 +1,35 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import templates
|
||||
|
||||
class RuntimeTypingHeader:
|
||||
def __init__(self, mapping):
|
||||
self.str = templates.rt_header % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize()
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
def emit(self):
|
||||
f = open('%s-rt.h'%self.schema_name, 'w', encoding='utf-8')
|
||||
f.write(str(self))
|
||||
f.close()
|
||||
@@ -0,0 +1,102 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import templates
|
||||
|
||||
class RuntimeTypingImplementation:
|
||||
def __init__(self, mapping):
|
||||
schema_name = mapping.schema.name.capitalize()
|
||||
|
||||
entity_descriptors = []
|
||||
enumeration_descriptors = []
|
||||
derived_field_statements = []
|
||||
|
||||
for name, type in mapping.schema.simpletypes.items():
|
||||
entity_descriptors.append(templates.entity_descriptor % {
|
||||
'type' : name,
|
||||
'parent_statement' : '0',
|
||||
'entity_descriptor_attributes' : templates.entity_descriptor_attribute % {
|
||||
'name' : 'wrappedValue',
|
||||
'optional' : 'false',
|
||||
'type' : mapping.make_argument_type(mapping.schema.types[name].type)
|
||||
}
|
||||
})
|
||||
|
||||
emitted_entities = set()
|
||||
entities_to_emit = mapping.schema.entities.keys()
|
||||
while len(emitted_entities) < len(mapping.schema.entities):
|
||||
for name, type in mapping.schema.entities.items():
|
||||
if name in emitted_entities: continue
|
||||
if len(type.supertypes) == 0 or set(type.supertypes) < emitted_entities:
|
||||
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
|
||||
entity_descriptor_attributes = []
|
||||
for arg in constructor_arguments:
|
||||
if not arg['is_inherited']:
|
||||
tmpl = templates.entity_descriptor_attribute_enum if arg['argument_type_enum'] == 'IfcUtil::Argument_ENUMERATION' else templates.entity_descriptor_attribute
|
||||
entity_descriptor_attributes.append(tmpl % {
|
||||
'name' : arg['name'],
|
||||
'optional' : 'true' if arg['is_optional'] else 'false',
|
||||
'type' : arg['argument_type_enum'],
|
||||
'enum_type' : arg['argument_type']
|
||||
})
|
||||
|
||||
emitted_entities.add(name)
|
||||
parent_statement = '0' if len(type.supertypes) != 1 else templates.entity_descriptor_parent % {
|
||||
'type' : type.supertypes[0]
|
||||
}
|
||||
entity_descriptors.append(templates.entity_descriptor % {
|
||||
'type' : name,
|
||||
'parent_statement' : parent_statement,
|
||||
'entity_descriptor_attributes' : '\n'.join(entity_descriptor_attributes)
|
||||
})
|
||||
|
||||
for name, enum in mapping.schema.enumerations.items():
|
||||
enumeration_descriptor_values = '\n'.join([templates.enumeration_descriptor_value % {
|
||||
'name' : v
|
||||
} for v in enum.values])
|
||||
enumeration_descriptors.append(templates.enumeration_descriptor % {
|
||||
'type' : name,
|
||||
'enumeration_descriptor_values' : enumeration_descriptor_values
|
||||
})
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
|
||||
statements = ''.join(templates.derived_field_statement_attrs % (a['index']-1) for a in constructor_arguments if a['is_derived'])
|
||||
if len(statements):
|
||||
derived_field_statements.append(templates.derived_field_statement % {
|
||||
'type' : name,
|
||||
'statements' : statements
|
||||
})
|
||||
|
||||
self.str = templates.rt_implementation % {
|
||||
'schema_name_upper' : mapping.schema.name.upper(),
|
||||
'schema_name' : mapping.schema.name.capitalize(),
|
||||
'entity_descriptors' : '\n'.join(entity_descriptors),
|
||||
'enumeration_descriptors' : '\n'.join(enumeration_descriptors),
|
||||
'derived_field_statements' : '\n'.join(derived_field_statements)
|
||||
}
|
||||
|
||||
self.schema_name = mapping.schema.name.capitalize()
|
||||
def __repr__(self):
|
||||
return self.str
|
||||
def emit(self):
|
||||
f = open('%s-rt.cpp'%self.schema_name, 'w', encoding='utf-8')
|
||||
f.write(str(self))
|
||||
f.close()
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
import nodes
|
||||
import collections
|
||||
|
||||
class Schema:
|
||||
def is_enumeration(self, v):
|
||||
return v in self.enumerations
|
||||
def is_select(self, v):
|
||||
return v in self.selects
|
||||
def is_simpletype(self, v):
|
||||
return v in self.simpletypes
|
||||
def is_type(self, v):
|
||||
return v in self.types
|
||||
def is_entity(self, v):
|
||||
return v in self.entities
|
||||
def __init__(self, parsetree):
|
||||
self.name = parsetree[1]
|
||||
|
||||
sort = lambda d: collections.OrderedDict(sorted(d.items()))
|
||||
|
||||
self.types = sort({t.name:t for t in parsetree if isinstance(t, nodes.TypeDeclaration)})
|
||||
self.entities = sort({t.name:t for t in parsetree if isinstance(t, nodes.EntityDeclaration)})
|
||||
|
||||
of_type = lambda *types: sort({a: b.type.type for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)})
|
||||
|
||||
self.enumerations = of_type(nodes.EnumerationType)
|
||||
self.selects = of_type(nodes.SelectType)
|
||||
self.simpletypes = of_type(str, nodes.AggregationType)
|
||||
@@ -0,0 +1,361 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
header = """
|
||||
#ifndef %(schema_name_upper)s_H
|
||||
#define %(schema_name_upper)s_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/%(schema_name)senum.h"
|
||||
|
||||
#define IfcSchema %(schema_name)s
|
||||
|
||||
namespace %(schema_name)s {
|
||||
|
||||
// Forward definitions
|
||||
%(forward_definitions)s
|
||||
|
||||
%(declarations)s
|
||||
|
||||
%(class_definitions)s
|
||||
void InitStringMap();
|
||||
IfcUtil::IfcSchemaEntity SchemaEntity(IfcAbstractEntityPtr e = 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
enum_header = """
|
||||
#ifndef %(schema_name_upper)sENUM_H
|
||||
#define %(schema_name_upper)sENUM_H
|
||||
|
||||
#define IfcSchema %(schema_name)s
|
||||
|
||||
namespace %(schema_name)s {
|
||||
|
||||
namespace Type {
|
||||
typedef enum {
|
||||
%(types)s, ALL
|
||||
} Enum;
|
||||
Enum Parent(Enum v);
|
||||
Enum FromString(const std::string& s);
|
||||
std::string ToString(Enum v);
|
||||
bool IsSimple(Enum v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
rt_header = """
|
||||
#ifndef %(schema_name_upper)sRT_H
|
||||
#define %(schema_name_upper)sRT_H
|
||||
|
||||
#define IfcSchema %(schema_name)s
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace %(schema_name)s {
|
||||
namespace Type {
|
||||
int GetAttributeCount(Enum t);
|
||||
int GetAttributeIndex(Enum t, const std::string& a);
|
||||
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
|
||||
const std::string& GetAttributeName(Enum t, unsigned char a);
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
implementation= """
|
||||
#include "../ifcparse/%(schema_name)s.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
using namespace %(schema_name)s;
|
||||
using namespace IfcParse;
|
||||
using namespace IfcWrite;
|
||||
|
||||
IfcUtil::IfcSchemaEntity %(schema_name)s::SchemaEntity(IfcAbstractEntityPtr e) {
|
||||
switch(e->type()) {
|
||||
%(schema_entity_statements)s
|
||||
default: throw IfcException("Unable to find find keyword in schema"); break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Type::ToString(Enum v) {
|
||||
if (v < 0 || v >= %(max_id)d) throw IfcException("Unable to find find keyword in schema");
|
||||
const char* names[] = { %(type_name_strings)s };
|
||||
return names[v];
|
||||
}
|
||||
|
||||
static std::map<std::string,Type::Enum> string_map;
|
||||
void %(schema_name)s::InitStringMap() {
|
||||
%(string_map_statements)s
|
||||
}
|
||||
|
||||
Type::Enum Type::FromString(const std::string& s) {
|
||||
std::map<std::string,Type::Enum>::const_iterator it = string_map.find(s);
|
||||
if ( it == string_map.end() ) throw IfcException("Unable to find find keyword in schema");
|
||||
else return it->second;
|
||||
}
|
||||
|
||||
Type::Enum Type::Parent(Enum v){
|
||||
if (v < 0 || v >= %(max_id)d) return (Enum)-1;
|
||||
%(parent_type_statements)s
|
||||
return (Enum)-1;
|
||||
}
|
||||
|
||||
bool Type::IsSimple(Enum v) {
|
||||
return %(simple_type_statement)s;
|
||||
}
|
||||
|
||||
%(enumeration_functions)s
|
||||
|
||||
#define RETURN_INVERSE(T) \
|
||||
IfcEntities e = entity->getInverse(T::Class()); \
|
||||
SHARED_PTR< IfcTemplatedEntityList<T> > l ( new IfcTemplatedEntityList<T>() ); \
|
||||
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { \
|
||||
l->push(reinterpret_pointer_cast<IfcBaseClass,T>(*it)); \
|
||||
} \
|
||||
return l;
|
||||
|
||||
#define RETURN_AS_SINGLE(T,a) \
|
||||
return reinterpret_pointer_cast<IfcBaseClass,T>(*entity->getArgument(a));
|
||||
|
||||
#define RETURN_AS_LIST(T,a) \
|
||||
IfcEntities e = *entity->getArgument(a); \
|
||||
SHARED_PTR< IfcTemplatedEntityList<T> > l ( new IfcTemplatedEntityList<T>() ); \
|
||||
for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { \
|
||||
l->push(reinterpret_pointer_cast<IfcBaseClass,T>(*it)); \
|
||||
} \
|
||||
return l;
|
||||
|
||||
%(entity_implementations)s
|
||||
"""
|
||||
|
||||
rt_implementation = """
|
||||
#include "../ifcparse/%(schema_name)s.h"
|
||||
#include "../ifcparse/%(schema_name)s-rt.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
|
||||
using namespace %(schema_name)s;
|
||||
using namespace IfcParse;
|
||||
using namespace IfcWrite;
|
||||
using namespace IfcUtil;
|
||||
|
||||
std::map<Type::Enum,IfcEntityDescriptor*> entity_descriptor_map;
|
||||
std::map<Type::Enum,IfcEnumerationDescriptor*> enumeration_descriptor_map;
|
||||
void InitDescriptorMap() {
|
||||
IfcEntityDescriptor* current;
|
||||
%(entity_descriptors)s
|
||||
// Enumerations
|
||||
IfcEnumerationDescriptor* current_enum;
|
||||
std::vector<std::string> values;
|
||||
%(enumeration_descriptors)s
|
||||
}
|
||||
|
||||
int Type::GetAttributeIndex(Enum t, const std::string& a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentIndex(a);
|
||||
}
|
||||
|
||||
int Type::GetAttributeCount(Enum t) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentCount();
|
||||
}
|
||||
|
||||
ArgumentType Type::GetAttributeType(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentType(a);
|
||||
}
|
||||
|
||||
const std::string& Type::GetAttributeName(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentName(a);
|
||||
}
|
||||
|
||||
bool Type::GetAttributeOptional(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentOptional(a);
|
||||
}
|
||||
|
||||
std::pair<const char*, int> Type::GetEnumerationIndex(Enum t, const std::string& a) {
|
||||
if (enumeration_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEnumerationDescriptor*>::const_iterator i = enumeration_descriptor_map.find(t);
|
||||
if ( i == enumeration_descriptor_map.end() ) throw IfcException("Value not found");
|
||||
else return i->second->getIndex(a);
|
||||
}
|
||||
|
||||
Type::Enum Type::GetAttributeEnumerationClass(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else {
|
||||
Type::Enum t = i->second->getArgumentEnumerationClass(a);
|
||||
if ( t == Type::ALL ) throw IfcException("Not an enumeration");
|
||||
else return t;
|
||||
}
|
||||
}
|
||||
|
||||
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
||||
Type::Enum type = e->type();
|
||||
%(derived_field_statements)s
|
||||
}
|
||||
"""
|
||||
|
||||
entity_descriptor = """ current = entity_descriptor_map[Type::%(type)s] = new IfcEntityDescriptor(Type::%(type)s,%(parent_statement)s);
|
||||
%(entity_descriptor_attributes)s"""
|
||||
|
||||
entity_descriptor_parent = "entity_descriptor_map.find(Type::%(type)s)->second"
|
||||
entity_descriptor_attribute = ' current->add("%(name)s",%(optional)s,%(type)s);'
|
||||
entity_descriptor_attribute_enum = ' current->add("%(name)s",%(optional)s,%(type)s,Type::%(enum_type)s);'
|
||||
|
||||
enumeration_descriptor = """ values.clear(); values.reserve(128);
|
||||
%(enumeration_descriptor_values)s
|
||||
current_enum = enumeration_descriptor_map[Type::%(type)s] = new IfcEnumerationDescriptor(Type::%(type)s, values);"""
|
||||
|
||||
enumeration_descriptor_value = ' values.push_back("%(name)s");'
|
||||
|
||||
derived_field_statement = ' if (type == Type::%(type)s) { %(statements)s}';
|
||||
derived_field_statement_attrs = 'e->setArgumentDerived(%d); '
|
||||
|
||||
simpletype = """%(documentation)s
|
||||
typedef %(type)s %(name)s;
|
||||
"""
|
||||
|
||||
select = """%(documentation)s
|
||||
typedef IfcUtil::IfcSchemaEntity %(name)s;
|
||||
"""
|
||||
|
||||
enumeration = """namespace %(name)s {
|
||||
%(documentation)s
|
||||
typedef enum {%(values)s} %(name)s;
|
||||
const char* ToString(%(name)s v);
|
||||
%(name)s FromString(const std::string& s);
|
||||
}
|
||||
"""
|
||||
|
||||
entity = """%(documentation)s
|
||||
class %(name)s %(superclass)s{
|
||||
public:
|
||||
%(attributes)s virtual unsigned int getArgumentCount() const { return %(argument_count)d; }
|
||||
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const {%(argument_type_function_body)s}
|
||||
virtual const char* getArgumentName(unsigned int i) const {%(argument_name_function_body)s}
|
||||
virtual ArgumentPtr getArgument(unsigned int i) const { return entity->getArgument(i); }
|
||||
%(inverse)s bool is(Type::Enum v) const;
|
||||
Type::Enum type() const;
|
||||
static Type::Enum Class();
|
||||
%(name)s (IfcAbstractEntityPtr e);
|
||||
%(name)s (%(constructor_arguments)s);
|
||||
typedef %(name)s* ptr;
|
||||
typedef SHARED_PTR< IfcTemplatedEntityList< %(name)s > > list;
|
||||
typedef IfcTemplatedEntityList< %(name)s >::it it;
|
||||
};
|
||||
"""
|
||||
|
||||
enumeration_function="""
|
||||
const char* %(name)s::ToString(%(name)s v) {
|
||||
if ( v < 0 || v >= %(max_id)d ) throw IfcException("Unable to find find keyword in schema");
|
||||
const char* names[] = { %(values)s };
|
||||
return names[v];
|
||||
}
|
||||
|
||||
%(name)s::%(name)s %(name)s::FromString(const std::string& s) {
|
||||
%(from_string_statements)s
|
||||
throw IfcException("Unable to find find keyword in schema");
|
||||
}
|
||||
"""
|
||||
|
||||
entity_implementation = """// Function implementations for %(name)s
|
||||
%(attributes)s%(inverse)sbool %(name)s::is(Type::Enum v) const { return v == Type::%(name)s%(parent_type_test)s; }
|
||||
Type::Enum %(name)s::type() const { return Type::%(name)s; }
|
||||
Type::Enum %(name)s::Class() { return Type::%(name)s; }
|
||||
%(name)s::%(name)s(IfcAbstractEntityPtr e) : %(superclass)s { if (!e) return; if (!e->is(Type::%(name)s)) throw IfcException("Unable to find find keyword in schema"); entity = e; }
|
||||
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s { IfcWritableEntity* e = new IfcWritableEntity(Class());%(constructor_implementation)s entity = e; EntityBuffer::Add(this); }
|
||||
"""
|
||||
|
||||
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
|
||||
|
||||
function = "%(return_type)s %(class_name)s::%(name)s(%(arguments)s) { %(body)s }"
|
||||
|
||||
array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/"
|
||||
list_type = "SHARED_PTR< IfcTemplatedEntityList< %(instance_type)s > >"
|
||||
untyped_list = "IfcEntities"
|
||||
inverse_attr = "SHARED_PTR< IfcTemplatedEntityList< %(entity)s > > %(name)s(); // INVERSE %(entity)s::%(attribute)s"
|
||||
|
||||
enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;'
|
||||
|
||||
schema_entity_stmt = ' case Type::%(name)s: return new %(name)s(e); break;'
|
||||
schema_simple_stmt = ' case Type::%(name)s: return new IfcUtil::IfcEntitySelect(e); break;'
|
||||
string_map_statement = ' string_map["%(uppercase_name)s"%(padding)s] = Type::%(name)s;'
|
||||
parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }'
|
||||
|
||||
parent_type_test = " || %s::is(v)"
|
||||
|
||||
optional_attr_stmt = "return !entity->getArgument(%(index)d)->isNull();"
|
||||
|
||||
get_attr_stmt = "return *entity->getArgument(%(index)d);"
|
||||
get_attr_stmt_enum = "return %(type)s::FromString(*entity->getArgument(%(index)d));"
|
||||
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcSchemaEntity)(*entity->getArgument(%(index)d)));"
|
||||
get_attr_stmt_array = "RETURN_AS_LIST(%(list_instance_type)s,%(index)d)"
|
||||
|
||||
get_inverse = "RETURN_INVERSE(%(type)s)"
|
||||
|
||||
set_attr_stmt = "if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%(index)d,v);"
|
||||
set_attr_stmt_enum = "if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%(index)d,v,%(type)s::ToString(v));"
|
||||
set_attr_stmt_array = "if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%(index)d,v->generalize());"
|
||||
|
||||
constructor_stmt = " e->setArgument(%(index)d,(%(name)s));"
|
||||
constructor_stmt_enum = " e->setArgument(%(index)d,%(name)s,%(type)s::ToString(%(name)s));"
|
||||
constructor_stmt_array = " e->setArgument(%(index)d,(%(name)s)->generalize());"
|
||||
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { e->setArgument(%(index)d); }"
|
||||
constructor_stmt_derived = " e->setArgumentDerived(%(index)d);"
|
||||
|
||||
def multi_line_comment(li):
|
||||
return ("/// %s"%("\n/// ".join(li))) if len(li) else ""
|
||||
|
||||
+14
-5
@@ -40,7 +40,7 @@
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
|
||||
#include "../ifcgeom/IfcShapeList.h"
|
||||
#include "../ifcgeom/IfcRepresentationShapeItem.h"
|
||||
|
||||
namespace IfcGeom {
|
||||
|
||||
@@ -73,17 +73,22 @@ namespace IfcGeom {
|
||||
// the interpretation of IfcParamaterValues of IfcTrimmedCurves
|
||||
// Default: -1.0 (= not set, fist try degrees, then radians)
|
||||
GV_PLANEANGLE_UNIT,
|
||||
// The precision used in boolean operations, setting this value too low results
|
||||
// in artefacts and potentially modelling failures
|
||||
// Default: 0.00001 (obtained from IfcGeometricRepresentationContext if available)
|
||||
GV_PRECISION
|
||||
};
|
||||
|
||||
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
|
||||
bool convert_shapes(const IfcUtil::IfcBaseClass* L, ShapeList& result);
|
||||
bool convert_shapes(const IfcUtil::IfcBaseClass* L, IfcRepresentationShapeItems& result);
|
||||
bool is_shape_collection(const IfcUtil::IfcBaseClass* L);
|
||||
const TopoDS_Shape* convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
||||
bool convert_shape(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
||||
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
|
||||
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Face& result);
|
||||
bool convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes);
|
||||
bool convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings, const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes);
|
||||
bool convert_openings(const IfcSchema::IfcProduct::ptr entity, const IfcSchema::IfcRelVoidsElement::list& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
|
||||
bool convert_openings_fast(const IfcSchema::IfcProduct::ptr entity, const IfcSchema::IfcRelVoidsElement::list& openings, const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes);
|
||||
IfcSchema::IfcSurfaceStyleShading* get_surface_style(IfcSchema::IfcRepresentationItem* item);
|
||||
bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid);
|
||||
bool is_compound(const TopoDS_Shape& shape);
|
||||
bool is_convex(const TopoDS_Wire& wire);
|
||||
@@ -94,9 +99,13 @@ namespace IfcGeom {
|
||||
bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
double shape_volume(const TopoDS_Shape& s);
|
||||
double face_area(const TopoDS_Face& f);
|
||||
void apply_tolerance(TopoDS_Shape& s, double t);
|
||||
void SetValue(GeomValue var, double value);
|
||||
double GetValue(GeomValue var);
|
||||
std::string create_brep_data(Ifc2x3::IfcProduct* s);
|
||||
IfcSchema::IfcProductDefinitionShape* tesselate(TopoDS_Shape& shape, double deflection, IfcEntities es);
|
||||
|
||||
|
||||
|
||||
namespace Cache {
|
||||
void Purge();
|
||||
|
||||
@@ -77,13 +77,13 @@
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCircle::ptr l, Handle(Geom_Curve)& curve) {
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( r <= 0.0f ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
|
||||
IfcSchema::IfcAxis2Placement placement = l->Position();
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert((IfcAxis2Placement2D*)placement,trsf2d);
|
||||
@@ -93,27 +93,28 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircle::ptr l, Handle(Geom_Curve)& curve)
|
||||
curve = new Geom_Circle(ax, r);
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcEllipse::ptr l, Handle(Geom_Curve)& curve) {
|
||||
double x = l->SemiAxis1() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
double y = l->SemiAxis2() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( x == 0.0f || y == 0.0f || y > x ) { return false; }
|
||||
gp_Trsf trsf;
|
||||
Ifc2x3::IfcAxis2Placement placement = l->Position();
|
||||
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
|
||||
IfcSchema::IfcAxis2Placement placement = l->Position();
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
gp_Trsf2d trsf2d;
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf2d);
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf2d);
|
||||
trsf = trsf2d;
|
||||
}
|
||||
gp_Ax2 ax = gp_Ax2().Transformed(trsf);
|
||||
curve = new Geom_Ellipse(ax, x, y);
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcLine::ptr l, Handle(Geom_Curve)& curve) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcLine::ptr l, Handle(Geom_Curve)& curve) {
|
||||
gp_Pnt pnt;gp_Vec vec;
|
||||
IfcGeom::convert(l->Pnt(),pnt);
|
||||
IfcGeom::convert(l->Dir(),vec);
|
||||
// See note at IfcGeomWires.cpp:237
|
||||
curve = new Geom_Line(pnt,vec);
|
||||
return true;
|
||||
}
|
||||
@@ -78,10 +78,10 @@
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
Ifc2x3::IfcFaceBound::list bounds = l->Bounds();
|
||||
Ifc2x3::IfcFaceBound::it it = bounds->begin();
|
||||
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
|
||||
bool IfcGeom::convert(const IfcSchema::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
IfcSchema::IfcFaceBound::list bounds = l->Bounds();
|
||||
IfcSchema::IfcFaceBound::it it = bounds->begin();
|
||||
IfcSchema::IfcLoop::ptr loop = (*it)->Bound();
|
||||
TopoDS_Wire outer_wire;
|
||||
if ( ! IfcGeom::convert_wire(loop,outer_wire) ) return false;
|
||||
BRepBuilderAPI_MakeFace mf (outer_wire);
|
||||
@@ -98,7 +98,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
face = mf.Face();
|
||||
} else {
|
||||
for( ++it; it != bounds->end(); ++ it) {
|
||||
Ifc2x3::IfcLoop::ptr loop = (*it)->Bound();
|
||||
IfcSchema::IfcLoop::ptr loop = (*it)->Bound();
|
||||
TopoDS_Wire wire;
|
||||
if ( ! IfcGeom::convert_wire(loop,wire) ) return false;
|
||||
mf.Add(wire);
|
||||
@@ -183,17 +183,17 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) {
|
||||
// return face_area(face) > 0.0001;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcArbitraryClosedProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcArbitraryClosedProfileDef::ptr l, TopoDS_Face& face) {
|
||||
TopoDS_Wire wire;
|
||||
if ( ! IfcGeom::convert_wire(l->OuterCurve(),wire) ) return false;
|
||||
return IfcGeom::convert_wire_to_face(wire,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcArbitraryProfileDefWithVoids::ptr l, TopoDS_Face& face) {
|
||||
TopoDS_Wire profile;
|
||||
if ( ! IfcGeom::convert_wire(l->OuterCurve(),profile) ) return false;
|
||||
BRepBuilderAPI_MakeFace mf(profile);
|
||||
Ifc2x3::IfcCurve::list voids = l->InnerCurves();
|
||||
for( Ifc2x3::IfcCurve::it it = voids->begin(); it != voids->end(); ++ it ) {
|
||||
IfcSchema::IfcCurve::list voids = l->InnerCurves();
|
||||
for( IfcSchema::IfcCurve::it it = voids->begin(); it != voids->end(); ++ it ) {
|
||||
TopoDS_Wire hole;
|
||||
if ( IfcGeom::convert_wire(*it,hole) ) {
|
||||
mf.Add(hole);
|
||||
@@ -204,7 +204,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcArbitraryProfileDefWithVoids::ptr l, Topo
|
||||
face = TopoDS::Face(sfs.Shape());
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcRectangleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->XDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->YDim() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
@@ -218,7 +218,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcRectangleProfileDef::ptr l, TopoDS_Face&
|
||||
double coords[8] = {-x,-y,x,-y,x,y,-x,y};
|
||||
return IfcGeom::profile_helper(4,coords,0,0,0,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcIShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->OverallWidth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->OverallDepth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WebThickness() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
@@ -242,7 +242,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcIShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
double radii[4] = {f,f,f,f};
|
||||
return IfcGeom::profile_helper(12,coords,doFillet ? 4 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double x = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double y = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d1 = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
@@ -267,7 +267,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
double radii[8] = {f2,f2,f1,f1,f1,f1,f2,f2};
|
||||
return IfcGeom::profile_helper(12,coords,doFillet ? 8 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcLShapeProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double y = l->Depth() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double x = l->Width() / 2.0f * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double d = l->Thickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
@@ -294,7 +294,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcLShapeProfileDef::ptr l, TopoDS_Face& fac
|
||||
double radii[3] = {f2,f1,f2};
|
||||
return IfcGeom::profile_helper(6,coords,doFillet ? 3 : 0,fillets,radii,trsf2d,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCircleProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
if ( r == 0.0f ) {
|
||||
Logger::Message(Logger::LOG_NOTICE,"Skipping zero sized profile:",l->entity);
|
||||
@@ -311,7 +311,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCircleProfileDef::ptr l, TopoDS_Face& fac
|
||||
w.Add(edge);
|
||||
return IfcGeom::convert_wire_to_face(w,face);
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCircleHollowProfileDef::ptr l, TopoDS_Face& face) {
|
||||
const double r = l->Radius() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
const double t = l->WallThickness() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
|
||||
#include <BRepGProp_Face.hxx>
|
||||
|
||||
#include <BRepMesh.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Poly_Array1OfTriangle.hxx>
|
||||
|
||||
#include <BRepTools.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
@@ -126,15 +132,15 @@ const TopoDS_Shape& IfcGeom::ensure_fit_for_subtraction(const TopoDS_Shape& shap
|
||||
return solid;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings,
|
||||
const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes) {
|
||||
bool IfcGeom::convert_openings(const IfcSchema::IfcProduct::ptr entity, const IfcSchema::IfcRelVoidsElement::list& openings,
|
||||
const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) {
|
||||
// Iterate over IfcOpeningElements
|
||||
IfcGeom::ShapeList opening_shapes;
|
||||
IfcGeom::IfcRepresentationShapeItems opening_shapes;
|
||||
unsigned int last_size = 0;
|
||||
for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||
Ifc2x3::IfcRelVoidsElement::ptr v = *it;
|
||||
Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
|
||||
if ( fes->is(Ifc2x3::Type::IfcOpeningElement) ) {
|
||||
for ( IfcSchema::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||
IfcSchema::IfcRelVoidsElement::ptr v = *it;
|
||||
IfcSchema::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
|
||||
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||
|
||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
||||
gp_Trsf opening_trsf;
|
||||
@@ -143,26 +149,26 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
// Move the opening into the coordinate system of the IfcProduct
|
||||
opening_trsf.PreMultiply(entity_trsf.Inverted());
|
||||
|
||||
Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation();
|
||||
Ifc2x3::IfcRepresentation::list reps = prodrep->Representations();
|
||||
IfcSchema::IfcProductRepresentation::ptr prodrep = fes->Representation();
|
||||
IfcSchema::IfcRepresentation::list reps = prodrep->Representations();
|
||||
|
||||
for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||
for ( IfcSchema::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||
IfcGeom::convert_shapes(*it2,opening_shapes);
|
||||
}
|
||||
|
||||
const unsigned int current_size = (const unsigned int) opening_shapes.size();
|
||||
for ( unsigned int i = last_size; i < current_size; ++ i ) {
|
||||
opening_shapes[i].first->PreMultiply(opening_trsf);
|
||||
opening_shapes[i].prepend(opening_trsf);
|
||||
}
|
||||
last_size = current_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over the shapes of the IfcProduct
|
||||
for ( IfcGeom::ShapeList::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||
TopoDS_Shape entity_shape_solid;
|
||||
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it3->second),entity_shape_solid);
|
||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
|
||||
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
|
||||
TopoDS_Shape entity_shape;
|
||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to:",entity->entity);
|
||||
@@ -172,10 +178,10 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
}
|
||||
|
||||
// Iterate over the shapes of the IfcOpeningElements
|
||||
for ( IfcGeom::ShapeList::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
|
||||
TopoDS_Shape opening_shape_solid;
|
||||
const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it4->second),opening_shape_solid);
|
||||
const gp_GTrsf& opening_shape_gtrsf = *(it4->first);
|
||||
const TopoDS_Shape& opening_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it4->Shape(),opening_shape_solid);
|
||||
const gp_GTrsf& opening_shape_gtrsf = it4->Placement();
|
||||
if ( opening_shape_gtrsf.Form() == gp_Other ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to opening of:",entity->entity);
|
||||
}
|
||||
@@ -214,29 +220,24 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
|
||||
}
|
||||
|
||||
}
|
||||
cut_shapes.push_back(IfcGeom::LocationShape(new gp_GTrsf(),new TopoDS_Shape(entity_shape)));
|
||||
}
|
||||
|
||||
// Delete references to opening transformations, but keep shapes in the cache
|
||||
for ( IfcGeom::ShapeList::const_iterator it5 = opening_shapes.begin(); it5 != opening_shapes.end(); ++ it5 ) {
|
||||
delete it5->first;
|
||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(entity_shape, &it3->Style()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings,
|
||||
const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes) {
|
||||
bool IfcGeom::convert_openings_fast(const IfcSchema::IfcProduct::ptr entity, const IfcSchema::IfcRelVoidsElement::list& openings,
|
||||
const IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcRepresentationShapeItems& cut_shapes) {
|
||||
|
||||
// Create a compound of all opening shapes in order to speed up the boolean operations
|
||||
TopoDS_Compound opening_compound;
|
||||
BRep_Builder builder;
|
||||
builder.MakeCompound(opening_compound);
|
||||
|
||||
for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||
Ifc2x3::IfcRelVoidsElement::ptr v = *it;
|
||||
Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
|
||||
if ( fes->is(Ifc2x3::Type::IfcOpeningElement) ) {
|
||||
for ( IfcSchema::IfcRelVoidsElement::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||
IfcSchema::IfcRelVoidsElement::ptr v = *it;
|
||||
IfcSchema::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement();
|
||||
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||
|
||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
||||
gp_Trsf opening_trsf;
|
||||
@@ -245,35 +246,32 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
|
||||
// Move the opening into the coordinate system of the IfcProduct
|
||||
opening_trsf.PreMultiply(entity_trsf.Inverted());
|
||||
|
||||
Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation();
|
||||
Ifc2x3::IfcRepresentation::list reps = prodrep->Representations();
|
||||
IfcSchema::IfcProductRepresentation::ptr prodrep = fes->Representation();
|
||||
IfcSchema::IfcRepresentation::list reps = prodrep->Representations();
|
||||
|
||||
IfcGeom::ShapeList opening_shapes;
|
||||
IfcGeom::IfcRepresentationShapeItems opening_shapes;
|
||||
|
||||
for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||
for ( IfcSchema::IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||
IfcGeom::convert_shapes(*it2,opening_shapes);
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
|
||||
gp_GTrsf& gtrsf = *opening_shapes[i].first;
|
||||
gp_GTrsf gtrsf = opening_shapes[i].Placement();
|
||||
gtrsf.PreMultiply(opening_trsf);
|
||||
const TopoDS_Shape& opening_shape = gtrsf.Form() == gp_Other
|
||||
? BRepBuilderAPI_GTransform(*opening_shapes[i].second,gtrsf,true).Shape()
|
||||
: (*opening_shapes[i].second).Moved(gtrsf.Trsf());
|
||||
? BRepBuilderAPI_GTransform(opening_shapes[i].Shape(),gtrsf,true).Shape()
|
||||
: (opening_shapes[i].Shape()).Moved(gtrsf.Trsf());
|
||||
builder.Add(opening_compound,opening_shape);
|
||||
}
|
||||
|
||||
for ( IfcGeom::ShapeList::const_iterator it5 = opening_shapes.begin(); it5 != opening_shapes.end(); ++ it5 ) {
|
||||
delete it5->first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over the shapes of the IfcProduct
|
||||
for ( IfcGeom::ShapeList::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||
TopoDS_Shape entity_shape_solid;
|
||||
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(*(it3->second),entity_shape_solid);
|
||||
const gp_GTrsf& entity_shape_gtrsf = *(it3->first);
|
||||
const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
|
||||
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
|
||||
TopoDS_Shape entity_shape;
|
||||
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to:",entity->entity);
|
||||
@@ -290,7 +288,7 @@ bool IfcGeom::convert_openings_fast(const Ifc2x3::IfcProduct::ptr entity, const
|
||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
||||
is_valid = analyser.IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
cut_shapes.push_back(IfcGeom::LocationShape(new gp_GTrsf(),new TopoDS_Shape(brep_cut_result)));
|
||||
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(brep_cut_result, &it3->Style()));
|
||||
}
|
||||
}
|
||||
if ( !is_valid ) {
|
||||
@@ -427,6 +425,11 @@ gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) {
|
||||
}
|
||||
}
|
||||
|
||||
void IfcGeom::apply_tolerance(TopoDS_Shape& s, double t) {
|
||||
ShapeFix_ShapeTolerance tol;
|
||||
tol.SetTolerance(s, t);
|
||||
}
|
||||
|
||||
static double deflection_tolerance = 0.001;
|
||||
static double wire_creation_tolerance = 0.0001;
|
||||
static double minimal_face_area = 0.000001;
|
||||
@@ -435,6 +438,7 @@ static double max_faces_to_sew = -1.0;
|
||||
static double ifc_length_unit = 1.0;
|
||||
static double ifc_planeangle_unit = -1.0;
|
||||
static double force_ccw_face_orientation = -1.0;
|
||||
static double modelling_precision = 0.00001;
|
||||
|
||||
void IfcGeom::SetValue(GeomValue var, double value) {
|
||||
switch (var) {
|
||||
@@ -462,6 +466,9 @@ void IfcGeom::SetValue(GeomValue var, double value) {
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
force_ccw_face_orientation = value;
|
||||
break;
|
||||
case GV_PRECISION:
|
||||
modelling_precision = value;
|
||||
break;
|
||||
default:
|
||||
assert(!"never reach here");
|
||||
}
|
||||
@@ -488,11 +495,78 @@ double IfcGeom::GetValue(GeomValue var) {
|
||||
case GV_FORCE_CCW_FACE_ORIENTATION:
|
||||
return force_ccw_face_orientation;
|
||||
break;
|
||||
case GV_PRECISION:
|
||||
return modelling_precision;
|
||||
break;
|
||||
}
|
||||
assert(!"never reach here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* IfcGeom::tesselate(TopoDS_Shape& shape, double deflection, IfcEntities es) {
|
||||
BRepMesh::Mesh(shape, deflection);
|
||||
|
||||
IfcSchema::IfcFace::list faces (new IfcTemplatedEntityList<IfcSchema::IfcFace>());
|
||||
|
||||
for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
|
||||
const TopoDS_Face& face = TopoDS::Face(exp.Current());
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(face, loc);
|
||||
|
||||
if (! tri.IsNull()) {
|
||||
const TColgp_Array1OfPnt& nodes = tri->Nodes();
|
||||
std::vector<IfcSchema::IfcCartesianPoint*> vertices;
|
||||
for (int i = 1; i <= nodes.Length(); ++i) {
|
||||
const gp_Pnt& pnt = nodes(i);
|
||||
std::vector<double> xyz; xyz.push_back(pnt.X()); xyz.push_back(pnt.Y()); xyz.push_back(pnt.Z());
|
||||
IfcSchema::IfcCartesianPoint* cpnt = new IfcSchema::IfcCartesianPoint(xyz);
|
||||
vertices.push_back(cpnt);
|
||||
es->push(cpnt);
|
||||
}
|
||||
const Poly_Array1OfTriangle& triangles = tri->Triangles();
|
||||
for (int i = 1; i <= triangles.Length(); ++ i) {
|
||||
int n1, n2, n3;
|
||||
triangles(i).Get(n1, n2, n3);
|
||||
IfcSchema::IfcCartesianPoint::list points (new IfcTemplatedEntityList<IfcSchema::IfcCartesianPoint>());
|
||||
points->push(vertices[n1-1]);
|
||||
points->push(vertices[n2-1]);
|
||||
points->push(vertices[n3-1]);
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, face.Orientation() != TopAbs_REVERSED);
|
||||
IfcSchema::IfcFaceBound::list bounds (new IfcTemplatedEntityList<IfcSchema::IfcFaceBound>());
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
es->push(loop);
|
||||
es->push(bound);
|
||||
es->push(face);
|
||||
faces->push(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
|
||||
IfcSchema::IfcConnectedFaceSet::list shells (new IfcTemplatedEntityList<IfcSchema::IfcConnectedFaceSet>());
|
||||
shells->push(shell);
|
||||
IfcSchema::IfcFaceBasedSurfaceModel* surface_model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
|
||||
|
||||
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
|
||||
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
|
||||
|
||||
items->push(surface_model);
|
||||
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
0, std::string("Facetation"), std::string("SurfaceModel"), items);
|
||||
|
||||
reps->push(rep);
|
||||
IfcSchema::IfcProductDefinitionShape* shapedef = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
|
||||
es->push(shell);
|
||||
es->push(surface_model);
|
||||
es->push(rep);
|
||||
es->push(shapedef);
|
||||
|
||||
return shapedef;
|
||||
}
|
||||
|
||||
std::string IfcGeom::create_brep_data(Ifc2x3::IfcProduct* ifc_product) {
|
||||
if (!ifc_product->hasRepresentation()) return "";
|
||||
|
||||
@@ -507,7 +581,7 @@ std::string IfcGeom::create_brep_data(Ifc2x3::IfcProduct* ifc_product) {
|
||||
}
|
||||
}
|
||||
|
||||
IfcGeom::ShapeList shapes;
|
||||
IfcGeom::IfcRepresentationShapeItems shapes;
|
||||
if (!IfcGeom::convert_shapes(shape_rep,shapes)) {
|
||||
return "";
|
||||
}
|
||||
@@ -519,42 +593,43 @@ std::string IfcGeom::create_brep_data(Ifc2x3::IfcProduct* ifc_product) {
|
||||
|
||||
// Does the IfcElement have any IfcOpenings?
|
||||
// Note that openings for IfcOpeningElements are not processed
|
||||
Ifc2x3::IfcRelVoidsElement::list openings = Ifc2x3::IfcRelVoidsElement::list();
|
||||
if ( ifc_product->is(Ifc2x3::Type::IfcElement) && !ifc_product->is(Ifc2x3::Type::IfcOpeningElement) ) {
|
||||
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
|
||||
IfcSchema::IfcRelVoidsElement::list openings = IfcSchema::IfcRelVoidsElement::list();
|
||||
if ( ifc_product->is(IfcSchema::Type::IfcElement) && !ifc_product->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||
IfcSchema::IfcElement::ptr element = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcElement>(ifc_product);
|
||||
openings = element->HasOpenings();
|
||||
}
|
||||
// Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
|
||||
if ( ifc_product->is(Ifc2x3::Type::IfcBuildingElementPart ) ) {
|
||||
Ifc2x3::IfcBuildingElementPart::ptr part = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcBuildingElementPart>(ifc_product);
|
||||
Ifc2x3::IfcRelDecomposes::list decomposes = part->Decomposes();
|
||||
for ( Ifc2x3::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
Ifc2x3::IfcObjectDefinition::ptr obdef = (*it)->RelatingObject();
|
||||
if ( obdef->is(Ifc2x3::Type::IfcElement) ) {
|
||||
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcObjectDefinition,Ifc2x3::IfcElement>(obdef);
|
||||
if ( ifc_product->is(IfcSchema::Type::IfcBuildingElementPart ) ) {
|
||||
IfcSchema::IfcBuildingElementPart::ptr part = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcBuildingElementPart>(ifc_product);
|
||||
#ifdef USE_IFC4
|
||||
IfcSchema::IfcRelAggregates::list decomposes = part->Decomposes();
|
||||
for ( IfcSchema::IfcRelAggregates::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
#else
|
||||
IfcSchema::IfcRelDecomposes::list decomposes = part->Decomposes();
|
||||
for ( IfcSchema::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
#endif
|
||||
IfcSchema::IfcObjectDefinition::ptr obdef = (*it)->RelatingObject();
|
||||
if ( obdef->is(IfcSchema::Type::IfcElement) ) {
|
||||
IfcSchema::IfcElement::ptr element = reinterpret_pointer_cast<IfcSchema::IfcObjectDefinition,IfcSchema::IfcElement>(obdef);
|
||||
openings->push(element->HasOpenings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( openings && openings->Size() ) {
|
||||
IfcGeom::ShapeList opened_shapes;
|
||||
IfcGeom::IfcRepresentationShapeItems opened_shapes;
|
||||
try {
|
||||
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
|
||||
} catch(...) {
|
||||
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity);
|
||||
}
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
it->first->PreMultiply(trsf);
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = gp_Trsf();
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
delete it->first;
|
||||
delete it->second;
|
||||
}
|
||||
} else {
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
it->first->PreMultiply(trsf);
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = gp_Trsf();
|
||||
}
|
||||
@@ -562,9 +637,9 @@ std::string IfcGeom::create_brep_data(Ifc2x3::IfcProduct* ifc_product) {
|
||||
TopoDS_Compound compound;
|
||||
BRep_Builder builder;
|
||||
builder.MakeCompound(compound);
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
const TopoDS_Shape& s = *(*it).second;
|
||||
const gp_GTrsf& trsf = *(*it).first;
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
const TopoDS_Shape& s = it->Shape();
|
||||
const gp_GTrsf& trsf = it->Placement();
|
||||
bool trsf_valid = false;
|
||||
gp_Trsf _trsf;
|
||||
try {
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace IfcGeom {
|
||||
if ( it != Cache::T.end() ) { e = it->second; return true; }
|
||||
#define CACHE(T,E,e) Cache::T[E->entity->id()] = e;
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
IN_CACHE(IfcCartesianPoint,l,gp_Pnt,point)
|
||||
std::vector<double> xyz = l->Coordinates();
|
||||
point = gp_Pnt(
|
||||
@@ -98,7 +98,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianPoint::ptr l, gp_Pnt& point) {
|
||||
CACHE(IfcCartesianPoint,l,point)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcDirection::ptr l, gp_Dir& dir) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcDirection::ptr l, gp_Dir& dir) {
|
||||
IN_CACHE(IfcDirection,l,gp_Dir,dir)
|
||||
std::vector<double> xyz = l->DirectionRatios();
|
||||
dir = gp_Dir(
|
||||
@@ -109,7 +109,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcDirection::ptr l, gp_Dir& dir) {
|
||||
CACHE(IfcDirection,l,dir)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcVector::ptr l, gp_Vec& v) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcVector::ptr l, gp_Vec& v) {
|
||||
IN_CACHE(IfcVector,l,gp_Vec,v)
|
||||
gp_Dir d;
|
||||
IfcGeom::convert(l->Orientation(),d);
|
||||
@@ -117,7 +117,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcVector::ptr l, gp_Vec& v) {
|
||||
CACHE(IfcVector,l,v)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement3D::ptr l, gp_Trsf& trsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement3D::ptr l, gp_Trsf& trsf) {
|
||||
IN_CACHE(IfcAxis2Placement3D,l,gp_Trsf,trsf)
|
||||
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection;
|
||||
IfcGeom::convert(l->Location(),o);
|
||||
@@ -131,7 +131,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement3D::ptr l, gp_Trsf& trsf) {
|
||||
CACHE(IfcAxis2Placement3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3D::ptr l, gp_Trsf& trsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3D::ptr l, gp_Trsf& trsf) {
|
||||
IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf)
|
||||
gp_Pnt origin;
|
||||
IfcGeom::convert(l->LocalOrigin(),origin);
|
||||
@@ -150,7 +150,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3D::ptr l,
|
||||
CACHE(IfcCartesianTransformationOperator3D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2D::ptr l, gp_Trsf2d& trsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2D::ptr l, gp_Trsf2d& trsf) {
|
||||
IN_CACHE(IfcCartesianTransformationOperator2D,l,gp_Trsf2d,trsf)
|
||||
gp_Pnt origin;
|
||||
IfcGeom::convert(l->LocalOrigin(),origin);
|
||||
@@ -163,7 +163,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2D::ptr l,
|
||||
CACHE(IfcCartesianTransformationOperator2D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUniform::ptr l, gp_GTrsf& gtrsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator3DnonUniform::ptr l, gp_GTrsf& gtrsf) {
|
||||
IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf)
|
||||
gp_Trsf trsf;
|
||||
gp_Pnt origin;
|
||||
@@ -190,7 +190,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUnifo
|
||||
CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUniform::ptr l, gp_GTrsf2d& gtrsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCartesianTransformationOperator2DnonUniform::ptr l, gp_GTrsf2d& gtrsf) {
|
||||
IN_CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gp_GTrsf2d,gtrsf)
|
||||
gp_Trsf2d trsf;
|
||||
gp_Pnt origin;
|
||||
@@ -209,9 +209,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator2DnonUnifo
|
||||
CACHE(IfcCartesianTransformationOperator2DnonUniform,l,gtrsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcPlane::ptr pln, gp_Pln& plane) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcPlane::ptr pln, gp_Pln& plane) {
|
||||
IN_CACHE(IfcPlane,pln,gp_Pln,plane)
|
||||
Ifc2x3::IfcAxis2Placement3D::ptr l = pln->Position();
|
||||
IfcSchema::IfcAxis2Placement3D::ptr l = pln->Position();
|
||||
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection;
|
||||
IfcGeom::convert(l->Location(),o);
|
||||
bool hasRef = l->hasRefDirection();
|
||||
@@ -224,7 +224,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcPlane::ptr pln, gp_Pln& plane) {
|
||||
CACHE(IfcPlane,pln,plane)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement2D::ptr l, gp_Trsf2d& trsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcAxis2Placement2D::ptr l, gp_Trsf2d& trsf) {
|
||||
IN_CACHE(IfcAxis2Placement2D,l,gp_Trsf2d,trsf)
|
||||
gp_Pnt P; gp_Dir V (1,0,0);
|
||||
IfcGeom::convert(l->Location(),P);
|
||||
@@ -236,21 +236,21 @@ bool IfcGeom::convert(const Ifc2x3::IfcAxis2Placement2D::ptr l, gp_Trsf2d& trsf)
|
||||
CACHE(IfcAxis2Placement2D,l,trsf)
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcObjectPlacement::ptr l, gp_Trsf& trsf) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcObjectPlacement::ptr l, gp_Trsf& trsf) {
|
||||
IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf)
|
||||
if ( ! l->is(Ifc2x3::Type::IfcLocalPlacement) ) return false;
|
||||
Ifc2x3::IfcLocalPlacement::ptr current = reinterpret_pointer_cast<Ifc2x3::IfcObjectPlacement,Ifc2x3::IfcLocalPlacement>(l);
|
||||
if ( ! l->is(IfcSchema::Type::IfcLocalPlacement) ) return false;
|
||||
IfcSchema::IfcLocalPlacement::ptr current = reinterpret_pointer_cast<IfcSchema::IfcObjectPlacement,IfcSchema::IfcLocalPlacement>(l);
|
||||
while (1) {
|
||||
gp_Trsf trsf2;
|
||||
Ifc2x3::IfcAxis2Placement relplacement = current->RelativePlacement();
|
||||
if ( relplacement->is(Ifc2x3::Type::IfcAxis2Placement3D) ) {
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)relplacement,trsf2);
|
||||
IfcSchema::IfcAxis2Placement relplacement = current->RelativePlacement();
|
||||
if ( relplacement->is(IfcSchema::Type::IfcAxis2Placement3D) ) {
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)relplacement,trsf2);
|
||||
trsf.PreMultiply(trsf2);
|
||||
}
|
||||
if ( current->hasPlacementRelTo() ) {
|
||||
Ifc2x3::IfcObjectPlacement::ptr relto = current->PlacementRelTo();
|
||||
if ( relto->is(Ifc2x3::Type::IfcLocalPlacement) )
|
||||
current = reinterpret_pointer_cast<Ifc2x3::IfcObjectPlacement,Ifc2x3::IfcLocalPlacement>(current->PlacementRelTo());
|
||||
IfcSchema::IfcObjectPlacement::ptr relto = current->PlacementRelTo();
|
||||
if ( relto->is(IfcSchema::Type::IfcLocalPlacement) )
|
||||
current = reinterpret_pointer_cast<IfcSchema::IfcObjectPlacement,IfcSchema::IfcLocalPlacement>(current->PlacementRelTo());
|
||||
else break;
|
||||
} else break;
|
||||
}
|
||||
|
||||
+367
-197
@@ -18,6 +18,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
|
||||
#include <gp_Mat.hxx>
|
||||
#include <gp_Mat2d.hxx>
|
||||
@@ -47,45 +49,51 @@
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
// Welds vertices that belong to different faces
|
||||
bool weld_vertices = true;
|
||||
static bool weld_vertices = true;
|
||||
|
||||
bool convert_back_units = false;
|
||||
bool use_faster_booleans = false;
|
||||
bool disable_subtractions = false;
|
||||
static bool convert_back_units = false;
|
||||
static bool use_faster_booleans = false;
|
||||
static bool disable_subtractions = false;
|
||||
static bool disable_triangulation = false;
|
||||
|
||||
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
|
||||
int IfcGeomObjects::IfcRepresentationTriangulation::addvert(int material_index, const gp_XYZ& p) {
|
||||
const float X = convert_back_units ? (float) (p.X() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.X();
|
||||
const float Y = convert_back_units ? (float) (p.Y() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Y();
|
||||
const float Z = convert_back_units ? (float) (p.Z() / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT)) : (float)p.Z();
|
||||
int i = (int) verts.size() / 3;
|
||||
int i = (int) _verts.size() / 3;
|
||||
if ( weld_vertices ) {
|
||||
const VertKey key = VertKey(X,std::pair<float,float>(Y,Z));
|
||||
const VertKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
|
||||
VertKeyMap::const_iterator it = welds.find(key);
|
||||
if ( it != welds.end() ) return it->second;
|
||||
i = (int) welds.size();
|
||||
welds[key] = i;
|
||||
}
|
||||
verts.push_back(X);
|
||||
verts.push_back(Y);
|
||||
verts.push_back(Z);
|
||||
_verts.push_back(X);
|
||||
_verts.push_back(Y);
|
||||
_verts.push_back(Z);
|
||||
return i;
|
||||
}
|
||||
|
||||
bool use_world_coords = false;
|
||||
bool use_brep_data = false;
|
||||
static bool use_world_coords = false;
|
||||
static bool use_brep_data = false;
|
||||
|
||||
static IfcParse::IfcFile* ifc_file = 0;
|
||||
|
||||
IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
id = i;
|
||||
|
||||
if ( use_brep_data ) {
|
||||
IfcGeomObjects::IfcRepresentationBrepData::IfcRepresentationBrepData(const IfcRepresentationShapeModel& shapes)
|
||||
: _id(shapes.getId())
|
||||
{
|
||||
try {
|
||||
TopoDS_Compound compound;
|
||||
BRep_Builder builder;
|
||||
builder.MakeCompound(compound);
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
const TopoDS_Shape& s = *(*it).second;
|
||||
const gp_GTrsf& trsf = *(*it).first;
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
const TopoDS_Shape& s = it->Shape();
|
||||
gp_GTrsf trsf = it->Placement();
|
||||
if (convert_back_units) {
|
||||
gp_Trsf scale;
|
||||
scale.SetScaleFactor(1.0 / IfcGeom::GetValue(IfcGeom::GV_LENGTH_UNIT));
|
||||
trsf.PreMultiply(scale);
|
||||
}
|
||||
bool trsf_valid = false;
|
||||
gp_Trsf _trsf;
|
||||
try {
|
||||
@@ -98,19 +106,38 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
}
|
||||
std::stringstream sstream;
|
||||
BRepTools::Write(compound,sstream);
|
||||
brep_data = sstream.str();
|
||||
} else
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
_brep_data = sstream.str();
|
||||
} catch(...) {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to serialize shape:",ifc_file->EntityById(_id)->entity);
|
||||
}
|
||||
}
|
||||
|
||||
const TopoDS_Shape& s = *(*it).second;
|
||||
const gp_GTrsf& trsf = *(*it).first;
|
||||
IfcGeomObjects::IfcRepresentationTriangulation::IfcRepresentationTriangulation(const IfcRepresentationShapeModel& shapes)
|
||||
: _id(shapes.getId())
|
||||
{
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
|
||||
int surface_style_id = -1;
|
||||
if (it->hasStyle()) {
|
||||
Material adapter(&it->Style());
|
||||
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
|
||||
if (jt == _materials.end()) {
|
||||
surface_style_id = _materials.size();
|
||||
_materials.push_back(adapter);
|
||||
} else {
|
||||
surface_style_id = jt - _materials.begin();
|
||||
}
|
||||
}
|
||||
|
||||
const TopoDS_Shape& s = it->Shape();
|
||||
const gp_GTrsf& trsf = it->Placement();
|
||||
|
||||
// Triangulate the shape
|
||||
try {
|
||||
// BRepTools::Clean(s);
|
||||
BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE));
|
||||
} catch(...) {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to triangulate mesh:",ifc_file->EntityById(i)->entity);
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to triangulate shape:",ifc_file->EntityById(_id)->entity);
|
||||
continue;
|
||||
}
|
||||
TopExp_Explorer exp;
|
||||
@@ -143,7 +170,7 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
for( int i = 1; i <= nodes.Length(); ++ i ) {
|
||||
coords.push_back(nodes(i).Transformed(loc).XYZ());
|
||||
trsf.Transforms(*coords.rbegin());
|
||||
dict[i] = addvert(*coords.rbegin());
|
||||
dict[i] = addvert(surface_style_id, *coords.rbegin());
|
||||
|
||||
if ( calculate_normals ) {
|
||||
const gp_Pnt2d& uv = uvs(i);
|
||||
@@ -151,9 +178,9 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
gp_Vec normal_direction;
|
||||
prop.Normal(uv.X(),uv.Y(),p,normal_direction);
|
||||
gp_Dir normal = gp_Dir(normal_direction.XYZ() * rotation_matrix);
|
||||
normals.push_back((float)normal.X());
|
||||
normals.push_back((float)normal.Y());
|
||||
normals.push_back((float)normal.Z());
|
||||
_normals.push_back((float)normal.X());
|
||||
_normals.push_back((float)normal.Y());
|
||||
_normals.push_back((float)normal.Z());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,116 +200,142 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
|
||||
const gp_XYZ v1 = pt2-pt1;
|
||||
const gp_XYZ v2 = pt3-pt2;
|
||||
gp_Dir normal = gp_Dir(v1^v2);
|
||||
normals.push_back((float)normal.X());
|
||||
normals.push_back((float)normal.Y());
|
||||
normals.push_back((float)normal.Z());
|
||||
_normals.push_back((float)normal.X());
|
||||
_normals.push_back((float)normal.Y());
|
||||
_normals.push_back((float)normal.Z());
|
||||
*/
|
||||
|
||||
faces.push_back(dict[n1]);
|
||||
faces.push_back(dict[n2]);
|
||||
faces.push_back(dict[n3]);
|
||||
_faces.push_back(dict[n1]);
|
||||
_faces.push_back(dict[n2]);
|
||||
_faces.push_back(dict[n3]);
|
||||
|
||||
_material_ids.push_back(surface_style_id);
|
||||
|
||||
addedge(n1,n2,edgecount,edges_temp);
|
||||
addedge(n2,n3,edgecount,edges_temp);
|
||||
addedge(n3,n1,edgecount,edges_temp);
|
||||
}
|
||||
for ( std::vector<std::pair<int,int> >::const_iterator it = edges_temp.begin(); it != edges_temp.end(); ++it ) {
|
||||
edges.push_back(edgecount[*it]==1);
|
||||
_edges.push_back(edgecount[*it]==1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IfcGeomObjects::IfcObject::IfcObject(int my_id,
|
||||
int p_id,
|
||||
const std::string& n,
|
||||
const std::string& t,
|
||||
const std::string& g,
|
||||
const gp_Trsf& trsf) {
|
||||
|
||||
IfcGeomObjects::IfcObject::IfcObject(
|
||||
int id,
|
||||
int parent_id,
|
||||
const std::string& name,
|
||||
const std::string& type,
|
||||
const std::string& guid,
|
||||
const gp_Trsf& trsf)
|
||||
: _id(id)
|
||||
, _parent_id(parent_id)
|
||||
, _name(name)
|
||||
, _type(type)
|
||||
, _guid(guid)
|
||||
{
|
||||
// Convert the gp_Trsf into a 4x3 Matrix
|
||||
for( int i = 1; i < 5; ++ i )
|
||||
for ( int j = 1; j < 4; ++ j )
|
||||
matrix.push_back((float)trsf.Value(j,i));
|
||||
|
||||
id = my_id;
|
||||
parent_id = p_id;
|
||||
name = n;
|
||||
type = t;
|
||||
guid = g;
|
||||
_matrix.push_back((float)trsf.Value(j,i));
|
||||
}
|
||||
|
||||
IfcGeomObjects::IfcGeomObject::IfcGeomObject(int my_id,
|
||||
int p_id,
|
||||
const std::string& n,
|
||||
const std::string& t,
|
||||
const std::string& g,
|
||||
const gp_Trsf& trsf,
|
||||
IfcMesh* m) : IfcObject(my_id,p_id,n,t,g,trsf) {
|
||||
IfcGeomObjects::IfcGeomShapeModelObject::IfcGeomShapeModelObject(
|
||||
int id,
|
||||
int parent_id,
|
||||
const std::string& name,
|
||||
const std::string& type,
|
||||
const std::string& guid,
|
||||
const gp_Trsf& trsf,
|
||||
IfcRepresentationShapeModel* shapes)
|
||||
: IfcObject(id,parent_id,name,type,guid,trsf)
|
||||
, _mesh(shapes)
|
||||
{}
|
||||
|
||||
mesh = m;
|
||||
}
|
||||
IfcGeomObjects::IfcGeomBrepDataObject::IfcGeomBrepDataObject(
|
||||
const IfcGeomShapeModelObject& shape_model)
|
||||
: IfcObject(shape_model)
|
||||
, _mesh(new IfcRepresentationBrepData(shape_model.mesh()))
|
||||
{}
|
||||
|
||||
IfcGeomObjects::IfcGeomObject::IfcGeomObject(
|
||||
const IfcGeomShapeModelObject& shape_model)
|
||||
: IfcObject(shape_model)
|
||||
, _mesh(new IfcRepresentationTriangulation(shape_model.mesh()))
|
||||
{}
|
||||
|
||||
// A container and iterator for IfcShapeRepresentations
|
||||
Ifc2x3::IfcShapeRepresentation::list shapereps;
|
||||
Ifc2x3::IfcShapeRepresentation::it outer;
|
||||
static IfcSchema::IfcShapeRepresentation::list shapereps;
|
||||
static IfcSchema::IfcShapeRepresentation::it shaperep_iterator;
|
||||
|
||||
// The object is fetched beforehand to be positive an entity actually exists
|
||||
IfcGeomObjects::IfcGeomObject* current_geom_obj;
|
||||
static IfcGeomObjects::IfcGeomObject* current_geom_obj = 0;
|
||||
static IfcGeomObjects::IfcGeomShapeModelObject* current_shape_model_obj = 0;
|
||||
static IfcGeomObjects::IfcGeomBrepDataObject* current_brep_data_obj = 0;
|
||||
|
||||
// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *outer
|
||||
Ifc2x3::IfcProduct::list entities;
|
||||
Ifc2x3::IfcProduct::it inner;
|
||||
// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *shaperep_iterator
|
||||
static IfcSchema::IfcProduct::list entities;
|
||||
static IfcSchema::IfcProduct::it ifcproduct_iterator;
|
||||
|
||||
int done;
|
||||
int total;
|
||||
static int done;
|
||||
static int total;
|
||||
|
||||
// Move the the next IfcShapeRepresentation
|
||||
void _nextShape() {
|
||||
entities.reset();
|
||||
++ outer;
|
||||
++ shaperep_iterator;
|
||||
++ done;
|
||||
}
|
||||
|
||||
int _getParentId(const Ifc2x3::IfcProduct::ptr ifc_product) {
|
||||
int _getParentId(const IfcSchema::IfcProduct::ptr ifc_product) {
|
||||
int parent_id = -1;
|
||||
// In case of an opening element, parent to the RelatingBuildingElement
|
||||
if ( ifc_product->is(Ifc2x3::Type::IfcOpeningElement ) ) {
|
||||
Ifc2x3::IfcOpeningElement::ptr opening = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcOpeningElement>(ifc_product);
|
||||
Ifc2x3::IfcRelVoidsElement::list voids = opening->VoidsElements();
|
||||
if ( ifc_product->is(IfcSchema::Type::IfcOpeningElement ) ) {
|
||||
IfcSchema::IfcOpeningElement::ptr opening = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcOpeningElement>(ifc_product);
|
||||
IfcSchema::IfcRelVoidsElement::list voids = opening->VoidsElements();
|
||||
if ( voids->Size() ) {
|
||||
Ifc2x3::IfcRelVoidsElement::ptr ifc_void = *voids->begin();
|
||||
IfcSchema::IfcRelVoidsElement::ptr ifc_void = *voids->begin();
|
||||
parent_id = ifc_void->RelatingBuildingElement()->entity->id();
|
||||
}
|
||||
} else if ( ifc_product->is(Ifc2x3::Type::IfcElement ) ) {
|
||||
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
|
||||
Ifc2x3::IfcRelFillsElement::list fills = element->FillsVoids();
|
||||
} else if ( ifc_product->is(IfcSchema::Type::IfcElement ) ) {
|
||||
IfcSchema::IfcElement::ptr element = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcElement>(ifc_product);
|
||||
IfcSchema::IfcRelFillsElement::list fills = element->FillsVoids();
|
||||
// Incase of a RelatedBuildingElement parent to the opening element
|
||||
if ( fills->Size() ) {
|
||||
for ( Ifc2x3::IfcRelFillsElement::it it = fills->begin(); it != fills->end(); ++ it ) {
|
||||
Ifc2x3::IfcRelFillsElement::ptr fill = *it;
|
||||
Ifc2x3::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement();
|
||||
for ( IfcSchema::IfcRelFillsElement::it it = fills->begin(); it != fills->end(); ++ it ) {
|
||||
IfcSchema::IfcRelFillsElement::ptr fill = *it;
|
||||
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement();
|
||||
if ( ifc_product == ifc_objectdef ) continue;
|
||||
parent_id = ifc_objectdef->entity->id();
|
||||
}
|
||||
}
|
||||
// Else simply parent to the containing structure
|
||||
if ( parent_id == -1 ) {
|
||||
Ifc2x3::IfcRelContainedInSpatialStructure::list parents = element->ContainedInStructure();
|
||||
IfcSchema::IfcRelContainedInSpatialStructure::list parents = element->ContainedInStructure();
|
||||
if ( parents->Size() ) {
|
||||
Ifc2x3::IfcRelContainedInSpatialStructure::ptr parent = *parents->begin();
|
||||
IfcSchema::IfcRelContainedInSpatialStructure::ptr parent = *parents->begin();
|
||||
parent_id = parent->RelatingStructure()->entity->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parent decompositions to the RelatingObject
|
||||
if ( parent_id == -1 ) {
|
||||
IfcEntities parents = ifc_product->entity->getInverse(Ifc2x3::Type::IfcRelAggregates);
|
||||
parents->push(ifc_product->entity->getInverse(Ifc2x3::Type::IfcRelNests));
|
||||
IfcEntities parents = ifc_product->entity->getInverse(IfcSchema::Type::IfcRelAggregates);
|
||||
parents->push(ifc_product->entity->getInverse(IfcSchema::Type::IfcRelNests));
|
||||
for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) {
|
||||
Ifc2x3::IfcRelDecomposes::ptr decompose = reinterpret_pointer_cast<IfcBaseClass,Ifc2x3::IfcRelDecomposes>(*it);
|
||||
Ifc2x3::IfcObjectDefinition* ifc_objectdef = decompose->RelatingObject();
|
||||
IfcSchema::IfcRelDecomposes::ptr decompose = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,IfcSchema::IfcRelDecomposes>(*it);
|
||||
IfcSchema::IfcObjectDefinition* ifc_objectdef;
|
||||
#ifdef USE_IFC4
|
||||
if (decompose->is(IfcSchema::Type::IfcRelAggregates)) {
|
||||
ifc_objectdef = ((IfcSchema::IfcRelAggregates*)decompose)->RelatingObject();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
ifc_objectdef = decompose->RelatingObject();
|
||||
#endif
|
||||
if ( ifc_product == ifc_objectdef ) continue;
|
||||
parent_id = ifc_objectdef->entity->id();
|
||||
}
|
||||
@@ -290,17 +343,16 @@ int _getParentId(const Ifc2x3::IfcProduct::ptr ifc_product) {
|
||||
return parent_id;
|
||||
}
|
||||
|
||||
// Returns the current IfcGeomObject*
|
||||
IfcGeomObjects::IfcGeomObject* _get() {
|
||||
IfcGeomObjects::IfcGeomShapeModelObject* create_shape_model_for_next_entity() {
|
||||
while ( true ) {
|
||||
Ifc2x3::IfcShapeRepresentation::ptr shaperep;
|
||||
IfcSchema::IfcShapeRepresentation::ptr shaperep;
|
||||
|
||||
// Have we reached the end of our list of representations?
|
||||
if ( outer == shapereps->end() ) {
|
||||
if ( shaperep_iterator == shapereps->end() ) {
|
||||
shapereps.reset();
|
||||
return 0;
|
||||
}
|
||||
shaperep = *outer;
|
||||
shaperep = *shaperep_iterator;
|
||||
|
||||
// Has the list of IfcProducts for this representation been initialized?
|
||||
if ( ! entities ) {
|
||||
@@ -314,11 +366,11 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Ifc2x3::IfcProductRepresentation::list prodreps = shaperep->OfProductRepresentation();
|
||||
entities = Ifc2x3::IfcProduct::list( new IfcTemplatedEntityList<Ifc2x3::IfcProduct>() );
|
||||
for ( Ifc2x3::IfcProductRepresentation::it it = prodreps->begin(); it != prodreps->end(); ++it ) {
|
||||
if ( (*it)->is(Ifc2x3::Type::IfcProductDefinitionShape) ) {
|
||||
Ifc2x3::IfcProductDefinitionShape::ptr pds = reinterpret_pointer_cast<Ifc2x3::IfcProductRepresentation,Ifc2x3::IfcProductDefinitionShape>(*it);
|
||||
IfcSchema::IfcProductRepresentation::list prodreps = shaperep->OfProductRepresentation();
|
||||
entities = IfcSchema::IfcProduct::list( new IfcTemplatedEntityList<IfcSchema::IfcProduct>() );
|
||||
for ( IfcSchema::IfcProductRepresentation::it it = prodreps->begin(); it != prodreps->end(); ++it ) {
|
||||
if ( (*it)->is(IfcSchema::Type::IfcProductDefinitionShape) ) {
|
||||
IfcSchema::IfcProductDefinitionShape::ptr pds = reinterpret_pointer_cast<IfcSchema::IfcProductRepresentation,IfcSchema::IfcProductDefinitionShape>(*it);
|
||||
entities->push(pds->ShapeOfProduct());
|
||||
} else {
|
||||
// http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
|
||||
@@ -327,9 +379,9 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
|
||||
// IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
|
||||
// Let's find the IfcProducts that reference the IfcProductRepresentation anyway
|
||||
IfcEntities products = (*it)->entity->getInverse(Ifc2x3::Type::IfcProduct);
|
||||
IfcEntities products = (*it)->entity->getInverse(IfcSchema::Type::IfcProduct);
|
||||
for ( IfcEntityList::it it = products->begin(); it != products->end(); ++ it ) {
|
||||
entities->push(reinterpret_pointer_cast<IfcBaseClass,Ifc2x3::IfcProduct>(*it));
|
||||
entities->push(reinterpret_pointer_cast<IfcUtil::IfcBaseClass,IfcSchema::IfcProduct>(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,23 +390,23 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
_nextShape();
|
||||
continue;
|
||||
}
|
||||
inner = entities->begin();
|
||||
ifcproduct_iterator = entities->begin();
|
||||
}
|
||||
// Have we reached the end of our list of IfcProducts?
|
||||
if ( inner == entities->end() ) {
|
||||
if ( ifcproduct_iterator == entities->end() ) {
|
||||
_nextShape();
|
||||
continue;
|
||||
}
|
||||
|
||||
IfcGeomObjects::IfcMesh* shape;
|
||||
IfcGeom::ShapeList shapes;
|
||||
IfcGeomObjects::IfcRepresentationShapeModel* shape;
|
||||
IfcGeom::IfcRepresentationShapeItems shapes;
|
||||
|
||||
if ( !IfcGeom::convert_shapes(shaperep,shapes) ) {
|
||||
_nextShape();
|
||||
continue;
|
||||
}
|
||||
|
||||
Ifc2x3::IfcProduct::ptr ifc_product = *inner;
|
||||
IfcSchema::IfcProduct::ptr ifc_product = *ifcproduct_iterator;
|
||||
|
||||
int parent_id = -1;
|
||||
try {
|
||||
@@ -371,34 +423,35 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
|
||||
// Does the IfcElement have any IfcOpenings?
|
||||
// Note that openings for IfcOpeningElements are not processed
|
||||
Ifc2x3::IfcRelVoidsElement::list openings = Ifc2x3::IfcRelVoidsElement::list();
|
||||
if ( ifc_product->is(Ifc2x3::Type::IfcElement) && !ifc_product->is(Ifc2x3::Type::IfcOpeningElement) ) {
|
||||
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
|
||||
IfcSchema::IfcRelVoidsElement::list openings = IfcSchema::IfcRelVoidsElement::list();
|
||||
if ( ifc_product->is(IfcSchema::Type::IfcElement) && !ifc_product->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||
IfcSchema::IfcElement::ptr element = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcElement>(ifc_product);
|
||||
openings = element->HasOpenings();
|
||||
}
|
||||
// Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
|
||||
if ( ifc_product->is(Ifc2x3::Type::IfcBuildingElementPart ) ) {
|
||||
Ifc2x3::IfcBuildingElementPart::ptr part = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcBuildingElementPart>(ifc_product);
|
||||
Ifc2x3::IfcRelDecomposes::list decomposes = part->Decomposes();
|
||||
for ( Ifc2x3::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
Ifc2x3::IfcObjectDefinition::ptr obdef = (*it)->RelatingObject();
|
||||
if ( obdef->is(Ifc2x3::Type::IfcElement) ) {
|
||||
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcObjectDefinition,Ifc2x3::IfcElement>(obdef);
|
||||
if ( ifc_product->is(IfcSchema::Type::IfcBuildingElementPart ) ) {
|
||||
IfcSchema::IfcBuildingElementPart::ptr part = reinterpret_pointer_cast<IfcSchema::IfcProduct,IfcSchema::IfcBuildingElementPart>(ifc_product);
|
||||
#ifdef USE_IFC4
|
||||
IfcSchema::IfcRelAggregates::list decomposes = part->Decomposes();
|
||||
for ( IfcSchema::IfcRelAggregates::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
#else
|
||||
IfcSchema::IfcRelDecomposes::list decomposes = part->Decomposes();
|
||||
for ( IfcSchema::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
|
||||
#endif
|
||||
IfcSchema::IfcObjectDefinition::ptr obdef = (*it)->RelatingObject();
|
||||
if ( obdef->is(IfcSchema::Type::IfcElement) ) {
|
||||
IfcSchema::IfcElement::ptr element = reinterpret_pointer_cast<IfcSchema::IfcObjectDefinition,IfcSchema::IfcElement>(obdef);
|
||||
openings->push(element->HasOpenings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !disable_subtractions && openings && openings->Size() ) {
|
||||
IfcGeom::ShapeList opened_shapes;
|
||||
IfcGeom::IfcRepresentationShapeItems opened_shapes;
|
||||
try {
|
||||
if ( use_faster_booleans ) {
|
||||
bool succes = IfcGeom::convert_openings_fast(ifc_product,openings,shapes,trsf,opened_shapes);
|
||||
if ( ! succes ) {
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
delete it->first;
|
||||
delete it->second;
|
||||
}
|
||||
opened_shapes.clear();
|
||||
IfcGeom::convert_openings(ifc_product,openings,shapes,trsf,opened_shapes);
|
||||
}
|
||||
@@ -409,61 +462,76 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",ifc_product->entity);
|
||||
}
|
||||
if ( use_world_coords ) {
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
it->first->PreMultiply(trsf);
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = gp_Trsf();
|
||||
}
|
||||
shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),opened_shapes);
|
||||
for ( IfcGeom::ShapeList::const_iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
||||
delete it->first;
|
||||
delete it->second;
|
||||
}
|
||||
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),opened_shapes);
|
||||
} else if ( use_world_coords ) {
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
it->first->PreMultiply(trsf);
|
||||
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = gp_Trsf();
|
||||
shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),shapes);
|
||||
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes);
|
||||
} else {
|
||||
shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),shapes);
|
||||
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),shapes);
|
||||
}
|
||||
|
||||
IfcGeomObjects::IfcGeomObject* geom_obj = new IfcGeomObjects::IfcGeomObject(ifc_product->entity->id(), parent_id, name,
|
||||
Ifc2x3::Type::ToString(ifc_product->type()), guid, trsf, shape);
|
||||
|
||||
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
||||
delete it->first;
|
||||
}
|
||||
|
||||
return geom_obj;
|
||||
return new IfcGeomObjects::IfcGeomShapeModelObject(ifc_product->entity->id(), parent_id, name,
|
||||
IfcSchema::Type::ToString(ifc_product->type()), guid, trsf, shape);
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeomObjects::Next() {
|
||||
if ( current_geom_obj ) {
|
||||
delete current_geom_obj->mesh;
|
||||
delete current_geom_obj;
|
||||
}
|
||||
if ( entities ) {
|
||||
++inner;
|
||||
}
|
||||
current_geom_obj = _get();
|
||||
if ( ! current_geom_obj ) {
|
||||
bool try_and_create_representations_for_current_entity() {
|
||||
current_shape_model_obj = create_shape_model_for_next_entity();
|
||||
if (current_shape_model_obj == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (use_brep_data) {
|
||||
current_brep_data_obj = new IfcGeomObjects::IfcGeomBrepDataObject(*current_shape_model_obj);
|
||||
if (current_brep_data_obj == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!disable_triangulation) {
|
||||
current_geom_obj = new IfcGeomObjects::IfcGeomObject(*current_shape_model_obj);
|
||||
if (current_geom_obj == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
std::vector<IfcGeomObjects::IfcObject*> returned_objects;
|
||||
|
||||
bool IfcGeomObjects::Next() {
|
||||
// Free all possible representations of the current geometrical entity
|
||||
delete current_geom_obj;
|
||||
delete current_brep_data_obj;
|
||||
delete current_shape_model_obj;
|
||||
current_geom_obj = 0;
|
||||
current_brep_data_obj = 0;
|
||||
current_shape_model_obj = 0;
|
||||
|
||||
// Increment the iterator over the list of products using the current
|
||||
// shape representation
|
||||
if (entities) {
|
||||
++ifcproduct_iterator;
|
||||
}
|
||||
|
||||
return try_and_create_representations_for_current_entity();
|
||||
}
|
||||
|
||||
static std::vector<IfcGeomObjects::IfcObject*> returned_objects;
|
||||
bool IfcGeomObjects::CleanUp() {
|
||||
// TODO: Correctly implement destructor for IfcFile
|
||||
delete ifc_file;
|
||||
IfcGeom::Cache::Purge();
|
||||
for ( std::vector<IfcGeomObjects::IfcObject*>::const_iterator it = returned_objects.begin();
|
||||
it != returned_objects.end();
|
||||
++ it ) {
|
||||
delete *it;
|
||||
std::vector<IfcGeomObjects::IfcObject*>::const_iterator it;
|
||||
for (it = returned_objects.begin(); it != returned_objects.end(); ++ it ) {
|
||||
delete *it;
|
||||
}
|
||||
returned_objects.clear();
|
||||
return true;
|
||||
@@ -472,8 +540,8 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||
IfcObject* ifc_object = 0;
|
||||
try {
|
||||
const IfcParse::IfcEntity& ifc_entity = ifc_file->EntityById(id);
|
||||
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
|
||||
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
|
||||
if ( ifc_entity->is(IfcSchema::Type::IfcProduct) ) {
|
||||
IfcSchema::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,IfcSchema::IfcProduct>(ifc_entity);
|
||||
int parent_id = -1;
|
||||
try {
|
||||
parent_id = _getParentId(ifc_product);
|
||||
@@ -484,7 +552,7 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||
IfcGeom::convert(ifc_product->ObjectPlacement(),trsf);
|
||||
} catch (...) {}
|
||||
ifc_object = new IfcObject(ifc_product->entity->id(),parent_id,name,
|
||||
Ifc2x3::Type::ToString(ifc_product->type()),ifc_product->GlobalId(),trsf);
|
||||
IfcSchema::Type::ToString(ifc_product->type()),ifc_product->GlobalId(),trsf);
|
||||
}
|
||||
} catch(...) {}
|
||||
if ( !ifc_object ) ifc_object = new IfcObject(-1,-1,"","","",gp_Trsf());
|
||||
@@ -492,46 +560,87 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
|
||||
return ifc_object;
|
||||
}
|
||||
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
|
||||
if (disable_triangulation) {
|
||||
throw std::runtime_error("No triangulation available");
|
||||
}
|
||||
return current_geom_obj;
|
||||
}
|
||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
|
||||
if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
|
||||
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
|
||||
const IfcGeomObjects::IfcGeomShapeModelObject* IfcGeomObjects::GetShapeModel() {
|
||||
return current_shape_model_obj;
|
||||
}
|
||||
const IfcGeomObjects::IfcGeomBrepDataObject* IfcGeomObjects::GetBrepData() {
|
||||
if (!use_brep_data) {
|
||||
throw std::runtime_error("No BRep data available");
|
||||
}
|
||||
return current_brep_data_obj;
|
||||
}
|
||||
double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) {
|
||||
if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
|
||||
else return 1.0f;
|
||||
}
|
||||
|
||||
void IfcGeomObjects::InitPrecision() {
|
||||
IfcSchema::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
|
||||
// Currently, IfcGeometricRepresentationContext aren't used as much as they should be
|
||||
// in the evaluation of shape representations, hence, we try to find the one with the
|
||||
// lowest precision. Typically, a value of 1e-5 is encountered. This value is applied
|
||||
// to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions.
|
||||
// TODO: Many of the empirically found tolerances should probably be substituted by
|
||||
// one that is defined in the model file.
|
||||
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
|
||||
bool any_precision_encountered = false;
|
||||
for (IfcSchema::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) {
|
||||
IfcSchema::IfcGeometricRepresentationContext* rep_context = *it;
|
||||
if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue;
|
||||
if (rep_context->hasPrecision()) {
|
||||
const double precision = rep_context->Precision();
|
||||
if (precision < lowest_precision_encountered) {
|
||||
any_precision_encountered = true;
|
||||
lowest_precision_encountered = precision;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (any_precision_encountered) {
|
||||
IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string unit_name = "METER";
|
||||
static float unit_magnitude = 1.0f;
|
||||
|
||||
void IfcGeomObjects::InitUnits() {
|
||||
// Set default units, set length to meters, angles to undefined
|
||||
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,1.0);
|
||||
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,-1.0);
|
||||
|
||||
Ifc2x3::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<Ifc2x3::IfcUnitAssignment>();
|
||||
IfcSchema::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<IfcSchema::IfcUnitAssignment>();
|
||||
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
|
||||
if ( unit_assignments->Size() ) {
|
||||
Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
|
||||
IfcSchema::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
|
||||
units = unit_assignment->Units();
|
||||
}
|
||||
if ( ! units ) {
|
||||
// No units eh... Since tolerances and deflection are specified internally in meters
|
||||
// we will try to find another indication of the model size.
|
||||
Ifc2x3::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<Ifc2x3::IfcExtrudedAreaSolid>();
|
||||
IfcSchema::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<IfcSchema::IfcExtrudedAreaSolid>();
|
||||
if ( ! extrusions->Size() ) return;
|
||||
double max_height = -1.0f;
|
||||
for ( Ifc2x3::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
|
||||
for ( IfcSchema::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
|
||||
const double depth = (*it)->Depth();
|
||||
if ( depth > max_height ) max_height = depth;
|
||||
}
|
||||
@@ -540,36 +649,46 @@ void IfcGeomObjects::InitUnits() {
|
||||
}
|
||||
try {
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
|
||||
std::string current_unit_name = "";
|
||||
const IfcUtil::IfcAbstractSelect::ptr base = *it;
|
||||
Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr();
|
||||
IfcSchema::IfcSIUnit::ptr unit = IfcSchema::IfcSIUnit::ptr();
|
||||
double value = 1.0f;
|
||||
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
|
||||
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
|
||||
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
|
||||
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
|
||||
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = (Ifc2x3::IfcSIUnit*) u3;
|
||||
if ( base->is(IfcSchema::Type::IfcConversionBasedUnit) ) {
|
||||
const IfcSchema::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcSchema::IfcConversionBasedUnit>(base);
|
||||
current_unit_name = u->Name();
|
||||
const IfcSchema::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
|
||||
IfcSchema::IfcUnit u3 = u2->UnitComponent();
|
||||
if ( u3->is(IfcSchema::Type::IfcSIUnit) ) {
|
||||
unit = (IfcSchema::IfcSIUnit*) u3;
|
||||
}
|
||||
Ifc2x3::IfcValue v = u2->ValueComponent();
|
||||
IfcSchema::IfcValue v = u2->ValueComponent();
|
||||
IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v;
|
||||
const double f = *v2->wrappedValue();
|
||||
value *= f;
|
||||
} else if ( base->is(Ifc2x3::Type::IfcSIUnit) ) {
|
||||
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcSIUnit>(base);
|
||||
} else if ( base->is(IfcSchema::Type::IfcSIUnit) ) {
|
||||
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcSchema::IfcSIUnit>(base);
|
||||
}
|
||||
if ( unit ) {
|
||||
if ( unit->hasPrefix() ) {
|
||||
value *= UnitPrefixToValue(unit->Prefix());
|
||||
}
|
||||
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
||||
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
||||
IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
||||
if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
||||
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,value);
|
||||
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
|
||||
if (current_unit_name.empty()) {
|
||||
if (unit->hasPrefix()) {
|
||||
current_unit_name = IfcSchema::IfcSIPrefix::ToString(unit->Prefix());
|
||||
}
|
||||
current_unit_name += IfcSchema::IfcSIUnitName::ToString(unit->Name());
|
||||
}
|
||||
unit_magnitude = value;
|
||||
unit_name = current_unit_name;
|
||||
} else if ( type == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
|
||||
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( IfcException ex ) {
|
||||
} catch ( IfcParse::IfcException ex ) {
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
}
|
||||
}
|
||||
@@ -579,15 +698,17 @@ bool IfcGeomObjects::Init(const std::string fn) {
|
||||
}
|
||||
bool _Init() {
|
||||
IfcGeomObjects::InitUnits();
|
||||
IfcGeomObjects::InitPrecision();
|
||||
|
||||
shapereps = ifc_file->EntitiesByType<Ifc2x3::IfcShapeRepresentation>();
|
||||
shapereps = ifc_file->EntitiesByType<IfcSchema::IfcShapeRepresentation>();
|
||||
if ( ! shapereps ) return false;
|
||||
|
||||
outer = shapereps->begin();
|
||||
shaperep_iterator = shapereps->begin();
|
||||
entities.reset();
|
||||
current_geom_obj = _get();
|
||||
|
||||
if ( ! current_geom_obj ) return false;
|
||||
|
||||
if (!try_and_create_representations_for_current_entity()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
done = 0;
|
||||
total = shapereps->Size();
|
||||
@@ -637,15 +758,64 @@ void IfcGeomObjects::Settings(int setting, bool value) {
|
||||
case DISABLE_OPENING_SUBTRACTIONS:
|
||||
disable_subtractions = value;
|
||||
break;
|
||||
case DISABLE_TRIANGULATION:
|
||||
disable_triangulation = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int IfcGeomObjects::Progress() {
|
||||
return 100 * done / total;
|
||||
}
|
||||
std::string IfcGeomObjects::GetLog() {
|
||||
|
||||
const std::string& IfcGeomObjects::GetUnitName() {
|
||||
return unit_name;
|
||||
}
|
||||
|
||||
const float IfcGeomObjects::GetUnitMagnitude() {
|
||||
return unit_magnitude;
|
||||
}
|
||||
|
||||
const std::string IfcGeomObjects::GetLog() {
|
||||
return Logger::GetLog();
|
||||
}
|
||||
|
||||
IfcParse::IfcFile* IfcGeomObjects::GetFile() {
|
||||
return ifc_file;
|
||||
}
|
||||
|
||||
static double black[3] = {0,0,0};
|
||||
|
||||
IfcGeomObjects::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {}
|
||||
bool IfcGeomObjects::Material::hasDiffuse() const { return style->Diffuse(); }
|
||||
bool IfcGeomObjects::Material::hasSpecular() const { return style->Specular(); }
|
||||
bool IfcGeomObjects::Material::hasTransparency() const { return style->Transparency(); }
|
||||
bool IfcGeomObjects::Material::hasSpecularity() const { return style->Specularity(); }
|
||||
const double* IfcGeomObjects::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; }
|
||||
const double* IfcGeomObjects::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
|
||||
double IfcGeomObjects::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
|
||||
double IfcGeomObjects::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
|
||||
const std::string IfcGeomObjects::Material::name() const { return style->Name(); }
|
||||
bool IfcGeomObjects::Material::operator==(const IfcGeomObjects::Material& other) const { return style == other.style; }
|
||||
|
||||
int IfcGeomObjects::IfcRepresentationBrepData::id() const { return _id; }
|
||||
const std::string& IfcGeomObjects::IfcRepresentationBrepData::brep_data() const { return _brep_data; }
|
||||
|
||||
int IfcGeomObjects::IfcRepresentationTriangulation::id() const { return _id; }
|
||||
const std::vector<float>& IfcGeomObjects::IfcRepresentationTriangulation::verts() const { return _verts; }
|
||||
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::faces() const { return _faces; }
|
||||
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::edges() const { return _edges; }
|
||||
const std::vector<float>& IfcGeomObjects::IfcRepresentationTriangulation::normals() const { return _normals; }
|
||||
const std::vector<int>& IfcGeomObjects::IfcRepresentationTriangulation::material_ids() const { return _material_ids; }
|
||||
const std::vector<IfcGeomObjects::Material>& IfcGeomObjects::IfcRepresentationTriangulation::materials() const { return _materials; }
|
||||
|
||||
int IfcGeomObjects::IfcObject::id() const { return _id; }
|
||||
int IfcGeomObjects::IfcObject::parent_id() const { return _parent_id; }
|
||||
const std::string& IfcGeomObjects::IfcObject::name() const { return _name; }
|
||||
const std::string& IfcGeomObjects::IfcObject::type() const { return _type; }
|
||||
const std::string& IfcGeomObjects::IfcObject::guid() const { return _guid; }
|
||||
const std::vector<float>& IfcGeomObjects::IfcObject::matrix() const { return _matrix; }
|
||||
|
||||
const IfcGeomObjects::IfcRepresentationShapeModel& IfcGeomObjects::IfcGeomShapeModelObject::mesh() const { return *_mesh; }
|
||||
const IfcGeomObjects::IfcRepresentationTriangulation& IfcGeomObjects::IfcGeomObject::mesh() const { return *_mesh; }
|
||||
const IfcGeomObjects::IfcRepresentationBrepData& IfcGeomObjects::IfcGeomBrepDataObject::mesh() const { return *_mesh; }
|
||||
|
||||
|
||||
+152
-33
@@ -63,7 +63,7 @@
|
||||
#include <gp_Trsf2d.hxx>
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcgeom/IfcShapeList.h"
|
||||
#include "../ifcgeom/IfcRepresentationShapeItem.h"
|
||||
|
||||
namespace IfcGeomObjects {
|
||||
|
||||
@@ -100,68 +100,187 @@ namespace IfcGeomObjects {
|
||||
// Disables the subtraction of IfcOpeningElement representations from
|
||||
// the related building element representations.
|
||||
const int DISABLE_OPENING_SUBTRACTIONS = 8;
|
||||
// Disables the triangulation of the topological representations. Useful if
|
||||
// the client application understands Open Cascade's native format.
|
||||
const int DISABLE_TRIANGULATION = 9;
|
||||
|
||||
// End of settings enumeration.
|
||||
|
||||
// Some typedefs for convenience
|
||||
typedef std::vector<int>::const_iterator IntIt;
|
||||
typedef std::vector<float>::const_iterator FltIt;
|
||||
// A nested pair of doubles to be able to store an XYZ coordinate in a map.
|
||||
typedef std::pair< float,std::pair<float,float> > VertKey;
|
||||
// A nested pair of floats and a material index to be able to store an XYZ coordinate in a map.
|
||||
// TODO: Make this a std::tuple when compilers add support for that.
|
||||
typedef std::pair<int, std::pair<float,std::pair<float,float> > > VertKey;
|
||||
typedef std::map<VertKey,int> VertKeyMap;
|
||||
typedef std::pair<int,int> Edge;
|
||||
|
||||
class IfcMesh {
|
||||
public:
|
||||
int id;
|
||||
std::vector<float> verts;
|
||||
std::vector<int> faces;
|
||||
std::vector<int> edges;
|
||||
std::vector<float> normals;
|
||||
std::string brep_data;
|
||||
VertKeyMap welds;
|
||||
|
||||
IfcMesh(int i, const IfcGeom::ShapeList& s);
|
||||
class Material {
|
||||
private:
|
||||
int addvert(const gp_XYZ& p);
|
||||
const IfcGeom::SurfaceStyle* style;
|
||||
public:
|
||||
explicit Material(const IfcGeom::SurfaceStyle* style);
|
||||
// Material(const Material& other);
|
||||
// Material& operator=(const Material& other);
|
||||
bool hasDiffuse() const;
|
||||
bool hasSpecular() const;
|
||||
bool hasTransparency() const;
|
||||
bool hasSpecularity() const;
|
||||
const double* diffuse() const;
|
||||
const double* specular() const;
|
||||
double transparency() const;
|
||||
double specularity() const;
|
||||
const std::string name() const;
|
||||
bool operator==(const Material& other) const;
|
||||
};
|
||||
|
||||
class IfcRepresentationShapeModel {
|
||||
private:
|
||||
unsigned int id;
|
||||
const IfcGeom::IfcRepresentationShapeItems shapes;
|
||||
IfcRepresentationShapeModel(const IfcRepresentationShapeModel& other);
|
||||
IfcRepresentationShapeModel& operator=(const IfcRepresentationShapeModel& other);
|
||||
public:
|
||||
IfcRepresentationShapeModel(unsigned int id, const IfcGeom::IfcRepresentationShapeItems& shapes)
|
||||
: id(id)
|
||||
, shapes(shapes)
|
||||
{}
|
||||
virtual ~IfcRepresentationShapeModel() {}
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator begin() const { return shapes.begin(); }
|
||||
IfcGeom::IfcRepresentationShapeItems::const_iterator end() const { return shapes.end(); }
|
||||
const unsigned int& getId() const { return id; }
|
||||
};
|
||||
|
||||
class IfcRepresentationBrepData {
|
||||
private:
|
||||
int _id;
|
||||
std::string _brep_data;
|
||||
public:
|
||||
int id() const;
|
||||
const std::string& brep_data() const;
|
||||
IfcRepresentationBrepData(const IfcRepresentationShapeModel& s);
|
||||
virtual ~IfcRepresentationBrepData() {}
|
||||
private:
|
||||
IfcRepresentationBrepData();
|
||||
IfcRepresentationBrepData(const IfcRepresentationBrepData&);
|
||||
IfcRepresentationBrepData& operator=(const IfcRepresentationBrepData&);
|
||||
};
|
||||
|
||||
class IfcRepresentationTriangulation {
|
||||
private:
|
||||
int _id;
|
||||
std::vector<float> _verts;
|
||||
std::vector<int> _faces;
|
||||
std::vector<int> _edges;
|
||||
std::vector<float> _normals;
|
||||
std::vector<int> _material_ids;
|
||||
std::vector<Material> _materials;
|
||||
VertKeyMap welds;
|
||||
public:
|
||||
int id() const;
|
||||
const std::vector<float>& verts() const;
|
||||
const std::vector<int>& faces() const;
|
||||
const std::vector<int>& edges() const;
|
||||
const std::vector<float>& normals() const;
|
||||
const std::vector<int>& material_ids() const;
|
||||
const std::vector<Material>& materials() const;
|
||||
IfcRepresentationTriangulation(const IfcRepresentationShapeModel& s);
|
||||
virtual ~IfcRepresentationTriangulation() {}
|
||||
private:
|
||||
int addvert(int material_index, const gp_XYZ& p);
|
||||
inline void addedge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
|
||||
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
|
||||
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
|
||||
else edgecount[e] ++;
|
||||
edges_temp.push_back(e);
|
||||
}
|
||||
IfcRepresentationTriangulation();
|
||||
IfcRepresentationTriangulation(const IfcRepresentationTriangulation&);
|
||||
IfcRepresentationTriangulation& operator=(const IfcRepresentationTriangulation&);
|
||||
};
|
||||
|
||||
class IfcObject {
|
||||
private:
|
||||
int _id;
|
||||
int _parent_id;
|
||||
std::string _name;
|
||||
std::string _type;
|
||||
std::string _guid;
|
||||
std::vector<float> _matrix;
|
||||
public:
|
||||
int id;
|
||||
int parent_id;
|
||||
std::string name;
|
||||
std::string type;
|
||||
std::string guid;
|
||||
std::vector<float> matrix;
|
||||
IfcObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf);
|
||||
int id() const;
|
||||
int parent_id() const;
|
||||
const std::string& name() const;
|
||||
const std::string& type() const;
|
||||
const std::string& guid() const;
|
||||
const std::vector<float>& matrix() const;
|
||||
IfcObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf);
|
||||
virtual ~IfcObject() {}
|
||||
};
|
||||
|
||||
class IfcGeomShapeModelObject : public IfcObject {
|
||||
private:
|
||||
IfcRepresentationShapeModel* _mesh;
|
||||
public:
|
||||
const IfcRepresentationShapeModel& mesh() const;
|
||||
IfcGeomShapeModelObject(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid, const gp_Trsf& trsf, IfcRepresentationShapeModel* mesh);
|
||||
virtual ~IfcGeomShapeModelObject() {
|
||||
delete _mesh;
|
||||
}
|
||||
private:
|
||||
IfcGeomShapeModelObject(const IfcGeomShapeModelObject& other);
|
||||
IfcGeomShapeModelObject& operator=(const IfcGeomShapeModelObject& other);
|
||||
};
|
||||
|
||||
class IfcGeomObject : public IfcObject {
|
||||
private:
|
||||
IfcRepresentationTriangulation* _mesh;
|
||||
public:
|
||||
IfcMesh* mesh;
|
||||
IfcGeomObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf, IfcMesh* m);
|
||||
const IfcRepresentationTriangulation& mesh() const;
|
||||
IfcGeomObject(const IfcGeomShapeModelObject& shape_model);
|
||||
virtual ~IfcGeomObject() {
|
||||
delete _mesh;
|
||||
}
|
||||
private:
|
||||
IfcGeomObject(const IfcGeomObject& other);
|
||||
IfcGeomObject& operator=(const IfcGeomObject& other);
|
||||
};
|
||||
|
||||
class IfcGeomBrepDataObject : public IfcObject {
|
||||
private:
|
||||
IfcRepresentationBrepData* _mesh;
|
||||
public:
|
||||
const IfcRepresentationBrepData& mesh() const;
|
||||
IfcGeomBrepDataObject(const IfcGeomShapeModelObject& shape_model);
|
||||
virtual ~IfcGeomBrepDataObject() {
|
||||
delete _mesh;
|
||||
}
|
||||
private:
|
||||
IfcGeomBrepDataObject(const IfcGeomBrepDataObject& other);
|
||||
IfcGeomBrepDataObject& operator=(const IfcGeomBrepDataObject& other);
|
||||
};
|
||||
|
||||
void InitUnits();
|
||||
bool Init(const std::string fn);
|
||||
bool Init(void* data, int len);
|
||||
bool Init(const std::string fn, std::ostream* log1= 0, std::ostream* log2= 0);
|
||||
bool Init(std::istream& f, int len, std::ostream* log1= 0, std::ostream* log2= 0);
|
||||
|
||||
void Settings(int setting, bool value);
|
||||
bool CleanUp();
|
||||
void InitUnits();
|
||||
void InitPrecision();
|
||||
|
||||
const IfcGeomObject* Get();
|
||||
bool Next();
|
||||
int Progress();
|
||||
const IfcObject* GetObject(int id);
|
||||
std::string GetLog();
|
||||
IfcParse::IfcFile* GetFile();
|
||||
const IfcGeomBrepDataObject* GetBrepData();
|
||||
const IfcGeomShapeModelObject* GetShapeModel();
|
||||
|
||||
bool Next();
|
||||
int Progress();
|
||||
|
||||
const std::string& GetUnitName();
|
||||
const float GetUnitMagnitude();
|
||||
|
||||
const std::string GetLog();
|
||||
IfcParse::IfcFile* GetFile();
|
||||
|
||||
bool CleanUp();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "IfcGeomRenderStyles.h"
|
||||
|
||||
namespace IfcGeom {
|
||||
namespace Cache {
|
||||
std::map<int,SurfaceStyle> Style;
|
||||
void PurgeStyleCache() {
|
||||
Style.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool process_colour(IfcSchema::IfcColourRgb* colour, std::tr1::array<double, 3>& rgb) {
|
||||
if (colour != 0) {
|
||||
rgb[0] = colour->Red();
|
||||
rgb[1] = colour->Green();
|
||||
rgb[2] = colour->Blue();
|
||||
}
|
||||
return colour != 0;
|
||||
}
|
||||
|
||||
bool process_colour(IfcUtil::IfcBaseEntity* factor, std::tr1::array<double, 3>& rgb) {
|
||||
if (factor != 0) {
|
||||
const double f = *factor->entity->getArgument(0);
|
||||
rgb[0] = rgb[1] = rgb[2] = f;
|
||||
}
|
||||
return factor != 0;
|
||||
}
|
||||
|
||||
bool process_colour(IfcSchema::IfcColourOrFactor colour_or_factor, std::tr1::array<double, 3>& rgb) {
|
||||
if (colour_or_factor == 0) {
|
||||
return false;
|
||||
} else if (colour_or_factor->is(IfcSchema::Type::IfcColourRgb)) {
|
||||
return process_colour(static_cast<IfcSchema::IfcColourRgb*>(colour_or_factor), rgb);
|
||||
} else if (colour_or_factor->is(IfcSchema::Type::IfcNormalisedRatioMeasure)) {
|
||||
return process_colour(static_cast<IfcUtil::IfcBaseEntity*>(colour_or_factor), rgb);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const IfcGeom::SurfaceStyle* IfcGeom::get_style(IfcSchema::IfcRepresentationItem* item) {
|
||||
std::pair<IfcSchema::IfcSurfaceStyle*, IfcSchema::IfcSurfaceStyleShading*> shading_styles = get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item);
|
||||
if (shading_styles.second == 0) {
|
||||
return 0;
|
||||
}
|
||||
int surface_style_id = shading_styles.first->entity->id();
|
||||
std::map<int,SurfaceStyle>::const_iterator it = Cache::Style.find(surface_style_id);
|
||||
if (it != Cache::Style.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
SurfaceStyle surface_style;
|
||||
if (shading_styles.first->hasName()) {
|
||||
surface_style = SurfaceStyle(surface_style_id, shading_styles.first->Name());
|
||||
} else {
|
||||
surface_style = SurfaceStyle(surface_style_id);
|
||||
}
|
||||
std::tr1::array<double, 3> rgb;
|
||||
if (process_colour(shading_styles.second->SurfaceColour(), rgb)) {
|
||||
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
||||
}
|
||||
if (shading_styles.second->is(IfcSchema::Type::IfcSurfaceStyleRendering)) {
|
||||
IfcSchema::IfcSurfaceStyleRendering* rendering_style = static_cast<IfcSchema::IfcSurfaceStyleRendering*>(shading_styles.second);
|
||||
if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) {
|
||||
SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1,1,1));
|
||||
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2]));
|
||||
}
|
||||
if (rendering_style->hasDiffuseTransmissionColour()) {
|
||||
// Not supported
|
||||
}
|
||||
if (rendering_style->hasReflectionColour()) {
|
||||
// Not supported
|
||||
}
|
||||
if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) {
|
||||
surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
||||
}
|
||||
if (rendering_style->hasSpecularHighlight()) {
|
||||
// Not supported
|
||||
}
|
||||
if (rendering_style->hasTransmissionColour()) {
|
||||
// Not supported
|
||||
}
|
||||
if (rendering_style->hasTransparency()) {
|
||||
const double d = rendering_style->Transparency();
|
||||
surface_style.Transparency().reset(d);
|
||||
}
|
||||
}
|
||||
return &(Cache::Style[surface_style_id] = surface_style);
|
||||
}
|
||||
|
||||
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials;
|
||||
static IfcGeom::SurfaceStyle default_material;
|
||||
static bool default_materials_initialized = false;
|
||||
|
||||
void InitDefaultMaterials() {
|
||||
default_materials.insert(std::make_pair("IfcSite", IfcGeom::SurfaceStyle("IfcSite")));
|
||||
default_materials["IfcSite" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcSlab", IfcGeom::SurfaceStyle("IfcSlab")));
|
||||
default_materials["IfcSlab" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4 , 0.4, 0.4 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcWallStandardCase", IfcGeom::SurfaceStyle("IfcWallStandardCase")));
|
||||
default_materials["IfcWallStandardCase"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9 , 0.9, 0.9 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcWall", IfcGeom::SurfaceStyle("IfcWall")));
|
||||
default_materials["IfcWall" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9 , 0.9, 0.9 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcWindow", IfcGeom::SurfaceStyle("IfcWindow")));
|
||||
default_materials["IfcWindow" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75));
|
||||
default_materials["IfcWindow" ].Transparency().reset(0.3);
|
||||
|
||||
default_materials.insert(std::make_pair("IfcDoor", IfcGeom::SurfaceStyle("IfcDoor")));
|
||||
default_materials["IfcDoor" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcBeam", IfcGeom::SurfaceStyle("IfcBeam")));
|
||||
default_materials["IfcBeam" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcRailing", IfcGeom::SurfaceStyle("IfcRailing")));
|
||||
default_materials["IfcRailing" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcMember", IfcGeom::SurfaceStyle("IfcMember")));
|
||||
default_materials["IfcMember" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6 ));
|
||||
|
||||
default_materials.insert(std::make_pair("IfcPlate", IfcGeom::SurfaceStyle("IfcPlate")));
|
||||
default_materials["IfcPlate" ].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8 , 0.8, 0.8 ));
|
||||
|
||||
default_material = IfcGeom::SurfaceStyle("DefaultMaterial");
|
||||
default_material.Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7));
|
||||
|
||||
default_materials_initialized = true;
|
||||
}
|
||||
|
||||
const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) {
|
||||
if (!default_materials_initialized) InitDefaultMaterials();
|
||||
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find(s);
|
||||
if (it == default_materials.end()) return &default_material;
|
||||
else {
|
||||
const IfcGeom::SurfaceStyle& surface_style = it->second;
|
||||
return &surface_style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCGEOMRENDERSTYLES_H
|
||||
#define IFCGEOMRENDERSTYLES_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <tr1/array>
|
||||
#else
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#endif
|
||||
|
||||
namespace IfcGeom {
|
||||
class SurfaceStyle {
|
||||
public:
|
||||
class ColorComponent {
|
||||
private:
|
||||
std::tr1::array<double, 3> data;
|
||||
public:
|
||||
ColorComponent(double r, double g, double b) {
|
||||
data[0] = r; data[1] = g; data[2] = b;
|
||||
}
|
||||
const double& R() const { return data[0]; }
|
||||
const double& G() const { return data[1]; }
|
||||
const double& B() const { return data[2]; }
|
||||
double& R() { return data[0]; }
|
||||
double& G() { return data[1]; }
|
||||
double& B() { return data[2]; }
|
||||
};
|
||||
private:
|
||||
boost::optional<std::string> name;
|
||||
boost::optional<int> id;
|
||||
boost::optional<ColorComponent> diffuse, specular;
|
||||
boost::optional<double> transparency;
|
||||
boost::optional<double> specularity;
|
||||
public:
|
||||
SurfaceStyle() {}
|
||||
SurfaceStyle(int id) : id(id) {}
|
||||
SurfaceStyle(const std::string& name) : name(name) {}
|
||||
SurfaceStyle(int id, const std::string& name) : id(id), name(name) {}
|
||||
|
||||
// Not used at this point. In fact, equality testing in the current
|
||||
// architecture can just as easily be accomplished by comparing the
|
||||
// pointer addresses of the styles, as they are always referenced
|
||||
// from out of a global map of some sort.
|
||||
bool operator==(const SurfaceStyle& other) {
|
||||
if (name && other.name) {
|
||||
return *name == *other.name;
|
||||
} else if (id && other.id) {
|
||||
return *id == *other.id;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string Name() const {
|
||||
if (name && id) {
|
||||
std::stringstream sstr;
|
||||
sstr << (*id) << "_" << (*name);
|
||||
return sstr.str();
|
||||
} else if (name) {
|
||||
return *name;
|
||||
} else if (id) {
|
||||
std::stringstream sstr;
|
||||
sstr << "IfcSurfaceStyleShading_" << (*id);
|
||||
return sstr.str();
|
||||
} else {
|
||||
return "IfcSurfaceStyleShading";
|
||||
}
|
||||
}
|
||||
|
||||
const boost::optional<ColorComponent>& Diffuse() const { return diffuse; }
|
||||
const boost::optional<ColorComponent>& Specular() const { return specular; }
|
||||
const boost::optional<double>& Transparency() const { return transparency; }
|
||||
const boost::optional<double>& Specularity() const { return specularity; }
|
||||
boost::optional<ColorComponent>& Diffuse() { return diffuse; }
|
||||
boost::optional<ColorComponent>& Specular() { return specular; }
|
||||
boost::optional<double>& Transparency() { return transparency; }
|
||||
boost::optional<double>& Specularity() { return specularity; }
|
||||
};
|
||||
|
||||
template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> get_surface_style(IfcSchema::IfcRepresentationItem* representation_item) {
|
||||
IfcSchema::IfcStyledItem::list styled_items = representation_item->StyledByItem();
|
||||
for (IfcSchema::IfcStyledItem::it jt = styled_items->begin(); jt != styled_items->end(); ++jt) {
|
||||
#ifdef USE_IFC4
|
||||
IfcUtil::IfcAbstractSelect::list style_assignments = (*jt)->Styles();
|
||||
for (IfcUtil::IfcAbstractSelect::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
||||
if (!(*kt)->is(IfcSchema::Type::IfcPresentationStyleAssignment)) {
|
||||
continue;
|
||||
}
|
||||
IfcSchema::IfcPresentationStyleAssignment::ptr style_assignment = (IfcSchema::IfcPresentationStyleAssignment::ptr) *kt;
|
||||
#else
|
||||
IfcSchema::IfcPresentationStyleAssignment::list style_assignments = (*jt)->Styles();
|
||||
for (IfcSchema::IfcPresentationStyleAssignment::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
||||
IfcSchema::IfcPresentationStyleAssignment::ptr style_assignment = *kt;
|
||||
#endif
|
||||
IfcUtil::IfcAbstractSelect::list styles = style_assignment->Styles();
|
||||
for (IfcUtil::IfcAbstractSelect::it lt = styles->begin(); lt != styles->end(); ++lt) {
|
||||
IfcUtil::IfcAbstractSelect::ptr style = *lt;
|
||||
if (style->is(IfcSchema::Type::IfcSurfaceStyle)) {
|
||||
IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style;
|
||||
if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) {
|
||||
IfcUtil::IfcAbstractSelect::list styles_elements = surface_style->Styles();
|
||||
for (IfcUtil::IfcAbstractSelect::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
|
||||
if ((*mt)->is(T::Class())) {
|
||||
return std::make_pair(surface_style, (T*) *mt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StyledByItem is a SET [0:1] OF IfcStyledItem, so we
|
||||
// break after encountering the first IfcStyledItem
|
||||
break;
|
||||
}
|
||||
|
||||
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0,0);
|
||||
}
|
||||
|
||||
const SurfaceStyle* get_style(IfcSchema::IfcRepresentationItem* representation_item);
|
||||
const SurfaceStyle* get_default_style(const std::string& ifc_type);
|
||||
|
||||
namespace Cache {
|
||||
void PurgeStyleCache();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+74
-156
@@ -78,7 +78,7 @@
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Face face;
|
||||
if ( ! IfcGeom::convert_face(l->SweptArea(),face) ) return false;
|
||||
const double height = l->Depth() * IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
@@ -92,68 +92,74 @@ bool IfcGeom::convert(const Ifc2x3::IfcExtrudedAreaSolid::ptr l, TopoDS_Shape& s
|
||||
shape.Move(trsf);
|
||||
return ! shape.IsNull();
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcFacetedBrep::ptr l, ShapeList& shape) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcFacetedBrep::ptr l, IfcRepresentationShapeItems& shape) {
|
||||
TopoDS_Shape s;
|
||||
if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(l->Outer(),s) ) {
|
||||
shape.push_back(LocationShape(new gp_GTrsf(),shape_id));
|
||||
if (IfcGeom::convert_shape(l->Outer(),s) ) {
|
||||
shape.push_back(IfcRepresentationShapeItem(s, get_style(l->Outer())));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcFaceBasedSurfaceModel::ptr l, ShapeList& shapes) {
|
||||
Ifc2x3::IfcConnectedFaceSet::list facesets = l->FbsmFaces();
|
||||
for( Ifc2x3::IfcConnectedFaceSet::it it = facesets->begin(); it != facesets->end(); ++ it ) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcFaceBasedSurfaceModel::ptr l, IfcRepresentationShapeItems& shapes) {
|
||||
IfcSchema::IfcConnectedFaceSet::list facesets = l->FbsmFaces();
|
||||
const SurfaceStyle* collective_style = get_style(l);
|
||||
for( IfcSchema::IfcConnectedFaceSet::it it = facesets->begin(); it != facesets->end(); ++ it ) {
|
||||
TopoDS_Shape s;
|
||||
if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s) ) {
|
||||
shapes.push_back(LocationShape(new gp_GTrsf(),shape_id));
|
||||
const SurfaceStyle* shell_style = get_style(*it);
|
||||
if (IfcGeom::convert_shape(*it,s)) {
|
||||
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcHalfSpaceSolid::ptr l, TopoDS_Shape& shape) {
|
||||
Ifc2x3::IfcSurface::ptr surface = l->BaseSurface();
|
||||
if ( ! surface->is(Ifc2x3::Type::IfcPlane) ) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcHalfSpaceSolid::ptr l, TopoDS_Shape& shape) {
|
||||
IfcSchema::IfcSurface::ptr surface = l->BaseSurface();
|
||||
if ( ! surface->is(IfcSchema::Type::IfcPlane) ) {
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcSurface,Ifc2x3::IfcPlane>(surface),pln);
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcSchema::IfcSurface,IfcSchema::IfcPlane>(surface),pln);
|
||||
const gp_Pnt pnt = pln.Location().Translated( l->AgreementFlag() ? -pln.Axis().Direction() : pln.Axis().Direction());
|
||||
shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_Shape& shape) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcPolygonalBoundedHalfSpace::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Shape halfspace;
|
||||
if ( ! IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcPolygonalBoundedHalfSpace,Ifc2x3::IfcHalfSpaceSolid>(l),halfspace) ) return false;
|
||||
if ( ! IfcGeom::convert(reinterpret_pointer_cast<IfcSchema::IfcPolygonalBoundedHalfSpace,IfcSchema::IfcHalfSpaceSolid>(l),halfspace) ) return false;
|
||||
TopoDS_Wire wire;
|
||||
if ( ! IfcGeom::convert_wire(l->PolygonalBoundary(),wire) || ! wire.Closed() ) return false;
|
||||
gp_Trsf trsf;
|
||||
convert(l->Position(),trsf);
|
||||
TopoDS_Shape prism = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,200));
|
||||
gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-100.0));
|
||||
prism.Move(down*trsf);
|
||||
prism.Move(trsf*down);
|
||||
shape = BRepAlgoAPI_Common(halfspace,prism);
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcShellBasedSurfaceModel::ptr l, ShapeList& shapes) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcShellBasedSurfaceModel::ptr l, IfcRepresentationShapeItems& shapes) {
|
||||
IfcUtil::IfcAbstractSelect::list shells = l->SbsmBoundary();
|
||||
const SurfaceStyle* collective_style = get_style(l);
|
||||
for( IfcUtil::IfcAbstractSelect::it it = shells->begin(); it != shells->end(); ++ it ) {
|
||||
TopoDS_Shape s;
|
||||
if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s) ) {
|
||||
shapes.push_back(LocationShape(new gp_GTrsf(),shape_id));
|
||||
const SurfaceStyle* shell_style = 0;
|
||||
if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) {
|
||||
shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
|
||||
}
|
||||
if (IfcGeom::convert_shape(*it,s)) {
|
||||
shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcBooleanClippingResult::ptr l, TopoDS_Shape& shape) {
|
||||
TopoDS_Shape s1, s2;
|
||||
TopoDS_Wire boundary_wire;
|
||||
Ifc2x3::IfcBooleanOperand operand2 = l->SecondOperand();
|
||||
bool is_halfspace = operand2->is(Ifc2x3::Type::IfcHalfSpaceSolid);
|
||||
bool is_bounded = operand2->is(Ifc2x3::Type::IfcPolygonalBoundedHalfSpace);
|
||||
bool is_convex_bound = false;
|
||||
IfcSchema::IfcBooleanOperand operand1 = l->FirstOperand();
|
||||
IfcSchema::IfcBooleanOperand operand2 = l->SecondOperand();
|
||||
bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);
|
||||
|
||||
if ( ! IfcGeom::convert_shape(l->FirstOperand(),s1) )
|
||||
if ( ! IfcGeom::convert_shape(operand1,s1) )
|
||||
return false;
|
||||
|
||||
const double first_operand_volume = shape_volume(s1);
|
||||
@@ -166,13 +172,6 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( is_bounded ) {
|
||||
Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr ifc_bounded_halfspace =
|
||||
(Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr) operand2;
|
||||
IfcGeom::convert_wire(ifc_bounded_halfspace->PolygonalBoundary(),boundary_wire);
|
||||
is_convex_bound = is_convex(boundary_wire);
|
||||
}
|
||||
|
||||
if ( ! is_halfspace ) {
|
||||
const double second_operand_volume = shape_volume(s2);
|
||||
if ( second_operand_volume <= ALMOST_ZERO )
|
||||
@@ -180,102 +179,19 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
}
|
||||
|
||||
bool valid_cut = false;
|
||||
if ( !is_bounded || !is_convex_bound ) {
|
||||
BRepAlgoAPI_Cut brep_cut(s1,s2);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
if ( !valid_cut && !is_bounded ) {
|
||||
Ifc2x3::IfcHalfSpaceSolid::ptr ifc_halfspace = (Ifc2x3::IfcHalfSpaceSolid::ptr) operand2;
|
||||
Ifc2x3::IfcSurface::ptr surface = ifc_halfspace->BaseSurface();
|
||||
if ( surface->is(Ifc2x3::Type::IfcPlane) ) {
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcSurface,Ifc2x3::IfcPlane>(surface),pln);
|
||||
gp_Pnt pnt = pln.Location();
|
||||
bool reverse = ifc_halfspace->AgreementFlag();
|
||||
gp_Vec direction = pln.Axis().Direction();
|
||||
if ( reverse ) direction *= -1;
|
||||
pnt.Translate(direction);
|
||||
pln.SetLocation(pln.Location().Translated(direction * -0.0001));
|
||||
TopoDS_Shape halfspace = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
BRepAlgoAPI_Cut brep_cut(s1,s2);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
|
||||
BRepAlgoAPI_Cut brep_cut(s1,halfspace);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
Logger::Message(Logger::LOG_WARNING,"Slightly nudged the SecondOperand of:",l->entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr ifc_bounded_halfspace =
|
||||
(Ifc2x3::IfcPolygonalBoundedHalfSpace::ptr) operand2;
|
||||
gp_Trsf trsf;
|
||||
convert(ifc_bounded_halfspace->Position(),trsf);
|
||||
TopoDS_Shape face = BRepBuilderAPI_MakeFace(boundary_wire).Face();
|
||||
TopoDS_Shape prism = BRepPrimAPI_MakePrism (boundary_wire,gp_Vec(0,0,1),1);
|
||||
prism.Move(trsf);
|
||||
face.Move(trsf);
|
||||
|
||||
gp_Pln pln = plane_from_face(TopoDS::Face(face));
|
||||
gp_Pnt pnt = point_above_plane(pln,ifc_bounded_halfspace->AgreementFlag());
|
||||
|
||||
TopoDS_Shape halfspace;
|
||||
Ifc2x3::IfcHalfSpaceSolid::ptr ifc_halfspace = (Ifc2x3::IfcHalfSpaceSolid::ptr) operand2;
|
||||
if ( ! IfcGeom::convert(ifc_halfspace,halfspace) ) return false;
|
||||
|
||||
TopoDS_Shape subtraction_volume = s1;
|
||||
double subtraction_volume_volume = shape_volume(subtraction_volume);
|
||||
|
||||
const double minimal_substraction_difference = subtraction_volume_volume * 0.0001;
|
||||
|
||||
BRepAlgoAPI_Common brep_common(subtraction_volume,halfspace);
|
||||
if ( brep_common.IsDone() ) {
|
||||
TopoDS_Shape brep_common_shape = brep_common;
|
||||
bool is_valid = BRepCheck_Analyzer(brep_common_shape).IsValid() != 0;
|
||||
double new_subtraction_volume_volume = shape_volume(brep_common_shape);
|
||||
double subtraction_volume_difference = subtraction_volume_volume - new_subtraction_volume_volume;
|
||||
if ( is_valid && subtraction_volume_difference > minimal_substraction_difference ) {
|
||||
subtraction_volume = brep_common_shape;
|
||||
subtraction_volume_volume = new_subtraction_volume_volume;
|
||||
}
|
||||
}
|
||||
|
||||
TopExp_Explorer exp(prism,TopAbs_FACE);
|
||||
while ( exp.More() ) {
|
||||
TopoDS_Shape halfspace = halfspace_from_plane(plane_from_face(TopoDS::Face(exp.Current())),pnt);
|
||||
BRepAlgoAPI_Common brep_common(subtraction_volume,halfspace);
|
||||
if ( brep_common.IsDone() ) {
|
||||
TopoDS_Shape brep_common_shape = brep_common;
|
||||
bool is_valid = BRepCheck_Analyzer(brep_common_shape).IsValid() != 0;
|
||||
double new_subtraction_volume_volume = shape_volume(brep_common_shape);
|
||||
double subtraction_volume_difference = subtraction_volume_volume - new_subtraction_volume_volume;
|
||||
if ( is_valid && subtraction_volume_difference > minimal_substraction_difference ) {
|
||||
subtraction_volume = brep_common_shape;
|
||||
subtraction_volume_volume = new_subtraction_volume_volume;
|
||||
}
|
||||
}
|
||||
exp.Next();
|
||||
}
|
||||
|
||||
BRepAlgoAPI_Cut brep_cut(s1,subtraction_volume);
|
||||
if ( brep_cut.IsDone() ) {
|
||||
TopoDS_Shape result = brep_cut;
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
ShapeFix_Shape fix(result);
|
||||
fix.Perform();
|
||||
result = fix.Shape();
|
||||
|
||||
bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
|
||||
if ( is_valid ) {
|
||||
shape = result;
|
||||
valid_cut = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( valid_cut ) {
|
||||
@@ -288,10 +204,9 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
|
||||
Ifc2x3::IfcFace::list faces = l->CfsFaces();
|
||||
bool IfcGeom::convert(const IfcSchema::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
|
||||
IfcSchema::IfcFace::list faces = l->CfsFaces();
|
||||
bool facesAdded = false;
|
||||
const unsigned int num_faces = faces->Size();
|
||||
if ( num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) {
|
||||
@@ -299,7 +214,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
for( IfcSchema::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
TopoDS_Face face;
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
|
||||
builder.Add(face);
|
||||
@@ -320,7 +235,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
TopoDS_Compound compound;
|
||||
BRep_Builder builder;
|
||||
builder.MakeCompound(compound);
|
||||
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
for( IfcSchema::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
|
||||
TopoDS_Face face;
|
||||
if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) {
|
||||
builder.Add(compound,face);
|
||||
@@ -334,52 +249,55 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcMappedItem::ptr l, IfcRepresentationShapeItems& shapes) {
|
||||
gp_GTrsf gtrsf;
|
||||
Ifc2x3::IfcCartesianTransformationOperator::ptr transform = l->MappingTarget();
|
||||
if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
|
||||
Ifc2x3::IfcCartesianTransformationOperator3DnonUniform>(transform),gtrsf);
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
|
||||
IfcSchema::IfcCartesianTransformationOperator::ptr transform = l->MappingTarget();
|
||||
if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3DnonUniform) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcSchema::IfcCartesianTransformationOperator,
|
||||
IfcSchema::IfcCartesianTransformationOperator3DnonUniform>(transform),gtrsf);
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2DnonUniform) ) {
|
||||
return false;
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator3D) ) {
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator3D) ) {
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
|
||||
Ifc2x3::IfcCartesianTransformationOperator3D>(transform),trsf);
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcSchema::IfcCartesianTransformationOperator,
|
||||
IfcSchema::IfcCartesianTransformationOperator3D>(transform),trsf);
|
||||
gtrsf = trsf;
|
||||
} else if ( transform->is(Ifc2x3::Type::IfcCartesianTransformationOperator2D) ) {
|
||||
} else if ( transform->is(IfcSchema::Type::IfcCartesianTransformationOperator2D) ) {
|
||||
gp_Trsf2d trsf_2d;
|
||||
IfcGeom::convert(reinterpret_pointer_cast<Ifc2x3::IfcCartesianTransformationOperator,
|
||||
Ifc2x3::IfcCartesianTransformationOperator2D>(transform),trsf_2d);
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcSchema::IfcCartesianTransformationOperator,
|
||||
IfcSchema::IfcCartesianTransformationOperator2D>(transform),trsf_2d);
|
||||
gtrsf = (gp_Trsf) trsf_2d;
|
||||
}
|
||||
Ifc2x3::IfcRepresentationMap::ptr map = l->MappingSource();
|
||||
Ifc2x3::IfcAxis2Placement placement = map->MappingOrigin();
|
||||
IfcSchema::IfcRepresentationMap::ptr map = l->MappingSource();
|
||||
IfcSchema::IfcAxis2Placement placement = map->MappingOrigin();
|
||||
gp_Trsf trsf;
|
||||
if (placement->is(Ifc2x3::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement3D*)placement,trsf);
|
||||
if (placement->is(IfcSchema::Type::IfcAxis2Placement3D)) {
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement3D*)placement,trsf);
|
||||
} else {
|
||||
gp_Trsf2d trsf_2d;
|
||||
IfcGeom::convert((Ifc2x3::IfcAxis2Placement2D*)placement,trsf_2d);
|
||||
IfcGeom::convert((IfcSchema::IfcAxis2Placement2D*)placement,trsf_2d);
|
||||
trsf = trsf_2d;
|
||||
}
|
||||
gtrsf.Multiply(trsf);
|
||||
const unsigned int previous_size = (const unsigned int) shapes.size();
|
||||
bool b = IfcGeom::convert_shapes(map->MappedRepresentation(),shapes);
|
||||
for ( unsigned int i = previous_size; i < shapes.size(); ++ i ) {
|
||||
shapes[i].first->Multiply(gtrsf);
|
||||
shapes[i].append(gtrsf);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcShapeRepresentation::ptr l, ShapeList& shapes) {
|
||||
Ifc2x3::IfcRepresentationItem::list items = l->Items();
|
||||
|
||||
bool IfcGeom::convert(const IfcSchema::IfcShapeRepresentation::ptr l, IfcRepresentationShapeItems& shapes) {
|
||||
IfcSchema::IfcRepresentationItem::list items = l->Items();
|
||||
if ( ! items->Size() ) return false;
|
||||
for ( Ifc2x3::IfcRepresentationItem::it it = items->begin(); it != items->end(); ++ it ) {
|
||||
if ( IfcGeom::is_shape_collection(*it) ) IfcGeom::convert_shapes(*it,shapes);
|
||||
for ( IfcSchema::IfcRepresentationItem::it it = items->begin(); it != items->end(); ++ it ) {
|
||||
IfcSchema::IfcRepresentationItem* representation_item = *it;
|
||||
if ( IfcGeom::is_shape_collection(representation_item) ) IfcGeom::convert_shapes(*it,shapes);
|
||||
else {
|
||||
TopoDS_Shape s;
|
||||
if ( const TopoDS_Shape* shape_id = IfcGeom::convert_shape(*it,s))
|
||||
shapes.push_back(LocationShape(new gp_GTrsf(),shape_id));
|
||||
if (IfcGeom::convert_shape(representation_item,s)) {
|
||||
shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
|
||||
bool IfcGeom::convert(const IfcSchema::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) {
|
||||
if ( IfcGeom::GetValue(GV_PLANEANGLE_UNIT)<0 ) {
|
||||
Logger::Message(Logger::LOG_WARNING,"Creating a composite curve without unit information:",l->entity);
|
||||
|
||||
@@ -107,7 +107,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
} catch (...) {}
|
||||
|
||||
// Restore to unknown unit state
|
||||
//IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0);
|
||||
IfcGeom::SetValue(GV_PLANEANGLE_UNIT,-1.0);
|
||||
|
||||
if ( succes_degrees && ! succes_radians ) {
|
||||
use_degrees = true;
|
||||
@@ -135,12 +135,14 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
Logger::Message(Logger::LOG_NOTICE,"Used degrees to create composite curve");
|
||||
wire = wire_degrees;
|
||||
}
|
||||
|
||||
return use_radians || use_degrees;
|
||||
}
|
||||
Ifc2x3::IfcCompositeCurveSegment::list segments = l->Segments();
|
||||
IfcSchema::IfcCompositeCurveSegment::list segments = l->Segments();
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
//TopoDS_Vertex last_vertex;
|
||||
for( Ifc2x3::IfcCompositeCurveSegment::it it = segments->begin(); it != segments->end(); ++ it ) {
|
||||
const Ifc2x3::IfcCurve::ptr curve = (*it)->ParentCurve();
|
||||
for( IfcSchema::IfcCompositeCurveSegment::it it = segments->begin(); it != segments->end(); ++ it ) {
|
||||
const IfcSchema::IfcCurve::ptr curve = (*it)->ParentCurve();
|
||||
TopoDS_Wire wire2;
|
||||
if ( ! IfcGeom::convert_wire(curve,wire2) ) {
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert curve:",curve->entity);
|
||||
@@ -169,13 +171,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire)
|
||||
wire = w.Wire();
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
Ifc2x3::IfcCurve::ptr basis_curve = l->BasisCurve();
|
||||
bool isConic = basis_curve->is(Ifc2x3::Type::IfcConic);
|
||||
bool IfcGeom::convert(const IfcSchema::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
IfcSchema::IfcCurve::ptr basis_curve = l->BasisCurve();
|
||||
bool isConic = basis_curve->is(IfcSchema::Type::IfcConic);
|
||||
double parameterFactor = isConic ? IfcGeom::GetValue(GV_PLANEANGLE_UNIT) : IfcGeom::GetValue(GV_LENGTH_UNIT);
|
||||
Handle(Geom_Curve) curve;
|
||||
if ( ! IfcGeom::convert_curve(basis_curve,curve) ) return false;
|
||||
bool trim_cartesian = l->MasterRepresentation() == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||
bool trim_cartesian = l->MasterRepresentation() == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN;
|
||||
IfcUtil::IfcAbstractSelect::list trims1 = l->Trim1();
|
||||
IfcUtil::IfcAbstractSelect::list trims2 = l->Trim2();
|
||||
bool trimmed1 = false;
|
||||
@@ -188,22 +190,22 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = trims1->begin(); it != trims1->end(); it ++ ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr i = *it;
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[sense_agreement] );
|
||||
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcSchema::IfcCartesianPoint>(i), pnts[sense_agreement] );
|
||||
has_pnts[sense_agreement] = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
|
||||
const double value = *((IfcUtil::IfcBaseEntity*)i)->entity->getArgument(0);
|
||||
flts[sense_agreement] = value * parameterFactor;
|
||||
has_flts[sense_agreement] = true;
|
||||
}
|
||||
}
|
||||
for ( IfcUtil::IfcAbstractSelect::it it = trims2->begin(); it != trims2->end(); it ++ ) {
|
||||
const IfcUtil::IfcAbstractSelect::ptr i = *it;
|
||||
if ( i->is(Ifc2x3::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcCartesianPoint>(i), pnts[1-sense_agreement] );
|
||||
if ( i->is(IfcSchema::Type::IfcCartesianPoint) ) {
|
||||
IfcGeom::convert(reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcSchema::IfcCartesianPoint>(i), pnts[1-sense_agreement] );
|
||||
has_pnts[1-sense_agreement] = true;
|
||||
} else if ( i->is(Ifc2x3::Type::IfcParameterValue) ) {
|
||||
const double value = *reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,IfcUtil::IfcArgumentSelect>(i)->wrappedValue();
|
||||
} else if ( i->is(IfcSchema::Type::IfcParameterValue) ) {
|
||||
const double value = *((IfcUtil::IfcBaseEntity*)i)->entity->getArgument(0);
|
||||
flts[1-sense_agreement] = value * parameterFactor;
|
||||
has_flts[1-sense_agreement] = true;
|
||||
}
|
||||
@@ -232,6 +234,15 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
}
|
||||
}
|
||||
if ( (!trim_cartesian || trim_cartesian_failed) && (has_flts[0] && has_flts[1]) ) {
|
||||
// The Geom_Line is constructed from a gp_Pnt and gp_Dir, whereas the IfcLine
|
||||
// is defined by an IfcCartesianPoint and an IfcVector with Magnitude. Because
|
||||
// the vector is normalised when passed to Geom_Line constructor the magnitude
|
||||
// needs to be factored in with the IfcParameterValue here.
|
||||
if ( basis_curve->is(IfcSchema::Type::IfcLine) ) {
|
||||
IfcSchema::IfcLine* line = static_cast<IfcSchema::IfcLine*>(basis_curve);
|
||||
const double magnitude = line->Dir()->Magnitude();
|
||||
flts[0] *= magnitude; flts[1] *= magnitude;
|
||||
}
|
||||
if ( isConic && ALMOST_THE_SAME(fmod(flts[1]-flts[0],(double)(M_PI*2.0)),0.0f) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(curve));
|
||||
} else {
|
||||
@@ -248,12 +259,12 @@ bool IfcGeom::convert(const Ifc2x3::IfcTrimmedCurve::ptr l, TopoDS_Wire& wire) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
Ifc2x3::IfcCartesianPoint::list points = l->Points();
|
||||
bool IfcGeom::convert(const IfcSchema::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
IfcSchema::IfcCartesianPoint::list points = l->Points();
|
||||
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
gp_Pnt P1;gp_Pnt P2;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
for( IfcSchema::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) )
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
@@ -263,13 +274,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) {
|
||||
result = w.Wire();
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(const Ifc2x3::IfcPolyLoop::ptr l, TopoDS_Wire& result) {
|
||||
Ifc2x3::IfcCartesianPoint::list points = l->Polygon();
|
||||
bool IfcGeom::convert(const IfcSchema::IfcPolyLoop::ptr l, TopoDS_Wire& result) {
|
||||
IfcSchema::IfcCartesianPoint::list points = l->Polygon();
|
||||
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
gp_Pnt P1;gp_Pnt P2;gp_Pnt F;
|
||||
int count = 0;
|
||||
for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
for( IfcSchema::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
IfcGeom::convert(*it,P2);
|
||||
if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) {
|
||||
w.Add(BRepBuilderAPI_MakeEdge(P1,P2));
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace IfcGeom {
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Ifc2x3;
|
||||
using namespace IfcSchema;
|
||||
using namespace IfcUtil;
|
||||
|
||||
bool IfcGeom::convert_shapes(const IfcBaseClass* l, ShapeList& r) {
|
||||
bool IfcGeom::convert_shapes(const IfcBaseClass* l, IfcRepresentationShapeItems& r) {
|
||||
#include "IfcRegisterConvertShapes.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return false;
|
||||
@@ -40,13 +40,21 @@ bool IfcGeom::is_shape_collection(const IfcBaseClass* l) {
|
||||
#include "IfcRegisterIsShapeCollection.h"
|
||||
return false;
|
||||
}
|
||||
const TopoDS_Shape* IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) {
|
||||
bool IfcGeom::convert_shape(const IfcBaseClass* l, TopoDS_Shape& r) {
|
||||
const unsigned int id = l->entity->id();
|
||||
bool success = false;
|
||||
bool processed = false;
|
||||
std::map<int,TopoDS_Shape>::const_iterator it = Cache::Shape.find(id);
|
||||
if ( it != Cache::Shape.end() ) { r = it->second; return &(it->second); }
|
||||
if ( it != Cache::Shape.end() ) { r = it->second; return true; }
|
||||
#include "IfcRegisterConvertShape.h"
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
return 0;
|
||||
if ( processed ) {
|
||||
const double precision = IfcGeom::GetValue(GV_PRECISION);
|
||||
IfcGeom::apply_tolerance(r, precision);
|
||||
Cache::Shape[id] = r;
|
||||
} else {
|
||||
Logger::Message(Logger::LOG_ERROR,"No operation defined for:",l->entity);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
bool IfcGeom::convert_wire(const IfcBaseClass* l, TopoDS_Wire& r) {
|
||||
#include "IfcRegisterConvertWire.h"
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
using namespace Ifc2x3;
|
||||
using namespace IfcSchema;
|
||||
|
||||
SHAPES(IfcShellBasedSurfaceModel);
|
||||
SHAPES(IfcFaceBasedSurfaceModel);
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define SHAPE(T) \
|
||||
if ( l->is(T::Class()) ) { \
|
||||
if ( !processed && l->is(T::Class()) ) { \
|
||||
processed = true; \
|
||||
try { \
|
||||
if ( convert((T*)l,r) ) { \
|
||||
Cache::Shape[id] = r; \
|
||||
return &(Cache::Shape[id]); \
|
||||
success = true; \
|
||||
} \
|
||||
} catch(...) { } \
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||
return 0; \
|
||||
if ( !success) { \
|
||||
Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
#include "IfcRegisterDef.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "IfcRegisterUndef.h"
|
||||
#define CLASS(T,V) bool convert(const T::ptr L, V& r);
|
||||
#define SHAPES(T) CLASS(T,ShapeList)
|
||||
#define SHAPES(T) CLASS(T,IfcRepresentationShapeItems)
|
||||
#define SHAPE(T) CLASS(T,TopoDS_Shape)
|
||||
#define WIRE(T) CLASS(T,TopoDS_Wire)
|
||||
#define FACE(T) CLASS(T,TopoDS_Face)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCSHAPELIST_H
|
||||
#define IFCSHAPELIST_H
|
||||
|
||||
#include <gp_GTrsf.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
||||
|
||||
namespace IfcGeom {
|
||||
class IfcRepresentationShapeItem {
|
||||
private:
|
||||
gp_GTrsf placement;
|
||||
TopoDS_Shape shape;
|
||||
const SurfaceStyle* style;
|
||||
public:
|
||||
IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape, const SurfaceStyle* style)
|
||||
: placement(placement), shape(shape), style(style) {}
|
||||
IfcRepresentationShapeItem(const gp_GTrsf& placement, const TopoDS_Shape& shape)
|
||||
: placement(placement), shape(shape), style(0) {}
|
||||
IfcRepresentationShapeItem(const TopoDS_Shape& shape, const SurfaceStyle* style)
|
||||
: shape(shape), style(style) {}
|
||||
IfcRepresentationShapeItem(const TopoDS_Shape& shape)
|
||||
: shape(shape), style(0) {}
|
||||
void append(const gp_GTrsf& trsf) { placement.Multiply(trsf); }
|
||||
void prepend(const gp_GTrsf& trsf) { placement.PreMultiply(trsf); }
|
||||
const TopoDS_Shape& Shape() const { return shape; }
|
||||
const gp_GTrsf& Placement() const { return placement; }
|
||||
bool hasStyle() const { return style != 0; }
|
||||
const SurfaceStyle& Style() const { return *style; }
|
||||
};
|
||||
typedef std::vector<IfcRepresentationShapeItem> IfcRepresentationShapeItems;
|
||||
}
|
||||
#endif
|
||||
+11
-11
@@ -27,7 +27,7 @@
|
||||
#include "org_ifcopenshell_IfcOpenShellModel.h"
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
bool has_more = false;
|
||||
static bool has_more = false;
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_org_ifcopenshell_IfcOpenShellModel_getGeometry (JNIEnv * env, jobject) {
|
||||
if ( ! has_more ) return 0;
|
||||
@@ -37,19 +37,19 @@ JNIEXPORT jobject JNICALL Java_org_ifcopenshell_IfcOpenShellModel_getGeometry (J
|
||||
if ( ! jconstructor ) return 0;
|
||||
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
|
||||
|
||||
jstring name = env->NewStringUTF(o->name.c_str());
|
||||
jstring type = env->NewStringUTF(o->type.c_str());
|
||||
jstring guid = env->NewStringUTF(o->guid.c_str());
|
||||
jstring name = env->NewStringUTF(o->name().c_str());
|
||||
jstring type = env->NewStringUTF(o->type().c_str());
|
||||
jstring guid = env->NewStringUTF(o->guid().c_str());
|
||||
|
||||
jintArray indices = env->NewIntArray(o->mesh->faces.size());
|
||||
jfloatArray positions = env->NewFloatArray(o->mesh->verts.size());
|
||||
jfloatArray normals = env->NewFloatArray(o->mesh->normals.size());
|
||||
jintArray indices = env->NewIntArray(o->mesh().faces().size());
|
||||
jfloatArray positions = env->NewFloatArray(o->mesh().verts().size());
|
||||
jfloatArray normals = env->NewFloatArray(o->mesh().normals().size());
|
||||
|
||||
env->SetIntArrayRegion(indices,0,o->mesh->faces.size(),(jint*) &o->mesh->faces[0]);
|
||||
env->SetFloatArrayRegion(positions,0,o->mesh->verts.size(),(jfloat*) &o->mesh->verts[0]);
|
||||
env->SetFloatArrayRegion(normals,0,o->mesh->normals.size(),(jfloat*) &o->mesh->normals[0]);
|
||||
env->SetIntArrayRegion(indices,0,o->mesh().faces().size(),(jint*) &o->mesh().faces()[0]);
|
||||
env->SetFloatArrayRegion(positions,0,o->mesh().verts().size(),(jfloat*) &o->mesh().verts()[0]);
|
||||
env->SetFloatArrayRegion(normals,0,o->mesh().normals().size(),(jfloat*) &o->mesh().normals()[0]);
|
||||
|
||||
jobject return_obj = env->NewObject(class_def, jconstructor, o->id, name, type, guid, indices, positions, normals);
|
||||
jobject return_obj = env->NewObject(class_def, jconstructor, o->id(), name, type, guid, indices, positions, normals);
|
||||
|
||||
env->DeleteLocalRef(name);
|
||||
env->DeleteLocalRef(type);
|
||||
|
||||
+155
-59
@@ -17,14 +17,15 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Max.h"
|
||||
#include "stdmat.h"
|
||||
#include "istdplug.h"
|
||||
#include <Max.h>
|
||||
#include <stdmat.h>
|
||||
#include <istdplug.h>
|
||||
|
||||
#include "../ifcmax/IfcMax.h"
|
||||
#include "../ifcmax/MaxMaterials.h"
|
||||
#include "../ifcgeom/IfcGeomObjects.h"
|
||||
|
||||
static const int NUM_MATERIAL_SLOTS = 24;
|
||||
|
||||
int controlsInit = false;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
|
||||
@@ -101,81 +102,176 @@ void IFCImp::ShowAbout(HWND hWnd) {}
|
||||
|
||||
DWORD WINAPI fn(LPVOID arg) { return 0; }
|
||||
|
||||
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) {
|
||||
#if MAX_RELEASE > 14000
|
||||
# define S(x) (TSTR::FromCStr(x.c_str()))
|
||||
#elif defined(_UNICODE)
|
||||
# define S(x) (WStr(x.c_str()))
|
||||
#else
|
||||
# define S(x) (CStr(x.c_str()))
|
||||
#endif
|
||||
|
||||
itfc->ProgressStart("Importing file...", TRUE, fn, NULL);
|
||||
Mtl* FindMaterialByName(MtlBaseLib* library, const std::string& material_name) {
|
||||
const int mat_index = library->FindMtlByName(S(material_name));
|
||||
Mtl* m = 0;
|
||||
if (mat_index != -1) {
|
||||
m = static_cast<Mtl*>((*library)[mat_index]);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Mtl* FindOrCreateMaterial(MtlBaseLib* library, Interface* max_interface, int& slot, const IfcGeomObjects::Material& material) {
|
||||
Mtl* m = FindMaterialByName(library, material.name());
|
||||
if (m == 0) {
|
||||
StdMat2* stdm = NewDefaultStdMat();
|
||||
const TimeValue t = -1;
|
||||
if (material.hasDiffuse()) {
|
||||
const double* diffuse = material.diffuse();
|
||||
stdm->SetDiffuse(Color(diffuse[0], diffuse[1], diffuse[2]),t);
|
||||
}
|
||||
if (material.hasSpecular()) {
|
||||
const double* specular = material.specular();
|
||||
stdm->SetSpecular(Color(specular[0], specular[1], specular[2]),t);
|
||||
}
|
||||
if (material.hasSpecularity()) {
|
||||
stdm->SetShininess(material.specularity(), t);
|
||||
}
|
||||
if (material.hasTransparency()) {
|
||||
stdm->SetOpacity(1.0 - material.transparency(), t);
|
||||
}
|
||||
m = stdm;
|
||||
m->SetName(S(material.name()));
|
||||
library->Add(m);
|
||||
if (slot < NUM_MATERIAL_SLOTS) {
|
||||
max_interface->PutMtlToMtlEditor(m,slot++);
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Mtl* ComposeMultiMaterial(std::map<std::vector<std::string>, Mtl*>& multi_mats, MtlBaseLib* library, Interface* max_interface, int& slot, const std::vector<IfcGeomObjects::Material>& materials, const std::string& object_type, const std::vector<int>& material_ids) {
|
||||
std::vector<std::string> material_names;
|
||||
bool needs_default = std::find(material_ids.begin(), material_ids.end(), -1) != material_ids.end();
|
||||
if (needs_default) {
|
||||
material_names.push_back(object_type);
|
||||
}
|
||||
for (auto it = materials.begin(); it != materials.end(); ++it) {
|
||||
material_names.push_back(it->name());
|
||||
}
|
||||
Mtl* default_material = 0;
|
||||
if (needs_default) {
|
||||
default_material = FindMaterialByName(library, object_type);
|
||||
if (default_material == 0) {
|
||||
default_material = NewDefaultStdMat();
|
||||
default_material->SetName(S(object_type));
|
||||
library->Add(default_material);
|
||||
if (slot < NUM_MATERIAL_SLOTS) {
|
||||
max_interface->PutMtlToMtlEditor(default_material, slot++);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (material_names.size() == 1) {
|
||||
if (needs_default) {
|
||||
return default_material;
|
||||
} else {
|
||||
return FindOrCreateMaterial(library, max_interface, slot, *materials.begin());
|
||||
}
|
||||
}
|
||||
std::map<std::vector<std::string>, Mtl*>::const_iterator i = multi_mats.find(material_names);
|
||||
if (i != multi_mats.end()) {
|
||||
return i->second;
|
||||
}
|
||||
MultiMtl* multi_mat = NewDefaultMultiMtl();
|
||||
multi_mat->SetNumSubMtls(material_names.size());
|
||||
int mtl_id = 0;
|
||||
if (needs_default) {
|
||||
multi_mat->SetSubMtlAndName(mtl_id ++, default_material, default_material->GetName());
|
||||
}
|
||||
for (auto it = materials.begin(); it != materials.end(); ++it) {
|
||||
Mtl* mtl = FindOrCreateMaterial(library, max_interface, slot, *it);
|
||||
multi_mat->SetSubMtl(mtl_id ++, mtl);
|
||||
}
|
||||
library->Add(multi_mat);
|
||||
if (slot < NUM_MATERIAL_SLOTS) {
|
||||
max_interface->PutMtlToMtlEditor(multi_mat,slot++);
|
||||
}
|
||||
multi_mats.insert(std::pair<std::vector<std::string>, Mtl*>(material_names, multi_mat));
|
||||
return multi_mat;
|
||||
}
|
||||
|
||||
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) {
|
||||
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true);
|
||||
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
|
||||
|
||||
if ( ! IfcGeomObjects::Init((char*)name,0,0) ) return false;
|
||||
#ifdef _UNICODE
|
||||
int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0);
|
||||
char* fn_mb = new char[fn_buffer_size];
|
||||
WideCharToMultiByte(CP_UTF8, 0, name, -1, fn_mb, fn_buffer_size, 0, 0);
|
||||
#else
|
||||
const char* fn_mb = name;
|
||||
#endif
|
||||
|
||||
if ( ! IfcGeomObjects::Init(fn_mb,0,0) ) return false;
|
||||
|
||||
itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL);
|
||||
|
||||
//std::map<int, TriObject*> dict;
|
||||
MtlBaseLib* mats = itfc->GetSceneMtls();
|
||||
int slot = mats->Count();
|
||||
|
||||
std::map<std::vector<std::string>, Mtl*> material_cache;
|
||||
|
||||
do{
|
||||
|
||||
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
|
||||
|
||||
Mtl *m;
|
||||
const int matIndex = mats->FindMtlByName(MSTR(o->type.c_str()));
|
||||
if ( matIndex == -1 ) {
|
||||
StdMat2* stdm = GetMaterial(o->type);
|
||||
m = stdm;
|
||||
m->SetName(o->type.c_str());
|
||||
mats->Add(m);
|
||||
itfc->PutMtlToMtlEditor(m,slot++);
|
||||
} else {
|
||||
m = static_cast<Mtl*>((*mats)[matIndex]);
|
||||
}
|
||||
|
||||
// This mapping is useless for now, because this even in case
|
||||
// meshes entities in IFC share the same representation elements
|
||||
// they will never be given the same id.
|
||||
// TODO: Fix this!
|
||||
// std::map<int, TriObject*>::const_iterator it = dict.find(o->mesh->id);
|
||||
|
||||
TriObject* tri;
|
||||
// if ( it == dict.end() ) {
|
||||
tri = CreateNewTriObject();
|
||||
const int numVerts = o->mesh->verts.size()/3;
|
||||
tri->mesh.setNumVerts(numVerts);
|
||||
for( int i = 0; i < numVerts; i ++ ) {
|
||||
tri->mesh.setVert(i,o->mesh->verts[3*i+0],o->mesh->verts[3*i+1],o->mesh->verts[3*i+2]);
|
||||
}
|
||||
const int numFaces = o->mesh->faces.size()/3;
|
||||
tri->mesh.setNumFaces(numFaces);
|
||||
for( int i = 0; i < numFaces; i ++ ) {
|
||||
tri->mesh.faces[i].setVerts(o->mesh->faces[3*i+0],o->mesh->faces[3*i+1],o->mesh->faces[3*i+2]);
|
||||
tri->mesh.faces[i].setEdgeVisFlags(o->mesh->edges[3*i+0],o->mesh->edges[3*i+1],o->mesh->edges[3*i+2]);
|
||||
}
|
||||
TSTR o_type = S(o->type());
|
||||
TSTR o_guid = S(o->guid());
|
||||
|
||||
Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->mesh().materials(), o->type(), o->mesh().material_ids());
|
||||
|
||||
TriObject* tri = CreateNewTriObject();
|
||||
|
||||
const int numVerts = o->mesh().verts().size()/3;
|
||||
tri->mesh.setNumVerts(numVerts);
|
||||
for( int i = 0; i < numVerts; i ++ ) {
|
||||
tri->mesh.setVert(i,o->mesh().verts()[3*i+0],o->mesh().verts()[3*i+1],o->mesh().verts()[3*i+2]);
|
||||
}
|
||||
const int numFaces = o->mesh().faces().size()/3;
|
||||
tri->mesh.setNumFaces(numFaces);
|
||||
|
||||
bool needs_default = std::find(o->mesh().material_ids().begin(), o->mesh().material_ids().end(), -1) != o->mesh().material_ids().end();
|
||||
|
||||
for( int i = 0; i < numFaces; i ++ ) {
|
||||
tri->mesh.faces[i].setVerts(o->mesh().faces()[3*i+0],o->mesh().faces()[3*i+1],o->mesh().faces()[3*i+2]);
|
||||
tri->mesh.faces[i].setEdgeVisFlags(o->mesh().edges()[3*i+0],o->mesh().edges()[3*i+1],o->mesh().edges()[3*i+2]);
|
||||
MtlID mtlid = o->mesh().material_ids()[i];
|
||||
if (needs_default) mtlid ++;
|
||||
tri->mesh.faces[i].setMatID(mtlid);
|
||||
}
|
||||
|
||||
tri->mesh.buildNormals();
|
||||
// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
|
||||
// properly oriented normals. Using only the line below will result in a consistent
|
||||
// orientation of normals accross shells, but not always oriented towards the
|
||||
// outside.
|
||||
// tri->mesh.UnifyNormals(false);
|
||||
tri->mesh.BuildStripsAndEdges();
|
||||
tri->mesh.InvalidateTopologyCache();
|
||||
tri->mesh.InvalidateGeomCache();
|
||||
|
||||
// dict[o->mesh->id] = tri;
|
||||
// } else {
|
||||
// tri = (*it).second;
|
||||
// }
|
||||
tri->mesh.buildNormals();
|
||||
// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
|
||||
// properly oriented normals. Using only the line below will result in a consistent
|
||||
// orientation of normals accross shells, but not always oriented towards the
|
||||
// outside.
|
||||
// tri->mesh.UnifyNormals(false);
|
||||
tri->mesh.BuildStripsAndEdges();
|
||||
tri->mesh.InvalidateTopologyCache();
|
||||
tri->mesh.InvalidateGeomCache();
|
||||
|
||||
ImpNode* node = impitfc->CreateNode();
|
||||
node->Reference(tri);
|
||||
node->SetName(o->guid.c_str());
|
||||
node->GetINode()->SetMtl(m);
|
||||
node->SetTransform(0,Matrix3 ( Point3(o->matrix[0],o->matrix[1],o->matrix[2]),Point3(o->matrix[3],o->matrix[4],o->matrix[5]),
|
||||
Point3(o->matrix[6],o->matrix[7],o->matrix[8]),Point3(o->matrix[9],o->matrix[10],o->matrix[11]) ));
|
||||
node->SetName(o_guid);
|
||||
node->GetINode()->Hide(o->type() == "IfcOpeningElement" || o->type() == "IfcSpace");
|
||||
if (m) {
|
||||
node->GetINode()->SetMtl(m);
|
||||
}
|
||||
node->SetTransform(0,Matrix3 ( Point3(o->matrix()[0],o->matrix()[1],o->matrix()[2]),Point3(o->matrix()[3],o->matrix()[4],o->matrix()[5]),
|
||||
Point3(o->matrix()[6],o->matrix()[7],o->matrix()[8]),Point3(o->matrix()[9],o->matrix()[10],o->matrix()[11]) ));
|
||||
impitfc->AddNodeToScene(node);
|
||||
|
||||
itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,"");
|
||||
itfc->ProgressUpdate(IfcGeomObjects::Progress(),true,_T(""));
|
||||
|
||||
} while ( IfcGeomObjects::Next() );
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef ARGUMENTTYPE_H
|
||||
#define ARGUMENTTYPE_H
|
||||
|
||||
namespace IfcUtil {
|
||||
enum ArgumentType {
|
||||
Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENUMERATION, Argument_UNKNOWN
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+2937
-2770
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,11 @@
|
||||
#ifndef IFC2X3RT_H
|
||||
#define IFC2X3RT_H
|
||||
|
||||
#include "../ifcparse/ArgumentType.h"
|
||||
#define IfcSchema Ifc2x3
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace Ifc2x3 {
|
||||
namespace Type {
|
||||
@@ -38,7 +42,7 @@ namespace Type {
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+4517
-3734
File diff suppressed because one or more lines are too long
+5451
-5298
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from IFC4.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFC4RT_H
|
||||
#define IFC4RT_H
|
||||
|
||||
#define IfcSchema Ifc4
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace Ifc4 {
|
||||
namespace Type {
|
||||
int GetAttributeCount(Enum t);
|
||||
int GetAttributeIndex(Enum t, const std::string& a);
|
||||
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
|
||||
const std::string& GetAttributeName(Enum t, unsigned char a);
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
#endif
|
||||
+15752
File diff suppressed because one or more lines are too long
+54630
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -364,4 +364,4 @@ IfcCharacterEncoder::operator std::string() {
|
||||
#ifdef HAVE_ICU
|
||||
UErrorCode IfcCharacterEncoder::status = U_ZERO_ERROR;
|
||||
UConverter* IfcCharacterEncoder::converter = 0;
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCENTITYDESCRIPTOR_H
|
||||
#define IFCENTITYDESCRIPTOR_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
|
||||
namespace IfcUtil {
|
||||
|
||||
class IfcEnumerationDescriptor {
|
||||
private:
|
||||
IfcSchema::Type::Enum type;
|
||||
std::vector<std::string> values;
|
||||
public:
|
||||
IfcEnumerationDescriptor(IfcSchema::Type::Enum type, const std::vector<std::string>& values)
|
||||
: type(type), values(values) {}
|
||||
std::pair<const char*, int> getIndex(const std::string& value) const {
|
||||
std::vector<std::string>::const_iterator it = std::find(values.begin(), values.end(), value);
|
||||
if (it != values.end()) {
|
||||
return std::make_pair(it->c_str(), std::distance(it, values.begin()));
|
||||
} else {
|
||||
throw IfcParse::IfcException("Invalid enumeration value");
|
||||
}
|
||||
}
|
||||
const std::vector<std::string>& getValues() {
|
||||
return values;
|
||||
}
|
||||
IfcSchema::Type::Enum getType() {
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
class IfcEntityDescriptor {
|
||||
public:
|
||||
class IfcArgumentDescriptor
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
bool optional;
|
||||
ArgumentType argument_type;
|
||||
IfcSchema::Type::Enum data_type;
|
||||
IfcArgumentDescriptor(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type)
|
||||
: name(name), optional(optional), argument_type(argument_type), data_type(data_type) {}
|
||||
};
|
||||
private:
|
||||
IfcSchema::Type::Enum type;
|
||||
IfcEntityDescriptor* parent;
|
||||
std::vector<IfcArgumentDescriptor> arguments;
|
||||
unsigned argument_start() const {
|
||||
return parent ? parent->getArgumentCount() : 0;
|
||||
}
|
||||
const IfcArgumentDescriptor& get_argument(unsigned i) const {
|
||||
if (i < arguments.size()) return arguments[i];
|
||||
else throw IfcParse::IfcException("Argument out of range");
|
||||
}
|
||||
public:
|
||||
IfcEntityDescriptor(IfcSchema::Type::Enum type, IfcEntityDescriptor* parent)
|
||||
: type(type), parent(parent) {}
|
||||
void add(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type = IfcSchema::Type::ALL) {
|
||||
arguments.push_back(IfcArgumentDescriptor(name, optional, argument_type, data_type));
|
||||
}
|
||||
unsigned getArgumentCount() const {
|
||||
return (parent ? parent->getArgumentCount() : 0) + arguments.size();
|
||||
}
|
||||
const std::string& getArgumentName(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentName(i)
|
||||
: get_argument(i-a).name;
|
||||
}
|
||||
ArgumentType getArgumentType(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentType(i)
|
||||
: get_argument(i-a).argument_type;
|
||||
}
|
||||
bool getArgumentOptional(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentOptional(i)
|
||||
: get_argument(i-a).optional;
|
||||
}
|
||||
IfcSchema::Type::Enum getArgumentEnumerationClass(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentEnumerationClass(i)
|
||||
: get_argument(i-a).data_type;
|
||||
}
|
||||
unsigned getArgumentIndex(const std::string& s) const {
|
||||
unsigned a = argument_start();
|
||||
for(std::vector<IfcArgumentDescriptor>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) {
|
||||
if (i->name == s) return a;
|
||||
a++;
|
||||
}
|
||||
if (parent) return parent->getArgumentIndex(s);
|
||||
throw IfcParse::IfcException(std::string("Argument ") + s + " not found on " + IfcSchema::Type::ToString(type));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+47
-15
@@ -1,21 +1,36 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file provides functions for loading an IFC file into memory and access *
|
||||
* its entities either by ID, by an IfcSchema::Type or by reference *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCFILE_H
|
||||
#define IFCFILE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "IfcUtil.h"
|
||||
#include "IfcParse.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
||||
//typedef IfcEntities IfcEntities;
|
||||
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||
typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
|
||||
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
|
||||
typedef std::map<unsigned int,unsigned int> MapOffsetById;
|
||||
|
||||
/// This class provides several static convenience functions and variables
|
||||
/// and provide access to the entities in an IFC file
|
||||
class IfcFile {
|
||||
@@ -27,6 +42,12 @@ private:
|
||||
MapOffsetById offsets;
|
||||
unsigned int lastId;
|
||||
unsigned int MaxId;
|
||||
std::string _filename;
|
||||
std::string _timestamp;
|
||||
std::string _author;
|
||||
std::string _author_email;
|
||||
std::string _author_organisation;
|
||||
void initTimestamp();
|
||||
public:
|
||||
typedef MapEntityById::const_iterator const_iterator;
|
||||
IfcFile();
|
||||
@@ -53,7 +74,7 @@ public:
|
||||
/// Returns all entities in the file that match the positional argument.
|
||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||
/// IfcWall will also return IfcWallStandardCase entities
|
||||
IfcEntities EntitiesByType(Ifc2x3::Type::Enum t);
|
||||
IfcEntities EntitiesByType(IfcSchema::Type::Enum t);
|
||||
/// Returns all entities in the file that match the positional argument.
|
||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||
/// IfcWall will also return IfcWallStandardCase entities
|
||||
@@ -63,7 +84,7 @@ public:
|
||||
/// Returns the entity with the specified id
|
||||
IfcEntity EntityById(int id);
|
||||
/// Returns the entity with the specified GlobalId
|
||||
Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
IfcSchema::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
bool Init(const std::string& fn);
|
||||
bool Init(std::istream& fn, int len);
|
||||
bool Init(void* data, int len);
|
||||
@@ -71,8 +92,19 @@ public:
|
||||
unsigned int FreshId() { MaxId ++; return MaxId; }
|
||||
void AddEntity(IfcUtil::IfcSchemaEntity e);
|
||||
void AddEntities(IfcEntities es);
|
||||
|
||||
void filename(const std::string& s);
|
||||
std::string filename() const;
|
||||
void timestamp(const std::string& s);
|
||||
std::string timestamp() const;
|
||||
void author(const std::string& name, const std::string& email, const std::string& organisation);
|
||||
std::string authorName() const;
|
||||
std::string authorEmail() const;
|
||||
std::string authorOrganisation() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,23 +26,17 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HAS_BOOST_UUID
|
||||
|
||||
#ifdef HAS_BOOST_UUID
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include "IfcWrite.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
|
||||
static const char* chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$";
|
||||
|
||||
#ifdef HAS_BOOST_UUID
|
||||
|
||||
// Converts an unsigned integer into a base64 string of length l
|
||||
std::string base64(unsigned v, int l) {
|
||||
std::string r;
|
||||
@@ -64,7 +58,7 @@ unsigned from_base64(const std::string& s) {
|
||||
for ( std::string::const_iterator i = s.begin()+zeros; i != s.end(); ++ i ) {
|
||||
r *= 64;
|
||||
const char* c = strchr(chars,*i);
|
||||
if ( !c ) throw IfcException("Failed to decode GlobalId");
|
||||
if ( !c ) throw IfcParse::IfcException("Failed to decode GlobalId");
|
||||
r += (c-chars);
|
||||
}
|
||||
return r;
|
||||
@@ -95,10 +89,7 @@ void expand(const std::string& s, std::vector<unsigned char>& v) {
|
||||
// A random number generator for the UUID
|
||||
static boost::uuids::basic_random_generator<boost::mt19937> gen;
|
||||
|
||||
#endif
|
||||
|
||||
IfcWrite::IfcGuidHelper::IfcGuidHelper() {
|
||||
#ifdef HAS_BOOST_UUID
|
||||
boost::uuids::uuid u = gen();
|
||||
std::vector<unsigned char> v(u.size());
|
||||
std::copy(u.begin(), u.end(), v.begin());
|
||||
@@ -108,13 +99,6 @@ IfcWrite::IfcGuidHelper::IfcGuidHelper() {
|
||||
expand(data,v2);
|
||||
boost::uuids::uuid u2;
|
||||
std::copy(v2.begin(), v2.end(), u2.begin());
|
||||
#else
|
||||
if ( ! seeded ) { srand((unsigned int)time(0)); seeded = true; }
|
||||
data.resize(length);
|
||||
for ( unsigned int i = 0; i < length; ++ i ) {
|
||||
data[i] = chars[rand()%strlen(chars)];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
IfcWrite::IfcGuidHelper::operator std::string() const {
|
||||
return data;
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This class is a subclass of the regular IfcFile class that implements *
|
||||
* several convenience functions for creating geometrical representations and *
|
||||
* spatial containers. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../ifcparse/IfcHierarchyHelper.h"
|
||||
|
||||
IfcSchema::IfcAxis2Placement3D* IfcHierarchyHelper::addPlacement3d(
|
||||
double ox, double oy, double oz,
|
||||
double zx, double zy, double zz,
|
||||
double xx, double xy, double xz)
|
||||
{
|
||||
IfcSchema::IfcDirection* x = addTriplet<IfcSchema::IfcDirection>(xx, xy, xz);
|
||||
IfcSchema::IfcDirection* z = addTriplet<IfcSchema::IfcDirection>(zx, zy, zz);
|
||||
IfcSchema::IfcCartesianPoint* o = addTriplet<IfcSchema::IfcCartesianPoint>(ox, oy, oz);
|
||||
IfcSchema::IfcAxis2Placement3D* p3d = new IfcSchema::IfcAxis2Placement3D(o, z, x);
|
||||
AddEntity(p3d);
|
||||
return p3d;
|
||||
}
|
||||
|
||||
IfcSchema::IfcAxis2Placement2D* IfcHierarchyHelper::addPlacement2d(
|
||||
double ox, double oy,
|
||||
double xx, double xy)
|
||||
{
|
||||
IfcSchema::IfcDirection* x = addDoublet<IfcSchema::IfcDirection>(xx, xy);
|
||||
IfcSchema::IfcCartesianPoint* o = addDoublet<IfcSchema::IfcCartesianPoint>(ox, oy);
|
||||
IfcSchema::IfcAxis2Placement2D* p2d = new IfcSchema::IfcAxis2Placement2D(o, x);
|
||||
AddEntity(p2d);
|
||||
return p2d;
|
||||
}
|
||||
|
||||
IfcSchema::IfcLocalPlacement* IfcHierarchyHelper::addLocalPlacement(
|
||||
double ox, double oy, double oz,
|
||||
double zx, double zy, double zz,
|
||||
double xx, double xy, double xz)
|
||||
{
|
||||
IfcSchema::IfcLocalPlacement* lp = new IfcSchema::IfcLocalPlacement(0,
|
||||
addPlacement3d(ox, oy, oz, zx, zy, zz, xx, xy, xz));
|
||||
|
||||
AddEntity(lp);
|
||||
return lp;
|
||||
}
|
||||
|
||||
IfcSchema::IfcOwnerHistory* IfcHierarchyHelper::addOwnerHistory() {
|
||||
IfcSchema::IfcPerson* person = new IfcSchema::IfcPerson(boost::none, boost::none, std::string(""),
|
||||
boost::none, boost::none, boost::none, boost::none, boost::none);
|
||||
|
||||
IfcSchema::IfcOrganization* organization = new IfcSchema::IfcOrganization(boost::none,
|
||||
"IfcOpenShell", boost::none, boost::none, boost::none);
|
||||
|
||||
IfcSchema::IfcPersonAndOrganization* person_and_org = new IfcSchema::IfcPersonAndOrganization(person, organization, boost::none);
|
||||
IfcSchema::IfcApplication* application = new IfcSchema::IfcApplication(organization,
|
||||
IFCOPENSHELL_VERSION, "IfcOpenShell", "IfcOpenShell");
|
||||
|
||||
int timestamp = (int) time(0);
|
||||
IfcSchema::IfcOwnerHistory* owner_hist = new IfcSchema::IfcOwnerHistory(person_and_org, application,
|
||||
boost::none, IfcSchema::IfcChangeActionEnum::IfcChangeAction_ADDED, boost::none, person_and_org, application, timestamp);
|
||||
|
||||
AddEntity(person);
|
||||
AddEntity(organization);
|
||||
AddEntity(person_and_org);
|
||||
AddEntity(application);
|
||||
AddEntity(owner_hist);
|
||||
|
||||
return owner_hist;
|
||||
}
|
||||
|
||||
IfcSchema::IfcProject* IfcHierarchyHelper::addProject(IfcSchema::IfcOwnerHistory* owner_hist) {
|
||||
IfcSchema::IfcRepresentationContext::list rep_contexts (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationContext>());
|
||||
IfcSchema::IfcGeometricRepresentationContext* rep_context = new IfcSchema::IfcGeometricRepresentationContext(
|
||||
std::string("Plan"), std::string("Model"), 3, 1e-5, addPlacement3d(), addTriplet<IfcSchema::IfcDirection>(0, 1, 0));
|
||||
|
||||
rep_contexts->push(rep_context);
|
||||
|
||||
IfcEntities units (new IfcEntityList());
|
||||
IfcSchema::IfcDimensionalExponents* dimexp = new IfcSchema::IfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0);
|
||||
IfcSchema::IfcSIUnit* unit1 = new IfcSchema::IfcSIUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT,
|
||||
IfcSchema::IfcSIPrefix::IfcSIPrefix_MILLI, IfcSchema::IfcSIUnitName::IfcSIUnitName_METRE);
|
||||
IfcSchema::IfcSIUnit* unit2a = new IfcSchema::IfcSIUnit(IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT,
|
||||
boost::none, IfcSchema::IfcSIUnitName::IfcSIUnitName_RADIAN);
|
||||
IfcSchema::IfcMeasureWithUnit* unit2b = new IfcSchema::IfcMeasureWithUnit(
|
||||
new IfcWrite::IfcSelectHelper(0.017453293, IfcSchema::Type::IfcPlaneAngleMeasure), unit2a);
|
||||
IfcSchema::IfcConversionBasedUnit* unit2 = new IfcSchema::IfcConversionBasedUnit(dimexp,
|
||||
IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, "Degrees", unit2b);
|
||||
|
||||
units->push(unit1);
|
||||
units->push(unit2);
|
||||
|
||||
IfcSchema::IfcUnitAssignment* unit_assignment = new IfcSchema::IfcUnitAssignment(units);
|
||||
|
||||
IfcSchema::IfcProject* project = new IfcSchema::IfcProject(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none,
|
||||
boost::none, boost::none, boost::none, rep_contexts, unit_assignment);
|
||||
|
||||
AddEntity(rep_context);
|
||||
AddEntity(dimexp);
|
||||
AddEntity(unit1);
|
||||
AddEntity(unit2a);
|
||||
AddEntity(unit2b);
|
||||
AddEntity(unit2);
|
||||
AddEntity(unit_assignment);
|
||||
AddEntity(project);
|
||||
|
||||
return project;
|
||||
}
|
||||
|
||||
void IfcHierarchyHelper::relatePlacements(IfcSchema::IfcProduct* parent, IfcSchema::IfcProduct* product) {
|
||||
IfcSchema::IfcObjectPlacement* place = product->hasObjectPlacement() ? product->ObjectPlacement() : 0;
|
||||
if (place && place->is(IfcSchema::Type::IfcLocalPlacement)) {
|
||||
IfcSchema::IfcLocalPlacement* local_place = (IfcSchema::IfcLocalPlacement*) place;
|
||||
if (parent->hasObjectPlacement()) {
|
||||
local_place->setPlacementRelTo(parent->ObjectPlacement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::IfcSite* IfcHierarchyHelper::addSite(IfcSchema::IfcProject* proj, IfcSchema::IfcOwnerHistory* owner_hist) {
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
if (! proj) {
|
||||
proj = getSingle<IfcSchema::IfcProject>();
|
||||
}
|
||||
if (! proj) {
|
||||
proj = addProject(owner_hist);
|
||||
}
|
||||
|
||||
IfcSchema::IfcSite* site = new IfcSchema::IfcSite(IfcWrite::IfcGuidHelper(), owner_hist, boost::none,
|
||||
boost::none, boost::none, addLocalPlacement(), 0, boost::none,
|
||||
IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
|
||||
boost::none, boost::none, boost::none, boost::none, 0);
|
||||
|
||||
AddEntity(site);
|
||||
addRelatedObject<IfcSchema::IfcRelAggregates>(proj, site);
|
||||
return site;
|
||||
}
|
||||
|
||||
IfcSchema::IfcBuilding* IfcHierarchyHelper::addBuilding(IfcSchema::IfcSite* site, IfcSchema::IfcOwnerHistory* owner_hist) {
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
if (! site) {
|
||||
site = getSingle<IfcSchema::IfcSite>();
|
||||
}
|
||||
if (! site) {
|
||||
site = addSite(0, owner_hist);
|
||||
}
|
||||
IfcSchema::IfcBuilding* building = new IfcSchema::IfcBuilding(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none, boost::none,
|
||||
addLocalPlacement(), 0, boost::none, IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT,
|
||||
boost::none, boost::none, 0);
|
||||
|
||||
AddEntity(building);
|
||||
addRelatedObject<IfcSchema::IfcRelAggregates>(site, building);
|
||||
relatePlacements(site, building);
|
||||
|
||||
return building;
|
||||
}
|
||||
|
||||
IfcSchema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingStorey(IfcSchema::IfcBuilding* building,
|
||||
IfcSchema::IfcOwnerHistory* owner_hist)
|
||||
{
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
if (! building) {
|
||||
building = getSingle<IfcSchema::IfcBuilding>();
|
||||
}
|
||||
if (! building) {
|
||||
building = addBuilding(0, owner_hist);
|
||||
}
|
||||
IfcSchema::IfcBuildingStorey* storey = new IfcSchema::IfcBuildingStorey(IfcWrite::IfcGuidHelper(),
|
||||
owner_hist, boost::none, boost::none, boost::none, addLocalPlacement(), 0, boost::none,
|
||||
IfcSchema::IfcElementCompositionEnum::IfcElementComposition_ELEMENT, boost::none);
|
||||
|
||||
AddEntity(storey);
|
||||
addRelatedObject<IfcSchema::IfcRelAggregates>(building, storey);
|
||||
relatePlacements(building, storey);
|
||||
|
||||
return storey;
|
||||
}
|
||||
|
||||
IfcSchema::IfcBuildingStorey* IfcHierarchyHelper::addBuildingProduct(IfcSchema::IfcProduct* product,
|
||||
IfcSchema::IfcBuildingStorey* storey, IfcSchema::IfcOwnerHistory* owner_hist)
|
||||
{
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
if (! storey) {
|
||||
storey = getSingle<IfcSchema::IfcBuildingStorey>();
|
||||
}
|
||||
if (! storey) {
|
||||
storey = addBuildingStorey(0, owner_hist);
|
||||
}
|
||||
AddEntity(product);
|
||||
addRelatedObject<IfcSchema::IfcRelContainedInSpatialStructure>(storey, product);
|
||||
relatePlacements(storey, product);
|
||||
return storey;
|
||||
}
|
||||
|
||||
void IfcHierarchyHelper::addExtrudedPolyline(IfcSchema::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2,
|
||||
IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list cartesian_points (new IfcTemplatedEntityList<IfcSchema::IfcCartesianPoint>());
|
||||
for (std::vector<std::pair<double, double> >::const_iterator i = points.begin(); i != points.end(); ++i) {
|
||||
cartesian_points->push(addDoublet<IfcSchema::IfcCartesianPoint>(i->first, i->second));
|
||||
}
|
||||
if (cartesian_points->Size()) cartesian_points->push(*cartesian_points->begin());
|
||||
IfcSchema::IfcPolyline* line = new IfcSchema::IfcPolyline(cartesian_points);
|
||||
IfcSchema::IfcArbitraryClosedProfileDef* profile = new IfcSchema::IfcArbitraryClosedProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, boost::none, line);
|
||||
|
||||
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(
|
||||
profile, place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<IfcSchema::IfcDirection>(0, 0, 1), h);
|
||||
|
||||
IfcSchema::IfcRepresentationItem::list items = rep->Items();
|
||||
items->push(solid);
|
||||
rep->setItems(items);
|
||||
|
||||
AddEntity(line);
|
||||
AddEntity(profile);
|
||||
AddEntity(solid);
|
||||
}
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2, IfcSchema::IfcDirection* dir,
|
||||
IfcSchema::IfcRepresentationContext* context)
|
||||
{
|
||||
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
|
||||
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(context
|
||||
? context
|
||||
: getSingle<IfcSchema::IfcRepresentationContext>(), std::string("Body"), std::string("SweptSolid"), items);
|
||||
reps->push(rep);
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
AddEntity(rep);
|
||||
AddEntity(shape);
|
||||
addExtrudedPolyline(rep, points, h, place, place2, dir, context);
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
void IfcHierarchyHelper::addBox(IfcSchema::IfcShapeRepresentation* rep, double w, double d, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place, IfcSchema::IfcAxis2Placement3D* place2,
|
||||
IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
|
||||
{
|
||||
if (false) {
|
||||
IfcSchema::IfcRectangleProfileDef* profile = new IfcSchema::IfcRectangleProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, 0, place ? place : addPlacement2d(), w, d);
|
||||
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
|
||||
place2 ? place2 : addPlacement3d(), dir ? dir : addTriplet<IfcSchema::IfcDirection>(0, 0, 1), h);
|
||||
|
||||
AddEntity(profile);
|
||||
AddEntity(solid);
|
||||
IfcSchema::IfcRepresentationItem::list items = rep->Items();
|
||||
items->push(solid);
|
||||
rep->setItems(items);
|
||||
} else {
|
||||
std::vector<std::pair<double, double> > points;
|
||||
points.push_back(std::pair<double, double>(-w/2, -d/2));
|
||||
points.push_back(std::pair<double, double>(w/2, -d/2));
|
||||
points.push_back(std::pair<double, double>(w/2, d/2));
|
||||
points.push_back(std::pair<double, double>(-w/2, d/2));
|
||||
points.push_back(*points.begin());
|
||||
addExtrudedPolyline(rep, points, h, place, place2, dir, context);
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* IfcHierarchyHelper::addBox(double w, double d, double h, IfcSchema::IfcAxis2Placement2D* place,
|
||||
IfcSchema::IfcAxis2Placement3D* place2, IfcSchema::IfcDirection* dir, IfcSchema::IfcRepresentationContext* context)
|
||||
{
|
||||
IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
|
||||
IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
context ? context : getSingle<IfcSchema::IfcRepresentationContext>(), std::string("Body"), std::string("SweptSolid"), items);
|
||||
reps->push(rep);
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
AddEntity(rep);
|
||||
AddEntity(shape);
|
||||
addBox(rep, w, d, h, place, place2, dir, context);
|
||||
return shape;
|
||||
}
|
||||
|
||||
void IfcHierarchyHelper::clipRepresentation(IfcSchema::IfcProductRepresentation* shape,
|
||||
IfcSchema::IfcAxis2Placement3D* place, bool agree)
|
||||
{
|
||||
IfcSchema::IfcPlane* plane = new IfcSchema::IfcPlane(place);
|
||||
IfcSchema::IfcHalfSpaceSolid* half_space = new IfcSchema::IfcHalfSpaceSolid(plane, agree);
|
||||
IfcSchema::IfcRepresentation::list reps = shape->Representations();
|
||||
for (IfcSchema::IfcRepresentation::it j = reps->begin(); j != reps->end(); ++j) {
|
||||
IfcSchema::IfcRepresentation* rep = *j;
|
||||
if (rep->RepresentationIdentifier() != "Body") continue;
|
||||
rep->setRepresentationType("Clipping");
|
||||
IfcSchema::IfcRepresentationItem::list items = rep->Items();
|
||||
IfcSchema::IfcRepresentationItem::list new_items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
|
||||
AddEntity(plane);
|
||||
AddEntity(half_space);
|
||||
for (IfcSchema::IfcRepresentationItem::it i = items->begin(); i != items->end(); ++i) {
|
||||
IfcSchema::IfcRepresentationItem* item = *i;
|
||||
IfcSchema::IfcBooleanClippingResult* clip = new IfcSchema::IfcBooleanClippingResult(
|
||||
IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE, item, half_space);
|
||||
AddEntity(clip);
|
||||
new_items->push(clip);
|
||||
}
|
||||
rep->setItems(new_items);
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::IfcPresentationStyleAssignment* IfcHierarchyHelper::setSurfaceColour(
|
||||
IfcSchema::IfcProductRepresentation* shape, double r, double g, double b, double a)
|
||||
{
|
||||
IfcSchema::IfcColourRgb* colour = new IfcSchema::IfcColourRgb(boost::none, r, g, b);
|
||||
IfcSchema::IfcSurfaceStyleRendering* rendering = a == 1.0
|
||||
? new IfcSchema::IfcSurfaceStyleRendering(colour, boost::none, boost::none, boost::none, boost::none, boost::none,
|
||||
boost::none, boost::none, IfcSchema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT)
|
||||
: new IfcSchema::IfcSurfaceStyleRendering(colour, 1.0-a, boost::none, boost::none, boost::none, boost::none,
|
||||
boost::none, boost::none, IfcSchema::IfcReflectanceMethodEnum::IfcReflectanceMethod_FLAT);
|
||||
|
||||
IfcEntities styles(new IfcEntityList());
|
||||
styles->push(rendering);
|
||||
IfcSchema::IfcSurfaceStyle* surface_style = new IfcSchema::IfcSurfaceStyle(
|
||||
boost::none, IfcSchema::IfcSurfaceSide::IfcSurfaceSide_BOTH, styles);
|
||||
IfcEntities surface_styles(new IfcEntityList());
|
||||
surface_styles->push(surface_style);
|
||||
IfcSchema::IfcPresentationStyleAssignment* style_assignment =
|
||||
new IfcSchema::IfcPresentationStyleAssignment(surface_styles);
|
||||
AddEntity(colour);
|
||||
AddEntity(rendering);
|
||||
AddEntity(surface_style);
|
||||
AddEntity(style_assignment);
|
||||
setSurfaceColour(shape, style_assignment);
|
||||
return style_assignment;
|
||||
}
|
||||
|
||||
void IfcHierarchyHelper::setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
|
||||
IfcSchema::IfcPresentationStyleAssignment* style_assignment)
|
||||
{
|
||||
#ifdef USE_IFC4
|
||||
IfcEntities style_assignments (new IfcEntityList());
|
||||
#else
|
||||
IfcSchema::IfcPresentationStyleAssignment::list style_assignments (new IfcTemplatedEntityList<IfcSchema::IfcPresentationStyleAssignment>());
|
||||
#endif
|
||||
style_assignments->push(style_assignment);
|
||||
IfcSchema::IfcRepresentation::list reps = shape->Representations();
|
||||
for (IfcSchema::IfcRepresentation::it j = reps->begin(); j != reps->end(); ++j) {
|
||||
IfcSchema::IfcRepresentation* rep = *j;
|
||||
if (rep->RepresentationIdentifier() != "Body" && rep->RepresentationIdentifier() != "Facetation") continue;
|
||||
IfcSchema::IfcRepresentationItem::list items = rep->Items();
|
||||
for (IfcSchema::IfcRepresentationItem::it i = items->begin(); i != items->end(); ++i) {
|
||||
IfcSchema::IfcRepresentationItem* item = *i;
|
||||
IfcSchema::IfcStyledItem* styled_item = new IfcSchema::IfcStyledItem(item, style_assignments, boost::none);
|
||||
AddEntity(styled_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This class is a subclass of the regular IfcFile class that implements *
|
||||
* several convenience functions for creating geometrical representations and *
|
||||
* spatial containers. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCHIERARCHYHELPER_H
|
||||
#define IFCHIERARCHYHELPER_H
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#endif
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
|
||||
class IfcHierarchyHelper : public IfcParse::IfcFile {
|
||||
public:
|
||||
template <class T>
|
||||
T* addTriplet(double x, double y, double z) {
|
||||
std::vector<double> a; a.push_back(x); a.push_back(y); a.push_back(z);
|
||||
T* t = new T(a);
|
||||
AddEntity(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* addDoublet(double x, double y) {
|
||||
std::vector<double> a; a.push_back(x); a.push_back(y);
|
||||
T* t = new T(a);
|
||||
AddEntity(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* getSingle() {
|
||||
typename T::list ts = EntitiesByType<T>();
|
||||
if (ts->Size() != 1) return 0;
|
||||
return *ts->begin();
|
||||
}
|
||||
|
||||
IfcSchema::IfcAxis2Placement3D* addPlacement3d(double ox=0.0, double oy=0.0, double oz=0.0,
|
||||
double zx=0.0, double zy=0.0, double zz=1.0,
|
||||
double xx=1.0, double xy=0.0, double xz=0.0);
|
||||
|
||||
IfcSchema::IfcAxis2Placement2D* addPlacement2d(double ox=0.0, double oy=0.0,
|
||||
double xx=1.0, double xy=0.0);
|
||||
|
||||
IfcSchema::IfcLocalPlacement* addLocalPlacement(double ox=0.0, double oy=0.0, double oz=0.0,
|
||||
double zx=0.0, double zy=0.0, double zz=1.0,
|
||||
double xx=1.0, double xy=0.0, double xz=0.0);
|
||||
|
||||
template <class T>
|
||||
void addRelatedObject(IfcSchema::IfcObjectDefinition* related_object,
|
||||
IfcSchema::IfcObjectDefinition* relating_object, IfcSchema::IfcOwnerHistory* owner_hist = 0)
|
||||
{
|
||||
typename T::list li = EntitiesByType<T>();
|
||||
bool found = false;
|
||||
for (typename T::it i = li->begin(); i != li->end(); ++i) {
|
||||
T* rel = *i;
|
||||
if (rel->RelatingObject() == relating_object) {
|
||||
IfcSchema::IfcObjectDefinition::list products = rel->RelatedObjects();
|
||||
products->push(related_object);
|
||||
rel->setRelatedObjects(products);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! found) {
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
IfcSchema::IfcObjectDefinition::list relating_objects (new IfcTemplatedEntityList<IfcSchema::IfcObjectDefinition>());
|
||||
relating_objects->push(relating_object);
|
||||
T* t = new T(IfcWrite::IfcGuidHelper(), owner_hist, boost::none, boost::none, related_object, relating_objects);
|
||||
AddEntity(t);
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::IfcOwnerHistory* addOwnerHistory();
|
||||
IfcSchema::IfcProject* addProject(IfcSchema::IfcOwnerHistory* owner_hist = 0);
|
||||
void relatePlacements(IfcSchema::IfcProduct* parent, IfcSchema::IfcProduct* product);
|
||||
IfcSchema::IfcSite* addSite(IfcSchema::IfcProject* proj = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
|
||||
IfcSchema::IfcBuilding* addBuilding(IfcSchema::IfcSite* site = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
|
||||
|
||||
IfcSchema::IfcBuildingStorey* addBuildingStorey(IfcSchema::IfcBuilding* building = 0,
|
||||
IfcSchema::IfcOwnerHistory* owner_hist = 0);
|
||||
|
||||
IfcSchema::IfcBuildingStorey* addBuildingProduct(IfcSchema::IfcProduct* product,
|
||||
IfcSchema::IfcBuildingStorey* storey = 0, IfcSchema::IfcOwnerHistory* owner_hist = 0);
|
||||
|
||||
void addExtrudedPolyline(IfcSchema::IfcShapeRepresentation* rep, const std::vector<std::pair<double, double> >& points, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0,
|
||||
IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* addExtrudedPolyline(const std::vector<std::pair<double, double> >& points, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0, IfcSchema::IfcDirection* dir=0,
|
||||
IfcSchema::IfcRepresentationContext* context=0);
|
||||
|
||||
void addBox(IfcSchema::IfcShapeRepresentation* rep, double w, double d, double h,
|
||||
IfcSchema::IfcAxis2Placement2D* place=0, IfcSchema::IfcAxis2Placement3D* place2=0,
|
||||
IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* addBox(double w, double d, double h, IfcSchema::IfcAxis2Placement2D* place=0,
|
||||
IfcSchema::IfcAxis2Placement3D* place2=0, IfcSchema::IfcDirection* dir=0, IfcSchema::IfcRepresentationContext* context=0);
|
||||
|
||||
void clipRepresentation(IfcSchema::IfcProductRepresentation* shape,
|
||||
IfcSchema::IfcAxis2Placement3D* place, bool agree);
|
||||
|
||||
IfcSchema::IfcPresentationStyleAssignment* setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
|
||||
double r, double g, double b, double a=1.0);
|
||||
|
||||
void setSurfaceColour(IfcSchema::IfcProductRepresentation* shape,
|
||||
IfcSchema::IfcPresentationStyleAssignment* style_assignment);
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
inline void IfcHierarchyHelper::addRelatedObject <IfcSchema::IfcRelContainedInSpatialStructure> (IfcSchema::IfcObjectDefinition* related_object,
|
||||
IfcSchema::IfcObjectDefinition* relating_object, IfcSchema::IfcOwnerHistory* owner_hist)
|
||||
{
|
||||
IfcSchema::IfcRelContainedInSpatialStructure::list li = EntitiesByType<IfcSchema::IfcRelContainedInSpatialStructure>();
|
||||
bool found = false;
|
||||
for (IfcSchema::IfcRelContainedInSpatialStructure::it i = li->begin(); i != li->end(); ++i) {
|
||||
IfcSchema::IfcRelContainedInSpatialStructure* rel = *i;
|
||||
if (rel->RelatingStructure() == relating_object) {
|
||||
IfcSchema::IfcProduct::list products = rel->RelatedElements();
|
||||
products->push((IfcSchema::IfcProduct*)related_object);
|
||||
rel->setRelatedElements(products);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! found) {
|
||||
if (! owner_hist) {
|
||||
owner_hist = getSingle<IfcSchema::IfcOwnerHistory>();
|
||||
}
|
||||
if (! owner_hist) {
|
||||
owner_hist = addOwnerHistory();
|
||||
}
|
||||
IfcSchema::IfcProduct::list relating_objects (new IfcTemplatedEntityList<IfcSchema::IfcProduct>());
|
||||
relating_objects->push((IfcSchema::IfcProduct*)relating_object);
|
||||
IfcSchema::IfcRelContainedInSpatialStructure* t = new IfcSchema::IfcRelContainedInSpatialStructure(IfcWrite::IfcGuidHelper(), owner_hist,
|
||||
boost::none, boost::none, relating_objects, (IfcSchema::IfcSpatialStructureElement*)related_object);
|
||||
|
||||
AddEntity(t);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+94
-46
@@ -21,15 +21,22 @@
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
#include "../ifcparse/IfcUntypedEntity.h"
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
//
|
||||
@@ -37,15 +44,23 @@ using namespace IfcParse;
|
||||
//
|
||||
IfcSpfStream::IfcSpfStream(const std::string& fn) {
|
||||
eof = false;
|
||||
stream.open(fn.c_str(),std::ios_base::binary);
|
||||
if ( ! stream.good() ) {
|
||||
#ifdef _MSC_VER_NO
|
||||
int fn_buffer_size = MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, 0, 0);
|
||||
wchar_t* fn_wide = new wchar_t[fn_buffer_size];
|
||||
MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, fn_wide, fn_buffer_size);
|
||||
stream = _wfopen(fn_wide, L"rb");
|
||||
delete[] fn_wide;
|
||||
#else
|
||||
stream = fopen(fn.c_str(), "rb");
|
||||
#endif
|
||||
if (stream == NULL) {
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
valid = true;
|
||||
stream.seekg(0,std::ios_base::end);
|
||||
size = (unsigned int) stream.tellg();
|
||||
stream.seekg(0,std::ios_base::beg);
|
||||
fseek(stream, 0, SEEK_END);
|
||||
size = (unsigned int) ftell(stream);;
|
||||
rewind(stream);
|
||||
#ifdef BUF_SIZE
|
||||
offset = 0;
|
||||
paging = size > BUF_SIZE;
|
||||
@@ -87,7 +102,7 @@ IfcSpfStream::IfcSpfStream(void* data, int l) {
|
||||
|
||||
void IfcSpfStream::Close() {
|
||||
#ifdef BUF_SIZE
|
||||
if ( paging ) stream.close();
|
||||
if ( paging ) fclose(stream);
|
||||
#endif
|
||||
delete[] buffer;
|
||||
}
|
||||
@@ -99,23 +114,22 @@ void IfcSpfStream::ReadBuffer(bool inc) {
|
||||
#ifdef BUF_SIZE
|
||||
if ( inc ) {
|
||||
offset += len;
|
||||
stream.seekg(offset,std::ios_base::beg);
|
||||
fseek(stream, offset, SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
eof = stream.eof();
|
||||
eof = feof(stream) != 0;
|
||||
if ( eof ) return;
|
||||
#ifdef BUF_SIZE
|
||||
stream.read(buffer,size < BUF_SIZE ? size : BUF_SIZE);
|
||||
len = (unsigned int) fread(buffer, 1, size < BUF_SIZE ? size : BUF_SIZE, stream);
|
||||
#else
|
||||
stream.read(buffer,size);
|
||||
len = (unsigned int) fread(buffer, 1, size, stream);
|
||||
#endif
|
||||
len = (unsigned int) stream.gcount();
|
||||
eof = len == 0;
|
||||
ptr = 0;
|
||||
#ifdef BUF_SIZE
|
||||
if (!paging) stream.close();
|
||||
if (!paging) fclose(stream);
|
||||
#else
|
||||
stream.close();
|
||||
fclose(stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -134,8 +148,8 @@ void IfcSpfStream::Seek(unsigned int o) {
|
||||
ptr = o - offset;
|
||||
} else {
|
||||
offset = o;
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
clearerr(stream);
|
||||
fseek(stream, o, SEEK_SET);
|
||||
ReadBuffer(false);
|
||||
}
|
||||
#endif
|
||||
@@ -160,9 +174,9 @@ char IfcSpfStream::Read(unsigned int o) {
|
||||
} else if ( o >= offset && (o < (offset+len)) ) {
|
||||
return buffer[o-offset];
|
||||
} else {
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
return stream.peek();
|
||||
clearerr(stream);
|
||||
fseek(stream, o, SEEK_SET);
|
||||
return ungetc(getc(stream), stream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -352,8 +366,8 @@ TokenArgument::TokenArgument(const Token& t) {
|
||||
token = t;
|
||||
}
|
||||
|
||||
EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, const Token& t) {
|
||||
entity = new Ifc::IfcUntypedEntity(new Entity(0,t.first->file,t.second));
|
||||
EntityArgument::EntityArgument(IfcSchema::Type::Enum ty, const Token& t) {
|
||||
entity = new IfcUntypedEntity(new Entity(0,t.first->file,t.second));
|
||||
}
|
||||
|
||||
//
|
||||
@@ -505,7 +519,7 @@ Entity::Entity(unsigned int i, IfcFile* f) { //: file(f) {
|
||||
file = f;
|
||||
Token datatype = f->tokens->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
||||
_id = i;
|
||||
args = ArgumentPtr();
|
||||
offset = datatype.second;
|
||||
@@ -549,7 +563,7 @@ void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
||||
file->tokens->stream->Seek(offset);
|
||||
Token datatype = file->tokens->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
||||
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
||||
}
|
||||
Token open = file->tokens->Next();
|
||||
args = new ArgumentList(file->tokens, ids);
|
||||
@@ -558,7 +572,7 @@ void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
||||
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
|
||||
}
|
||||
|
||||
Ifc2x3::Type::Enum Entity::type() const {
|
||||
IfcSchema::Type::Enum Entity::type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
@@ -566,7 +580,7 @@ Ifc2x3::Type::Enum Entity::type() const {
|
||||
// Returns the CamelCase string representation of the datatype as it is defined in the schema
|
||||
//
|
||||
std::string Entity::datatype() {
|
||||
return Ifc2x3::Type::ToString(_type);
|
||||
return IfcSchema::Type::ToString(_type);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -597,18 +611,18 @@ Entity::~Entity() {
|
||||
//
|
||||
// Returns the entities of type c that have this entity in their ArgumentList
|
||||
//
|
||||
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c) {
|
||||
IfcEntities Entity::getInverse(IfcSchema::Type::Enum c) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
IfcEntities all = file->EntitiesByReference(_id);
|
||||
if ( ! all ) return l;
|
||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
||||
if ( c == IfcSchema::Type::ALL || (*it)->is(c) ) {
|
||||
l->push(*it);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) {
|
||||
IfcEntities Entity::getInverse(IfcSchema::Type::Enum c, int i, const std::string& a) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
IfcEntities all = getInverse(c);
|
||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||
@@ -619,7 +633,7 @@ IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a
|
||||
}
|
||||
return l;
|
||||
}
|
||||
bool Entity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
||||
bool Entity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
unsigned int Entity::id() { return _id; }
|
||||
|
||||
bool Entity::isWritable() {
|
||||
@@ -631,6 +645,7 @@ IfcFile::IfcFile() {
|
||||
lastId = 0;
|
||||
tokens = 0;
|
||||
MaxId = 0;
|
||||
initTimestamp();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -648,7 +663,7 @@ bool IfcFile::Init(void* data, int len) {
|
||||
return IfcFile::Init(new IfcSpfStream(data,len));
|
||||
}
|
||||
bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
Ifc2x3::InitStringMap();
|
||||
IfcSchema::InitStringMap();
|
||||
file = f;
|
||||
if ( ! file->valid ) return false;
|
||||
tokens = new Tokens (file,this);
|
||||
@@ -664,8 +679,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
if ( currentId ) {
|
||||
try {
|
||||
e = new Entity(currentId,this);
|
||||
//entity = Ifc2x3::SchemaEntity(e);
|
||||
entity = new Ifc::IfcUntypedEntity(e);
|
||||
entity = new IfcUntypedEntity(e);
|
||||
} catch (IfcException ex) {
|
||||
currentId = 0;
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
@@ -676,8 +690,8 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
std::stringstream ss; ss << "\r#" << currentId;
|
||||
Logger::Status(ss.str(), false);
|
||||
}
|
||||
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
||||
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
||||
if ( entity->is(IfcSchema::Type::IfcRoot) ) {
|
||||
IfcSchema::IfcRoot::ptr ifc_root = (IfcSchema::IfcRoot::ptr) entity;
|
||||
try {
|
||||
const std::string guid = ifc_root->GlobalId();
|
||||
if ( byguid.find(guid) != byguid.end() ) {
|
||||
@@ -690,7 +704,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
}
|
||||
}
|
||||
Ifc2x3::Type::Enum ty = entity->type();
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
do {
|
||||
IfcEntities L = EntitiesByType(ty);
|
||||
if ( L == 0 ) {
|
||||
@@ -698,7 +712,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
bytype[ty] = L;
|
||||
}
|
||||
L->push(entity);
|
||||
ty = Ifc2x3::Type::Parent(ty);
|
||||
ty = IfcSchema::Type::Parent(ty);
|
||||
} while ( ty > -1 );
|
||||
if ( byid.find(currentId) != byid.end() ) {
|
||||
std::stringstream ss;
|
||||
@@ -706,7 +720,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
}
|
||||
byid[currentId] = entity;
|
||||
MaxId = std::max(MaxId,currentId);
|
||||
MaxId = (std::max)(MaxId,currentId);
|
||||
currentId = 0;
|
||||
} else {
|
||||
try { token = tokens->Next(); }
|
||||
@@ -737,8 +751,8 @@ void IfcFile::AddEntities(IfcEntities es) {
|
||||
}
|
||||
}
|
||||
void IfcFile::AddEntity(IfcUtil::IfcSchemaEntity entity) {
|
||||
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
||||
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
||||
if ( entity->is(IfcSchema::Type::IfcRoot) ) {
|
||||
IfcSchema::IfcRoot::ptr ifc_root = (IfcSchema::IfcRoot::ptr) entity;
|
||||
try {
|
||||
const std::string guid = ifc_root->GlobalId();
|
||||
if ( byguid.find(guid) != byguid.end() ) {
|
||||
@@ -751,7 +765,7 @@ void IfcFile::AddEntity(IfcUtil::IfcSchemaEntity entity) {
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
}
|
||||
}
|
||||
Ifc2x3::Type::Enum ty = entity->type();
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
do {
|
||||
IfcEntities L = EntitiesByType(ty);
|
||||
if ( L == 0 ) {
|
||||
@@ -759,7 +773,7 @@ void IfcFile::AddEntity(IfcUtil::IfcSchemaEntity entity) {
|
||||
bytype[ty] = L;
|
||||
}
|
||||
L->push(entity);
|
||||
ty = Ifc2x3::Type::Parent(ty);
|
||||
ty = IfcSchema::Type::Parent(ty);
|
||||
} while ( ty > -1 );
|
||||
int new_id = -1;
|
||||
// For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set
|
||||
@@ -778,14 +792,14 @@ void IfcFile::AddEntity(IfcUtil::IfcSchemaEntity entity) {
|
||||
byid[new_id] = entity;
|
||||
|
||||
}
|
||||
IfcEntities IfcFile::EntitiesByType(Ifc2x3::Type::Enum t) {
|
||||
IfcEntities IfcFile::EntitiesByType(IfcSchema::Type::Enum t) {
|
||||
MapEntitiesByType::const_iterator it = bytype.find(t);
|
||||
return (it == bytype.end()) ? IfcEntities() : it->second;
|
||||
}
|
||||
IfcEntities IfcFile::EntitiesByType(const std::string& t) {
|
||||
std::string ty = t;
|
||||
for (std::string::iterator p = ty.begin(); p != ty.end(); ++p ) *p = toupper(*p);
|
||||
return EntitiesByType(Ifc2x3::Type::FromString(ty));
|
||||
return EntitiesByType(IfcSchema::Type::FromString(ty));
|
||||
}
|
||||
IfcEntities IfcFile::EntitiesByReference(int t) {
|
||||
MapEntitiesByRef::const_iterator it = byref.find(t);
|
||||
@@ -798,13 +812,13 @@ IfcUtil::IfcSchemaEntity IfcFile::EntityById(int id) {
|
||||
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
||||
const unsigned int offset = (*it2).second;
|
||||
EntityPtr e = EntityPtr(new Entity(id,this,offset));
|
||||
IfcUtil::IfcSchemaEntity entity = Ifc2x3::SchemaEntity(e);
|
||||
IfcUtil::IfcSchemaEntity entity = IfcSchema::SchemaEntity(e);
|
||||
byid[id] = entity;
|
||||
return entity;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
Ifc2x3::IfcRoot::ptr IfcFile::EntityByGuid(const std::string& guid) {
|
||||
IfcSchema::IfcRoot::ptr IfcFile::EntityByGuid(const std::string& guid) {
|
||||
MapEntityByGuid::const_iterator it = byguid.find(guid);
|
||||
if ( it == byguid.end() ) {
|
||||
throw IfcException("Entity not found");
|
||||
@@ -838,8 +852,20 @@ std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) {
|
||||
os << "ISO-10303-21;" << std::endl;
|
||||
os << "HEADER;" << std::endl;
|
||||
os << "FILE_DESCRIPTION(('ViewDefinition []'),'2;1');" << std::endl;
|
||||
os << "FILE_NAME('','',(''),('',''),'IfcOpenShell','IfcOpenShell','');" << std::endl;
|
||||
os << "FILE_NAME("
|
||||
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.filename())) << ","
|
||||
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.timestamp())) << ",("
|
||||
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorOrganisation())) << "),("
|
||||
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorName())) << ","
|
||||
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorEmail()))
|
||||
<< "),'IfcOpenShell " << IFCOPENSHELL_VERSION
|
||||
<< "','IfcOpenShell " << IFCOPENSHELL_VERSION
|
||||
<< "','');" << std::endl;
|
||||
#ifdef USE_IFC4
|
||||
os << "FILE_SCHEMA(('IFC4'));" << std::endl;
|
||||
#else
|
||||
os << "FILE_SCHEMA(('IFC2X3'));" << std::endl;
|
||||
#endif
|
||||
os << "ENDSEC;" << std::endl;
|
||||
os << "DATA;" << std::endl;
|
||||
|
||||
@@ -853,3 +879,25 @@ std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) {
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
void IfcFile::filename(const std::string& s) { _filename = s; }
|
||||
std::string IfcFile::filename() const { return _filename; }
|
||||
void IfcFile::timestamp(const std::string& s) { _timestamp = s; }
|
||||
std::string IfcFile::timestamp() const { return _timestamp; }
|
||||
void IfcFile::author(const std::string& name, const std::string& email, const std::string& organisation) {
|
||||
_author = name;
|
||||
_author_email = email;
|
||||
_author_organisation = organisation;
|
||||
}
|
||||
std::string IfcFile::authorName() const { return _author; }
|
||||
std::string IfcFile::authorEmail() const { return _author_email; }
|
||||
std::string IfcFile::authorOrganisation() const { return _author_organisation; }
|
||||
void IfcFile::initTimestamp() {
|
||||
char buf[255];
|
||||
time_t t;
|
||||
time(&t);
|
||||
struct tm * ti = localtime (&t);
|
||||
if (strftime(buf,255,"%Y-%m-%dT%H:%M:%S",ti)) {
|
||||
_timestamp = std::string(buf);
|
||||
}
|
||||
}
|
||||
+26
-12
@@ -20,14 +20,14 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file provides functions for loading an IFC file into memory and access *
|
||||
* its entities either by ID, by an Ifc2x3::Type or by reference *
|
||||
* its entities either by ID, by an IfcSchema::Type or by reference *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCPARSE_H
|
||||
#define IFCPARSE_H
|
||||
|
||||
#define IFCOPENSHELL_VERSION "0.3.0-rc3"
|
||||
#define IFCOPENSHELL_VERSION "0.5.0-dev"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -40,10 +40,16 @@
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
#include "../ifcparse/IfcUntypedEntity.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
class Entity;
|
||||
@@ -162,9 +168,9 @@ namespace IfcParse {
|
||||
/// ===================== =====================
|
||||
class EntityArgument : public Argument {
|
||||
private:
|
||||
Ifc::IfcUntypedEntity* entity;
|
||||
IfcUntypedEntity* entity;
|
||||
public:
|
||||
EntityArgument(Ifc2x3::Type::Enum ty, const Token& t);
|
||||
EntityArgument(IfcSchema::Type::Enum ty, const Token& t);
|
||||
~EntityArgument();
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
@@ -189,7 +195,7 @@ namespace IfcParse {
|
||||
private:
|
||||
//IfcFile* file;
|
||||
ArgumentPtr args;
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
public:
|
||||
/// The EXPRESS ENTITY_INSTANCE_NAME
|
||||
unsigned int _id;
|
||||
@@ -198,20 +204,28 @@ namespace IfcParse {
|
||||
Entity(unsigned int i, IfcFile* t);
|
||||
Entity(unsigned int i, IfcFile* t, unsigned int o);
|
||||
~Entity();
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c, int i, const std::string& a);
|
||||
void Load(std::vector<unsigned int>& ids, bool seek=false);
|
||||
ArgumentPtr getArgument (unsigned int i);
|
||||
unsigned int getArgumentCount();
|
||||
std::string toString(bool upper=false);
|
||||
std::string datatype();
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
unsigned int id();
|
||||
bool isWritable();
|
||||
};
|
||||
|
||||
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v );
|
||||
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
||||
//typedef IfcEntities IfcEntities;
|
||||
typedef std::map<IfcSchema::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||
typedef std::map<std::string,IfcSchema::IfcRoot::ptr> MapEntityByGuid;
|
||||
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
|
||||
typedef std::map<unsigned int,unsigned int> MapOffsetById;
|
||||
|
||||
double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
// loads a file on disk into multiple chunks, has been disabled.
|
||||
// It proved to be an inefficient way of working with large files,
|
||||
// as often these did not facilitate to be parsed in a sequential
|
||||
// manner efficiently, to enable the paging functionality uncomment
|
||||
// manner efficiently. To enable the paging functionality uncomment
|
||||
// the following statement.
|
||||
//const int BUF_SIZE = (128 * 1024 * 1024);
|
||||
// #define BUF_SIZE (8 * 1024 * 1024)
|
||||
|
||||
namespace IfcParse {
|
||||
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
|
||||
@@ -48,7 +48,7 @@ namespace IfcParse {
|
||||
/// detrimental for the performance of the parser.
|
||||
class IfcSpfStream {
|
||||
private:
|
||||
std::ifstream stream;
|
||||
FILE* stream;
|
||||
char* buffer;
|
||||
unsigned int ptr;
|
||||
unsigned int len;
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
#include "IfcUtil.h"
|
||||
#include "IfcWrite.h"
|
||||
#include "Ifc2x3-rt.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/Ifc2x3-rt.h"
|
||||
|
||||
IfcWrite::IfcWritableEntity* Ifc::IfcUntypedEntity::writable_entity() {
|
||||
#include "IfcUntypedEntity.h"
|
||||
|
||||
using namespace IfcUtil;
|
||||
|
||||
IfcWrite::IfcWritableEntity* IfcParse::IfcUntypedEntity::writable_entity() {
|
||||
IfcWrite::IfcWritableEntity* e;
|
||||
if (entity->isWritable()) {
|
||||
e = (IfcWrite::IfcWritableEntity*) entity;
|
||||
@@ -15,130 +19,131 @@ IfcWrite::IfcWritableEntity* Ifc::IfcUntypedEntity::writable_entity() {
|
||||
}
|
||||
return e;
|
||||
}
|
||||
Ifc::IfcUntypedEntity::IfcUntypedEntity(const std::string& s) {
|
||||
IfcParse::IfcUntypedEntity::IfcUntypedEntity(const std::string& s) {
|
||||
std::string S = s;
|
||||
for (std::string::iterator i = S.begin(); i != S.end(); ++i ) *i = toupper(*i);
|
||||
_type = Ifc2x3::Type::FromString(S);
|
||||
_type = IfcSchema::Type::FromString(S);
|
||||
entity = new IfcWrite::IfcWritableEntity(_type);
|
||||
IfcSchema::Type::PopulateDerivedFields(writable_entity());
|
||||
}
|
||||
Ifc::IfcUntypedEntity::IfcUntypedEntity(IfcAbstractEntity* e) {
|
||||
IfcParse::IfcUntypedEntity::IfcUntypedEntity(IfcAbstractEntity* e) {
|
||||
entity = e;
|
||||
_type = e->type();
|
||||
}
|
||||
bool Ifc::IfcUntypedEntity::is(Ifc2x3::Type::Enum v) const {
|
||||
Ifc2x3::Type::Enum _ty = _type;
|
||||
bool IfcParse::IfcUntypedEntity::is(IfcSchema::Type::Enum v) const {
|
||||
IfcSchema::Type::Enum _ty = _type;
|
||||
if (v == _ty) return true;
|
||||
while (_ty != -1) {
|
||||
_ty = Ifc2x3::Type::Parent(_ty);
|
||||
_ty = IfcSchema::Type::Parent(_ty);
|
||||
if (v == _ty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::string Ifc::IfcUntypedEntity::is_a() const {
|
||||
return Ifc2x3::Type::ToString(_type);
|
||||
std::string IfcParse::IfcUntypedEntity::is_a() const {
|
||||
return IfcSchema::Type::ToString(_type);
|
||||
}
|
||||
bool Ifc::IfcUntypedEntity::is_a(const std::string& s) const {
|
||||
bool IfcParse::IfcUntypedEntity::is_a(const std::string& s) const {
|
||||
std::string S = s;
|
||||
for (std::string::iterator i = S.begin(); i != S.end(); ++i ) *i = toupper(*i);
|
||||
return is(Ifc2x3::Type::FromString(S));
|
||||
return is(IfcSchema::Type::FromString(S));
|
||||
}
|
||||
Ifc2x3::Type::Enum Ifc::IfcUntypedEntity::type() const {
|
||||
IfcSchema::Type::Enum IfcParse::IfcUntypedEntity::type() const {
|
||||
return _type;
|
||||
}
|
||||
unsigned int Ifc::IfcUntypedEntity::getArgumentCount() const {
|
||||
return Ifc2x3::Type::GetAttributeCount(_type);
|
||||
unsigned int IfcParse::IfcUntypedEntity::getArgumentCount() const {
|
||||
return IfcSchema::Type::GetAttributeCount(_type);
|
||||
}
|
||||
IfcUtil::ArgumentType Ifc::IfcUntypedEntity::getArgumentType(unsigned int i) const {
|
||||
return Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
IfcUtil::ArgumentType IfcParse::IfcUntypedEntity::getArgumentType(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeType(_type,i);
|
||||
}
|
||||
ArgumentPtr Ifc::IfcUntypedEntity::getArgument(unsigned int i) const {
|
||||
ArgumentPtr IfcParse::IfcUntypedEntity::getArgument(unsigned int i) const {
|
||||
return entity->getArgument(i);
|
||||
}
|
||||
const char* Ifc::IfcUntypedEntity::getArgumentName(unsigned int i) const {
|
||||
return Ifc2x3::Type::GetAttributeName(_type,i).c_str();
|
||||
const char* IfcParse::IfcUntypedEntity::getArgumentName(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeName(_type,i).c_str();
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::invalid_argument(unsigned int i, const std::string& t) {
|
||||
const std::string arg_name = Ifc2x3::Type::GetAttributeName(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::invalid_argument(unsigned int i, const std::string& t) {
|
||||
const std::string arg_name = IfcSchema::Type::GetAttributeName(_type,i);
|
||||
throw IfcException(t + " is not a valid type for '" + arg_name + "'");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i) {
|
||||
bool is_optional = Ifc2x3::Type::GetAttributeOptional(_type, i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i) {
|
||||
bool is_optional = IfcSchema::Type::GetAttributeOptional(_type, i);
|
||||
if (is_optional) {
|
||||
writable_entity()->setArgument(i);
|
||||
} else invalid_argument(i,"NULL");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, int v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, int v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_INT) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else if ( (arg_type == Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
|
||||
writable_entity()->setArgument(i, (bool) v);
|
||||
} else invalid_argument(i,"INT");
|
||||
writable_entity()->setArgument(i, v == 1);
|
||||
} else invalid_argument(i,"INT");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, bool v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, bool v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_BOOL) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"BOOL");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, double v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, double v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_DOUBLE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"DOUBLE");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, const std::string& a) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, const std::string& a) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_STRING) {
|
||||
writable_entity()->setArgument(i,a);
|
||||
} else if (arg_type == Argument_ENUMERATION) {
|
||||
std::pair<const char*, int> enum_data = Ifc2x3::Type::GetEnumerationIndex(Ifc2x3::Type::GetAttributeEnumerationClass(_type, i), a);
|
||||
std::pair<const char*, int> enum_data = IfcSchema::Type::GetEnumerationIndex(IfcSchema::Type::GetAttributeEnumerationClass(_type, i), a);
|
||||
writable_entity()->setArgument(i, enum_data.second, enum_data.first);
|
||||
} else invalid_argument(i,"STRING");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<int>& v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<int>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_VECTOR_INT) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"LIST of INT");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<double>& v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<double>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_VECTOR_DOUBLE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"LIST of DOUBLE");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<std::string>& v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, const std::vector<std::string>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_VECTOR_STRING) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"LIST of STRING");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, Ifc::IfcUntypedEntity* v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, IfcParse::IfcUntypedEntity* v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_ENTITY) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"ENTITY");
|
||||
}
|
||||
void Ifc::IfcUntypedEntity::setArgument(unsigned int i, IfcEntities v) {
|
||||
IfcUtil::ArgumentType arg_type = Ifc2x3::Type::GetAttributeType(_type,i);
|
||||
void IfcParse::IfcUntypedEntity::setArgument(unsigned int i, IfcEntities v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(_type,i);
|
||||
if (arg_type == Argument_ENTITY_LIST) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"LIST of ENTITY");
|
||||
}
|
||||
std::pair<IfcUtil::ArgumentType,ArgumentPtr> Ifc::IfcUntypedEntity::get_argument(unsigned i) {
|
||||
std::pair<IfcUtil::ArgumentType,ArgumentPtr> IfcParse::IfcUntypedEntity::get_argument(unsigned i) {
|
||||
return std::pair<IfcUtil::ArgumentType,ArgumentPtr>(getArgumentType(i),getArgument(i));
|
||||
}
|
||||
std::pair<IfcUtil::ArgumentType,ArgumentPtr> Ifc::IfcUntypedEntity::get_argument(const std::string& a) {
|
||||
return get_argument(Ifc2x3::Type::GetAttributeIndex(_type,a));
|
||||
std::pair<IfcUtil::ArgumentType,ArgumentPtr> IfcParse::IfcUntypedEntity::get_argument(const std::string& a) {
|
||||
return get_argument(IfcSchema::Type::GetAttributeIndex(_type,a));
|
||||
}
|
||||
unsigned Ifc::IfcUntypedEntity::getArgumentIndex(const std::string& a) const {
|
||||
return Ifc2x3::Type::GetAttributeIndex(_type,a);
|
||||
unsigned IfcParse::IfcUntypedEntity::getArgumentIndex(const std::string& a) const {
|
||||
return IfcSchema::Type::GetAttributeIndex(_type,a);
|
||||
}
|
||||
std::string Ifc::IfcUntypedEntity::toString() {
|
||||
std::string IfcParse::IfcUntypedEntity::toString() {
|
||||
return entity->toString(false);
|
||||
}
|
||||
bool Ifc::IfcUntypedEntity::is_valid() {
|
||||
bool IfcParse::IfcUntypedEntity::is_valid() {
|
||||
const unsigned arg_count = getArgumentCount();
|
||||
bool valid = true;
|
||||
std::ostringstream oss;
|
||||
@@ -149,7 +154,7 @@ bool Ifc::IfcUntypedEntity::is_valid() {
|
||||
const Argument& arg = *getArgument(i);
|
||||
is_null = arg.isNull();
|
||||
} catch(IfcException) {}
|
||||
if (!Ifc2x3::Type::GetAttributeOptional(_type,i) && is_null) {
|
||||
if (!IfcSchema::Type::GetAttributeOptional(_type,i) && is_null) {
|
||||
if (!valid) {
|
||||
oss << ", ";
|
||||
}
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "IfcUtil.h"
|
||||
#include "IfcWrite.h"
|
||||
#include "IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace Ifc {
|
||||
namespace IfcParse {
|
||||
|
||||
class IfcUntypedEntity : public IfcUtil::IfcBaseEntity {
|
||||
private:
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
IfcWrite::IfcWritableEntity* writable_entity();
|
||||
void invalid_argument(unsigned int i, const std::string& t);
|
||||
public:
|
||||
IfcUntypedEntity(const std::string& s);
|
||||
IfcUntypedEntity(IfcAbstractEntity* e);
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is_a(const std::string& s) const;
|
||||
std::string is_a() const;
|
||||
unsigned int getArgumentCount() const;
|
||||
|
||||
@@ -34,14 +34,14 @@ IfcEntityList::it IfcEntityList::end() { return ls.end(); }
|
||||
IfcUtil::IfcSchemaEntity IfcEntityList::operator[] (int i) {
|
||||
return ls[i];
|
||||
}
|
||||
IfcEntities IfcEntityList::getInverse(Ifc2x3::Type::Enum c) {
|
||||
IfcEntities IfcEntityList::getInverse(IfcSchema::Type::Enum c) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
for( it i = begin(); i != end(); ++i ) {
|
||||
l->push((*i)->entity->getInverse(c));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
IfcEntities IfcEntityList::getInverse(Ifc2x3::Type::Enum c, int ar, const std::string& a) {
|
||||
IfcEntities IfcEntityList::getInverse(IfcSchema::Type::Enum c, int ar, const std::string& a) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
for( it i = begin(); i != end(); ++i ) {
|
||||
l->push((*i)->entity->getInverse(c,ar,a));
|
||||
@@ -49,16 +49,16 @@ IfcEntities IfcEntityList::getInverse(Ifc2x3::Type::Enum c, int ar, const std::s
|
||||
return l;
|
||||
}
|
||||
|
||||
bool IfcUtil::IfcEntitySelect::is(Ifc2x3::Type::Enum v) const { return entity->is(v); }
|
||||
Ifc2x3::Type::Enum IfcUtil::IfcEntitySelect::type() const { return entity->type(); }
|
||||
bool IfcUtil::IfcEntitySelect::is(IfcSchema::Type::Enum v) const { return entity->is(v); }
|
||||
IfcSchema::Type::Enum IfcUtil::IfcEntitySelect::type() const { return entity->type(); }
|
||||
IfcUtil::IfcEntitySelect::IfcEntitySelect(IfcSchemaEntity b) { entity = b->entity; }
|
||||
IfcUtil::IfcEntitySelect::IfcEntitySelect(IfcAbstractEntityPtr e) { entity = e; }
|
||||
bool IfcUtil::IfcEntitySelect::isSimpleType() { return false; }
|
||||
IfcUtil::IfcEntitySelect::~IfcEntitySelect() { delete entity; }
|
||||
|
||||
bool IfcUtil::IfcArgumentSelect::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
||||
Ifc2x3::Type::Enum IfcUtil::IfcArgumentSelect::type() const { return _type; }
|
||||
IfcUtil::IfcArgumentSelect::IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr a) { _type = t; arg = a; }
|
||||
bool IfcUtil::IfcArgumentSelect::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
IfcSchema::Type::Enum IfcUtil::IfcArgumentSelect::type() const { return _type; }
|
||||
IfcUtil::IfcArgumentSelect::IfcArgumentSelect(IfcSchema::Type::Enum t, ArgumentPtr a) { _type = t; arg = a; }
|
||||
ArgumentPtr IfcUtil::IfcArgumentSelect::wrappedValue() { return arg; }
|
||||
bool IfcUtil::IfcArgumentSelect::isSimpleType() { return true; }
|
||||
IfcUtil::IfcArgumentSelect::~IfcArgumentSelect() { delete arg; }
|
||||
@@ -83,6 +83,11 @@ void Logger::Status(const std::string& message, bool new_line) {
|
||||
else (*log1) << std::flush;
|
||||
}
|
||||
}
|
||||
void Logger::ProgressBar(int progress) {
|
||||
if ( log1 ) {
|
||||
Status("\r[" + std::string(progress,'#') + std::string(50 - progress,' ') + "]", false);
|
||||
}
|
||||
}
|
||||
std::string Logger::GetLog() {
|
||||
return log_stream.str();
|
||||
}
|
||||
|
||||
+40
-109
@@ -23,14 +23,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#include "../ifcparse/ArgumentType.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4enum.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#endif
|
||||
|
||||
class IfcAbstractEntity;
|
||||
//typedef SHARED_PTR<IfcAbstractEntity> IfcAbstractEntityPtr;
|
||||
@@ -52,102 +52,18 @@ inline T* reinterpret_pointer_cast(F* from) {
|
||||
}
|
||||
|
||||
namespace IfcUtil {
|
||||
enum ArgumentType {
|
||||
Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENTITY_LIST_LIST, Argument_ENUMERATION, Argument_UNKNOWN
|
||||
};
|
||||
}
|
||||
|
||||
class IfcEnumerationDescriptor {
|
||||
private:
|
||||
Ifc2x3::Type::Enum type;
|
||||
std::vector<std::string> values;
|
||||
public:
|
||||
IfcEnumerationDescriptor(Ifc2x3::Type::Enum type, const std::vector<std::string>& values)
|
||||
: type(type), values(values) {}
|
||||
std::pair<const char*, int> getIndex(const std::string& value) const {
|
||||
std::vector<std::string>::const_iterator it = std::find(values.begin(), values.end(), value);
|
||||
if (it != values.end()) {
|
||||
return std::make_pair(it->c_str(), std::distance(it, values.begin()));
|
||||
} else {
|
||||
throw IfcParse::IfcException("Invalid enumeration value");
|
||||
}
|
||||
}
|
||||
const std::vector<std::string>& getValues() {
|
||||
return values;
|
||||
}
|
||||
Ifc2x3::Type::Enum getType() {
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
class IfcEntityDescriptor {
|
||||
public:
|
||||
class IfcArgumentDescriptor
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
bool optional;
|
||||
ArgumentType argument_type;
|
||||
Ifc2x3::Type::Enum data_type;
|
||||
IfcArgumentDescriptor(const std::string& name, bool optional, ArgumentType argument_type, Ifc2x3::Type::Enum data_type)
|
||||
: name(name), optional(optional), argument_type(argument_type), data_type(data_type) {}
|
||||
};
|
||||
private:
|
||||
Ifc2x3::Type::Enum type;
|
||||
IfcEntityDescriptor* parent;
|
||||
std::vector<IfcArgumentDescriptor> arguments;
|
||||
unsigned argument_start() const {
|
||||
return parent ? parent->getArgumentCount() : 0;
|
||||
}
|
||||
const IfcArgumentDescriptor& get_argument(unsigned i) const {
|
||||
if (i < arguments.size()) return arguments[i];
|
||||
else throw IfcParse::IfcException("Argument out of range");
|
||||
}
|
||||
public:
|
||||
IfcEntityDescriptor(Ifc2x3::Type::Enum type, IfcEntityDescriptor* parent)
|
||||
: type(type), parent(parent) {}
|
||||
void add(const std::string& name, bool optional, ArgumentType argument_type, Ifc2x3::Type::Enum data_type = Ifc2x3::Type::ALL) {
|
||||
arguments.push_back(IfcArgumentDescriptor(name, optional, argument_type, data_type));
|
||||
}
|
||||
unsigned getArgumentCount() const {
|
||||
return (parent ? parent->getArgumentCount() : 0) + arguments.size();
|
||||
}
|
||||
const std::string& getArgumentName(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentName(i)
|
||||
: get_argument(i-a).name;
|
||||
}
|
||||
ArgumentType getArgumentType(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentType(i)
|
||||
: get_argument(i-a).argument_type;
|
||||
}
|
||||
bool getArgumentOptional(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentOptional(i)
|
||||
: get_argument(i-a).optional;
|
||||
}
|
||||
Ifc2x3::Type::Enum getArgumentEnumerationClass(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentEnumerationClass(i)
|
||||
: get_argument(i-a).data_type;
|
||||
}
|
||||
unsigned getArgumentIndex(const std::string& s) const {
|
||||
unsigned a = argument_start();
|
||||
for(std::vector<IfcArgumentDescriptor>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) {
|
||||
if (i->name == s) return a;
|
||||
a++;
|
||||
}
|
||||
if (parent) return parent->getArgumentIndex(s);
|
||||
throw IfcParse::IfcException(std::string("Argument ") + s + " not found on " + Ifc2x3::Type::ToString(type));
|
||||
}
|
||||
};
|
||||
namespace IfcUtil {
|
||||
|
||||
class IfcBaseClass {
|
||||
public:
|
||||
IfcAbstractEntityPtr entity;
|
||||
virtual bool is(Ifc2x3::Type::Enum v) const = 0;
|
||||
virtual Ifc2x3::Type::Enum type() const = 0;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
};
|
||||
|
||||
class IfcBaseEntity : public IfcBaseClass {
|
||||
@@ -163,18 +79,27 @@ typedef IfcBaseClass* IfcSchemaEntity;
|
||||
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityList;
|
||||
|
||||
class IfcEntityList {
|
||||
std::vector<IfcUtil::IfcSchemaEntity> ls;
|
||||
public:
|
||||
typedef std::vector<IfcUtil::IfcSchemaEntity>::const_iterator it;
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c, int i, const std::string& a);
|
||||
void push(IfcUtil::IfcSchemaEntity l);
|
||||
void push(IfcEntities l);
|
||||
it begin();
|
||||
it end();
|
||||
IfcUtil::IfcSchemaEntity operator[] (int i);
|
||||
int Size() const;
|
||||
template <class U>
|
||||
typename U::list as() {
|
||||
typename U::list r(new IfcTemplatedEntityList<U>());
|
||||
for ( it i = begin(); i != end(); ++ i ) if ((*i)->is(U::Class())) r->push((U*)*i);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -186,13 +111,18 @@ public:
|
||||
inline void push(SHARED_PTR< IfcTemplatedEntityList<T> > t) { for ( typename T::it it = t->begin(); it != t->end(); ++it ) push(*it); }
|
||||
inline it begin() { return ls.begin(); }
|
||||
inline it end() { return ls.end(); }
|
||||
//inline T operator[] (int i) { return ls[i]; }
|
||||
inline unsigned int Size() const { return (unsigned int) ls.size(); }
|
||||
IfcEntities generalize() {
|
||||
IfcEntities r (new IfcEntityList());
|
||||
for ( it i = begin(); i != end(); ++ i ) r->push(*i);
|
||||
return r;
|
||||
}
|
||||
template <class U>
|
||||
typename U::list as() {
|
||||
typename U::list r(new IfcTemplatedEntityList<U>());
|
||||
for ( it i = begin(); i != end(); ++ i ) if ((*i)->is(U::Class())) r->push(*i);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
namespace IfcUtil {
|
||||
@@ -209,20 +139,20 @@ namespace IfcUtil {
|
||||
IfcEntitySelect(IfcSchemaEntity b);
|
||||
IfcEntitySelect(IfcAbstractEntityPtr e);
|
||||
~IfcEntitySelect();
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool isSimpleType();
|
||||
};
|
||||
class IfcArgumentSelect : public IfcAbstractSelect {
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
ArgumentPtr arg;
|
||||
public:
|
||||
typedef IfcArgumentSelect* ptr;
|
||||
IfcArgumentSelect(Ifc2x3::Type::Enum t, ArgumentPtr a);
|
||||
IfcArgumentSelect(IfcSchema::Type::Enum t, ArgumentPtr a);
|
||||
~IfcArgumentSelect();
|
||||
ArgumentPtr wrappedValue();
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool isSimpleType();
|
||||
};
|
||||
}
|
||||
@@ -255,14 +185,14 @@ public:
|
||||
class IfcAbstractEntity {
|
||||
public:
|
||||
IfcParse::IfcFile* file;
|
||||
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL) = 0;
|
||||
virtual IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) = 0;
|
||||
virtual IfcEntities getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL) = 0;
|
||||
virtual IfcEntities getInverse(IfcSchema::Type::Enum c, int i, const std::string& a) = 0;
|
||||
virtual std::string datatype() = 0;
|
||||
virtual ArgumentPtr getArgument (unsigned int i) = 0;
|
||||
virtual unsigned int getArgumentCount() = 0;
|
||||
virtual ~IfcAbstractEntity() {};
|
||||
virtual Ifc2x3::Type::Enum type() const = 0;
|
||||
virtual bool is(Ifc2x3::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual std::string toString(bool upper=false) = 0;
|
||||
virtual unsigned int id() = 0;
|
||||
virtual bool isWritable() = 0;
|
||||
@@ -286,6 +216,7 @@ public:
|
||||
/// Log a message to the output stream
|
||||
static void Message(Severity type, const std::string& message, const IfcAbstractEntityPtr entity=0);
|
||||
static void Status(const std::string& message, bool new_line=true);
|
||||
static void ProgressBar(int progress);
|
||||
static std::string GetLog();
|
||||
};
|
||||
|
||||
|
||||
@@ -40,25 +40,29 @@ namespace IfcWrite {
|
||||
private:
|
||||
std::map<int,bool> writemask;
|
||||
std::map<int,ArgumentPtr> args;
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
int* _id;
|
||||
bool arg_writable(int i);
|
||||
void arg_writable(int i, bool b);
|
||||
template <typename T> void _setArgument(int i, const T&);
|
||||
public:
|
||||
IfcWritableEntity(Ifc2x3::Type::Enum t);
|
||||
IfcWritableEntity(IfcSchema::Type::Enum t);
|
||||
~IfcWritableEntity();
|
||||
int setId(int i=-1);
|
||||
IfcWritableEntity(IfcAbstractEntity* e);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c = Ifc2x3::Type::ALL);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c = IfcSchema::Type::ALL);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum c, int i, const std::string& a);
|
||||
std::string datatype();
|
||||
ArgumentPtr getArgument (unsigned int i);
|
||||
unsigned int getArgumentCount();
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
std::string toString(bool upper=false);
|
||||
unsigned int id();
|
||||
bool isWritable();
|
||||
void setArgument(int i);
|
||||
void setArgumentDerived(int i);
|
||||
void setArgument(int i,bool v);
|
||||
void setArgument(int i,int v);
|
||||
void setArgument(int i,int v, const char* c);
|
||||
void setArgument(int i,const std::string& v);
|
||||
|
||||
+187
-227
@@ -25,11 +25,14 @@
|
||||
|
||||
using namespace IfcWrite;
|
||||
|
||||
IfcWritableEntity::IfcWritableEntity(Ifc2x3::Type::Enum t) {
|
||||
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
|
||||
_type = t;
|
||||
_id = 0;
|
||||
file = 0;
|
||||
}
|
||||
IfcWritableEntity::~IfcWritableEntity() {
|
||||
delete _id;
|
||||
}
|
||||
int IfcWritableEntity::setId(int i) {
|
||||
return *(_id = new int(i > 0 ? i : file->FreshId()));
|
||||
}
|
||||
@@ -46,19 +49,19 @@ IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
|
||||
}
|
||||
}
|
||||
// TODO: Reove redundancy with IfcParse::Entity
|
||||
IfcEntities IfcWritableEntity::getInverse(Ifc2x3::Type::Enum c) {
|
||||
IfcEntities IfcWritableEntity::getInverse(IfcSchema::Type::Enum c) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
int id = _id ? *_id : setId();
|
||||
IfcEntities all = file->EntitiesByReference(id);
|
||||
if ( ! all ) return l;
|
||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
||||
if ( c == IfcSchema::Type::ALL || (*it)->is(c) ) {
|
||||
l->push(*it);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
IfcEntities IfcWritableEntity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) {
|
||||
IfcEntities IfcWritableEntity::getInverse(IfcSchema::Type::Enum c, int i, const std::string& a) {
|
||||
IfcEntities l = IfcEntities(new IfcEntityList());
|
||||
IfcEntities all = getInverse(c);
|
||||
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
||||
@@ -70,11 +73,11 @@ IfcEntities IfcWritableEntity::getInverse(Ifc2x3::Type::Enum c, int i, const std
|
||||
return l;
|
||||
}
|
||||
|
||||
std::string IfcWritableEntity::datatype() { return Ifc2x3::Type::ToString(_type); }
|
||||
std::string IfcWritableEntity::datatype() { return IfcSchema::Type::ToString(_type); }
|
||||
ArgumentPtr IfcWritableEntity::getArgument (unsigned int i) { if ( i >= getArgumentCount() ) throw IfcParse::IfcException("Argument not set"); return args[i]; }
|
||||
unsigned int IfcWritableEntity::getArgumentCount() {return args.size(); }
|
||||
Ifc2x3::Type::Enum IfcWritableEntity::type() const { return _type; }
|
||||
bool IfcWritableEntity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
||||
IfcSchema::Type::Enum IfcWritableEntity::type() const { return _type; }
|
||||
bool IfcWritableEntity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
std::string IfcWritableEntity::toString(bool upper) {
|
||||
std::stringstream ss;
|
||||
std::string dt = datatype();
|
||||
@@ -91,7 +94,12 @@ std::string IfcWritableEntity::toString(bool upper) {
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
}
|
||||
unsigned int IfcWritableEntity::id() { if ( !_id ) _id = new int(file->FreshId()); return *_id; }
|
||||
unsigned int IfcWritableEntity::id() {
|
||||
if ( !_id ) {
|
||||
_id = new int(file->FreshId());
|
||||
}
|
||||
return *_id;
|
||||
}
|
||||
bool IfcWritableEntity::isWritable() { return true; }
|
||||
bool IfcWritableEntity::arg_writable(int i) {
|
||||
std::map<int,bool>::const_iterator it = writemask.find(i);
|
||||
@@ -101,254 +109,201 @@ bool IfcWritableEntity::arg_writable(int i) {
|
||||
void IfcWritableEntity::arg_writable(int i, bool b) {
|
||||
writemask[i] = b;
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i) {
|
||||
|
||||
template <typename T> void IfcWritableEntity::_setArgument(int i, const T& t) {
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteNullArgument();
|
||||
IfcWriteArgument* arg = new IfcWriteArgument(this);
|
||||
args[i] = arg;
|
||||
arg->set(t);
|
||||
arg_writable(i,true);
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgument(int i) {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
void IfcWritableEntity::setArgumentDerived(int i) {
|
||||
_setArgument(i, IfcWriteArgument::Derived());
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v) {
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,bool v) {
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v, const char* c){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteEnumerationArgument(v,c);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, IfcWriteArgument::EnumerationReference(v, c));
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::string& v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,double v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcSchemaEntity v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
if ( v ) args[i] = new IfcWriteIntegralArgument(v);
|
||||
else args[i] = new IfcWriteNullArgument();
|
||||
arg_writable(i,true);
|
||||
if ( v ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcEntities v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
if ( v.get() ) args[i] = new IfcWriteEntityListArgument(v);
|
||||
else args[i] = new IfcWriteNullArgument();
|
||||
arg_writable(i,true);
|
||||
if ( v.get() ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<double>& v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<std::string>& v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<int>& v){
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
args[i] = new IfcWriteIntegralArgument(v);
|
||||
arg_writable(i,true);
|
||||
_setArgument(i, v);
|
||||
}
|
||||
|
||||
IfcWriteNullArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator std::string() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator std::vector<double>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator std::vector<int>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator std::vector<std::string>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteNullArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
bool IfcWriteNullArgument::isNull() const { return true; }
|
||||
ArgumentPtr IfcWriteNullArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
std::string IfcWriteNullArgument::toString(bool upper) const { return "$"; }
|
||||
unsigned int IfcWriteNullArgument::Size() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
class SizeVisitor : public boost::static_visitor<int> {
|
||||
public:
|
||||
int operator()(const boost::none_t& i) const { return -1; }
|
||||
int operator()(const IfcWriteArgument::Derived& i) const { return -1; }
|
||||
int operator()(const int& i) const { return -1; }
|
||||
int operator()(const bool& i) const { return -1; }
|
||||
int operator()(const double& i) const { return -1; }
|
||||
int operator()(const std::string& i) const { return i.size(); }
|
||||
int operator()(const std::vector<int>& i) const { return i.size(); }
|
||||
int operator()(const std::vector<double>& i) const { return i.size(); }
|
||||
int operator()(const std::vector<std::string>& i) const { return i.size(); }
|
||||
int operator()(const IfcWriteArgument::EnumerationReference& i) const { return -1; }
|
||||
int operator()(const IfcUtil::IfcSchemaEntity& i) const { return -1; }
|
||||
int operator()(const IfcEntities& i) const { return i->Size(); }
|
||||
};
|
||||
|
||||
IfcWriteEntityListArgument::IfcWriteEntityListArgument(const IfcEntities& v) { value = v; }
|
||||
IfcWriteEntityListArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator std::string() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator std::vector<double>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator std::vector<int>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator std::vector<std::string>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEntityListArgument::operator IfcEntities() const { return value; }
|
||||
bool IfcWriteEntityListArgument::isNull() const { return false; }
|
||||
unsigned int IfcWriteEntityListArgument::Size() const { return value->Size(); }
|
||||
ArgumentPtr IfcWriteEntityListArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
std::string IfcWriteEntityListArgument::toString(bool upper) const {
|
||||
std::ostringstream ss;
|
||||
ss << "(";
|
||||
for ( IfcEntityList::it it = value->begin(); it != value->end(); ++ it ) {
|
||||
if ( it != value->begin() ) ss << ",";
|
||||
IfcAbstractEntity* e = (*it)->entity;
|
||||
if ( Ifc2x3::Type::IsSimple(e->type()) ) {
|
||||
ss << e->toString(upper);
|
||||
class StringBuilderVisitor : public boost::static_visitor<void> {
|
||||
private:
|
||||
std::ostringstream& data;
|
||||
template <typename T> void serialize(const std::vector<T>& i) {
|
||||
data << "(";
|
||||
for (typename std::vector<T>::const_iterator it = i.begin(); it != i.end(); ++it) {
|
||||
if (it != i.begin()) data << ",";
|
||||
data << *it;
|
||||
}
|
||||
data << ")";
|
||||
}
|
||||
// The REAL token definition from the IFC SPF standard does not necessarily match
|
||||
// the output of the C++ ostream formatting operation.
|
||||
// REAL = [ SIGN ] DIGIT { DIGIT } "." { DIGIT } [ "E" [ SIGN ] DIGIT { DIGIT } ] .
|
||||
std::string format_double(const double& d) {
|
||||
std::ostringstream oss;
|
||||
oss << d;
|
||||
const std::string str = oss.str();
|
||||
oss.str("");
|
||||
std::string::size_type e = str.find('e');
|
||||
if (e == std::string::npos) {
|
||||
e = str.find('E');
|
||||
}
|
||||
const std::string mantissa = str.substr(0,e);
|
||||
oss << mantissa;
|
||||
if (mantissa.find('.') == std::string::npos) {
|
||||
oss << ".";
|
||||
}
|
||||
if (e != std::string::npos) {
|
||||
oss << "E";
|
||||
oss << str.substr(e+1);
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
void serialize_double(const std::vector<double>& i) {
|
||||
data << "(";
|
||||
for (std::vector<double>::const_iterator it = i.begin(); it != i.end(); ++it) {
|
||||
if (it != i.begin()) data << ",";
|
||||
data << format_double(*it);
|
||||
}
|
||||
data << ")";
|
||||
}
|
||||
bool upper;
|
||||
public:
|
||||
StringBuilderVisitor(std::ostringstream& stream, bool upper = false)
|
||||
: data(stream), upper(upper) {}
|
||||
void operator()(const boost::none_t& i) { data << "$"; }
|
||||
void operator()(const IfcWriteArgument::Derived& i) { data << "*"; }
|
||||
void operator()(const int& i) { data << i; }
|
||||
void operator()(const bool& i) { data << (i ? ".T." : ".F."); }
|
||||
void operator()(const double& i) { data << format_double(i); }
|
||||
void operator()(const std::string& i) {
|
||||
std::string s = i;
|
||||
if (upper) s = IfcCharacterEncoder(s);
|
||||
data << s;
|
||||
}
|
||||
void operator()(const std::vector<int>& i) { serialize(i); }
|
||||
void operator()(const std::vector<double>& i) { serialize_double(i); }
|
||||
void operator()(const std::vector<std::string>& i) { serialize(i); }
|
||||
void operator()(const IfcWriteArgument::EnumerationReference& i) {
|
||||
data << "." << i.enumeration_value << ".";
|
||||
}
|
||||
void operator()(const IfcUtil::IfcSchemaEntity& i) {
|
||||
IfcAbstractEntity* e = i->entity;
|
||||
if ( IfcSchema::Type::IsSimple(e->type()) ) {
|
||||
data << e->toString(upper);
|
||||
} else {
|
||||
if (e->file) {
|
||||
ss << "#" << e->id();
|
||||
data << "#" << e->id();
|
||||
} else {
|
||||
ss << "#?";
|
||||
data << "#?";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
IfcWriteEnumerationArgument::IfcWriteEnumerationArgument(int v, const char* c) {data=v; enumeration_value = c;}
|
||||
IfcWriteEnumerationArgument::operator int() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator bool() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator double() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator std::string() const { return std::string(enumeration_value); }
|
||||
IfcWriteEnumerationArgument::operator std::vector<double>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator std::vector<int>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator std::vector<std::string>() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator IfcUtil::IfcSchemaEntity() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWriteEnumerationArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
bool IfcWriteEnumerationArgument::isNull() const { return false; }
|
||||
ArgumentPtr IfcWriteEnumerationArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
std::string IfcWriteEnumerationArgument::toString(bool upper) const { return std::string(".") + enumeration_value + '.';}
|
||||
unsigned int IfcWriteEnumerationArgument::Size() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(int v) {data=new int(v); type = Argument_INT;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(bool v) {data=new bool(v); type = Argument_BOOL;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(double v) {data=new double(v); type = Argument_DOUBLE;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(const std::string& v) {data=new std::string(v); type = Argument_STRING;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(const std::vector<int> v) {data=new std::vector<int>(v); type = Argument_VECTOR_INT;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(const std::vector<double> v) {data=new std::vector<double>(v); type = Argument_VECTOR_DOUBLE;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(const std::vector<std::string> v) {data=new std::vector<std::string>(v); type = Argument_VECTOR_STRING;}
|
||||
IfcWriteIntegralArgument::IfcWriteIntegralArgument(IfcUtil::IfcSchemaEntity v) {data=v; type = Argument_ENTITY;}
|
||||
IfcWriteIntegralArgument::~IfcWriteIntegralArgument() {
|
||||
switch ( type ) {
|
||||
case Argument_INT:
|
||||
delete (int*) data;
|
||||
break;
|
||||
case Argument_BOOL:
|
||||
delete (bool*) data;
|
||||
break;
|
||||
case Argument_DOUBLE:
|
||||
delete (double*) data;
|
||||
break;
|
||||
case Argument_STRING:
|
||||
delete (std::string*) data;
|
||||
break;
|
||||
case Argument_VECTOR_INT:
|
||||
delete (std::vector<int>*) data;
|
||||
break;
|
||||
case Argument_VECTOR_DOUBLE:
|
||||
delete (std::vector<double>*) data;
|
||||
break;
|
||||
case Argument_VECTOR_STRING:
|
||||
delete (std::vector<std::string>*) data;
|
||||
break;
|
||||
case Argument_ENTITY:
|
||||
break;
|
||||
void operator()(const IfcEntities& i) {
|
||||
data << "(";
|
||||
for (IfcEntityList::it it = i->begin(); it != i->end(); ++it) {
|
||||
if (it != i->begin()) data << ",";
|
||||
(*this)(*it);
|
||||
}
|
||||
data << ")";
|
||||
}
|
||||
operator std::string() { return data.str(); }
|
||||
};
|
||||
|
||||
IfcWriteArgument::operator int() const { return as<int>(); }
|
||||
IfcWriteArgument::operator bool() const { return as<bool>(); }
|
||||
IfcWriteArgument::operator double() const { return as<double>(); }
|
||||
IfcWriteArgument::operator std::string() const { return as<std::string>(); }
|
||||
IfcWriteArgument::operator std::vector<double>() const { return as<std::vector<double> >(); }
|
||||
IfcWriteArgument::operator std::vector<int>() const { return as<std::vector<int> >(); }
|
||||
IfcWriteArgument::operator std::vector<std::string>() const { return as<std::vector<std::string > >(); }
|
||||
IfcWriteArgument::operator IfcUtil::IfcSchemaEntity() const { return as<IfcUtil::IfcSchemaEntity>(); }
|
||||
IfcWriteArgument::operator IfcEntities() const { return as<IfcEntities>(); }
|
||||
bool IfcWriteArgument::isNull() const { return argumentType() == argument_type_null; }
|
||||
ArgumentPtr IfcWriteArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
std::string IfcWriteArgument::toString(bool upper) const {
|
||||
std::ostringstream str;
|
||||
StringBuilderVisitor v(str, upper);
|
||||
container.apply_visitor(v);
|
||||
return v;
|
||||
}
|
||||
IfcWriteIntegralArgument::operator int() const { if ( type != Argument_INT ) throw IfcParse::IfcException("Invalid cast"); return *(int*)data; }
|
||||
IfcWriteIntegralArgument::operator bool() const { if ( type != Argument_BOOL ) throw IfcParse::IfcException("Invalid cast"); return *(bool*)data; }
|
||||
IfcWriteIntegralArgument::operator double() const { if ( type != Argument_DOUBLE ) throw IfcParse::IfcException("Invalid cast"); return *(double*)data; }
|
||||
IfcWriteIntegralArgument::operator std::string() const { if ( type != Argument_STRING ) throw IfcParse::IfcException("Invalid cast"); return *(std::string*)data; }
|
||||
IfcWriteIntegralArgument::operator std::vector<double>() const { if ( type != Argument_VECTOR_DOUBLE ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector<double>*)data; }
|
||||
IfcWriteIntegralArgument::operator std::vector<int>() const { if ( type != Argument_VECTOR_INT ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector<int>*)data; }
|
||||
IfcWriteIntegralArgument::operator std::vector<std::string>() const { if ( type != Argument_VECTOR_STRING ) throw IfcParse::IfcException("Invalid cast"); return *(std::vector<std::string>*)data; }
|
||||
IfcWriteIntegralArgument::operator IfcUtil::IfcSchemaEntity() const { if ( type != Argument_ENTITY ) throw IfcParse::IfcException("Invalid cast"); return (IfcUtil::IfcSchemaEntity)data; }
|
||||
IfcWriteIntegralArgument::operator IfcEntities() const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
bool IfcWriteIntegralArgument::isNull() const { return false; }
|
||||
unsigned int IfcWriteIntegralArgument::Size() const {
|
||||
switch ( type ) {
|
||||
case Argument_VECTOR_INT:
|
||||
return ((std::vector<int>*) data)->size();
|
||||
break;
|
||||
case Argument_VECTOR_DOUBLE:
|
||||
return ((std::vector<double>*) data)->size();
|
||||
break;
|
||||
case Argument_VECTOR_STRING:
|
||||
return ((std::vector<std::string>*) data)->size();
|
||||
break;
|
||||
default:
|
||||
unsigned int IfcWriteArgument::Size() const {
|
||||
SizeVisitor v;
|
||||
const int size = container.apply_visitor(v);
|
||||
if (size == -1) {
|
||||
throw IfcParse::IfcException("Invalid cast");
|
||||
break;
|
||||
} else {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
ArgumentPtr IfcWriteIntegralArgument::operator [] (unsigned int i) const { throw IfcParse::IfcException("Invalid cast"); }
|
||||
std::string IfcWriteIntegralArgument::toString(bool upper) const {
|
||||
std::ostringstream ss;
|
||||
switch ( type ) {
|
||||
case Argument_INT:
|
||||
ss << *(int*)data;
|
||||
break;
|
||||
case Argument_BOOL:
|
||||
ss << ((*(bool*) data) ? ".T." : ".F.");
|
||||
break;
|
||||
case Argument_DOUBLE:
|
||||
ss << *(double*) data;
|
||||
break;
|
||||
case Argument_STRING: {
|
||||
std::string d = *(std::string*) data;
|
||||
if ( upper ) d = IfcCharacterEncoder(d);
|
||||
ss << d;
|
||||
break;
|
||||
} case Argument_VECTOR_INT:
|
||||
ss << "(";
|
||||
{const std::vector<int>& v = *(std::vector<int>*) data;
|
||||
for ( std::vector<int>::const_iterator it = v.begin(); it != v.end(); ++ it ) {
|
||||
if ( it != v.begin() ) ss << ",";
|
||||
ss << *it;
|
||||
}}
|
||||
ss << ")";
|
||||
break;
|
||||
case Argument_VECTOR_DOUBLE:
|
||||
ss << "(";
|
||||
{const std::vector<double>& v = *(std::vector<double>*) data;
|
||||
for ( std::vector<double>::const_iterator it = v.begin(); it != v.end(); ++ it ) {
|
||||
if ( it != v.begin() ) ss << ",";
|
||||
ss << *it;
|
||||
}}
|
||||
ss << ")";
|
||||
break;
|
||||
case Argument_VECTOR_STRING:
|
||||
ss << "(";
|
||||
{const std::vector<std::string>& v = *(std::vector<std::string>*) data;
|
||||
for ( std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++ it ) {
|
||||
if ( it != v.begin() ) ss << ",";
|
||||
ss << '\'' << *it << '\'';
|
||||
}}
|
||||
ss << ")";
|
||||
break;
|
||||
case Argument_ENTITY:
|
||||
{IfcAbstractEntity* e = ((IfcUtil::IfcSchemaEntity)data)->entity;
|
||||
if ( Ifc2x3::Type::IsSimple(e->type()) ) {
|
||||
ss << e->toString(upper);
|
||||
} else {
|
||||
if (e->file) {
|
||||
ss << "#" << e->id();
|
||||
} else {
|
||||
ss << "#?";
|
||||
}
|
||||
}}
|
||||
break;
|
||||
default: throw IfcParse::IfcException("Invalid cast");
|
||||
}
|
||||
return ss.str();
|
||||
IfcWriteArgument::argument_type IfcWriteArgument::argumentType() const {
|
||||
return static_cast<argument_type>(container.which());
|
||||
}
|
||||
|
||||
IfcEntities IfcSelectHelperEntity::getInverse(Ifc2x3::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");}
|
||||
IfcEntities IfcSelectHelperEntity::getInverse(Ifc2x3::Type::Enum) {throw IfcParse::IfcException("Invalid cast");}
|
||||
std::string IfcSelectHelperEntity::datatype() { return Ifc2x3::Type::ToString(_type); }
|
||||
IfcEntities IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum,int,const std::string &) {throw IfcParse::IfcException("Invalid cast");}
|
||||
IfcEntities IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum) {throw IfcParse::IfcException("Invalid cast");}
|
||||
std::string IfcSelectHelperEntity::datatype() { return IfcSchema::Type::ToString(_type); }
|
||||
ArgumentPtr IfcSelectHelperEntity::getArgument(unsigned int i) {
|
||||
if ( i != 0 ) throw IfcParse::IfcException("Invalid cast");
|
||||
return arg;
|
||||
}
|
||||
unsigned int IfcSelectHelperEntity::getArgumentCount() { return 1; }
|
||||
Ifc2x3::Type::Enum IfcSelectHelperEntity::type() const { return _type; }
|
||||
bool IfcSelectHelperEntity::is(Ifc2x3::Type::Enum t) const { return _type == t; }
|
||||
IfcSchema::Type::Enum IfcSelectHelperEntity::type() const { return _type; }
|
||||
bool IfcSelectHelperEntity::is(IfcSchema::Type::Enum t) const { return _type == t; }
|
||||
std::string IfcSelectHelperEntity::toString(bool upper) {
|
||||
std::stringstream ss;
|
||||
std::string dt = datatype();
|
||||
@@ -361,28 +316,33 @@ std::string IfcSelectHelperEntity::toString(bool upper) {
|
||||
unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid cast"); }
|
||||
bool IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); }
|
||||
|
||||
IfcSelectHelper::IfcSelectHelper(const std::string& v, Ifc2x3::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteIntegralArgument(v);
|
||||
IfcSelectHelper::IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(const char* const v, Ifc2x3::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteIntegralArgument(std::string(v));
|
||||
IfcSelectHelper::IfcSelectHelper(const char* const v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set<std::string>(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(int v, Ifc2x3::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteIntegralArgument(v);
|
||||
IfcSelectHelper::IfcSelectHelper(int v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(double v, Ifc2x3::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteIntegralArgument(v);
|
||||
IfcSelectHelper::IfcSelectHelper(double v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(bool v, Ifc2x3::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteIntegralArgument(v);
|
||||
IfcSelectHelper::IfcSelectHelper(bool v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
bool IfcSelectHelper::is(Ifc2x3::Type::Enum t) const { return entity->is(t); }
|
||||
Ifc2x3::Type::Enum IfcSelectHelper::type() const { return entity->type(); }
|
||||
bool IfcSelectHelper::is(IfcSchema::Type::Enum t) const { return entity->is(t); }
|
||||
IfcSchema::Type::Enum IfcSelectHelper::type() const { return entity->type(); }
|
||||
|
||||
EntityBuffer* EntityBuffer::i = 0;
|
||||
EntityBuffer* EntityBuffer::instance() {
|
||||
|
||||
+93
-103
@@ -28,69 +28,92 @@
|
||||
#ifndef IFCWRITE_H
|
||||
#define IFCWRITE_H
|
||||
|
||||
#include "IfcUtil.h"
|
||||
#include "IfcParse.h"
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
namespace IfcWrite {
|
||||
|
||||
/// A placeholder class for grouping functionality geared towards writing IFC files
|
||||
/// This class is a writable container for attributes. A fundamental
|
||||
/// difference with the attribute types counterparts defined in the
|
||||
/// IfcParse namespace is that this class has a Boost.Variant member
|
||||
/// for storing its value, whereas the IfcParse classes only contain
|
||||
/// lazy references to byte offsets in the IFC-SPF file.
|
||||
class IfcWriteArgument : public Argument {
|
||||
|
||||
};
|
||||
|
||||
/// A null argument. It will always serialize to $
|
||||
class IfcWriteNullArgument : public IfcWriteArgument {
|
||||
public:
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
operator std::string() const;
|
||||
operator std::vector<double>() const;
|
||||
operator std::vector<int>() const;
|
||||
operator std::vector<std::string>() const;
|
||||
operator IfcUtil::IfcSchemaEntity() const;
|
||||
operator IfcEntities() const;
|
||||
bool isNull() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
unsigned int Size() const;
|
||||
};
|
||||
|
||||
/// An entity list argument. It will serialize to (#1,#2,#3)
|
||||
/// with possibly a datatype identifier for SELECT types, e.g:
|
||||
/// (IFCREAL(1.0),IFCINTEGER(1))
|
||||
class IfcWriteEntityListArgument : public IfcWriteArgument {
|
||||
class EnumerationReference {
|
||||
public:
|
||||
int data;
|
||||
const char* enumeration_value;
|
||||
EnumerationReference(int data, const char* enumeration_value)
|
||||
: data(data), enumeration_value(enumeration_value) {}
|
||||
};
|
||||
class Derived {};
|
||||
private:
|
||||
IfcEntities value;
|
||||
IfcAbstractEntity* entity;
|
||||
boost::variant<
|
||||
// A null argument, it will always serialize to $
|
||||
boost::none_t,
|
||||
// A derived argument, it will always serialize to *
|
||||
Derived,
|
||||
// An integer argument, e.g. 123
|
||||
int,
|
||||
// A boolean argument, it will serialize to either .T. or .F.
|
||||
bool,
|
||||
// A floating point argument, e.g. 12.3
|
||||
double,
|
||||
// A character string argument, e.g. 'IfcOpenShell'
|
||||
std::string,
|
||||
// A list of integers, e.g. (1,2,3)
|
||||
std::vector<int>,
|
||||
// A list of floats, e.g. (12.3,4.)
|
||||
std::vector<double>,
|
||||
// A list of strings, e.g. ('Ifc','Open','Shell')
|
||||
std::vector<std::string>,
|
||||
// An enumeration argument, e.g. .USERDEFINED.
|
||||
// To initialize the argument a string representation
|
||||
// has to be explicitely passed of the enumeration value
|
||||
// which is stored internally as an integer. The argument
|
||||
// itself does not keep track of what schema enumeration
|
||||
// type is represented.
|
||||
EnumerationReference,
|
||||
// An entity instance argument. It will either serialize to
|
||||
// e.g. #123 or datatype identifier for simple types, e.g.
|
||||
// IFCREAL(12.3)
|
||||
IfcUtil::IfcSchemaEntity,
|
||||
// An entity list argument. It will either serialize to
|
||||
// e.g. (#1,#2,#3) or datatype identifier for simple types,
|
||||
// e.g. (IFCREAL(1.2),IFCINTEGER(3.))
|
||||
IfcEntities
|
||||
> container;
|
||||
public:
|
||||
IfcWriteEntityListArgument(const IfcEntities& v);
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
operator std::string() const;
|
||||
operator std::vector<double>() const;
|
||||
operator std::vector<int>() const;
|
||||
operator std::vector<std::string>() const;
|
||||
operator IfcUtil::IfcSchemaEntity() const;
|
||||
operator IfcEntities() const;
|
||||
bool isNull() const;
|
||||
unsigned int Size() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
};
|
||||
|
||||
/// An enumeration argument. It will serialize to e.g:
|
||||
/// .USERDEFINED. To initialize the argument a string representation
|
||||
/// has to be explicitely passed of the enumeration value which
|
||||
/// is stored internally as an integer. The argument itself
|
||||
/// does not keep track of what schema enumeration type is
|
||||
/// represented.
|
||||
class IfcWriteEnumerationArgument : public IfcWriteArgument {
|
||||
private:
|
||||
int data;
|
||||
const char* enumeration_value;
|
||||
public:
|
||||
IfcWriteEnumerationArgument(int v, const char* c);
|
||||
enum argument_type {
|
||||
argument_type_null,
|
||||
argument_type_derived,
|
||||
argument_type_int,
|
||||
argument_type_bool,
|
||||
argument_type_double,
|
||||
argument_type_string,
|
||||
argument_type_vector_int,
|
||||
argument_type_vector_double,
|
||||
argument_type_vector_string,
|
||||
argument_type_enumeration,
|
||||
argument_type_schema_entity,
|
||||
argument_type_entities
|
||||
};
|
||||
IfcWriteArgument(IfcAbstractEntity* e) : entity(e) {}
|
||||
template <typename T> const T& as() const {
|
||||
if (const T* val = boost::get<T>(&container)) {
|
||||
return *val;
|
||||
} else {
|
||||
throw IfcParse::IfcException("Invalid cast");
|
||||
}
|
||||
}
|
||||
template <typename T> void set(const T& t) {
|
||||
container = t;
|
||||
}
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
@@ -104,38 +127,7 @@ namespace IfcWrite {
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
unsigned int Size() const;
|
||||
};
|
||||
|
||||
/// An argument for all remaining types of arguments. For example:
|
||||
/// #123 | 1 | 'Value' | (1.0,2.0,3.0). All data is casted to a
|
||||
/// void pointer.
|
||||
class IfcWriteIntegralArgument : public IfcWriteArgument {
|
||||
private:
|
||||
void* data;
|
||||
IfcUtil::ArgumentType type;
|
||||
public:
|
||||
IfcWriteIntegralArgument(int v);
|
||||
IfcWriteIntegralArgument(bool v);
|
||||
IfcWriteIntegralArgument(double v);
|
||||
IfcWriteIntegralArgument(const std::string& v);
|
||||
IfcWriteIntegralArgument(const std::vector<int> v);
|
||||
IfcWriteIntegralArgument(const std::vector<double> v);
|
||||
IfcWriteIntegralArgument(const std::vector<std::string> v);
|
||||
IfcWriteIntegralArgument(IfcUtil::IfcSchemaEntity v);
|
||||
~IfcWriteIntegralArgument();
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
operator std::string() const;
|
||||
operator std::vector<double>() const;
|
||||
operator std::vector<int>() const;
|
||||
operator std::vector<std::string>() const;
|
||||
operator IfcUtil::IfcSchemaEntity() const;
|
||||
operator IfcEntities() const;
|
||||
bool isNull() const;
|
||||
unsigned int Size() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
argument_type argumentType() const;
|
||||
};
|
||||
|
||||
/// An entity to help with passing of SELECT arguments that
|
||||
@@ -144,18 +136,18 @@ namespace IfcWrite {
|
||||
/// Proper memory management is difficult for now, so beware.
|
||||
class IfcSelectHelperEntity : public IfcAbstractEntity {
|
||||
private:
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
IfcWriteArgument* arg;
|
||||
public:
|
||||
// FIXME: Make this a non-pointer argument and implement a copy constructor
|
||||
IfcSelectHelperEntity(Ifc2x3::Type::Enum t, IfcWriteArgument* a) : _type(t), arg(a) {}
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum,int,const std::string &);
|
||||
IfcEntities getInverse(Ifc2x3::Type::Enum);
|
||||
IfcSelectHelperEntity(IfcSchema::Type::Enum t, IfcWriteArgument* a) : _type(t), arg(a) {}
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum,int,const std::string &);
|
||||
IfcEntities getInverse(IfcSchema::Type::Enum);
|
||||
std::string datatype();
|
||||
ArgumentPtr getArgument(unsigned int i);
|
||||
unsigned int getArgumentCount();
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(Ifc2x3::Type::Enum t) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum t) const;
|
||||
std::string toString(bool upper = false);
|
||||
unsigned int id();
|
||||
bool isWritable();
|
||||
@@ -167,18 +159,16 @@ namespace IfcWrite {
|
||||
/// Proper memory management is difficult for now, so beware.
|
||||
class IfcSelectHelper : public IfcUtil::IfcBaseClass {
|
||||
public:
|
||||
IfcSelectHelper(const std::string& v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcText);
|
||||
IfcSelectHelper(const char* const v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcText);
|
||||
IfcSelectHelper(int v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcInteger);
|
||||
IfcSelectHelper(double v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcReal);
|
||||
IfcSelectHelper(bool v, Ifc2x3::Type::Enum t=Ifc2x3::Type::IfcBoolean);
|
||||
bool is(Ifc2x3::Type::Enum t) const;
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcText);
|
||||
IfcSelectHelper(const char* const v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcText);
|
||||
IfcSelectHelper(int v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcInteger);
|
||||
IfcSelectHelper(double v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcReal);
|
||||
IfcSelectHelper(bool v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcBoolean);
|
||||
bool is(IfcSchema::Type::Enum t) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
};
|
||||
|
||||
/// A helper class for the creation of IFC GlobalIds.
|
||||
/// At this moment an actual UUID is not generated according to
|
||||
/// the ISO standard, but merely a sequence of random characters.
|
||||
class IfcGuidHelper {
|
||||
private:
|
||||
std::string data;
|
||||
|
||||
+27
-27
@@ -21,10 +21,10 @@
|
||||
%include "std_string.i"
|
||||
%include "exception.i"
|
||||
|
||||
%ignore Ifc::IfcUntypedEntity::is;
|
||||
%ignore Ifc::IfcUntypedEntity::type;
|
||||
%ignore Ifc::IfcUntypedEntity::getArgument;
|
||||
%ignore Ifc::IfcUntypedEntity::IfcUntypedEntity(IfcAbstractEntity);
|
||||
%ignore IfcParse::IfcUntypedEntity::is;
|
||||
%ignore IfcParse::IfcUntypedEntity::type;
|
||||
%ignore IfcParse::IfcUntypedEntity::getArgument;
|
||||
%ignore IfcParse::IfcUntypedEntity::IfcUntypedEntity(IfcAbstractEntity);
|
||||
|
||||
%ignore IfcParse::IfcFile::Init;
|
||||
%ignore IfcParse::IfcFile::EntityById;
|
||||
@@ -47,16 +47,17 @@
|
||||
|
||||
%typemap(in) IfcEntities {
|
||||
if (PySequence_Check($input)) {
|
||||
// $1 = std::make_shared<IfcEntityList>();
|
||||
$1 = SHARED_PTR<IfcEntityList>(new IfcEntityList());
|
||||
for(Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
|
||||
PyObject* obj = PySequence_GetItem($input, i);
|
||||
if (obj) {
|
||||
void *arg = 0;
|
||||
int res = SWIG_ConvertPtr(obj, &arg, SWIGTYPE_p_Ifc__IfcUntypedEntity, 0);
|
||||
int res = SWIG_ConvertPtr(obj, &arg, SWIGTYPE_p_IfcParse__IfcUntypedEntity, 0);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "Entity__set_argument" "', argument " "3"" of type '" "Ifc::IfcUntypedEntity *""'");
|
||||
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "Entity__set_argument" "', argument " "3"" of type '" "IfcParse::IfcUntypedEntity *""'");
|
||||
} else {
|
||||
$1->push(reinterpret_cast<Ifc::IfcUntypedEntity*>(arg));
|
||||
$1->push(reinterpret_cast<IfcParse::IfcUntypedEntity*>(arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,34 +70,34 @@
|
||||
const unsigned size = $1 ? $1->Size() : 0;
|
||||
$result = PyList_New(size);
|
||||
for (unsigned i = 0; i < size; ++i) {
|
||||
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*$1)[i]), SWIGTYPE_p_Ifc__IfcUntypedEntity, 0);
|
||||
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*$1)[i]), SWIGTYPE_p_IfcParse__IfcUntypedEntity, 0);
|
||||
PyList_SetItem($result,i,o);
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) std::pair<IfcUtil::ArgumentType,ArgumentPtr> {
|
||||
const Argument& arg = *($1.second);
|
||||
const ArgumentType type = $1.first;
|
||||
const IfcUtil::ArgumentType type = $1.first;
|
||||
if (arg.isNull()) {
|
||||
Py_INCREF(Py_None);
|
||||
$result = Py_None;
|
||||
} else {
|
||||
switch(type) {
|
||||
case Argument_INT:
|
||||
case IfcUtil::Argument_INT:
|
||||
$result = PyInt_FromLong((int)arg);
|
||||
break;
|
||||
case Argument_BOOL:
|
||||
case IfcUtil::Argument_BOOL:
|
||||
$result = PyBool_FromLong((bool)arg);
|
||||
break;
|
||||
case Argument_DOUBLE:
|
||||
case IfcUtil::Argument_DOUBLE:
|
||||
$result = PyFloat_FromDouble(arg);
|
||||
break;
|
||||
case Argument_ENUMERATION:
|
||||
case Argument_STRING: {
|
||||
case IfcUtil::Argument_ENUMERATION:
|
||||
case IfcUtil::Argument_STRING: {
|
||||
const std::string s = arg;
|
||||
$result = PyString_FromString(s.c_str());
|
||||
break; }
|
||||
case Argument_VECTOR_INT: {
|
||||
case IfcUtil::Argument_VECTOR_INT: {
|
||||
const std::vector<int> v = arg;
|
||||
const unsigned size = v.size();
|
||||
$result = PyList_New(size);
|
||||
@@ -104,7 +105,7 @@
|
||||
PyList_SetItem($result,i,PyInt_FromLong(v[i]));
|
||||
}
|
||||
break; }
|
||||
case Argument_VECTOR_DOUBLE: {
|
||||
case IfcUtil::Argument_VECTOR_DOUBLE: {
|
||||
const std::vector<double> v = arg;
|
||||
const unsigned size = v.size();
|
||||
$result = PyList_New(size);
|
||||
@@ -112,7 +113,7 @@
|
||||
PyList_SetItem($result,i,PyFloat_FromDouble(v[i]));
|
||||
}
|
||||
break; }
|
||||
case Argument_VECTOR_STRING: {
|
||||
case IfcUtil::Argument_VECTOR_STRING: {
|
||||
const std::vector<std::string> v = arg;
|
||||
const unsigned size = v.size();
|
||||
$result = PyList_New(size);
|
||||
@@ -120,20 +121,20 @@
|
||||
PyList_SetItem($result,i,PyString_FromString(v[i].c_str()));
|
||||
}
|
||||
break; }
|
||||
case Argument_ENTITY: {
|
||||
case IfcUtil::Argument_ENTITY: {
|
||||
IfcUtil::IfcSchemaEntity e = arg;
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr(e), SWIGTYPE_p_Ifc__IfcUntypedEntity, 0);
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr(e), SWIGTYPE_p_IfcParse__IfcUntypedEntity, 0);
|
||||
break; }
|
||||
case Argument_ENTITY_LIST: {
|
||||
case IfcUtil::Argument_ENTITY_LIST: {
|
||||
IfcEntities es = arg;
|
||||
const unsigned size = es->Size();
|
||||
$result = PyList_New(size);
|
||||
for (unsigned i = 0; i < size; ++i) {
|
||||
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*es)[i]), SWIGTYPE_p_Ifc__IfcUntypedEntity, 0);
|
||||
PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr((*es)[i]), SWIGTYPE_p_IfcParse__IfcUntypedEntity, 0);
|
||||
PyList_SetItem($result,i,o);
|
||||
}
|
||||
break; }
|
||||
case Argument_UNKNOWN:
|
||||
case IfcUtil::Argument_UNKNOWN:
|
||||
default:
|
||||
SWIG_exception(SWIG_RuntimeError,"Unknown argument type");
|
||||
break;
|
||||
@@ -152,20 +153,19 @@
|
||||
%module IfcImport %{
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "Interface.h"
|
||||
using namespace Ifc;
|
||||
using namespace IfcParse;
|
||||
%}
|
||||
|
||||
%include "Interface.h"
|
||||
|
||||
%extend IfcParse::IfcFile {
|
||||
Ifc::IfcUntypedEntity* by_id(unsigned id) {
|
||||
IfcParse::IfcUntypedEntity* by_id(unsigned id) {
|
||||
return (IfcUntypedEntity*) $self->EntityById(id);
|
||||
}
|
||||
Ifc::IfcUntypedEntity* by_guid(const std::string& guid) {
|
||||
IfcParse::IfcUntypedEntity* by_guid(const std::string& guid) {
|
||||
return (IfcUntypedEntity*) $self->EntityByGuid(guid);
|
||||
}
|
||||
void add(Ifc::IfcUntypedEntity* e) {
|
||||
void add(IfcParse::IfcUntypedEntity* e) {
|
||||
$self->AddEntity(e);
|
||||
}
|
||||
void write(const std::string& fn) {
|
||||
@@ -174,7 +174,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
%extend Ifc::IfcUntypedEntity {
|
||||
%extend IfcParse::IfcUntypedEntity {
|
||||
%pythoncode %{
|
||||
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self._set_argument(x,y)
|
||||
%}
|
||||
|
||||
+17
-12
@@ -3,7 +3,7 @@
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
|
||||
namespace Ifc { class IfcUntypedEntity; }
|
||||
namespace IfcParse { class IfcUntypedEntity; }
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/Ifc2x3.h"
|
||||
@@ -11,14 +11,14 @@ namespace Ifc { class IfcUntypedEntity; }
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
|
||||
|
||||
namespace Ifc {
|
||||
namespace IfcParse {
|
||||
class IfcUntypedEntity : public IfcUtil::IfcBaseEntity {
|
||||
private:
|
||||
Ifc2x3::Type::Enum _type;
|
||||
IfcSchema::Type::Enum _type;
|
||||
public:
|
||||
IfcUntypedEntity(const std::string& s);
|
||||
bool is(Ifc2x3::Type::Enum v) const;
|
||||
Ifc2x3::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is_a(const std::string& s) const;
|
||||
std::string is_a() const;
|
||||
unsigned int getArgumentCount() const;
|
||||
@@ -49,9 +49,9 @@ namespace Ifc {
|
||||
}
|
||||
|
||||
typedef IfcUtil::IfcSchemaEntity IfcEntity;
|
||||
typedef std::map<Ifc2x3::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<IfcSchema::Type::Enum,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||
typedef std::map<std::string,Ifc2x3::IfcRoot::ptr> MapEntityByGuid;
|
||||
typedef std::map<std::string,IfcSchema::IfcRoot::ptr> MapEntityByGuid;
|
||||
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
|
||||
typedef std::map<unsigned int,unsigned int> MapOffsetById;
|
||||
|
||||
@@ -68,13 +68,18 @@ namespace IfcParse {
|
||||
MapOffsetById offsets;
|
||||
unsigned int lastId;
|
||||
unsigned int MaxId;
|
||||
std::string _filename;
|
||||
std::string _timestamp;
|
||||
std::string _author;
|
||||
std::string _author_email;
|
||||
std::string _author_organisation;
|
||||
public:
|
||||
IfcParse::IfcSpfStream* file;
|
||||
IfcParse::Tokens* tokens;
|
||||
public:
|
||||
bool Init(const std::string& fn);
|
||||
IfcEntities EntitiesByType(const std::string& t);
|
||||
IfcEntity EntityById(int id);
|
||||
Ifc2x3::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
IfcSchema::IfcRoot::ptr EntityByGuid(const std::string& guid);
|
||||
void AddEntity(IfcUtil::IfcSchemaEntity e);
|
||||
IfcFile();
|
||||
~IfcFile();
|
||||
@@ -86,9 +91,9 @@ namespace IfcParse {
|
||||
return f;
|
||||
}
|
||||
|
||||
std::string create_shape(Ifc::IfcUntypedEntity* e) {
|
||||
if (!e->is(Ifc2x3::Type::IfcProduct)) throw IfcException("Entity is not an IfcProduct");
|
||||
Ifc2x3::IfcProduct* ifc_product = (Ifc2x3::IfcProduct*) e;
|
||||
std::string create_shape(IfcParse::IfcUntypedEntity* e) {
|
||||
if (!e->is(IfcSchema::Type::IfcProduct)) throw IfcException("Entity is not an IfcProduct");
|
||||
IfcSchema::IfcProduct* ifc_product = (IfcSchema::IfcProduct*) e;
|
||||
return IfcGeom::create_brep_data(ifc_product);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user