mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 02:47:48 +00:00
IfcConvert: Unit names and magnitudes + cosmetic fixes
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -274,6 +274,9 @@ namespace IfcGeomObjects {
|
||||
|
||||
bool Next();
|
||||
int Progress();
|
||||
|
||||
const std::string& GetUnitName();
|
||||
const float GetUnitMagnitude();
|
||||
|
||||
const std::string GetLog();
|
||||
IfcParse::IfcFile* GetFile();
|
||||
|
||||
Reference in New Issue
Block a user