diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 497daee0d..e810ca384 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -15,11 +15,6 @@ sub wkt { return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self; } -sub is_counter_clockwise { - my $self = shift; - return Slic3r::Geometry::Clipper::is_counter_clockwise($self->pp); -} - sub make_counter_clockwise { my $self = shift; if (!$self->is_counter_clockwise) { diff --git a/xs/src/ClipperUtils.cpp b/xs/src/ClipperUtils.cpp new file mode 100644 index 000000000..82e12e06d --- /dev/null +++ b/xs/src/ClipperUtils.cpp @@ -0,0 +1,177 @@ +#include "ClipperUtils.hpp" + +namespace Slic3r { + +void +ClipperPolygon_to_Slic3rPolygon(ClipperLib::Polygon &input, Slic3r::Polygon &output) +{ + output.points.clear(); + for (ClipperLib::Polygon::iterator pit = input.begin(); pit != input.end(); ++pit) { + output.points.push_back(Slic3r::Point( (*pit).X, (*pit).Y )); + } +} + +//----------------------------------------------------------- +// legacy code from Clipper documentation +void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons) +{ + size_t cnt = expolygons.size(); + expolygons.resize(cnt + 1); + ClipperPolygon_to_Slic3rPolygon(polynode.Contour, expolygons[cnt].contour); + expolygons[cnt].holes.resize(polynode.ChildCount()); + for (int i = 0; i < polynode.ChildCount(); ++i) + { + ClipperPolygon_to_Slic3rPolygon(polynode.Childs[i]->Contour, expolygons[cnt].holes[i]); + //Add outer polygons contained by (nested within) holes ... + for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j) + AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons); + } +} + +void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons) +{ + expolygons.clear(); + for (int i = 0; i < polytree.ChildCount(); ++i) + AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons); +} +//----------------------------------------------------------- + +void +Slic3rPolygon_to_ClipperPolygon(Slic3r::Polygon &input, ClipperLib::Polygon &output) +{ + output.clear(); + for (Slic3r::Points::iterator pit = input.points.begin(); pit != input.points.end(); ++pit) { + output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); + } +} + +void +Slic3rPolygons_to_ClipperPolygons(Slic3r::Polygons &input, ClipperLib::Polygons &output) +{ + output.clear(); + for (Slic3r::Polygons::iterator it = input.begin(); it != input.end(); ++it) { + ClipperLib::Polygon p; + Slic3rPolygon_to_ClipperPolygon(*it, p); + output.push_back(p); + } +} + +void +ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolygons &output) +{ + // init Clipper + ClipperLib::Clipper clipper; + clipper.Clear(); + + // perform union + clipper.AddPolygons(input, ClipperLib::ptSubject); + ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree(); + clipper.Execute(ClipperLib::ctUnion, *polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero + + // write to ExPolygons object + output.clear(); + PolyTreeToExPolygons(*polytree, output); + + delete polytree; +} + +void +scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale) +{ + for (ClipperLib::Polygons::iterator it = polygons.begin(); it != polygons.end(); ++it) { + for (ClipperLib::Polygon::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) { + (*pit).X *= scale; + (*pit).Y *= scale; + } + } +} + +void +offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // read input + ClipperLib::Polygons* input = new ClipperLib::Polygons(); + Slic3rPolygons_to_ClipperPolygons(polygons, *input); + + // scale input + scaleClipperPolygons(*input, scale); + + // perform offset + ClipperLib::Polygons* output = new ClipperLib::Polygons(); + ClipperLib::OffsetPolygons(*input, *output, (delta*scale), joinType, miterLimit); + delete input; + + // unscale output + scaleClipperPolygons(*output, 1/scale); + + // convert into ExPolygons + ClipperPolygons_to_Slic3rExPolygons(*output, retval); + delete output; +} + +void +offset2_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta1, + const float delta2, double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // read input + ClipperLib::Polygons* input = new ClipperLib::Polygons(); + Slic3rPolygons_to_ClipperPolygons(polygons, *input); + + // scale input + scaleClipperPolygons(*input, scale); + + // perform first offset + ClipperLib::Polygons* output1 = new ClipperLib::Polygons(); + ClipperLib::OffsetPolygons(*input, *output1, (delta1*scale), joinType, miterLimit); + delete input; + + // perform second offset + ClipperLib::Polygons* output2 = new ClipperLib::Polygons(); + ClipperLib::OffsetPolygons(*output1, *output2, (delta2*scale), joinType, miterLimit); + delete output1; + + // unscale output + scaleClipperPolygons(*output2, 1/scale); + + // convert into ExPolygons + ClipperPolygons_to_Slic3rExPolygons(*output2, retval); + delete output2; +} + +void +diff_ex(Slic3r::Polygons &subject, Slic3r::Polygons &clip, Slic3r::ExPolygons &retval, bool safety_offset) +{ + // read input + ClipperLib::Polygons* input_subject = new ClipperLib::Polygons(); + ClipperLib::Polygons* input_clip = new ClipperLib::Polygons(); + Slic3rPolygons_to_ClipperPolygons(subject, *input_subject); + Slic3rPolygons_to_ClipperPolygons(clip, *input_clip); + + // perform safety offset + if (safety_offset) { + // SafetyOffset(*input_clip); + } + + // init Clipper + ClipperLib::Clipper clipper; + clipper.Clear(); + + // add polygons + clipper.AddPolygons(*input_subject, ClipperLib::ptSubject); + delete input_subject; + clipper.AddPolygons(*input_clip, ClipperLib::ptClip); + delete input_clip; + + // perform operation + ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree(); + clipper.Execute(ClipperLib::ctDifference, *polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + + // convert into ExPolygons + PolyTreeToExPolygons(*polytree, retval); + delete polytree; +} + + + +} diff --git a/xs/src/ClipperUtils.hpp b/xs/src/ClipperUtils.hpp index ade09433f..37012591d 100644 --- a/xs/src/ClipperUtils.hpp +++ b/xs/src/ClipperUtils.hpp @@ -1,190 +1,36 @@ #ifndef slic3r_ClipperUtils_hpp_ #define slic3r_ClipperUtils_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include "clipper.hpp" +#include "ExPolygon.hpp" +#include "Polygon.hpp" namespace Slic3r { -void -ClipperPolygon_to_Slic3rPolygon(ClipperLib::Polygon &input, Slic3r::Polygon &output) -{ - output.points.clear(); - for (ClipperLib::Polygon::iterator pit = input.begin(); pit != input.end(); ++pit) { - output.points.push_back(Slic3r::Point( (*pit).X, (*pit).Y )); - } -} +void ClipperPolygon_to_Slic3rPolygon(ClipperLib::Polygon &input, Slic3r::Polygon &output); //----------------------------------------------------------- // legacy code from Clipper documentation -void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons) -{ - size_t cnt = expolygons.size(); - expolygons.resize(cnt + 1); - ClipperPolygon_to_Slic3rPolygon(polynode.Contour, expolygons[cnt].contour); - expolygons[cnt].holes.resize(polynode.ChildCount()); - for (int i = 0; i < polynode.ChildCount(); ++i) - { - ClipperPolygon_to_Slic3rPolygon(polynode.Childs[i]->Contour, expolygons[cnt].holes[i]); - //Add outer polygons contained by (nested within) holes ... - for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j) - AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons); - } -} - -void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons) -{ - expolygons.clear(); - for (int i = 0; i < polytree.ChildCount(); ++i) - AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons); -} +void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons& expolygons); +void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons); //----------------------------------------------------------- -void -Slic3rPolygon_to_ClipperPolygon(Slic3r::Polygon &input, ClipperLib::Polygon &output) -{ - output.clear(); - for (Slic3r::Points::iterator pit = input.points.begin(); pit != input.points.end(); ++pit) { - output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); - } -} +void Slic3rPolygon_to_ClipperPolygon(Slic3r::Polygon &input, ClipperLib::Polygon &output); +void Slic3rPolygons_to_ClipperPolygons(Slic3r::Polygons &input, ClipperLib::Polygons &output); +void ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolygons &output); -void -Slic3rPolygons_to_ClipperPolygons(Slic3r::Polygons &input, ClipperLib::Polygons &output) -{ - output.clear(); - for (Slic3r::Polygons::iterator it = input.begin(); it != input.end(); ++it) { - ClipperLib::Polygon p; - Slic3rPolygon_to_ClipperPolygon(*it, p); - output.push_back(p); - } -} +void scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale); -void -ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolygons &output) -{ - // init Clipper - ClipperLib::Clipper clipper; - clipper.Clear(); - - // perform union - clipper.AddPolygons(input, ClipperLib::ptSubject); - ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree(); - clipper.Execute(ClipperLib::ctUnion, *polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero - - // write to ExPolygons object - output.clear(); - PolyTreeToExPolygons(*polytree, output); - - delete polytree; -} - -void -scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale) -{ - for (ClipperLib::Polygons::iterator it = polygons.begin(); it != polygons.end(); ++it) { - for (ClipperLib::Polygon::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) { - (*pit).X *= scale; - (*pit).Y *= scale; - } - } -} - -void -offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta, +void offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3) -{ - // read input - ClipperLib::Polygons* input = new ClipperLib::Polygons(); - Slic3rPolygons_to_ClipperPolygons(polygons, *input); - - // scale input - scaleClipperPolygons(*input, scale); - - // perform offset - ClipperLib::Polygons* output = new ClipperLib::Polygons(); - ClipperLib::OffsetPolygons(*input, *output, (delta*scale), joinType, miterLimit); - delete input; - - // unscale output - scaleClipperPolygons(*output, 1/scale); - - // convert into ExPolygons - ClipperPolygons_to_Slic3rExPolygons(*output, retval); - delete output; -} + double miterLimit = 3); -void -offset2_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta1, +void offset2_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta1, const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3) -{ - // read input - ClipperLib::Polygons* input = new ClipperLib::Polygons(); - Slic3rPolygons_to_ClipperPolygons(polygons, *input); - - // scale input - scaleClipperPolygons(*input, scale); - - // perform first offset - ClipperLib::Polygons* output1 = new ClipperLib::Polygons(); - ClipperLib::OffsetPolygons(*input, *output1, (delta1*scale), joinType, miterLimit); - delete input; - - // perform second offset - ClipperLib::Polygons* output2 = new ClipperLib::Polygons(); - ClipperLib::OffsetPolygons(*output1, *output2, (delta2*scale), joinType, miterLimit); - delete output1; - - // unscale output - scaleClipperPolygons(*output2, 1/scale); - - // convert into ExPolygons - ClipperPolygons_to_Slic3rExPolygons(*output2, retval); - delete output2; -} - -void -diff_ex(Slic3r::Polygons &subject, Slic3r::Polygons &clip, Slic3r::ExPolygons &retval, bool safety_offset) -{ - // read input - ClipperLib::Polygons* input_subject = new ClipperLib::Polygons(); - ClipperLib::Polygons* input_clip = new ClipperLib::Polygons(); - Slic3rPolygons_to_ClipperPolygons(subject, *input_subject); - Slic3rPolygons_to_ClipperPolygons(clip, *input_clip); - - // perform safety offset - if (safety_offset) { - // SafetyOffset(*input_clip); - } - - // init Clipper - ClipperLib::Clipper clipper; - clipper.Clear(); - - // add polygons - clipper.AddPolygons(*input_subject, ClipperLib::ptSubject); - delete input_subject; - clipper.AddPolygons(*input_clip, ClipperLib::ptClip); - delete input_clip; - - // perform operation - ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree(); - clipper.Execute(ClipperLib::ctDifference, *polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); - - // convert into ExPolygons - PolyTreeToExPolygons(*polytree, retval); - delete polytree; -} - + double miterLimit = 3); +void diff_ex(Slic3r::Polygons &subject, Slic3r::Polygons &clip, Slic3r::ExPolygons &retval, bool safety_offset); } diff --git a/xs/src/ExPolygon.cpp b/xs/src/ExPolygon.cpp new file mode 100644 index 000000000..4805b156e --- /dev/null +++ b/xs/src/ExPolygon.cpp @@ -0,0 +1,98 @@ +#include "ExPolygon.hpp" +#include "Polygon.hpp" + +namespace Slic3r { + +void +ExPolygon::scale(double factor) +{ + contour.scale(factor); + for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { + (*it).scale(factor); + } +} + +void +ExPolygon::translate(double x, double y) +{ + contour.translate(x, y); + for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { + (*it).translate(x, y); + } +} + +void +ExPolygon::rotate(double angle, Point* center) +{ + contour.rotate(angle, center); + for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { + (*it).rotate(angle, center); + } +} + +SV* +ExPolygon::to_SV() { + const unsigned int num_holes = this->holes.size(); + AV* av = newAV(); + av_extend(av, num_holes); // -1 +1 + + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(this->contour) ); + av_store(av, 0, sv); + + for (unsigned int i = 0; i < num_holes; i++) { + sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(this->holes[i]) ); + av_store(av, i+1, sv); + } + return newRV_noinc((SV*)av); +} + +SV* +ExPolygon::to_SV_ref() { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::ExPolygon", new ExPolygon(*this) ); + return sv; +} + +SV* +ExPolygon::to_SV_pureperl() +{ + const unsigned int num_holes = this->holes.size(); + AV* av = newAV(); + av_extend(av, num_holes); // -1 +1 + av_store(av, 0, this->contour.to_SV_pureperl()); + for (unsigned int i = 0; i < num_holes; i++) { + av_store(av, i+1, this->holes[i].to_SV_pureperl()); + } + return newRV_noinc((SV*)av); +} + +void +ExPolygon::from_SV(SV* expoly_sv) +{ + AV* expoly_av = (AV*)SvRV(expoly_sv); + const unsigned int num_polygons = av_len(expoly_av)+1; + this->holes.resize(num_polygons-1); + + SV** polygon_sv = av_fetch(expoly_av, 0, 0); + this->contour.from_SV(*polygon_sv); + for (unsigned int i = 0; i < num_polygons-1; i++) { + polygon_sv = av_fetch(expoly_av, i+1, 0); + this->holes[i].from_SV(*polygon_sv); + } +} + +void +ExPolygon::from_SV_check(SV* expoly_sv) +{ + if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) { + // a XS ExPolygon was supplied + *this = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv )); + } else { + // a Perl arrayref was supplied + this->from_SV(expoly_sv); + } +} + +} diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp index a10cf9716..4c927f8b7 100644 --- a/xs/src/ExPolygon.hpp +++ b/xs/src/ExPolygon.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_ExPolygon_hpp_ #define slic3r_ExPolygon_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - #include "Polygon.hpp" #include @@ -31,98 +24,6 @@ class ExPolygon typedef std::vector ExPolygons; -void -ExPolygon::scale(double factor) -{ - contour.scale(factor); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).scale(factor); - } -} - -void -ExPolygon::translate(double x, double y) -{ - contour.translate(x, y); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).translate(x, y); - } -} - -void -ExPolygon::rotate(double angle, Point* center) -{ - contour.rotate(angle, center); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).rotate(angle, center); - } -} - -SV* -ExPolygon::to_SV() { - const unsigned int num_holes = this->holes.size(); - AV* av = newAV(); - av_extend(av, num_holes); // -1 +1 - - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(this->contour) ); - av_store(av, 0, sv); - - for (unsigned int i = 0; i < num_holes; i++) { - sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(this->holes[i]) ); - av_store(av, i+1, sv); - } - return newRV_noinc((SV*)av); -} - -SV* -ExPolygon::to_SV_ref() { - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::ExPolygon", new ExPolygon(*this) ); - return sv; -} - -SV* -ExPolygon::to_SV_pureperl() -{ - const unsigned int num_holes = this->holes.size(); - AV* av = newAV(); - av_extend(av, num_holes); // -1 +1 - av_store(av, 0, this->contour.to_SV_pureperl()); - for (unsigned int i = 0; i < num_holes; i++) { - av_store(av, i+1, this->holes[i].to_SV_pureperl()); - } - return newRV_noinc((SV*)av); -} - -void -ExPolygon::from_SV(SV* expoly_sv) -{ - AV* expoly_av = (AV*)SvRV(expoly_sv); - const unsigned int num_polygons = av_len(expoly_av)+1; - this->holes.resize(num_polygons-1); - - SV** polygon_sv = av_fetch(expoly_av, 0, 0); - this->contour.from_SV(*polygon_sv); - for (unsigned int i = 0; i < num_polygons-1; i++) { - polygon_sv = av_fetch(expoly_av, i+1, 0); - this->holes[i].from_SV(*polygon_sv); - } -} - -void -ExPolygon::from_SV_check(SV* expoly_sv) -{ - if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) { - // a XS ExPolygon was supplied - *this = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv )); - } else { - // a Perl arrayref was supplied - this->from_SV(expoly_sv); - } -} - } #endif diff --git a/xs/src/ExPolygonCollection.cpp b/xs/src/ExPolygonCollection.cpp new file mode 100644 index 000000000..d0f84990c --- /dev/null +++ b/xs/src/ExPolygonCollection.cpp @@ -0,0 +1,29 @@ +#include "ExPolygonCollection.hpp" + +namespace Slic3r { + +void +ExPolygonCollection::scale(double factor) +{ + for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (*it).scale(factor); + } +} + +void +ExPolygonCollection::translate(double x, double y) +{ + for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (*it).translate(x, y); + } +} + +void +ExPolygonCollection::rotate(double angle, Point* center) +{ + for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { + (*it).rotate(angle, center); + } +} + +} diff --git a/xs/src/ExPolygonCollection.hpp b/xs/src/ExPolygonCollection.hpp index 92527afc6..2cfd4bbc8 100644 --- a/xs/src/ExPolygonCollection.hpp +++ b/xs/src/ExPolygonCollection.hpp @@ -1,13 +1,7 @@ #ifndef slic3r_ExPolygonCollection_hpp_ #define slic3r_ExPolygonCollection_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include "ExPolygon.hpp" namespace Slic3r { @@ -22,30 +16,6 @@ class ExPolygonCollection void rotate(double angle, Point* center); }; -void -ExPolygonCollection::scale(double factor) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).scale(factor); - } -} - -void -ExPolygonCollection::translate(double x, double y) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).translate(x, y); - } -} - -void -ExPolygonCollection::rotate(double angle, Point* center) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).rotate(angle, center); - } -} - } #endif diff --git a/xs/src/ExtrusionEntity.cpp b/xs/src/ExtrusionEntity.cpp new file mode 100644 index 000000000..463bc75e9 --- /dev/null +++ b/xs/src/ExtrusionEntity.cpp @@ -0,0 +1,32 @@ +#include "ExtrusionEntity.hpp" + +namespace Slic3r { + +void +ExtrusionPath::reverse() +{ + this->polyline.reverse(); +} + +ExtrusionPath* +ExtrusionLoop::split_at_index(int index) +{ + Polyline* poly = this->polygon.split_at_index(index); + + ExtrusionPath* path = new ExtrusionPath(); + path->polyline = *poly; + path->role = this->role; + path->height = this->height; + path->flow_spacing = this->flow_spacing; + + delete poly; + return path; +} + +ExtrusionPath* +ExtrusionLoop::split_at_first_point() +{ + return this->split_at_index(0); +} + +} diff --git a/xs/src/ExtrusionEntity.hpp b/xs/src/ExtrusionEntity.hpp index 34fbda7db..dd6a48c6b 100644 --- a/xs/src/ExtrusionEntity.hpp +++ b/xs/src/ExtrusionEntity.hpp @@ -1,13 +1,7 @@ #ifndef slic3r_ExtrusionEntity_hpp_ #define slic3r_ExtrusionEntity_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include "Polygon.hpp" #include "Polyline.hpp" @@ -51,33 +45,6 @@ class ExtrusionLoop : public ExtrusionEntity ExtrusionPath* split_at_first_point(); }; -void -ExtrusionPath::reverse() -{ - this->polyline.reverse(); -} - -ExtrusionPath* -ExtrusionLoop::split_at_index(int index) -{ - Polyline* poly = this->polygon.split_at_index(index); - - ExtrusionPath* path = new ExtrusionPath(); - path->polyline = *poly; - path->role = this->role; - path->height = this->height; - path->flow_spacing = this->flow_spacing; - - delete poly; - return path; -} - -ExtrusionPath* -ExtrusionLoop::split_at_first_point() -{ - return this->split_at_index(0); -} - } #endif diff --git a/xs/src/Line.cpp b/xs/src/Line.cpp new file mode 100644 index 000000000..2c4d63250 --- /dev/null +++ b/xs/src/Line.cpp @@ -0,0 +1,83 @@ +#include "Line.hpp" +#include + +namespace Slic3r { + +void +Line::scale(double factor) +{ + this->a.scale(factor); + this->b.scale(factor); +} + +void +Line::translate(double x, double y) +{ + this->a.translate(x, y); + this->b.translate(x, y); +} + +void +Line::rotate(double angle, Point* center) +{ + this->a.rotate(angle, center); + this->b.rotate(angle, center); +} + +void +Line::reverse() +{ + std::swap(this->a, this->b); +} + +void +Line::from_SV(SV* line_sv) +{ + AV* line_av = (AV*)SvRV(line_sv); + this->a.from_SV_check(*av_fetch(line_av, 0, 0)); + this->b.from_SV_check(*av_fetch(line_av, 1, 0)); +} + +void +Line::from_SV_check(SV* line_sv) +{ + if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) { + *this = *(Line*)SvIV((SV*)SvRV( line_sv )); + } else { + this->from_SV(line_sv); + } +} + +SV* +Line::to_SV() { + AV* av = newAV(); + av_extend(av, 1); + + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Point", new Point(this->a) ); + av_store(av, 0, sv); + + sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Point", new Point(this->b) ); + av_store(av, 1, sv); + + return newRV_noinc((SV*)av); +} + +SV* +Line::to_SV_ref() { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Line", new Line(*this) ); + return sv; +} + +SV* +Line::to_SV_pureperl() { + AV* av = newAV(); + av_extend(av, 1); + av_store(av, 0, this->a.to_SV_pureperl()); + av_store(av, 1, this->b.to_SV_pureperl()); + return newRV_noinc((SV*)av); +} + +} diff --git a/xs/src/Line.hpp b/xs/src/Line.hpp index f383e0a51..6b5cba260 100644 --- a/xs/src/Line.hpp +++ b/xs/src/Line.hpp @@ -1,15 +1,8 @@ #ifndef slic3r_Line_hpp_ #define slic3r_Line_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include "Point.hpp" -#include namespace Slic3r { @@ -33,83 +26,6 @@ class Line typedef std::vector Lines; -void -Line::scale(double factor) -{ - this->a.scale(factor); - this->b.scale(factor); -} - -void -Line::translate(double x, double y) -{ - this->a.translate(x, y); - this->b.translate(x, y); -} - -void -Line::rotate(double angle, Point* center) -{ - this->a.rotate(angle, center); - this->b.rotate(angle, center); -} - -void -Line::reverse() -{ - std::swap(this->a, this->b); -} - -void -Line::from_SV(SV* line_sv) -{ - AV* line_av = (AV*)SvRV(line_sv); - this->a.from_SV_check(*av_fetch(line_av, 0, 0)); - this->b.from_SV_check(*av_fetch(line_av, 1, 0)); -} - -void -Line::from_SV_check(SV* line_sv) -{ - if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) { - *this = *(Line*)SvIV((SV*)SvRV( line_sv )); - } else { - this->from_SV(line_sv); - } -} - -SV* -Line::to_SV() { - AV* av = newAV(); - av_extend(av, 1); - - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Point", new Point(this->a) ); - av_store(av, 0, sv); - - sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Point", new Point(this->b) ); - av_store(av, 1, sv); - - return newRV_noinc((SV*)av); -} - -SV* -Line::to_SV_ref() { - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Line", new Line(*this) ); - return sv; -} - -SV* -Line::to_SV_pureperl() { - AV* av = newAV(); - av_extend(av, 1); - av_store(av, 0, this->a.to_SV_pureperl()); - av_store(av, 1, this->b.to_SV_pureperl()); - return newRV_noinc((SV*)av); -} - } #endif diff --git a/xs/src/MultiPoint.cpp b/xs/src/MultiPoint.cpp new file mode 100644 index 000000000..fae286994 --- /dev/null +++ b/xs/src/MultiPoint.cpp @@ -0,0 +1,82 @@ +#include "MultiPoint.hpp" + +namespace Slic3r { + +void +MultiPoint::scale(double factor) +{ + for (Points::iterator it = points.begin(); it != points.end(); ++it) { + (*it).scale(factor); + } +} + +void +MultiPoint::translate(double x, double y) +{ + for (Points::iterator it = points.begin(); it != points.end(); ++it) { + (*it).translate(x, y); + } +} + +void +MultiPoint::rotate(double angle, Point* center) +{ + for (Points::iterator it = points.begin(); it != points.end(); ++it) { + (*it).rotate(angle, center); + } +} + +void +MultiPoint::reverse() +{ + std::reverse(this->points.begin(), this->points.end()); +} + +void +MultiPoint::from_SV(SV* poly_sv) +{ + AV* poly_av = (AV*)SvRV(poly_sv); + const unsigned int num_points = av_len(poly_av)+1; + this->points.resize(num_points); + + for (unsigned int i = 0; i < num_points; i++) { + SV** point_sv = av_fetch(poly_av, i, 0); + this->points[i].from_SV_check(*point_sv); + } +} + +void +MultiPoint::from_SV_check(SV* poly_sv) +{ + if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) { + *this = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv )); + } else { + this->from_SV(poly_sv); + } +} + +SV* +MultiPoint::to_SV() { + const unsigned int num_points = this->points.size(); + AV* av = newAV(); + av_extend(av, num_points-1); + for (unsigned int i = 0; i < num_points; i++) { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Point", new Point(this->points[i]) ); + av_store(av, i, sv); + } + return newRV_noinc((SV*)av); +} + +SV* +MultiPoint::to_SV_pureperl() { + const unsigned int num_points = this->points.size(); + AV* av = newAV(); + av_extend(av, num_points-1); + for (unsigned int i = 0; i < num_points; i++) { + av_store(av, i, this->points[i].to_SV_pureperl()); + } + return newRV_noinc((SV*)av); +} + +} diff --git a/xs/src/MultiPoint.hpp b/xs/src/MultiPoint.hpp index 1952a65a5..650733a80 100644 --- a/xs/src/MultiPoint.hpp +++ b/xs/src/MultiPoint.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_MultiPoint_hpp_ #define slic3r_MultiPoint_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - #include "Point.hpp" #include #include @@ -28,83 +21,6 @@ class MultiPoint void reverse(); }; -void -MultiPoint::scale(double factor) -{ - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).scale(factor); - } -} - -void -MultiPoint::translate(double x, double y) -{ - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).translate(x, y); - } -} - -void -MultiPoint::rotate(double angle, Point* center) -{ - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).rotate(angle, center); - } -} - -void -MultiPoint::reverse() -{ - std::reverse(this->points.begin(), this->points.end()); -} - -void -MultiPoint::from_SV(SV* poly_sv) -{ - AV* poly_av = (AV*)SvRV(poly_sv); - const unsigned int num_points = av_len(poly_av)+1; - this->points.resize(num_points); - - for (unsigned int i = 0; i < num_points; i++) { - SV** point_sv = av_fetch(poly_av, i, 0); - this->points[i].from_SV_check(*point_sv); - } -} - -void -MultiPoint::from_SV_check(SV* poly_sv) -{ - if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) { - *this = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv )); - } else { - this->from_SV(poly_sv); - } -} - -SV* -MultiPoint::to_SV() { - const unsigned int num_points = this->points.size(); - AV* av = newAV(); - av_extend(av, num_points-1); - for (unsigned int i = 0; i < num_points; i++) { - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Point", new Point(this->points[i]) ); - av_store(av, i, sv); - } - return newRV_noinc((SV*)av); -} - -SV* -MultiPoint::to_SV_pureperl() { - const unsigned int num_points = this->points.size(); - AV* av = newAV(); - av_extend(av, num_points-1); - for (unsigned int i = 0; i < num_points; i++) { - av_store(av, i, this->points[i].to_SV_pureperl()); - } - return newRV_noinc((SV*)av); -} - } #endif diff --git a/xs/src/Point.cpp b/xs/src/Point.cpp new file mode 100644 index 000000000..874eeeb1d --- /dev/null +++ b/xs/src/Point.cpp @@ -0,0 +1,61 @@ +#include "Point.hpp" + +namespace Slic3r { + +void +Point::scale(double factor) +{ + this->x *= factor; + this->y *= factor; +} + +void +Point::translate(double x, double y) +{ + this->x += x; + this->y += y; +} + +void +Point::rotate(double angle, Point* center) +{ + double cur_x = (double)this->x; + double cur_y = (double)this->y; + this->x = (long)( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); + this->y = (long)( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); +} + +bool +Point::coincides_with(Point* point) +{ + return this->x == point->x && this->y == point->y; +} + +SV* +Point::to_SV_pureperl() { + AV* av = newAV(); + av_fill(av, 1); + av_store(av, 0, newSViv(this->x)); + av_store(av, 1, newSViv(this->y)); + return newRV_noinc((SV*)av); +} + +void +Point::from_SV(SV* point_sv) +{ + AV* point_av = (AV*)SvRV(point_sv); + this->x = (long)SvIV(*av_fetch(point_av, 0, 0)); + this->y = (long)SvIV(*av_fetch(point_av, 1, 0)); +} + +void +Point::from_SV_check(SV* point_sv) +{ + if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { + *this = *(Point*)SvIV((SV*)SvRV( point_sv )); + } else { + this->from_SV(point_sv); + } +} + +} diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index b324ac6d1..71b1476e6 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -1,13 +1,7 @@ #ifndef slic3r_Point_hpp_ #define slic3r_Point_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include #include @@ -30,62 +24,6 @@ class Point typedef std::vector Points; -void -Point::scale(double factor) -{ - this->x *= factor; - this->y *= factor; -} - -void -Point::translate(double x, double y) -{ - this->x += x; - this->y += y; -} - -void -Point::rotate(double angle, Point* center) -{ - double cur_x = (double)this->x; - double cur_y = (double)this->y; - this->x = (long)( (double)center->x + cos(angle) * (cur_x - (double)center->x) - sin(angle) * (cur_y - (double)center->y) ); - this->y = (long)( (double)center->y + cos(angle) * (cur_y - (double)center->y) + sin(angle) * (cur_x - (double)center->x) ); -} - -bool -Point::coincides_with(Point* point) -{ - return this->x == point->x && this->y == point->y; -} - -SV* -Point::to_SV_pureperl() { - AV* av = newAV(); - av_fill(av, 1); - av_store(av, 0, newSViv(this->x)); - av_store(av, 1, newSViv(this->y)); - return newRV_noinc((SV*)av); -} - -void -Point::from_SV(SV* point_sv) -{ - AV* point_av = (AV*)SvRV(point_sv); - this->x = (long)SvIV(*av_fetch(point_av, 0, 0)); - this->y = (long)SvIV(*av_fetch(point_av, 1, 0)); -} - -void -Point::from_SV_check(SV* point_sv) -{ - if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { - *this = *(Point*)SvIV((SV*)SvRV( point_sv )); - } else { - this->from_SV(point_sv); - } -} - } #endif diff --git a/xs/src/Polygon.cpp b/xs/src/Polygon.cpp new file mode 100644 index 000000000..9937668dc --- /dev/null +++ b/xs/src/Polygon.cpp @@ -0,0 +1,55 @@ +#include +#include "ClipperUtils.hpp" +#include "Polygon.hpp" +#include "Polyline.hpp" + +namespace Slic3r { + +SV* +Polygon::to_SV_ref() { + SV* sv = newSV(0); + sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(*this) ); + return sv; +} + +Lines +Polygon::lines() +{ + Lines lines; + for (int i = 0; i < this->points.size()-1; i++) { + lines.push_back(Line(this->points[i], this->points[i+1])); + } + lines.push_back(Line(this->points.back(), this->points.front())); + return lines; +} + +Polyline* +Polygon::split_at_index(int index) +{ + Polyline* poly = new Polyline; + for (int i = index; i < this->points.size(); i++) { + poly->points.push_back( this->points[i] ); + } + for (int i = 0; i <= index; i++) { + poly->points.push_back( this->points[i] ); + } + return poly; +} + +Polyline* +Polygon::split_at_first_point() +{ + return this->split_at_index(0); +} + +bool +Polygon::is_counter_clockwise() +{ + ClipperLib::Polygon* p = new ClipperLib::Polygon(); + Slic3rPolygon_to_ClipperPolygon(*this, *p); + bool orientation = ClipperLib::Orientation(*p); + delete p; + return orientation; +} + +} diff --git a/xs/src/Polygon.hpp b/xs/src/Polygon.hpp index d55684585..43c4c7e9f 100644 --- a/xs/src/Polygon.hpp +++ b/xs/src/Polygon.hpp @@ -1,14 +1,10 @@ #ifndef slic3r_Polygon_hpp_ #define slic3r_Polygon_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - +#include #include +#include "Line.hpp" +#include "MultiPoint.hpp" #include "Polyline.hpp" namespace Slic3r { @@ -19,47 +15,11 @@ class Polygon : public MultiPoint { Lines lines(); Polyline* split_at_index(int index); Polyline* split_at_first_point(); + bool is_counter_clockwise(); }; typedef std::vector Polygons; -SV* -Polygon::to_SV_ref() { - SV* sv = newSV(0); - sv_setref_pv( sv, "Slic3r::Polygon", new Polygon(*this) ); - return sv; -} - -Lines -Polygon::lines() -{ - Lines lines; - for (int i = 0; i < this->points.size()-1; i++) { - lines.push_back(Line(this->points[i], this->points[i+1])); - } - lines.push_back(Line(this->points.back(), this->points.front())); - return lines; -} - -Polyline* -Polygon::split_at_index(int index) -{ - Polyline* poly = new Polyline; - for (int i = index; i < this->points.size(); i++) { - poly->points.push_back( this->points[i] ); - } - for (int i = 0; i <= index; i++) { - poly->points.push_back( this->points[i] ); - } - return poly; -} - -Polyline* -Polygon::split_at_first_point() -{ - return this->split_at_index(0); -} - } #endif diff --git a/xs/src/Polyline.cpp b/xs/src/Polyline.cpp new file mode 100644 index 000000000..70fa6c77e --- /dev/null +++ b/xs/src/Polyline.cpp @@ -0,0 +1,15 @@ +#include "Polyline.hpp" + +namespace Slic3r { + +Lines +Polyline::lines() +{ + Lines lines; + for (int i = 0; i < this->points.size()-1; i++) { + lines.push_back(Line(this->points[i], this->points[i+1])); + } + return lines; +} + +} diff --git a/xs/src/Polyline.hpp b/xs/src/Polyline.hpp index a1e5a0193..67daf794c 100644 --- a/xs/src/Polyline.hpp +++ b/xs/src/Polyline.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_Polyline_hpp_ #define slic3r_Polyline_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - #include "Line.hpp" #include "MultiPoint.hpp" @@ -20,16 +13,6 @@ class Polyline : public MultiPoint { typedef std::vector Polylines; -Lines -Polyline::lines() -{ - Lines lines; - for (int i = 0; i < this->points.size()-1; i++) { - lines.push_back(Line(this->points[i], this->points[i+1])); - } - return lines; -} - } #endif diff --git a/xs/src/Surface.hpp b/xs/src/Surface.hpp index 5725e7214..32981df04 100644 --- a/xs/src/Surface.hpp +++ b/xs/src/Surface.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_Surface_hpp_ #define slic3r_Surface_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - #include "ExPolygon.hpp" namespace Slic3r { diff --git a/xs/src/SurfaceCollection.hpp b/xs/src/SurfaceCollection.hpp index e9f458dfd..091918c34 100644 --- a/xs/src/SurfaceCollection.hpp +++ b/xs/src/SurfaceCollection.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_SurfaceCollection_hpp_ #define slic3r_SurfaceCollection_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - #include "Surface.hpp" namespace Slic3r { diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index ec0869117..40421ce5a 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -1,15 +1,9 @@ #ifndef slic3r_TriangleMesh_hpp_ #define slic3r_TriangleMesh_hpp_ +#include #include -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - namespace Slic3r { class TriangleMesh diff --git a/xs/src/ZTable.hpp b/xs/src/ZTable.hpp index fcdf553fe..89ce3f387 100644 --- a/xs/src/ZTable.hpp +++ b/xs/src/ZTable.hpp @@ -1,13 +1,6 @@ #ifndef slic3r_ZTable_hpp_ #define slic3r_ZTable_hpp_ -extern "C" { -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -} - namespace Slic3r { class ZTable diff --git a/xs/src/myinit.h b/xs/src/myinit.h index 641099a42..c8fbf98f8 100644 --- a/xs/src/myinit.h +++ b/xs/src/myinit.h @@ -1,6 +1,15 @@ #ifndef _myinit_h_ #define _myinit_h_ +extern "C" { +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "ppport.h" +#undef do_open +#undef do_close +} + namespace Slic3r {} using namespace Slic3r; diff --git a/xs/t/06_polygon.t b/xs/t/06_polygon.t index 053bf5e65..913440944 100644 --- a/xs/t/06_polygon.t +++ b/xs/t/06_polygon.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 6; +use Test::More tests => 8; my $square = [ # ccw [100, 100], @@ -30,4 +30,11 @@ is_deeply [ map $_->pp, @$lines ], [ is_deeply $polygon->split_at_first_point->pp, [ @$square[0,1,2,3,0] ], 'split_at_first_point'; is_deeply $polygon->split_at_index(2)->pp, [ @$square[2,3,0,1,2] ], 'split_at_index'; +ok $polygon->is_counter_clockwise, 'is_counter_clockwise'; +{ + my $clone = $polygon->clone; + $clone->reverse; + ok !$clone->is_counter_clockwise, 'is_counter_clockwise'; +} + __END__ diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index 4217d1e80..1d454eb9b 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -21,6 +21,7 @@ %code{% const char* CLASS = "Slic3r::Polyline"; RETVAL = THIS->split_at_index(index); %}; Polyline* split_at_first_point() %code{% const char* CLASS = "Slic3r::Polyline"; RETVAL = THIS->split_at_first_point(); %}; + bool is_counter_clockwise(); %{ Polygon* diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 5c97d7dcb..adaf0c17e 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -1,3 +1,4 @@ +%typemap{bool}{simple}; %typemap{std::string}; %typemap{std::vector*}; %typemap{SV*};