IfcConvert: Unit names and magnitudes + cosmetic fixes

This commit is contained in:
Thomas Krijnen
2013-12-31 14:10:38 +00:00
parent 6b2dc3683a
commit 2bd37fd088
11 changed files with 106 additions and 18 deletions
+3 -4
View File
@@ -208,13 +208,12 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
closeLibrary();
}
void ColladaSerializer::ColladaExporter::startDocument() {
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;
// TODO: Get the appropriate unit from the IFC file.
asset.setUnit("meter", 1.0);
asset.setUnit(unit_name, unit_magnitude);
asset.setUpAxisType(COLLADASW::Asset::Z_UP);
asset.add();
}
@@ -271,7 +270,7 @@ bool ColladaSerializer::ready() {
}
void ColladaSerializer::writeHeader() {
exporter.startDocument();
exporter.startDocument(unit_name, unit_magnitude);
}
void ColladaSerializer::writeTesselated(const IfcGeomObjects::IfcGeomObject* o) {
+7 -1
View File
@@ -135,11 +135,13 @@ private:
{}
std::vector<DeferredObject> deferreds;
virtual ~ColladaExporter() {}
void startDocument();
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()
@@ -151,6 +153,10 @@ public:
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
+1
View File
@@ -31,6 +31,7 @@ public:
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
+30 -13
View File
@@ -69,6 +69,9 @@ std::string change_extension(const std::string& fn, const std::string& 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()
@@ -180,11 +183,13 @@ int main(int argc, char** argv) {
*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_WARNING, "Use world coords settings ignored for WaveFront OBJ files");
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);
@@ -201,6 +206,7 @@ int main(int argc, char** argv) {
serializer = new IgesSerializer(output_filename);
} else {
Logger::Message(Logger::LOG_ERROR, "Unknown output filename extension");
write_log();
printUsage(generic_options, geom_options);
return 1;
}
@@ -209,24 +215,32 @@ int main(int argc, char** argv) {
if (!serializer->ready()) {
Logger::Message(Logger::LOG_ERROR, "Unable to open output file for writing");
write_log();
return 1;
}
serializer->writeHeader();
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");
}
}
// 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) ) {
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;
@@ -269,14 +283,17 @@ int main(int argc, char** argv) {
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();
}
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;
}
}
+7
View File
@@ -22,6 +22,7 @@
#include <IGESControl_Controller.hxx>
#include <IGESControl_Writer.hxx>
#include <Interface_Static.hxx>
#include "../ifcgeom/IfcGeomObjects.h"
@@ -42,6 +43,12 @@ public:
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
@@ -62,3 +62,22 @@ void OpenCascadeBasedSerializer::writeShapeModel(const IfcGeomObjects::IfcGeomSh
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;
}
}
@@ -27,6 +27,7 @@
class OpenCascadeBasedSerializer : public GeometrySerializer {
protected:
const std::string& out_filename;
const char* getSymbolForUnitMagnitude(float mag);
public:
explicit OpenCascadeBasedSerializer(const std::string& out_filename)
: GeometrySerializer()
+13
View File
@@ -22,6 +22,7 @@
#include <STEPControl_Controller.hxx>
#include <STEPControl_Writer.hxx>
#include <Interface_Static.hxx>
#include "../ifcgeom/IfcGeomObjects.h"
@@ -37,10 +38,22 @@ public:
{}
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);
}
}
};
+1
View File
@@ -49,6 +49,7 @@ public:
void writeShapeModel(const IfcGeomObjects::IfcGeomShapeModelObject* o) {}
void finalize() {}
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {}
};
#endif
+21
View File
@@ -605,6 +605,9 @@ void IfcGeomObjects::InitPrecision() {
}
}
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);
@@ -631,11 +634,13 @@ 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();
double value = 1.0f;
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
current_unit_name = u->Name();
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
@@ -655,6 +660,14 @@ void IfcGeomObjects::InitUnits() {
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,value);
if (current_unit_name.empty()) {
if (unit->hasPrefix()) {
current_unit_name = Ifc2x3::IfcSIPrefix::ToString(unit->Prefix());
}
current_unit_name += Ifc2x3::IfcSIUnitName::ToString(unit->Name());
}
unit_magnitude = value;
unit_name = current_unit_name;
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
IfcGeom::SetValue(IfcGeom::GV_PLANEANGLE_UNIT,value);
}
@@ -740,6 +753,14 @@ int IfcGeomObjects::Progress() {
return 100 * done / total;
}
const std::string& IfcGeomObjects::GetUnitName() {
return unit_name;
}
const float IfcGeomObjects::GetUnitMagnitude() {
return unit_magnitude;
}
const std::string IfcGeomObjects::GetLog() {
return Logger::GetLog();
}
+3
View File
@@ -274,6 +274,9 @@ namespace IfcGeomObjects {
bool Next();
int Progress();
const std::string& GetUnitName();
const float GetUnitMagnitude();
const std::string GetLog();
IfcParse::IfcFile* GetFile();