/********************************************************************************
* *
* Copyright 2015 IfcOpenShell and ROOT B.V. *
* *
* 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 . *
* *
********************************************************************************/
#ifndef SVGSERIALIZER_H
#define SVGSERIALIZER_H
#include "../serializers/GeometrySerializer.h"
#include "../serializers/util.h"
#include "../ifcparse/utils.h"
#include
#include
#include
struct storey_sorter {
bool operator()(IfcUtil::IfcBaseEntity* a, IfcUtil::IfcBaseEntity* b) const {
const bool a_is_storey = a->declaration().is("IfcBuildingStorey");
const bool b_is_storey = b->declaration().is("IfcBuildingStorey");
if (a_is_storey && b_is_storey) {
boost::optional a_elev, b_elev;
try {
a_elev = static_cast(*a->get("Elevation"));
b_elev = static_cast(*b->get("Elevation"));
} catch (...) {};
if (a_elev && b_elev) {
return std::less()(*a_elev, *b_elev);
}
boost::optional a_name, b_name;
try {
a_name = static_cast(*a->get("Name"));
b_name = static_cast(*b->get("Name"));
} catch (...) {};
if (a_name && b_name) {
return std::less()(*a_name, *b_name);
}
}
return std::less()(a, b);
}
};
class SvgSerializer : public GeometrySerializer {
public:
typedef std::pair > path_object;
protected:
std::ofstream svg_file;
double xmin, ymin, xmax, ymax, width, height;
boost::optional>> section_heights;
bool rescale, print_space_names_, print_space_areas_;
std::multimap paths;
std::vector< boost::shared_ptr > xcoords;
std::vector< boost::shared_ptr > ycoords;
std::vector< boost::shared_ptr > radii;
IfcParse::IfcFile* file;
IfcUtil::IfcBaseEntity* storey_;
public:
SvgSerializer(const std::string& out_filename, const SerializerSettings& settings)
: GeometrySerializer(settings)
, svg_file(IfcUtil::path::from_utf8(out_filename).c_str())
, xmin(+std::numeric_limits::infinity())
, ymin(+std::numeric_limits::infinity())
, xmax(-std::numeric_limits::infinity())
, ymax(-std::numeric_limits::infinity())
, rescale(false)
, file(0)
, storey_(0)
{}
void addXCoordinate(const boost::shared_ptr& fi) { xcoords.push_back(fi); }
void addYCoordinate(const boost::shared_ptr& fi) { ycoords.push_back(fi); }
void addSizeComponent(const boost::shared_ptr& fi) { radii.push_back(fi); }
void growBoundingBox(double x, double y) { if (x < xmin) xmin = x; if (x > xmax) xmax = x; if (y < ymin) ymin = y; if (y > ymax) ymax = y; }
void writeHeader();
bool ready();
void write(const IfcGeom::TriangulationElement* /*o*/) {}
void write(const IfcGeom::BRepElement* o);
void write(path_object& p, const TopoDS_Wire& wire);
path_object& start_path(IfcUtil::IfcBaseEntity* storey, const std::string& id);
bool isTesselated() const { return false; }
void finalize();
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
void setFile(IfcParse::IfcFile* f);
void setBoundingRectangle(double width, double height);
void setSectionHeight(double h, IfcUtil::IfcBaseEntity* storey = 0);
void setSectionHeightsFromStoreys(double offset=1.);
void setPrintSpaceNames(bool b) { print_space_names_ = b; }
void setPrintSpaceAreas(bool b) { print_space_areas_ = b; }
std::string nameElement(const IfcGeom::Element* elem);
std::string nameElement(const IfcUtil::IfcBaseEntity* elem);
};
#endif