Merge branch 'master' of github.com:alexrj/Slic3r

This commit is contained in:
Alessandro Ranellucci 2014-09-21 14:42:09 +02:00
commit f3db284e2a
19 changed files with 448 additions and 347 deletions

View file

@ -16,6 +16,7 @@ BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &poin
this->max.x = std::max(it->x, this->max.x);
this->max.y = std::max(it->y, this->max.y);
}
this->defined = true;
}
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
@ -80,10 +81,15 @@ template void BoundingBoxBase<Pointf3>::scale(double factor);
template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const PointClass &point)
{
this->min.x = std::min(point.x, this->min.x);
this->min.y = std::min(point.y, this->min.y);
this->max.x = std::max(point.x, this->max.x);
this->max.y = std::max(point.y, this->max.y);
if (this->defined) {
this->min.x = std::min(point.x, this->min.x);
this->min.y = std::min(point.y, this->min.y);
this->max.x = std::max(point.x, this->max.x);
this->max.y = std::max(point.y, this->max.y);
} else {
this->min = this->max = point;
this->defined = true;
}
}
template void BoundingBoxBase<Point>::merge(const Point &point);
template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
@ -91,10 +97,16 @@ template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
{
this->min.x = std::min(bb.min.x, this->min.x);
this->min.y = std::min(bb.min.y, this->min.y);
this->max.x = std::max(bb.max.x, this->max.x);
this->max.y = std::max(bb.max.y, this->max.y);
if (this->defined) {
this->min.x = std::min(bb.min.x, this->min.x);
this->min.y = std::min(bb.min.y, this->min.y);
this->max.x = std::max(bb.max.x, this->max.x);
this->max.y = std::max(bb.max.y, this->max.y);
} else {
this->min = bb.min;
this->max = bb.max;
this->defined = true;
}
}
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
@ -102,18 +114,22 @@ template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const PointClass &point)
{
if (this->defined) {
this->min.z = std::min(point.z, this->min.z);
this->max.z = std::max(point.z, this->max.z);
}
BoundingBoxBase<PointClass>::merge(point);
this->min.z = std::min(point.z, this->min.z);
this->max.z = std::max(point.z, this->max.z);
}
template void BoundingBox3Base<Pointf3>::merge(const Pointf3 &point);
template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
{
if (this->defined) {
this->min.z = std::min(bb.min.z, this->min.z);
this->max.z = std::max(bb.max.z, this->max.z);
}
BoundingBoxBase<PointClass>::merge(bb);
this->min.z = std::min(bb.min.z, this->min.z);
this->max.z = std::max(bb.max.z, this->max.z);
}
template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb);

View file

@ -18,8 +18,9 @@ class BoundingBoxBase
public:
PointClass min;
PointClass max;
bool defined;
BoundingBoxBase() {};
BoundingBoxBase() : defined(false) {};
BoundingBoxBase(const std::vector<PointClass> &points);
void merge(const PointClass &point);
void merge(const BoundingBoxBase<PointClass> &bb);
@ -34,7 +35,7 @@ template <class PointClass>
class BoundingBox3Base : public BoundingBoxBase<PointClass>
{
public:
BoundingBox3Base() {};
BoundingBox3Base() : BoundingBoxBase<PointClass>() {};
BoundingBox3Base(const std::vector<PointClass> &points);
void merge(const PointClass &point);
void merge(const BoundingBox3Base<PointClass> &bb);
@ -50,7 +51,7 @@ class BoundingBox : public BoundingBoxBase<Point>
void polygon(Polygon* polygon) const;
Polygon polygon() const;
BoundingBox() {};
BoundingBox() : BoundingBoxBase<Point>() {};
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {};
BoundingBox(const Lines &lines);
};
@ -61,13 +62,13 @@ class BoundingBox3 : public BoundingBox3Base<Point3> {};
class BoundingBoxf : public BoundingBoxBase<Pointf> {
public:
BoundingBoxf() {};
BoundingBoxf() : BoundingBoxBase<Pointf>() {};
BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
};
class BoundingBoxf3 : public BoundingBox3Base<Pointf3> {
public:
BoundingBoxf3() {};
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};
};

View file

@ -158,6 +158,91 @@ Model::has_objects_with_no_instances() const
return false;
}
// makes sure all objects have at least one instance
bool
Model::add_default_instances()
{
bool added = false;
// apply a default position to all objects not having one
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
if ((*o)->instances.empty()) {
(*o)->add_instance();
added = true;
}
}
return true;
}
// this returns the bounding box of the *transformed* instances
void
Model::bounding_box(BoundingBoxf3* bb)
{
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
BoundingBoxf3 obb;
(*o)->bounding_box(&obb);
bb->merge(obb);
}
}
void
Model::center_instances_around_point(const Pointf &point)
{
BoundingBoxf3 bb;
this->bounding_box(&bb);
Sizef3 size = bb.size();
double shift_x = -bb.min.x + point.x - size.x/2;
double shift_y = -bb.min.y + point.y - size.y/2;
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
for (ModelInstancePtrs::const_iterator i = (*o)->instances.begin(); i != (*o)->instances.end(); ++i) {
(*i)->offset.translate(shift_x, shift_y);
}
(*o)->update_bounding_box();
}
}
void
Model::align_instances_to_origin()
{
BoundingBoxf3 bb;
this->bounding_box(&bb);
Pointf new_center = (Pointf)bb.size();
new_center.translate(-new_center.x/2, -new_center.y/2);
this->center_instances_around_point(new_center);
}
void
Model::translate(coordf_t x, coordf_t y, coordf_t z)
{
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
(*o)->translate(x, y, z);
}
}
// flattens everything to a single mesh
void
Model::mesh(TriangleMesh* mesh) const
{
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
TriangleMesh omesh;
(*o)->mesh(&omesh);
mesh->merge(omesh);
}
}
// flattens everything to a single mesh
void
Model::raw_mesh(TriangleMesh* mesh) const
{
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
TriangleMesh omesh;
(*o)->raw_mesh(&omesh);
mesh->merge(omesh);
}
}
#ifdef SLIC3RXS
REGISTER_CLASS(Model, "Model");
#endif
@ -306,12 +391,45 @@ ModelObject::clear_instances()
this->delete_instance(i);
}
// this returns the bounding box of the *transformed* instances
void
ModelObject::bounding_box(BoundingBoxf3* bb)
{
if (!this->_bounding_box_valid) this->update_bounding_box();
*bb = this->_bounding_box;
}
void
ModelObject::invalidate_bounding_box()
{
this->_bounding_box_valid = false;
}
void
ModelObject::update_bounding_box()
{
TriangleMesh mesh;
this->mesh(&mesh);
mesh.bounding_box(&this->_bounding_box);
this->_bounding_box_valid = true;
}
// flattens all volumes and instances into a single mesh
void
ModelObject::mesh(TriangleMesh* mesh) const
{
TriangleMesh raw_mesh;
this->raw_mesh(&raw_mesh);
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
TriangleMesh m = raw_mesh;
(*i)->transform_mesh(&m);
mesh->merge(m);
}
}
void
ModelObject::raw_mesh(TriangleMesh* mesh) const
{
@ -321,6 +439,156 @@ ModelObject::raw_mesh(TriangleMesh* mesh) const
}
}
void
ModelObject::raw_bounding_box(BoundingBoxf3* bb) const
{
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
if ((*v)->modifier) continue;
TriangleMesh mesh = (*v)->mesh;
if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
this->instances.front()->transform_mesh(&mesh, true);
BoundingBoxf3 mbb;
mesh.bounding_box(&mbb);
bb->merge(mbb);
}
}
// this returns the bounding box of the *transformed* given instance
void
ModelObject::instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const
{
TriangleMesh mesh;
this->raw_mesh(&mesh);
this->instances[instance_idx]->transform_mesh(&mesh);
mesh.bounding_box(bb);
}
void
ModelObject::center_around_origin()
{
// calculate the displacements needed to
// center this object around the origin
BoundingBoxf3 bb;
{
TriangleMesh mesh;
this->raw_mesh(&mesh);
mesh.bounding_box(&bb);
}
// first align to origin on XY
double shift_x = -bb.min.x;
double shift_y = -bb.min.y;
// then center it on XY
Sizef3 size = bb.size();
shift_x -= size.x/2;
shift_y -= size.y/2;
this->translate(shift_x, shift_y, 0);
this->origin_translation.translate(shift_x, shift_y);
if (!this->instances.empty()) {
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
(*i)->offset.translate(-shift_x, -shift_y);
}
this->update_bounding_box();
}
}
void
ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
{
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
(*v)->mesh.translate(x, y, z);
}
if (this->_bounding_box_valid) this->_bounding_box.translate(x, y, z);
}
void
ModelObject::scale(const Pointf3 &versor)
{
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
(*v)->mesh.scale(versor);
}
this->invalidate_bounding_box();
}
size_t
ModelObject::materials_count() const
{
std::set<t_model_material_id> material_ids;
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
material_ids.insert((*v)->material_id());
}
return material_ids.size();
}
size_t
ModelObject::facets_count() const
{
size_t num = 0;
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
if ((*v)->modifier) continue;
num += (*v)->mesh.stl.stats.number_of_facets;
}
return num;
}
bool
ModelObject::needed_repair() const
{
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
if ((*v)->modifier) continue;
if ((*v)->mesh.needed_repair()) return true;
}
return false;
}
void
ModelObject::cut(coordf_t z, Model* model) const
{
// clone this one to duplicate instances, materials etc.
ModelObject* upper = model->add_object(*this);
ModelObject* lower = model->add_object(*this);
upper->clear_volumes();
lower->clear_volumes();
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
ModelVolume* volume = *v;
if (volume->modifier) {
// don't cut modifiers
upper->add_volume(*volume);
lower->add_volume(*volume);
} else {
TriangleMeshSlicer tms(&volume->mesh);
TriangleMesh upper_mesh, lower_mesh;
// TODO: shouldn't we use object bounding box instead of per-volume bb?
tms.cut(z + volume->mesh.bounding_box().min.z, &upper_mesh, &lower_mesh);
upper_mesh.repair();
lower_mesh.repair();
upper_mesh.reset_repair_stats();
lower_mesh.reset_repair_stats();
if (upper_mesh.facets_count() > 0) {
ModelVolume* vol = upper->add_volume(upper_mesh);
vol->name = volume->name;
vol->config = volume->config;
vol->set_material(volume->material_id(), *volume->material());
}
if (lower_mesh.facets_count() > 0) {
ModelVolume* vol = lower->add_volume(lower_mesh);
vol->name = volume->name;
vol->config = volume->config;
vol->set_material(volume->material_id(), *volume->material());
}
}
}
}
#ifdef SLIC3RXS
REGISTER_CLASS(ModelObject, "Model::Object");
#endif
@ -358,6 +626,13 @@ ModelVolume::material() const
return this->object->get_model()->get_material(this->_material_id);
}
void
ModelVolume::set_material(t_model_material_id material_id, const ModelMaterial &material)
{
this->_material_id = material_id;
(void)this->object->get_model()->add_material(material_id, material);
}
ModelMaterial*
ModelVolume::assign_unique_material()
{

View file

@ -53,11 +53,13 @@ class Model
// void arrange_objects(coordf_t distance, const BoundingBox &bb);
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
bool has_objects_with_no_instances() const;
// void bounding_box(BoundingBox* bb) const;
// void align_to_origin();
// void center_instances_around_point(const Pointf &point);
// void translate(coordf_t x, coordf_t y, coordf_t z);
// void mesh(TriangleMesh* mesh) const;
bool add_default_instances();
void bounding_box(BoundingBoxf3* bb);
void center_instances_around_point(const Pointf &point);
void align_instances_to_origin();
void translate(coordf_t x, coordf_t y, coordf_t z);
void mesh(TriangleMesh* mesh) const;
void raw_mesh(TriangleMesh* mesh) const;
// void split_meshes();
// std::string get_material_name(t_model_material_id material_id);
@ -112,17 +114,21 @@ class ModelObject
void delete_last_instance();
void clear_instances();
void bounding_box(BoundingBoxf3* bb);
void invalidate_bounding_box();
void mesh(TriangleMesh* mesh) const;
void raw_mesh(TriangleMesh* mesh) const;
//void mesh(TriangleMesh* mesh) const;
//void instance_bounding_box(size_t instance_idx, BoundingBox* bb) const;
//void center_around_origin();
//void translate(coordf_t x, coordf_t y, coordf_t z);
//size_t materials_count() const;
//void unique_materials(std::vector<t_model_material_id>* materials) const;
//size_t facets_count() const;
//bool needed_repair() const;
void raw_bounding_box(BoundingBoxf3* bb) const;
void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const;
void center_around_origin();
void translate(coordf_t x, coordf_t y, coordf_t z);
void scale(const Pointf3 &versor);
size_t materials_count() const;
size_t facets_count() const;
bool needed_repair() const;
void cut(coordf_t z, Model* model) const;
void update_bounding_box(); // this is a private method but we expose it until we need to expose it via XS
private:
Model* model;
@ -132,7 +138,6 @@ class ModelObject
ModelObject& operator= (ModelObject other);
void swap(ModelObject &other);
~ModelObject();
void update_bounding_box();
};
class ModelVolume
@ -148,6 +153,7 @@ class ModelVolume
t_model_material_id material_id() const;
void material_id(t_model_material_id material_id);
ModelMaterial* material() const;
void set_material(t_model_material_id material_id, const ModelMaterial &material);
ModelMaterial* assign_unique_material();

View file

@ -153,6 +153,23 @@ TriangleMesh::reset_repair_stats() {
this->stl.stats.normals_fixed = 0;
}
bool
TriangleMesh::needed_repair() const
{
return this->stl.stats.degenerate_facets > 0
|| this->stl.stats.edges_fixed > 0
|| this->stl.stats.facets_removed > 0
|| this->stl.stats.facets_added > 0
|| this->stl.stats.facets_reversed > 0
|| this->stl.stats.backwards_edges > 0;
}
size_t
TriangleMesh::facets_count() const
{
return this->stl.stats.number_of_facets;
}
void
TriangleMesh::WriteOBJFile(char* output_file) {
stl_generate_shared_vertices(&stl);
@ -164,12 +181,12 @@ void TriangleMesh::scale(float factor)
stl_scale(&(this->stl), factor);
}
void TriangleMesh::scale(std::vector<double> versor)
void TriangleMesh::scale(const Pointf3 &versor)
{
float fversor[3];
fversor[0] = versor[0];
fversor[1] = versor[1];
fversor[2] = versor[2];
fversor[0] = versor.x;
fversor[1] = versor.y;
fversor[2] = versor.z;
stl_scale_versor(&this->stl, fversor);
}
@ -344,6 +361,14 @@ TriangleMesh::bounding_box(BoundingBoxf3* bb) const
bb->max.z = this->stl.stats.max.z;
}
BoundingBoxf3
TriangleMesh::bounding_box() const
{
BoundingBoxf3 bb;
this->bounding_box(&bb);
return bb;
}
void
TriangleMesh::require_shared_vertices()
{

View file

@ -29,7 +29,7 @@ class TriangleMesh
void repair();
void WriteOBJFile(char* output_file);
void scale(float factor);
void scale(std::vector<double> versor);
void scale(const Pointf3 &versor);
void translate(float x, float y, float z);
void rotate_x(float angle);
void rotate_y(float angle);
@ -44,7 +44,10 @@ class TriangleMesh
void horizontal_projection(ExPolygons &retval) const;
void convex_hull(Polygon* hull);
void bounding_box(BoundingBoxf3* bb) const;
BoundingBoxf3 bounding_box() const;
void reset_repair_stats();
bool needed_repair() const;
size_t facets_count() const;
stl_file stl;
bool repaired;

View file

@ -40,7 +40,7 @@ my $cube = {
$m->scale(2);
ok abs($m->stats->{volume} - 40*40*40) < 1E-2, 'scale';
$m->scale_xyz([2,1,1]);
$m->scale_xyz(Slic3r::Pointf3->new(2,1,1));
ok abs($m->stats->{volume} - 2*40*40*40) < 1E-2, 'scale_xyz';
$m->translate(5,10,0);
@ -51,7 +51,7 @@ my $cube = {
is_deeply $m->size, [80,40,40], 'size';
$m->scale_xyz([0.5,1,1]);
$m->scale_xyz(Slic3r::Pointf3->new(0.5,1,1));
$m->rotate(45, Slic3r::Point->new(20,20));
ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate';

View file

@ -4,7 +4,7 @@ use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 3;
use Test::More tests => 5;
{
my @points = (
@ -17,4 +17,11 @@ use Test::More tests => 3;
is_deeply $bb->max_point->pp, [500,200], 'max_point';
}
{
my $bb = Slic3r::Geometry::BoundingBox->new;
$bb->merge_point(Slic3r::Point->new(10, 10));
is_deeply $bb->min_point->pp, [10,10], 'min_point equals to the only defined point';
is_deeply $bb->max_point->pp, [10,10], 'max_point equals to the only defined point';
}
__END__

View file

@ -7,6 +7,7 @@
%}
%name{Slic3r::Geometry::BoundingBox} class BoundingBox {
BoundingBox();
~BoundingBox();
Clone<BoundingBox> clone()
%code{% RETVAL = THIS; %};
@ -41,6 +42,7 @@ new_from_points(CLASS, points)
};
%name{Slic3r::Geometry::BoundingBoxf} class BoundingBoxf {
BoundingBoxf();
~BoundingBoxf();
Clone<BoundingBoxf> clone()
%code{% RETVAL = THIS; %};
@ -76,6 +78,7 @@ new_from_points(CLASS, points)
};
%name{Slic3r::Geometry::BoundingBoxf3} class BoundingBoxf3 {
BoundingBoxf3();
~BoundingBoxf3();
Clone<BoundingBoxf3> clone()
%code{% RETVAL = THIS; %};

View file

@ -55,12 +55,21 @@
// void duplicate_objects(size_t copies_num, coordf_t distance, const BoundingBox &bb);
// void arrange_objects(coordf_t distance, const BoundingBox &bb);
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
bool has_objects_with_no_instances() const;
// void bounding_box(BoundingBox* bb) const;
// void center_instances_around_point(const Pointf &point);
// void align_instances_to_origin();
// void translate(coordf_t x, coordf_t y, coordf_t z);
// void mesh(TriangleMesh* mesh) const;
bool has_objects_with_no_instances();
bool add_default_instances();
BoundingBoxf3* bounding_box()
%code%{
RETVAL = new BoundingBoxf3();
THIS->bounding_box(RETVAL);
%};
void center_instances_around_point(Pointf* point)
%code%{ THIS->center_instances_around_point(*point); %};
void align_instances_to_origin();
void translate(double x, double y, double z);
TriangleMesh* mesh()
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
TriangleMesh* raw_mesh()
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
// void split_meshes();
// std::string get_material_name(t_model_material_id material_id);
@ -107,8 +116,21 @@ ModelMaterial::attributes()
%code%{ RETVAL = &THIS->instances; %};
void invalidate_bounding_box();
void update_bounding_box();
TriangleMesh* mesh()
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
TriangleMesh* raw_mesh()
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
BoundingBoxf3* raw_bounding_box()
%code%{
RETVAL = new BoundingBoxf3();
THIS->raw_bounding_box(RETVAL);
%};
BoundingBoxf3* instance_bounding_box(int idx)
%code%{
RETVAL = new BoundingBoxf3();
THIS->instance_bounding_box(idx, RETVAL);
%};
Ref<BoundingBoxf3> _bounding_box(BoundingBoxf3* new_bbox = NULL)
%code{%
@ -123,6 +145,11 @@ ModelMaterial::attributes()
RETVAL = &THIS->_bounding_box;
%};
BoundingBoxf3* bounding_box()
%code%{
RETVAL = new BoundingBoxf3();
THIS->bounding_box(RETVAL);
%};
%name{_add_volume} Ref<ModelVolume> add_volume(TriangleMesh* mesh)
%code%{ RETVAL = THIS->add_volume(*mesh); %};
@ -131,6 +158,8 @@ ModelMaterial::attributes()
void delete_volume(size_t idx);
void clear_volumes();
int volumes_count()
%code%{ RETVAL = THIS->volumes.size(); %};
%name{_add_instance} Ref<ModelInstance> add_instance();
Ref<ModelInstance> _add_instance_clone(ModelInstance* other)
@ -163,6 +192,20 @@ ModelMaterial::attributes()
%code%{ RETVAL = &THIS->origin_translation; %};
void set_origin_translation(Pointf* point)
%code%{ THIS->origin_translation = *point; %};
bool needed_repair() const;
int materials_count() const;
int facets_count();
void center_around_origin();
void translate(double x, double y, double z);
void scale_xyz(Pointf3* versor)
%code{% THIS->scale(*versor); %};
Model* cut(double z)
%code%{
RETVAL = new Model();
THIS->cut(z, RETVAL);
%};
};

View file

@ -17,8 +17,8 @@
void repair();
void WriteOBJFile(char* output_file);
void scale(float factor);
void scale_xyz(std::vector<double> versor)
%code{% THIS->scale(versor); %};
void scale_xyz(Pointf3* versor)
%code{% THIS->scale(*versor); %};
void translate(float x, float y, float z);
void rotate_x(float angle);
void rotate_y(float angle);
@ -38,8 +38,13 @@
RETVAL = new BoundingBoxf3();
THIS->bounding_box(RETVAL);
%};
int facets_count()
%code{% RETVAL = THIS->stl.stats.number_of_facets; %};
Pointf3* center()
%code{%
BoundingBoxf3 bb;
THIS->bounding_box(&bb);
RETVAL = new Pointf3(bb.center());
%};
int facets_count();
void reset_repair_stats();
%{