First push of a more all-round geometrical file conversion utility

This commit is contained in:
Thomas Krijnen
2013-03-24 10:48:39 +00:00
parent 852cb7d8c4
commit 5d4ff0b54a
20 changed files with 1330 additions and 264 deletions
+8 -3
View File
@@ -125,9 +125,14 @@ TARGET_LINK_LIBRARIES(IfcGeom IfcParse)
LINK_DIRECTORIES (${LINK_DIRECTORIES} ${IfcOpenShell_BINARY_DIR} ${OCC_LIBRARY_DIR} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 ${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS})
ADD_EXECUTABLE(IfcObj ../src/ifcobj/IfcObj.cpp)
ADD_EXECUTABLE(IfcConvert
../src/ifcconvert/ColladaSerializer.cpp
../src/ifcconvert/IfcConvert.cpp
../src/ifcconvert/OpenCascadeBasedSerializer.cpp
../src/ifcconvert/WavefrontObjSerializer.cpp
)
TARGET_LINK_LIBRARIES (IfcObj IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet)
TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES)
# Build python wrapper using separate CMakeLists.txt
ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
@@ -171,5 +176,5 @@ SET(include_files_parse
)
INSTALL(FILES ${include_files_geom} DESTINATION include/ifcgeom)
INSTALL(FILES ${include_files_parse} DESTINATION include/ifcparse)
INSTALL(TARGETS IfcObj DESTINATION bin)
INSTALL(TARGETS IfcConvert DESTINATION bin)
INSTALL(TARGETS IfcParse IfcGeom DESTINATION lib)
+206
View File
@@ -0,0 +1,206 @@
/********************************************************************************
* *
* 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 "ColladaSerializer.h"
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::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices) {
openMesh(mesh_id);
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions);
if (!normals.empty()) {
// 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.
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();
COLLADASW::Triangles triangles(mSW);
triangles.setCount(indices.size() / 3);
int offset = 0;
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) );
if (!normals.empty()) {
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++ ) );
}
triangles.prepareToAppendValues();
for (auto it = indices.begin(); it != indices.end(); ++it) {
const auto& idx = *it;
if (!normals.empty()) {
triangles.appendValues(idx, idx);
} else {
triangles.appendValues(idx);
}
}
triangles.finish();
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_id, const std::string& material_id, 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::DEFAULT);
// 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_id);
COLLADASW::InstanceMaterial material ("ColorMaterial", "#" + material_id);
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 SurfaceStyle& style) {
openEffect(style.Name() + "-fx");
COLLADASW::EffectProfile effect(mSW);
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(style.Diffuse().R(),style.Diffuse().G(),style.Diffuse().B())));
addEffectProfile(effect);
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close() {
closeLibrary();
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const SurfaceStyle& style) {
if (!contains(style.Name())) {
effects.write(style);
surface_styles.push_back(style);
}
}
bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const std::string& name) {
for (auto it = surface_styles.begin(); it != surface_styles.end(); ++it) {
if (it->Name() == name) return true;
}
return false;
}
void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
effects.close();
for (auto it = surface_styles.begin(); it != surface_styles.end(); ++it) {
const std::string& material_name = it->Name();
openMaterial(material_name);
addInstanceEffect("#" + material_name + "-fx");
closeLibrary();
}
}
void ColladaSerializer::ColladaExporter::startDocument() {
stream.startDocument();
COLLADASW::Asset asset(&stream);
asset.getContributor().mAuthoringTool = std::string("IfcOpenShell ") + IFCOPENSHELL_VERSION;
// TODO: Get the appropriate unit from the IFC file.
asset.setUnit("meter", 1.0);
asset.setUpAxisType(COLLADASW::Asset::Z_UP);
asset.add();
}
void ColladaSerializer::ColladaExporter::writeTesselated(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) {
if (!materials.contains(type)) materials.add(GetDefaultMaterial(type));
deferreds.push_back(DeferedObject(type, obj_id, matrix, vertices, normals, indices));
}
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 (auto it = deferreds.begin(); it != deferreds.end(); ++it) {
std::stringstream ss; ss << "object" << it->obj_id;
const std::string object_id = ss.str();
geometries.write(object_id, it->vertices, it->normals, it->indices);
}
geometries.close();
for (auto it = deferreds.begin(); it != deferreds.end(); ++it) {
std::stringstream ss; ss << "object" << it->obj_id;
const std::string object_id = ss.str();
scene.add(object_id, object_id, object_id, it->type, it->matrix);
}
scene.write();
stream.endDocument();
}
bool ColladaSerializer::ready() {
return true;
}
void ColladaSerializer::writeHeader() {
exporter.startDocument();
}
void ColladaSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
exporter.writeTesselated(o->type, o->id, o->matrix, o->mesh->verts, o->mesh->normals, o->mesh->faces);
}
void ColladaSerializer::finalize() {
exporter.endDocument();
}
+145
View File
@@ -0,0 +1,145 @@
/********************************************************************************
* *
* 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 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"
#include "../ifcconvert/SurfaceStyle.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::vector<float>& positions, const std::vector<float>& normals, const std::vector<int>& indices);
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_id, const std::string& material_id, 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 SurfaceStyle& style);
void close();
};
std::vector<SurfaceStyle> surface_styles;
ColladaEffects effects;
public:
explicit ColladaMaterials(COLLADASW::StreamWriter& stream)
: COLLADASW::LibraryMaterials(&stream)
, effects(stream)
{}
void add(const SurfaceStyle& style);
bool contains(const std::string& name);
void write();
};
class DeferedObject {
public:
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;
DeferedObject(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)
: type(type)
, obj_id(obj_id)
, matrix(matrix)
, vertices(vertices)
, normals(normals)
, indices(indices)
{}
};
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<DeferedObject> deferreds;
virtual ~ColladaExporter() {}
void startDocument();
void writeTesselated(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);
void endDocument();
};
ColladaExporter exporter;
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; }
};
#endif
+36
View File
@@ -0,0 +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/>. *
* *
********************************************************************************/
#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;
};
#endif
+288
View File
@@ -0,0 +1,288 @@
/********************************************************************************
* *
* 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/SurfaceStyle.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
<< " .dae Collada Digital Assets Exchange" << std::endl
<< " .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;
}
}
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 IfcOpening 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");
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("help") || !vmap.count("input-file")) {
printUsage(generic_options, geom_options);
return 1;
} else if (vmap.count("version")) {
printVersion();
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);
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);
}
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_WARNING, "Use world coord settings ignored for WaveFront OBJ files");
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, true);
}
serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename);
} else if (output_extension == ".dae") {
serializer = new ColladaSerializer(output_filename);
} 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");
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");
return 1;
}
serializer->writeHeader();
if (!serializer->isTesselated()) {
IfcGeomObjects::Settings(IfcGeomObjects::DISABLE_TRIANGULATION, true);
}
// Stream for log messages, we don't want to interupt our new progress bar...
std::stringstream ss;
// Parse the file supplied in argv[1]. Returns true on succes.
if ( ! IfcGeomObjects::Init(input_filename,&std::cout,&ss) ) {
Logger::Message(Logger::LOG_ERROR, "Unable to parse .ifc file or no geometrical entities found");
return 1;
}
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 ");
// Writes the material settings, defined in Materials.h
std::string log = ss.str();
if (!log.empty()) {
std::cerr << std::endl << "Log:" << std::endl;
std::cerr << ss.str();
}
time(&end);
int dif = (int) difftime (end,start);
printf ("\nConversion took %d seconds\n", dif );
}
SurfaceStyle GetDefaultMaterial(const std::string& s) {
if (s == "IfcSite" ) { return SurfaceStyle("IfcSite", 0.75,0.8,0.65); }
if (s == "IfcSlab" ) { return SurfaceStyle("IfcSlab", 0.4, 0.4,0.4 ); }
if (s == "IfcWallStandardCase") { return SurfaceStyle("IfcWallStandardCase",0.9, 0.9,0.9 ); }
if (s == "IfcWall" ) { return SurfaceStyle("IfcWall", 0.9, 0.9,0.9 ); }
if (s == "IfcWindow" ) { return SurfaceStyle("IfcWindow", 0.75,0.8,0.75, 1.0,1.0,1.0, 0.0,0.0,0.0, 500.0, 0.3); }
if (s == "IfcDoor" ) { return SurfaceStyle("IfcDoor", 0.55,0.3,0.15); }
if (s == "IfcBeam" ) { return SurfaceStyle("IfcBeam", 0.75,0.7,0.7 ); }
if (s == "IfcRailing" ) { return SurfaceStyle("IfcRailing", 0.65,0.6,0.6 ); }
if (s == "IfcMember" ) { return SurfaceStyle("IfcMember", 0.65,0.6,0.6 ); }
if (s == "IfcPlate" ) { return SurfaceStyle("IfcPlate", 0.8, 0.8,0.8 ); }
return SurfaceStyle(s);
}
+47
View File
@@ -0,0 +1,47 @@
/********************************************************************************
* *
* 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 "../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());
}
};
#endif
@@ -0,0 +1,56 @@
/********************************************************************************
* *
* 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::ShapeList::const_iterator it = o->mesh->begin(); it != o->mesh->end(); ++ it) {
gp_GTrsf gtrsf = *it->first;
gtrsf.PreMultiply(o->trsf);
const TopoDS_Shape& s = *it->second;
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);
}
}
@@ -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"
#include "../ifcconvert/SurfaceStyle.h"
class OpenCascadeBasedSerializer : public GeometrySerializer {
protected:
const std::string& out_filename;
public:
explicit OpenCascadeBasedSerializer(const std::string& out_filename)
: GeometrySerializer()
, out_filename(out_filename)
{}
virtual ~OpenCascadeBasedSerializer() {}
void writeHeader() {}
void writeMaterial(const 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
+47
View File
@@ -0,0 +1,47 @@
/********************************************************************************
* *
* 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 "../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) {
writer.Transfer(shape, STEPControl_AsIs);
}
void finalize() {
writer.Write(out_filename.c_str());
}
};
#endif
@@ -19,46 +19,60 @@
/********************************************************************************
* *
* This file defines materials in .mtl format for several IFC datatypes *
* This file defines default materials for several IFC datatypes *
* *
********************************************************************************/
#ifndef SURFACESTYLE_H
#define SURFACESTYLE_H
#include <string>
#include <sstream>
class ObjMaterial {
private:
std::string data;
#include <array>
class SurfaceStyle {
public:
ObjMaterial(const std::string& name,
double Kd_r = 0.7f,double Kd_g = 0.7f,double Kd_b = 0.7f,
double Ks_r = 0.2f,double Ks_g = 0.2f,double Ks_b = 0.2f,
double Ka_r = 0.1f,double Ka_g = 0.1f,double Ka_b = 0.1f,
double Ns = 10.0f, double Tr = 1.0f) {
std::stringstream ss;
ss << "newmtl " << name << std::endl;
ss << "Kd " << Kd_r << " " << Kd_g << " " << Kd_b << std::endl;
ss << "Ks " << Ks_r << " " << Ks_g << " " << Ks_b << std::endl;
ss << "Ka " << Ka_r << " " << Ka_g << " " << Ka_b << std::endl;
ss << "Ns " << Ns << std::endl;
ss << "Tr " << Tr << std::endl;
ss << "d " << Tr << std::endl;
ss << "D " << Tr << std::endl;
data = ss.str();
}
friend ostream& operator<<(ostream& o, const ObjMaterial& m) {o << m.data; return o;}
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; }
};
ObjMaterial GetMaterial(const std::string& s) {
if ( s == "IfcSite" ) { return ObjMaterial("IfcSite",0.75f,0.8f,0.65f); }
if ( s == "IfcSlab" ) { return ObjMaterial("IfcSlab",0.4f,0.4f,0.4f); }
if ( s == "IfcWallStandardCase" ) { return ObjMaterial("IfcWallStandardCase",0.9f,0.9f,0.9f); }
if ( s == "IfcWall" ) { return ObjMaterial("IfcWall",0.9f,0.9f,0.9f); }
if ( s == "IfcWindow" ) { return ObjMaterial("IfcWindow",0.75f,0.8f,0.75f,1.0f,1.0f,1.0f,0.0f,0.0f,0.0f,500.0f,0.3f); }
if ( s == "IfcDoor" ) { return ObjMaterial("IfcDoor",0.55f,0.3f,0.15f); }
if ( s == "IfcBeam" ) { return ObjMaterial("IfcBeam",0.75f,0.7f,0.7f); }
if ( s == "IfcRailing" ) { return ObjMaterial("IfcRailing",0.65f,0.6f,0.6f); }
if ( s == "IfcMember" ) { return ObjMaterial("IfcMember",0.65f,0.6f,0.6f); }
if ( s == "IfcPlate" ) { return ObjMaterial("IfcPlate",0.8f,0.8f,0.8f); }
return ObjMaterial(s);
}
SurfaceStyle GetDefaultMaterial(const std::string& s);
#endif
+84
View File
@@ -0,0 +1,84 @@
/********************************************************************************
* *
* 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 "../ifcconvert/SurfaceStyle.h"
#include "WavefrontOBJSerializer.h"
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 SurfaceStyle& style) {
mtl_stream << "newmtl " << style.Name() << std::endl
<< "Kd " << style.Diffuse().R() << " " << style.Diffuse().G() << " " << style.Diffuse().B() << std::endl
<< "Ks " << style.Specular().R() << " " << style.Specular().G() << " " << style.Specular().B() << std::endl
<< "Ka " << style.Ambient().R() << " " << style.Ambient().G() << " " << style.Ambient().B() << std::endl
<< "Ns " << style.Specularity() << std::endl
<< "Tr " << style.Transparency() << std::endl
<< "d " << style.Transparency() << std::endl
<< "D " << style.Transparency() << std::endl;
}
void WaveFrontOBJSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
const std::string name = o->name.empty() ? o->guid : o->name;
obj_stream << "g " << name << std::endl;
obj_stream << "s 1" << std::endl;
obj_stream << "usemtl " << o->type << std::endl;
if (materials.find(o->type) == materials.end()) {
writeMaterial(GetDefaultMaterial(o->type));
materials.insert(o->type);
}
const int vcount = o->mesh->verts.size() / 3;
for ( IfcGeomObjects::FltIt it = o->mesh->verts.begin(); it != o->mesh->verts.end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
obj_stream << "v " << x << " " << y << " " << z << std::endl;
}
for ( IfcGeomObjects::FltIt it = o->mesh->normals.begin(); it != o->mesh->normals.end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
obj_stream << "vn " << x << " " << y << " " << z << std::endl;
}
for ( IfcGeomObjects::IntIt it = o->mesh->faces.begin(); it != o->mesh->faces.end(); ) {
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;
}
+55
View File
@@ -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"
#include "../ifcconvert/SurfaceStyle.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 SurfaceStyle& style);
void writeTesselated(const IfcGeomObjects::IfcGeomObject* o);
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
void finalize() {}
bool isTesselated() const { return true; }
};
#endif
+127 -76
View File
@@ -51,8 +51,9 @@ bool weld_vertices = true;
bool convert_back_units = false;
bool use_faster_booleans = false;
bool disable_subtractions = false;
bool disable_triangulation = false;
int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
int IfcGeomObjects::IfcRepresentationTriangulation::addvert(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();
@@ -75,10 +76,10 @@ 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);
@@ -98,18 +99,25 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
std::stringstream sstream;
BRepTools::Write(compound,sstream);
brep_data = sstream.str();
} else
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Failed to serialize shape:",ifc_file->EntityById(id)->entity);
}
}
IfcGeomObjects::IfcRepresentationTriangulation::IfcRepresentationTriangulation(const IfcRepresentationShapeModel& shapes)
: id(shapes.getId())
{
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
const TopoDS_Shape& s = *(*it).second;
const gp_GTrsf& trsf = *(*it).first;
const TopoDS_Shape& s = *it->second;
const gp_GTrsf& trsf = *it->first;
// 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;
@@ -193,46 +201,62 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
}
}
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)
, trsf(trsf)
{
// 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;
}
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;
Ifc2x3::IfcShapeRepresentation::it shaperep_iterator;
// The object is fetched beforehand to be positive an entity actually exists
IfcGeomObjects::IfcGeomObject* current_geom_obj;
IfcGeomObjects::IfcGeomObject* current_geom_obj = 0;
IfcGeomObjects::IfcGeomShapeModelObject* current_shape_model_obj = 0;
IfcGeomObjects::IfcGeomBrepDataObject* current_brep_data_obj = 0;
// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *outer
// A container and iterator for IfcBuildingElements for the current IfcShapeRepresentation referenced by *shaperep_iterator
Ifc2x3::IfcProduct::list entities;
Ifc2x3::IfcProduct::it inner;
Ifc2x3::IfcProduct::it ifcproduct_iterator;
int done;
int total;
@@ -240,7 +264,7 @@ int total;
// Move the the next IfcShapeRepresentation
void _nextShape() {
entities.reset();
++ outer;
++ shaperep_iterator;
++ done;
}
@@ -289,17 +313,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;
// 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 ) {
@@ -337,15 +360,15 @@ 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;
IfcGeomObjects::IfcRepresentationShapeModel* shape;
IfcGeom::ShapeList shapes;
if ( !IfcGeom::convert_shapes(shaperep,shapes) ) {
@@ -353,7 +376,7 @@ IfcGeomObjects::IfcGeomObject* _get() {
continue;
}
Ifc2x3::IfcProduct::ptr ifc_product = *inner;
Ifc2x3::IfcProduct::ptr ifc_product = *ifcproduct_iterator;
int parent_id = -1;
try {
@@ -413,56 +436,74 @@ IfcGeomObjects::IfcGeomObject* _get() {
}
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 ) {
shape = new IfcGeomObjects::IfcRepresentationShapeModel(shaperep->entity->id(),opened_shapes,true);
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
delete it->first;
delete it->second;
}
} else if ( use_world_coords ) {
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
it->first->PreMultiply(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,
return new IfcGeomObjects::IfcGeomShapeModelObject(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;
}
}
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;
}
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();
}
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;
@@ -493,6 +534,12 @@ const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
return current_geom_obj;
}
const IfcGeomObjects::IfcGeomShapeModelObject* IfcGeomObjects::GetShapeModel() {
return current_shape_model_obj;
}
const IfcGeomObjects::IfcGeomBrepDataObject* IfcGeomObjects::GetBrepData() {
return current_brep_data_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;
@@ -582,11 +629,12 @@ bool _Init() {
shapereps = ifc_file->EntitiesByType<Ifc2x3::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();
@@ -636,6 +684,9 @@ 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() {
+88 -12
View File
@@ -100,6 +100,10 @@ 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. Note
// that this setting is implied by the USE_BREP_DATA setting.
const int DISABLE_TRIANGULATION = 9;
// End of settings enumeration.
@@ -111,17 +115,49 @@ namespace IfcGeomObjects {
typedef std::map<VertKey,int> VertKeyMap;
typedef std::pair<int,int> Edge;
class IfcMesh {
class IfcRepresentationShapeModel {
private:
unsigned int id;
bool owns_shapes;
const IfcGeom::ShapeList shapes;
IfcRepresentationShapeModel(const IfcRepresentationShapeModel& other);
IfcRepresentationShapeModel& operator=(const IfcRepresentationShapeModel& other);
public:
IfcRepresentationShapeModel(unsigned int id, const IfcGeom::ShapeList& shapes, bool owns_shapes = false)
: id(id)
, shapes(shapes)
, owns_shapes(owns_shapes)
{}
~IfcRepresentationShapeModel() {
for ( IfcGeom::ShapeList::const_iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
delete it->first;
if (owns_shapes) {
delete it->second;
}
}
}
IfcGeom::ShapeList::const_iterator begin() const { return shapes.begin(); }
IfcGeom::ShapeList::const_iterator end() const { return shapes.end(); }
const unsigned int& getId() const { return id; }
};
class IfcRepresentationBrepData {
public:
int id;
std::string brep_data;
IfcRepresentationBrepData(const IfcRepresentationShapeModel& s);
};
class IfcRepresentationTriangulation {
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);
IfcRepresentationTriangulation(const IfcRepresentationShapeModel& s);
private:
int addvert(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) {
@@ -129,7 +165,7 @@ namespace IfcGeomObjects {
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
else edgecount[e] ++;
edges_temp.push_back(e);
}
}
};
class IfcObject {
@@ -140,28 +176,68 @@ namespace IfcGeomObjects {
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);
gp_Trsf trsf;
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 {
public:
IfcRepresentationShapeModel* mesh;
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 {
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);
IfcRepresentationTriangulation* mesh;
IfcGeomObject(const IfcGeomShapeModelObject& shape_model);
virtual ~IfcGeomObject() {
delete mesh;
}
private:
IfcGeomObject(const IfcGeomObject& other);
IfcGeomObject& operator=(const IfcGeomObject& other);
};
class IfcGeomBrepDataObject : public IfcObject {
public:
IfcRepresentationBrepData* mesh;
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();
const IfcGeomObject* Get();
bool Next();
int Progress();
const IfcObject* GetObject(int id);
const IfcGeomBrepDataObject* GetBrepData();
const IfcGeomShapeModelObject* GetShapeModel();
bool Next();
int Progress();
std::string GetLog();
IfcParse::IfcFile* GetFile();
IfcParse::IfcFile* GetFile();
bool CleanUp();
}
#endif
-127
View File
@@ -1,127 +0,0 @@
/********************************************************************************
* *
* 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 is a brief example of how IfcOpenShell can be interfaced from within *
* a C++ context. The application reads an .ifc file and outputs geometry in *
* the Wavefront .obj file format. *
* *
********************************************************************************/
#include <fstream>
#include <sstream>
#include <set>
#include <time.h>
#include "../ifcgeom/IfcGeomObjects.h"
#include "../ifcobj/ObjMaterials.h"
int main ( int argc, char** argv ) {
if ( argc != 2 ) {
std::cout << "usage: IfcObj <filename.ifc>" << std::endl;
return 1;
}
const std::string fnObj = std::string(argv[1]) + ".obj";
const std::string fnMtl = std::string(argv[1]) + ".mtl";
ofstream fObj(fnObj.c_str());
ofstream fMtl(fnMtl.c_str());
if ( ! ( fObj.is_open() && fMtl.is_open() ) ) {
std::cout << "[Error] unable to open output file for writing" << std::endl;
return 1;
}
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,true);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,false);
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
// Stream for log messages, we don't want to interupt our new progress bar...
std::stringstream ss;
// Parse the file supplied in argv[1]. Returns true on succes.
if ( ! IfcGeomObjects::Init(argv[1],&std::cout,&ss) ) {
std::cout << "[Error] unable to parse .ifc file or no geometrical entities found" << std::endl;
return 1;
}
fObj << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
fObj << "mtllib " << fnMtl << std::endl;
std::set<std::string> materials;
time_t start,end;
time(&start);
int old_progress = -1;
std::cout << "Creating geometry..." << std::endl;
// 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
int vcount_total = 1;
do {
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
if ( o->type == "IfcSpace" || o->type == "IfcOpeningElement" ) continue;
const std::string name = o->name.empty() ? o->guid : o->name;
fObj << "g " << name << std::endl;
fObj << "s 1" << std::endl;
fObj << "usemtl " << o->type << std::endl;
materials.insert(o->type);
const int vcount = o->mesh->verts.size() / 3;
for ( IfcGeomObjects::FltIt it = o->mesh->verts.begin(); it != o->mesh->verts.end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
fObj << "v " << x << " " << y << " " << z << std::endl;
}
for ( IfcGeomObjects::FltIt it = o->mesh->normals.begin(); it != o->mesh->normals.end(); ) {
const double x = *(it++);
const double y = *(it++);
const double z = *(it++);
fObj << "vn " << x << " " << y << " " << z << std::endl;
}
for ( IfcGeomObjects::IntIt it = o->mesh->faces.begin(); it != o->mesh->faces.end(); ) {
const int v1 = *(it++)+vcount_total;
const int v2 = *(it++)+vcount_total;
const int v3 = *(it++)+vcount_total;
fObj << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << std::endl;
}
vcount_total += vcount;
const int progress = IfcGeomObjects::Progress() / 2;
if ( old_progress!= progress ) std::cout << "\r[" << std::string(progress,'#') << std::string(50 - progress,' ') << "]" << std::flush;
old_progress = progress;
} while ( IfcGeomObjects::Next() );
std::cout << "\rDone creating geometry " << std::endl;
// Writes the material settings, defined in Materials.h
fMtl << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << std::endl;
for( std::set<std::string>::iterator it = materials.begin(); it != materials.end(); ++ it ) {
fMtl << GetMaterial(*it);
}
std::string log = ss.str();
if ( log.size() ) {
std::cout << std::endl << "Log:" << std::endl;
std::cout << ss.str();
}
time(&end);
int dif = (int) difftime (end,start);
printf ("\nConversion took %d seconds\n", dif );
}
-5
View File
@@ -1,5 +0,0 @@
#include "../IfcObj/Materials.h"
void InitMaterials() {
materials["IFCSITE"] = ObjMaterial("IFCSITE",0.7f,0.8f,0.5f);
}
+5
View File
@@ -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();
}
+1
View File
@@ -212,6 +212,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();
};
+42 -6
View File
@@ -2,9 +2,9 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="IfcObj"
Name="IfcConvert"
ProjectGUID="{5B0BAAB3-9FC4-4C0C-9D38-8BF4B07F4A85}"
RootNamespace="IfcObj"
RootNamespace="IfcConvert"
TargetFrameworkVersion="196613"
>
<Platforms>
@@ -60,7 +60,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="TKerneld.lib TKMathd.lib TKBRepd.lib TKGeomBased.lib TKGeomAlgod.lib TKG3dd.lib TKG2dd.lib TKShHealingd.lib TKTopAlgod.lib TKMeshd.lib TKPrimd.lib TKBoold.lib TKBOd.lib TKFilletd.lib"
AdditionalDependencies="TKerneld.lib TKMathd.lib TKBRepd.lib TKGeomBased.lib TKGeomAlgod.lib TKG3dd.lib TKG2dd.lib TKShHealingd.lib TKTopAlgod.lib TKMeshd.lib TKPrimd.lib TKBoold.lib TKBOd.lib TKFilletd.lib TKSTEPd.lib TKSTEPBased.lib TKSTEPAttrd.lib TKXSBased.lib TKSTEP209d.lib TKIGESd.lib"
GenerateDebugInformation="true"
TargetMachine="1"
/>
@@ -130,7 +130,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="TKernel.lib TKMath.lib TKBRep.lib TKGeomBase.lib TKGeomAlgo.lib TKG3d.lib TKG2d.lib TKShHealing.lib TKTopAlgo.lib TKMesh.lib TKPrim.lib TKBool.lib TKBO.lib TKFillet.lib"
AdditionalDependencies="TKernel.lib TKMath.lib TKBRep.lib TKGeomBase.lib TKGeomAlgo.lib TKG3d.lib TKG2d.lib TKShHealing.lib TKTopAlgo.lib TKMesh.lib TKPrim.lib TKBool.lib TKBO.lib TKFillet.lib TKSTEP.lib TKSTEPBase.lib TKSTEPAttr.lib TKXSBase.lib TKSTEP209.lib TKIGES.lib"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
@@ -168,7 +168,19 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\src\ifcobj\IfcObj.cpp"
RelativePath="..\src\ifcconvert\ColladaSerializer.cpp"
>
</File>
<File
RelativePath="..\src\ifcconvert\IfcConvert.cpp"
>
</File>
<File
RelativePath="..\src\ifcconvert\OpenCascadeBasedSerializer.cpp"
>
</File>
<File
RelativePath="..\src\ifcconvert\WavefrontObjSerializer.cpp"
>
</File>
</Filter>
@@ -178,7 +190,31 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\src\ifcobj\ObjMaterials.h"
RelativePath="..\src\ifcconvert\ColladaSerializer.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\GeometrySerializer.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\IgesSerializer.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\OpenCascadeBasedSerializer.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\StepSerializer.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\SurfaceStyle.h"
>
</File>
<File
RelativePath="..\src\ifcconvert\WavefrontObjSerializer.h"
>
</File>
</Filter>
+1 -1
View File
@@ -13,7 +13,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IfcMax", "IfcMax.vcproj", "
{F7600775-3D48-426A-88E2-F3A4BF4408A2} = {F7600775-3D48-426A-88E2-F3A4BF4408A2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IfcObj", "IfcObj.vcproj", "{5B0BAAB3-9FC4-4C0C-9D38-8BF4B07F4A85}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IfcConvert", "IfcConvert.vcproj", "{5B0BAAB3-9FC4-4C0C-9D38-8BF4B07F4A85}"
ProjectSection(ProjectDependencies) = postProject
{BA57AF0F-1D12-4FAC-BD40-7474D729CAE9} = {BA57AF0F-1D12-4FAC-BD40-7474D729CAE9}
{F7600775-3D48-426A-88E2-F3A4BF4408A2} = {F7600775-3D48-426A-88E2-F3A4BF4408A2}