Add the full source of BambuStudio

using version 1.0.10
This commit is contained in:
lane.wei 2022-07-15 23:37:19 +08:00 committed by Lane.Wei
parent 30bcadab3e
commit 1555904bef
3771 changed files with 1251328 additions and 0 deletions

212
xs/CMakeLists.txt Normal file
View file

@ -0,0 +1,212 @@
project(XS)
# Find the Perl interpreter, add local-lib to PATH and PERL5LIB environment variables,
# so the locally installed modules (mainly the Alien::wxPerl) will be reached.
if (WIN32)
set(ENV_PATH_SEPARATOR ";")
else()
set(ENV_PATH_SEPARATOR ":")
endif()
# Install the XS.pm and XS.{so,dll,bundle} into the local-lib directory.
set(PERL_LOCAL_LIB_DIR ${PROJECT_SOURCE_DIR}/../local-lib)
set(ENV{PATH} "${PERL_LOCAL_LIB_DIR}/bin${ENV_PATH_SEPARATOR}$ENV{PATH}")
set(PERL_INCLUDE "${PERL_LOCAL_LIB_DIR}/lib/perl5${ENV_PATH_SEPARATOR}$ENV{PERL5LIB}")
message("PATH: $ENV{PATH}")
message("PERL_INCLUDE: ${PERL_INCLUDE}")
find_package(Perl REQUIRED)
if (WIN32)
# On Windows passing the PERL5LIB variable causes various problems (such as with MAX_PATH and others),
# basically I've found no good way to do it on Windows.
set(PERL5LIB_ENV_CMD "")
else()
set(PERL5LIB_ENV_CMD ${CMAKE_COMMAND} -E env PERL5LIB=${PERL_INCLUDE})
endif()
# Perl specific stuff
find_package(PerlLibs REQUIRED)
set(PerlEmbed_DEBUG 1)
find_package(PerlEmbed REQUIRED)
# Generate the Slic3r Perl module (XS) typemap file.
set(MyTypemap ${CMAKE_CURRENT_BINARY_DIR}/typemap)
add_custom_command(
OUTPUT ${MyTypemap}
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/xsp/my.map
COMMAND ${PERL5LIB_ENV_CMD} ${PERL_EXECUTABLE} -MExtUtils::Typemaps -MExtUtils::Typemaps::Basic -e "$typemap = ExtUtils::Typemaps->new(file => \"${CMAKE_CURRENT_LIST_DIR}/xsp/my.map\"); $typemap->merge(typemap => ExtUtils::Typemaps::Basic->new); $typemap->write(file => \"${MyTypemap}\")"
VERBATIM
)
# Generate the Slic3r Perl module (XS) main.xs file.
set(XS_MAIN_XS ${CMAKE_CURRENT_BINARY_DIR}/main.xs)
set(XSP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xsp)
#FIXME list the dependecies explicitely, add dependency on the typemap.
set(XS_XSP_FILES
${XSP_DIR}/BoundingBox.xsp
${XSP_DIR}/BridgeDetector.xsp
${XSP_DIR}/Clipper.xsp
${XSP_DIR}/Config.xsp
${XSP_DIR}/ExPolygon.xsp
${XSP_DIR}/ExPolygonCollection.xsp
${XSP_DIR}/ExtrusionEntityCollection.xsp
${XSP_DIR}/ExtrusionLoop.xsp
${XSP_DIR}/ExtrusionMultiPath.xsp
${XSP_DIR}/ExtrusionPath.xsp
${XSP_DIR}/ExtrusionSimulator.xsp
${XSP_DIR}/Filler.xsp
${XSP_DIR}/Flow.xsp
${XSP_DIR}/GCode.xsp
# ${XSP_DIR}/GCodeSender.xsp
${XSP_DIR}/Geometry.xsp
${XSP_DIR}/Layer.xsp
${XSP_DIR}/Line.xsp
${XSP_DIR}/Model.xsp
${XSP_DIR}/PerimeterGenerator.xsp
${XSP_DIR}/PlaceholderParser.xsp
${XSP_DIR}/Point.xsp
${XSP_DIR}/Polygon.xsp
${XSP_DIR}/Polyline.xsp
${XSP_DIR}/PolylineCollection.xsp
${XSP_DIR}/Print.xsp
${XSP_DIR}/Surface.xsp
${XSP_DIR}/SurfaceCollection.xsp
${XSP_DIR}/TriangleMesh.xsp
${XSP_DIR}/XS.xsp
)
foreach (file ${XS_XSP_FILES})
if (MSVC)
# Visual Studio C compiler has issues with FILE pragmas containing quotes.
set(INCLUDE_COMMANDS "${INCLUDE_COMMANDS}INCLUDE_COMMAND: $^X -MExtUtils::XSpp::Cmd -e xspp -- -t ${CMAKE_CURRENT_LIST_DIR}/xsp/typemap.xspt ${file}\n")
else ()
set(INCLUDE_COMMANDS "${INCLUDE_COMMANDS}INCLUDE_COMMAND: $^X -MExtUtils::XSpp::Cmd -e xspp -- -t \"${CMAKE_CURRENT_LIST_DIR}/xsp/typemap.xspt\" \"${file}\"\n")
endif ()
endforeach ()
configure_file(main.xs.in ${XS_MAIN_XS} @ONLY) # Insert INCLUDE_COMMANDS into main.xs
# Generate the Slic3r Perl module (XS) XS.cpp file.
#FIXME add the dependency on main.xs and typemap.
set(XS_MAIN_CPP ${CMAKE_CURRENT_BINARY_DIR}/XS.cpp)
add_custom_command(
OUTPUT ${XS_MAIN_CPP}
DEPENDS ${MyTypemap} ${XS_XSP_FILES} ${CMAKE_CURRENT_LIST_DIR}/xsp/typemap.xspt
COMMAND ${PERL5LIB_ENV_CMD} xsubpp -typemap typemap -output ${XS_MAIN_CPP} -hiertype ${XS_MAIN_XS}
VERBATIM
)
# Define the Perl XS shared library.
if(APPLE)
set(XS_SHARED_LIBRARY_TYPE MODULE)
else()
set(XS_SHARED_LIBRARY_TYPE SHARED)
endif()
add_library(XS ${XS_SHARED_LIBRARY_TYPE}
${XS_MAIN_CPP}
src/perlglue.cpp
src/ppport.h
src/xsinit.h
xsp/my.map
# mytype.map is empty. Is it required by Build.PL or the Perl xspp module?
xsp/mytype.map
# Used by Perl xsubpp to generate XS.cpp
xsp/typemap.xspt
)
if(APPLE)
set_target_properties(XS PROPERTIES BUNDLE TRUE)
# Ignore undefined symbols of the perl interpreter, they will be found in the caller image.
target_link_libraries(XS "-undefined dynamic_lookup")
endif()
target_link_libraries(XS libslic3r)
target_include_directories(XS PRIVATE src ${LIBDIR}/libslic3r)
target_compile_definitions(XS PRIVATE -DSLIC3RXS)
set_target_properties(XS PROPERTIES PREFIX "") # Prevent cmake from generating libXS.so instead of XS.so
if (APPLE)
# -liconv: boost links to libiconv by default
target_link_libraries(XS "-liconv -framework IOKit" "-framework CoreFoundation" -lc++)
elseif (MSVC)
target_link_libraries(XS )
else ()
target_link_libraries(XS -lstdc++)
endif ()
# Windows specific stuff
if (WIN32)
target_compile_definitions(XS PRIVATE -DNOGDI -DNOMINMAX -DHAS_BOOL)
endif ()
# SLIC3R_MSVC_PDB
if (MSVC AND SLIC3R_MSVC_PDB AND "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
set_target_properties(XS PROPERTIES
COMPILE_FLAGS "/Zi"
LINK_FLAGS "/DEBUG /OPT:REF /OPT:ICF"
)
endif()
if (CMAKE_BUILD_TYPE MATCHES DEBUG)
target_compile_definitions(XS PRIVATE -DSLIC3R_DEBUG -DDEBUG -D_DEBUG)
else ()
target_compile_definitions(XS PRIVATE -DNDEBUG)
endif ()
target_include_directories(XS PRIVATE ${PERL_INCLUDE_PATH})
target_compile_options(XS PRIVATE ${PerlEmbed_CCFLAGS})
if (WIN32)
target_link_libraries(XS ${PERL_LIBRARY})
endif()
set(PERL_LOCAL_LIB_ARCH_DIR "${PERL_LOCAL_LIB_DIR}/lib/perl5/${PerlEmbed_ARCHNAME}")
add_custom_command(
TARGET XS
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${PERL_LOCAL_LIB_ARCH_DIR}/auto/Slic3r/XS/"
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:XS>" "${PERL_LOCAL_LIB_ARCH_DIR}/auto/Slic3r/XS/"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PERL_LOCAL_LIB_ARCH_DIR}/Slic3r/"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/lib/Slic3r/XS.pm" "${PERL_LOCAL_LIB_ARCH_DIR}/Slic3r/"
COMMENT "Installing XS.pm and XS.{so,dll,bundle} into the local-lib directory ..."
)
if(APPLE)
add_custom_command(
TARGET XS
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E rename "${PERL_LOCAL_LIB_ARCH_DIR}/auto/Slic3r/XS/XS" "${PERL_LOCAL_LIB_ARCH_DIR}/auto/Slic3r/XS/XS.bundle"
)
endif()
if (MSVC)
# Here we associate some additional properties with the MSVC project to enable compilation and debugging out of the box.
get_filename_component(PROPS_PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY)
string(REPLACE "/" "\\" PROPS_PERL_BIN_PATH "${PROPS_PERL_BIN_PATH}")
string(REPLACE "/" "\\" PROPS_PERL_EXECUTABLE "${PERL_EXECUTABLE}")
string(REPLACE "/" "\\" PROPS_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}")
configure_file("../cmake/msvc/xs.wperl.props.in" "${CMAKE_BINARY_DIR}/xs.wperl.props" NEWLINE_STYLE CRLF)
set_target_properties(XS PROPERTIES VS_USER_PROPS "${CMAKE_BINARY_DIR}/xs.wperl.props")
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(_bits 64)
elseif ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
set(_bits 32)
endif ()
add_custom_command(TARGET XS POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${TOP_LEVEL_PROJECT_DIR}/deps/GMP/gmp/lib/win${_bits}/libgmp-10.dll "${PERL_LOCAL_LIB_ARCH_DIR}/auto/Slic3r/XS/"
COMMENT "Installing gmp runtime into the local-lib directory ..."
VERBATIM)
endif()
# Installation
install(TARGETS XS DESTINATION ${PERL_VENDORARCH}/auto/Slic3r/XS)
install(FILES lib/Slic3r/XS.pm DESTINATION ${PERL_VENDORLIB}/Slic3r)
# Unit / integration tests
enable_testing()
get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY)
if (MSVC)
set(PERL_PROVE "${PERL_BIN_PATH}/prove.bat")
else ()
set(PERL_PROVE "${PERL_BIN_PATH}/prove")
endif ()
add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PERL_LOCAL_LIB_DIR}/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/..)

303
xs/lib/Slic3r/XS.pm Normal file
View file

@ -0,0 +1,303 @@
package Slic3r::XS;
use warnings;
use strict;
our $VERSION = '0.01';
# We have to load these modules in order to have Wx.pm find the correct paths
# for wxWidgets dlls on MSW.
# We avoid loading these on OS X because Wx::Load() initializes a Wx App
# automatically and it steals focus even when we're not running Slic3r in GUI mode.
# TODO: only load these when compiling with GUI support
BEGIN {
if ($^O eq 'MSWin32') {
eval "use Wx";
eval "use Wx::GLCanvas";
eval "use Wx::GLContext";
eval "use Wx::Html";
eval "use Wx::Print"; # because of some Wx bug, thread creation fails if we don't have this (looks like Wx::Printout is hard-coded in some thread cleanup code)
}
}
use Carp qw();
use XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
package Slic3r::Line;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Point;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Pointf;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Pointf3;
use overload
'@{}' => sub { [ $_[0]->x, $_[0]->y, $_[0]->z ] }, #,
'fallback' => 1;
sub pp {
my ($self) = @_;
return [ @$self ];
}
package Slic3r::ExPolygon;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Polyline;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Polyline::Collection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::Polygon;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::ExPolygon::Collection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::ExtrusionPath::Collection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
sub new {
my ($class, @paths) = @_;
my $self = $class->_new;
$self->append(@paths);
return $self;
}
package Slic3r::ExtrusionLoop;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
sub new_from_paths {
my ($class, @paths) = @_;
my $loop = $class->new;
$loop->append($_) for @paths;
return $loop;
}
package Slic3r::ExtrusionMultiPath;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::ExtrusionPath;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
sub new {
my ($class, %args) = @_;
return $class->_new(
$args{polyline}, # required
$args{role}, # required
$args{mm3_per_mm} // die("Missing required mm3_per_mm in ExtrusionPath constructor"),
$args{width} // -1,
$args{height} // -1,
);
}
sub clone {
my ($self, %args) = @_;
return __PACKAGE__->_new(
$args{polyline} // $self->polyline,
$args{role} // $self->role,
$args{mm3_per_mm} // $self->mm3_per_mm,
$args{width} // $self->width,
$args{height} // $self->height,
);
}
package Slic3r::ExtrusionSimulator;
sub new {
my ($class, %args) = @_;
return $class->_new();
}
package Slic3r::Filler;
sub fill_surface {
my ($self, $surface, %args) = @_;
$self->set_density($args{density}) if defined($args{density});
$self->set_dont_adjust($args{dont_adjust}) if defined($args{dont_adjust});
$self->set_complete($args{complete}) if defined($args{complete});
return $self->_fill_surface($surface);
}
package Slic3r::Flow;
sub new {
my ($class, %args) = @_;
my $self = $class->_new(
@args{qw(width height nozzle_diameter)},
);
return $self;
}
sub new_from_width {
my ($class, %args) = @_;
return $class->_new_from_width(
@args{qw(role width nozzle_diameter layer_height)},
);
}
package Slic3r::Surface;
sub new {
my ($class, %args) = @_;
# defensive programming: make sure no negative bridge_angle is supplied
die "Error: invalid negative bridge_angle\n"
if defined $args{bridge_angle} && $args{bridge_angle} < 0;
return $class->_new(
$args{expolygon} // (die "Missing required expolygon\n"),
$args{surface_type} // (die "Missing required surface_type\n"),
$args{thickness} // -1,
$args{thickness_layers} // 1,
$args{bridge_angle} // -1,
$args{extra_perimeters} // 0,
);
}
sub clone {
my ($self, %args) = @_;
return (ref $self)->_new(
delete $args{expolygon} // $self->expolygon,
delete $args{surface_type} // $self->surface_type,
delete $args{thickness} // $self->thickness,
delete $args{thickness_layers} // $self->thickness_layers,
delete $args{bridge_angle} // $self->bridge_angle,
delete $args{extra_perimeters} // $self->extra_perimeters,
);
}
package Slic3r::Surface::Collection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
sub new {
my ($class, @surfaces) = @_;
my $self = $class->_new;
$self->append($_) for @surfaces;
return $self;
}
package Slic3r::Print::SupportMaterial2;
sub new {
my ($class, %args) = @_;
return $class->_new(
$args{print_config}, # required
$args{object_config}, # required
$args{first_layer_flow}, # required
$args{flow}, # required
$args{interface_flow}, # required
$args{soluble_interface} // 0
);
}
package Slic3r::GUI::_3DScene::GLVolume::Collection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package Slic3r::GUI::PresetCollection;
use overload
'@{}' => sub { $_[0]->arrayref },
'fallback' => 1;
package main;
for my $class (qw(
Slic3r::BridgeDetector
Slic3r::Config
Slic3r::Config::Full
Slic3r::Config::GCode
Slic3r::Config::Print
Slic3r::Config::PrintObject
Slic3r::Config::PrintRegion
Slic3r::Config::Static
Slic3r::ExPolygon
Slic3r::ExPolygon::Collection
Slic3r::ExtrusionLoop
Slic3r::ExtrusionMultiPath
Slic3r::ExtrusionPath
Slic3r::ExtrusionPath::Collection
Slic3r::ExtrusionSimulator
Slic3r::Filler
Slic3r::Flow
Slic3r::GCode
Slic3r::GCode::PlaceholderParser
Slic3r::Geometry::BoundingBox
Slic3r::Geometry::BoundingBoxf
Slic3r::Geometry::BoundingBoxf3
Slic3r::GUI::_3DScene::GLShader
Slic3r::GUI::_3DScene::GLVolume
Slic3r::GUI::Preset
Slic3r::GUI::PresetCollection
Slic3r::GUI::Tab
Slic3r::Layer
Slic3r::Layer::Region
Slic3r::Layer::Support
Slic3r::Line
Slic3r::Linef3
Slic3r::Model
Slic3r::Model::Instance
Slic3r::Model::Material
Slic3r::Model::Object
Slic3r::Model::Volume
Slic3r::Point
Slic3r::Point3
Slic3r::Pointf
Slic3r::Pointf3
Slic3r::Polygon
Slic3r::Polyline
Slic3r::Polyline::Collection
Slic3r::Print
Slic3r::Print::Object
Slic3r::Print::Region
Slic3r::Print::State
Slic3r::Surface
Slic3r::Surface::Collection
Slic3r::Print::SupportMaterial2
Slic3r::TriangleMesh
))
{
no strict 'refs';
my $ref_class = $class . "::Ref";
eval "package $ref_class; our \@ISA = '$class'; sub DESTROY {};";
}
1;

27
xs/main.xs.in Normal file
View file

@ -0,0 +1,27 @@
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <sstream>
// #include <libslic3r/GCodeSender.hpp>
#ifdef __cplusplus
/* extern "C" { */
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#undef do_open
#undef do_close
#ifdef __cplusplus
/* } */
#endif
#ifdef _WIN32
#undef XS_EXTERNAL
#define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#endif /* MSVC */
MODULE = Slic3r::XS PACKAGE = Slic3r::XS
@INCLUDE_COMMANDS@

549
xs/src/perlglue.cpp Normal file
View file

@ -0,0 +1,549 @@
#ifdef SLIC3RXS
#include <xsinit.h>
namespace Slic3r {
REGISTER_CLASS(ExPolygon, "ExPolygon");
REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection");
REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath");
REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
REGISTER_CLASS(Filler, "Filler");
REGISTER_CLASS(Flow, "Flow");
REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
REGISTER_CLASS(GCode, "GCode");
REGISTER_CLASS(Layer, "Layer");
REGISTER_CLASS(SupportLayer, "Layer::Support");
REGISTER_CLASS(LayerRegion, "Layer::Region");
REGISTER_CLASS(Line, "Line");
REGISTER_CLASS(Linef3, "Linef3");
REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator");
REGISTER_CLASS(PlaceholderParser, "GCode::PlaceholderParser");
REGISTER_CLASS(Polygon, "Polygon");
REGISTER_CLASS(Polyline, "Polyline");
REGISTER_CLASS(PolylineCollection, "Polyline::Collection");
REGISTER_CLASS(Print, "Print");
REGISTER_CLASS(PrintObject, "Print::Object");
REGISTER_CLASS(PrintRegion, "Print::Region");
REGISTER_CLASS(Model, "Model");
REGISTER_CLASS(ModelMaterial, "Model::Material");
REGISTER_CLASS(ModelObject, "Model::Object");
REGISTER_CLASS(ModelVolume, "Model::Volume");
REGISTER_CLASS(ModelInstance, "Model::Instance");
REGISTER_CLASS(BoundingBox, "Geometry::BoundingBox");
REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf");
REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3");
REGISTER_CLASS(BridgeDetector, "BridgeDetector");
REGISTER_CLASS(Point, "Point");
__REGISTER_CLASS(Vec2d, "Pointf");
__REGISTER_CLASS(Vec3d, "Pointf3");
REGISTER_CLASS(DynamicPrintConfig, "Config");
REGISTER_CLASS(StaticPrintConfig, "Config::Static");
REGISTER_CLASS(PrintObjectConfig, "Config::PrintObject");
REGISTER_CLASS(PrintRegionConfig, "Config::PrintRegion");
REGISTER_CLASS(GCodeConfig, "Config::GCode");
REGISTER_CLASS(PrintConfig, "Config::Print");
REGISTER_CLASS(FullPrintConfig, "Config::Full");
REGISTER_CLASS(Surface, "Surface");
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2");
REGISTER_CLASS(TriangleMesh, "TriangleMesh");
SV* ConfigBase__as_hash(ConfigBase* THIS)
{
HV* hv = newHV();
for (auto &key : THIS->keys())
(void)hv_store(hv, key.c_str(), key.length(), ConfigBase__get(THIS, key), 0);
return newRV_noinc((SV*)hv);
}
SV* ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key)
{
ConfigOption *opt = THIS->option(opt_key, false);
return (opt == nullptr) ?
&PL_sv_undef :
ConfigOption_to_SV(*opt, *THIS->def()->get(opt_key));
}
SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def)
{
switch (def.type) {
case coFloat:
case coPercent:
return newSVnv(static_cast<const ConfigOptionFloat*>(&opt)->value);
case coFloats:
case coPercents:
{
auto optv = static_cast<const ConfigOptionFloats*>(&opt);
AV* av = newAV();
av_fill(av, optv->values.size()-1);
for (const double &v : optv->values)
av_store(av, &v - optv->values.data(), newSVnv(v));
return newRV_noinc((SV*)av);
}
case coInt:
return newSViv(static_cast<const ConfigOptionInt*>(&opt)->value);
case coInts:
{
auto optv = static_cast<const ConfigOptionInts*>(&opt);
AV* av = newAV();
av_fill(av, optv->values.size()-1);
for (const int &v : optv->values)
av_store(av, &v - optv->values.data(), newSViv(v));
return newRV_noinc((SV*)av);
}
case coString:
{
auto optv = static_cast<const ConfigOptionString*>(&opt);
// we don't serialize() because that would escape newlines
return newSVpvn_utf8(optv->value.c_str(), optv->value.length(), true);
}
case coStrings:
{
auto optv = static_cast<const ConfigOptionStrings*>(&opt);
AV* av = newAV();
av_fill(av, optv->values.size()-1);
for (const std::string &v : optv->values)
av_store(av, &v - optv->values.data(), newSVpvn_utf8(v.c_str(), v.length(), true));
return newRV_noinc((SV*)av);
}
case coPoint:
return perl_to_SV_clone_ref(static_cast<const ConfigOptionPoint*>(&opt)->value);
case coPoint3:
return perl_to_SV_clone_ref(static_cast<const ConfigOptionPoint3*>(&opt)->value);
case coPoints:
{
auto optv = static_cast<const ConfigOptionPoints*>(&opt);
AV* av = newAV();
av_fill(av, optv->values.size()-1);
for (const Vec2d &v : optv->values)
av_store(av, &v - optv->values.data(), perl_to_SV_clone_ref(v));
return newRV_noinc((SV*)av);
}
case coBool:
return newSViv(static_cast<const ConfigOptionBool*>(&opt)->value ? 1 : 0);
case coBools:
{
auto optv = static_cast<const ConfigOptionBools*>(&opt);
AV* av = newAV();
av_fill(av, optv->values.size()-1);
for (size_t i = 0; i < optv->values.size(); ++ i)
av_store(av, i, newSViv(optv->values[i] ? 1 : 0));
return newRV_noinc((SV*)av);
}
default:
std::string serialized = opt.serialize();
return newSVpvn_utf8(serialized.c_str(), serialized.length(), true);
}
}
SV* ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i)
{
ConfigOption* opt = THIS->option(opt_key, false);
if (opt == nullptr)
return &PL_sv_undef;
const ConfigOptionDef* def = THIS->def()->get(opt_key);
switch (def->type) {
case coFloats:
case coPercents:
return newSVnv(static_cast<ConfigOptionFloats*>(opt)->get_at(i));
case coInts:
return newSViv(static_cast<ConfigOptionInts*>(opt)->get_at(i));
case coStrings:
{
// we don't serialize() because that would escape newlines
const std::string &val = static_cast<ConfigOptionStrings*>(opt)->get_at(i);
return newSVpvn_utf8(val.c_str(), val.length(), true);
}
case coPoints:
return perl_to_SV_clone_ref(static_cast<ConfigOptionPoints*>(opt)->get_at(i));
case coBools:
return newSViv(static_cast<ConfigOptionBools*>(opt)->get_at(i) ? 1 : 0);
default:
return &PL_sv_undef;
}
}
bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
{
ConfigOption* opt = THIS->option(opt_key, true);
if (opt == nullptr)
CONFESS("Trying to set non-existing option");
const ConfigOptionDef* def = THIS->def()->get(opt_key);
if (opt->type() != def->type)
CONFESS("Option type is different from the definition");
switch (def->type) {
case coFloat:
if (!looks_like_number(value))
return false;
static_cast<ConfigOptionFloat*>(opt)->value = SvNV(value);
break;
case coFloats:
{
std::vector<double> &values = static_cast<ConfigOptionFloats*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; ++ i) {
SV** elem = av_fetch(av, i, 0);
if (elem == NULL || !looks_like_number(*elem)) return false;
values.emplace_back(SvNV(*elem));
}
break;
}
case coPercents:
{
std::vector<double> &values = static_cast<ConfigOptionPercents*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
if (elem == NULL || !looks_like_number(*elem)) return false;
values.emplace_back(SvNV(*elem));
}
break;
}
case coInt:
if (!looks_like_number(value)) return false;
static_cast<ConfigOptionInt*>(opt)->value = SvIV(value);
break;
case coInts:
{
std::vector<int> &values = static_cast<ConfigOptionInts*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
if (elem == NULL || !looks_like_number(*elem)) return false;
values.emplace_back(SvIV(*elem));
}
break;
}
case coString:
static_cast<ConfigOptionString*>(opt)->value = std::string(SvPV_nolen(value), SvCUR(value));
break;
case coStrings:
{
std::vector<std::string> &values = static_cast<ConfigOptionStrings*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
if (elem == NULL) return false;
values.emplace_back(std::string(SvPV_nolen(*elem), SvCUR(*elem)));
}
break;
}
case coPoint:
return from_SV_check(value, &static_cast<ConfigOptionPoint*>(opt)->value);
// case coPoint3:
// not gonna fix it, die Perl die!
// return from_SV_check(value, &static_cast<ConfigOptionPoint3*>(opt)->value);
case coPoints:
{
std::vector<Vec2d> &values = static_cast<ConfigOptionPoints*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
Vec2d point(Vec2d::Zero());
if (elem == NULL || !from_SV_check(*elem, &point)) return false;
values.emplace_back(point);
}
break;
}
case coBool:
static_cast<ConfigOptionBool*>(opt)->value = SvTRUE(value);
break;
case coBools:
{
std::vector<unsigned char> &values = static_cast<ConfigOptionBools*>(opt)->values;
AV* av = (AV*)SvRV(value);
const size_t len = av_len(av)+1;
values.clear();
values.reserve(len);
for (size_t i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
if (elem == NULL) return false;
values.emplace_back(SvTRUE(*elem));
}
break;
}
default:
if (! opt->deserialize(std::string(SvPV_nolen(value)), ForwardCompatibilitySubstitutionRule::Disable))
return false;
}
return true;
}
/* This method is implemented as a workaround for this typemap bug:
https://rt.cpan.org/Public/Bug/Display.html?id=94110 */
bool ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str)
{
size_t len;
const char * c = SvPV(str, len);
std::string value(c, len);
ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable };
return THIS->set_deserialize_nothrow(opt_key, value, ctxt);
}
void ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize)
{
if (THIS->has(opt_key))
return;
if (deserialize)
ConfigBase__set_deserialize(THIS, opt_key, value);
else
ConfigBase__set(THIS, opt_key, value);
}
bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value)
{
const ConfigOptionDef* optdef = THIS->def()->get(opt_key);
if (optdef->shortcut.empty())
return ConfigBase__set(THIS, opt_key, value);
for (const t_config_option_key &key : optdef->shortcut)
if (! StaticConfig__set(THIS, key, value))
return false;
return true;
}
SV* to_AV(ExPolygon* expolygon)
{
const unsigned int num_holes = expolygon->holes.size();
AV* av = newAV();
av_extend(av, num_holes); // -1 +1
av_store(av, 0, perl_to_SV_ref(expolygon->contour));
for (unsigned int i = 0; i < num_holes; i++) {
av_store(av, i+1, perl_to_SV_ref(expolygon->holes[i]));
}
return newRV_noinc((SV*)av);
}
SV* to_SV_pureperl(const ExPolygon* expolygon)
{
const unsigned int num_holes = expolygon->holes.size();
AV* av = newAV();
av_extend(av, num_holes); // -1 +1
av_store(av, 0, to_SV_pureperl(&expolygon->contour));
for (unsigned int i = 0; i < num_holes; i++) {
av_store(av, i+1, to_SV_pureperl(&expolygon->holes[i]));
}
return newRV_noinc((SV*)av);
}
void from_SV(SV* expoly_sv, ExPolygon* expolygon)
{
AV* expoly_av = (AV*)SvRV(expoly_sv);
const unsigned int num_polygons = av_len(expoly_av)+1;
expolygon->holes.resize(num_polygons-1);
SV** polygon_sv = av_fetch(expoly_av, 0, 0);
from_SV(*polygon_sv, &expolygon->contour);
for (unsigned int i = 0; i < num_polygons-1; i++) {
polygon_sv = av_fetch(expoly_av, i+1, 0);
from_SV(*polygon_sv, &expolygon->holes[i]);
}
}
void from_SV_check(SV* expoly_sv, ExPolygon* expolygon)
{
if (sv_isobject(expoly_sv) && (SvTYPE(SvRV(expoly_sv)) == SVt_PVMG)) {
if (!sv_isa(expoly_sv, perl_class_name(expolygon)) && !sv_isa(expoly_sv, perl_class_name_ref(expolygon)))
CONFESS("Not a valid %s object", perl_class_name(expolygon));
// a XS ExPolygon was supplied
*expolygon = *(ExPolygon *)SvIV((SV*)SvRV( expoly_sv ));
} else {
// a Perl arrayref was supplied
from_SV(expoly_sv, expolygon);
}
}
void from_SV(SV* line_sv, Line* THIS)
{
AV* line_av = (AV*)SvRV(line_sv);
from_SV_check(*av_fetch(line_av, 0, 0), &THIS->a);
from_SV_check(*av_fetch(line_av, 1, 0), &THIS->b);
}
void from_SV_check(SV* line_sv, Line* THIS)
{
if (sv_isobject(line_sv) && (SvTYPE(SvRV(line_sv)) == SVt_PVMG)) {
if (!sv_isa(line_sv, perl_class_name(THIS)) && !sv_isa(line_sv, perl_class_name_ref(THIS)))
CONFESS("Not a valid %s object", perl_class_name(THIS));
*THIS = *(Line*)SvIV((SV*)SvRV( line_sv ));
} else {
from_SV(line_sv, THIS);
}
}
SV* to_AV(Line* THIS)
{
AV* av = newAV();
av_extend(av, 1);
av_store(av, 0, perl_to_SV_ref(THIS->a));
av_store(av, 1, perl_to_SV_ref(THIS->b));
return newRV_noinc((SV*)av);
}
SV* to_SV_pureperl(const Line* THIS)
{
AV* av = newAV();
av_extend(av, 1);
av_store(av, 0, to_SV_pureperl(&THIS->a));
av_store(av, 1, to_SV_pureperl(&THIS->b));
return newRV_noinc((SV*)av);
}
void from_SV(SV* poly_sv, MultiPoint* THIS)
{
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);
from_SV_check(*point_sv, &THIS->points[i]);
}
}
void from_SV_check(SV* poly_sv, MultiPoint* THIS)
{
if (sv_isobject(poly_sv) && (SvTYPE(SvRV(poly_sv)) == SVt_PVMG)) {
*THIS = *(MultiPoint*)SvIV((SV*)SvRV( poly_sv ));
} else {
from_SV(poly_sv, THIS);
}
}
SV* to_AV(MultiPoint* THIS)
{
const unsigned int num_points = THIS->points.size();
AV* av = newAV();
if (num_points > 0) av_extend(av, num_points-1);
for (unsigned int i = 0; i < num_points; i++) {
av_store(av, i, perl_to_SV_ref(THIS->points[i]));
}
return newRV_noinc((SV*)av);
}
SV* to_SV_pureperl(const MultiPoint* THIS)
{
const unsigned int num_points = THIS->points.size();
AV* av = newAV();
if (num_points > 0) av_extend(av, num_points-1);
for (unsigned int i = 0; i < num_points; i++) {
av_store(av, i, to_SV_pureperl(&THIS->points[i]));
}
return newRV_noinc((SV*)av);
}
void from_SV_check(SV* poly_sv, Polygon* THIS)
{
if (sv_isobject(poly_sv) && !sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
CONFESS("Not a valid %s object", perl_class_name(THIS));
from_SV_check(poly_sv, (MultiPoint*)THIS);
}
void from_SV_check(SV* poly_sv, Polyline* THIS)
{
if (!sv_isa(poly_sv, perl_class_name(THIS)) && !sv_isa(poly_sv, perl_class_name_ref(THIS)))
CONFESS("Not a valid %s object", perl_class_name(THIS));
from_SV_check(poly_sv, (MultiPoint*)THIS);
}
SV* to_SV_pureperl(const Point* THIS)
{
AV* av = newAV();
av_fill(av, 1);
av_store(av, 0, newSViv((*THIS)(0)));
av_store(av, 1, newSViv((*THIS)(1)));
return newRV_noinc((SV*)av);
}
void from_SV(SV* point_sv, Point* point)
{
AV* point_av = (AV*)SvRV(point_sv);
// get a double from Perl and round it, otherwise
// it would get truncated
(*point) = Point(SvNV(*av_fetch(point_av, 0, 0)), SvNV(*av_fetch(point_av, 1, 0)));
}
void from_SV_check(SV* point_sv, Point* point)
{
if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
*point = *(Point*)SvIV((SV*)SvRV( point_sv ));
} else {
from_SV(point_sv, point);
}
}
SV* to_SV_pureperl(const Vec2d* point)
{
AV* av = newAV();
av_fill(av, 1);
av_store(av, 0, newSVnv((*point)(0)));
av_store(av, 1, newSVnv((*point)(1)));
return newRV_noinc((SV*)av);
}
bool from_SV(SV* point_sv, Vec2d* point)
{
AV* point_av = (AV*)SvRV(point_sv);
SV* sv_x = *av_fetch(point_av, 0, 0);
SV* sv_y = *av_fetch(point_av, 1, 0);
if (!looks_like_number(sv_x) || !looks_like_number(sv_y)) return false;
*point = Vec2d(SvNV(sv_x), SvNV(sv_y));
return true;
}
bool from_SV_check(SV* point_sv, Vec2d* point)
{
if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) {
if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point)))
CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv))));
*point = *(Vec2d*)SvIV((SV*)SvRV( point_sv ));
return true;
} else {
return from_SV(point_sv, point);
}
}
void from_SV_check(SV* surface_sv, Surface* THIS)
{
if (!sv_isa(surface_sv, perl_class_name(THIS)) && !sv_isa(surface_sv, perl_class_name_ref(THIS)))
CONFESS("Not a valid %s object", perl_class_name(THIS));
// a XS Surface was supplied
*THIS = *(Surface *)SvIV((SV*)SvRV( surface_sv ));
}
SV* to_SV(TriangleMesh* THIS)
{
SV* sv = newSV(0);
sv_setref_pv( sv, perl_class_name(THIS), (void*)THIS );
return sv;
}
}
#endif

7063
xs/src/ppport.h Normal file

File diff suppressed because it is too large Load diff

259
xs/src/xsinit.h Normal file
View file

@ -0,0 +1,259 @@
#ifndef _xsinit_h_
#define _xsinit_h_
#ifdef _MSC_VER
// Disable some obnoxious warnings given by Visual Studio with the default warning level 4.
#pragma warning(disable: 4100 4127 4189 4244 4267 4700 4702 4800)
#endif
// undef some macros set by Perl which cause compilation errors on Win32
#undef read
#undef seekdir
#undef bind
#undef send
#undef connect
#undef wait
#undef accept
#undef close
#undef open
#undef write
#undef socket
#undef listen
#undef shutdown
#undef ioctl
#undef getpeername
#undef rect
#undef setsockopt
#undef getsockopt
#undef getsockname
#undef gethostname
#undef select
#undef socketpair
#undef recvfrom
#undef sendto
#undef pause
// these need to be included early for Win32 (listing it in Build.PL is not enough)
#include <ostream>
#include <iostream>
#include <sstream>
// #include <libslic3r.h>
#ifdef SLIC3RXS
// extern "C" {
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#undef do_open
#undef do_close
#undef bind
#undef seed
#undef push
#undef pop
#ifdef _MSC_VER
// Undef some of the macros set by Perl <xsinit.h>, which cause compilation errors on Win32
#undef connect
#undef link
#undef unlink
#undef seek
#undef send
#undef write
#undef open
#undef close
#undef seekdir
#undef setbuf
#undef fread
#undef fseek
#undef fputc
#undef fwrite
#undef fclose
#undef sleep
#undef snprintf
#undef strerror
#undef test
#undef times
#undef accept
#undef wait
#undef abort
// Breaks compilation with Eigen matrices embedded into Slic3r::Point.
#undef malloc
#undef realloc
#undef free
#undef select
// Because of TBB
#define _WIN32_WINNT 0x0502
#endif /* _MSC_VER */
#undef Zero
#undef Packet
#undef _
// }
#endif
#include <ClipperUtils.hpp>
#include <Config.hpp>
#include <ExPolygon.hpp>
#include <MultiPoint.hpp>
#include <Point.hpp>
#include <Polygon.hpp>
#include <Polyline.hpp>
#include <TriangleMesh.hpp>
namespace Slic3r {
template<class T>
struct ClassTraits {
// Name of a Perl alias of a C++ class type, owned by Perl, reference counted.
static const char* name;
// Name of a Perl alias of a C++ class type, owned by the C++ code.
// The references shall be enumerated at the end of XS.pm, where the desctructor is undefined with sub DESTROY {},
// so Perl will never delete the object instance.
static const char* name_ref;
};
// use this for typedefs for which the forward prototype
// in REGISTER_CLASS won't work
#define __REGISTER_CLASS(cname, perlname) \
template <>const char* ClassTraits<cname>::name = "Slic3r::" perlname; \
template <>const char* ClassTraits<cname>::name_ref = "Slic3r::" perlname "::Ref";
#define REGISTER_CLASS(cname,perlname) \
class cname; \
__REGISTER_CLASS(cname, perlname);
// Return Perl alias to a C++ class name.
template<class T>
const char* perl_class_name(const T*) { return ClassTraits<T>::name; }
// Return Perl alias to a C++ class name, suffixed with ::Ref.
// Such a C++ class instance will not be destroyed by Perl, the instance destruction is left to the C++ code.
template<class T>
const char* perl_class_name_ref(const T*) { return ClassTraits<T>::name_ref; }
// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object reference.
// Perl will never release the C++ instance.
template<class T>
SV* perl_to_SV_ref(T &t) {
SV* sv = newSV(0);
sv_setref_pv( sv, perl_class_name_ref(&t), &t );
return sv;
}
// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object instance.
// Perl will own the C++ instance, therefore it will also release it.
template<class T>
SV* perl_to_SV_clone_ref(const T &t) {
SV* sv = newSV(0);
sv_setref_pv( sv, perl_class_name(&t), new T(t) );
return sv;
}
// Reference wrapper to provide a C++ instance to Perl while keeping Perl from destroying the instance.
// The instance is created temporarily by XS.cpp just to provide Perl with a CLASS name and a object instance pointer.
template <class T>
class Ref {
T* val;
public:
Ref() : val(NULL) {}
Ref(T* t) : val(t) {}
Ref(const T* t) : val(const_cast<T*>(t)) {}
// Called by XS.cpp to convert the referenced object instance to a Perl SV, before it is blessed with the name
// returned by CLASS()
operator T*() const { return val; }
// Name to bless the Perl SV with. The name ends with a "::Ref" suffix to keep Perl from destroying the object instance.
static const char* CLASS() { return ClassTraits<T>::name_ref; }
};
// Wrapper to clone a C++ object instance before passing it to Perl for ownership.
// This wrapper instance is created temporarily by XS.cpp to provide Perl with a CLASS name and a object instance pointer.
template <class T>
class Clone {
T* val;
public:
Clone() : val(NULL) {}
Clone(T* t) : val(new T(*t)) {}
Clone(const T& t) : val(new T(t)) {}
// Called by XS.cpp to convert the cloned object instance to a Perl SV, before it is blessed with the name
// returned by CLASS()
operator T*() const { return val; }
// Name to bless the Perl SV with. If there is a destructor registered in the XSP file for this class, then Perl will
// call this destructor when the reference counter of this SV drops to zero.
static const char* CLASS() { return ClassTraits<T>::name; }
};
SV* ConfigBase__as_hash(ConfigBase* THIS);
SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def);
SV* ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key);
SV* ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i);
bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value);
bool ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str);
void ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize = false);
bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value);
SV* to_AV(ExPolygon* expolygon);
SV* to_SV_pureperl(const ExPolygon* expolygon);
void from_SV(SV* expoly_sv, ExPolygon* expolygon);
void from_SV_check(SV* expoly_sv, ExPolygon* expolygon);
void from_SV(SV* line_sv, Line* THIS);
void from_SV_check(SV* line_sv, Line* THIS);
SV* to_AV(Line* THIS);
SV* to_SV_pureperl(const Line* THIS);
void from_SV(SV* poly_sv, MultiPoint* THIS);
void from_SV_check(SV* poly_sv, MultiPoint* THIS);
SV* to_AV(MultiPoint* THIS);
SV* to_SV_pureperl(const MultiPoint* THIS);
void from_SV_check(SV* poly_sv, Polygon* THIS);
void from_SV_check(SV* poly_sv, Polyline* THIS);
SV* to_SV_pureperl(const Point* THIS);
void from_SV(SV* point_sv, Point* point);
void from_SV_check(SV* point_sv, Point* point);
SV* to_SV_pureperl(const Vec2d* point);
bool from_SV(SV* point_sv, Vec2d* point);
bool from_SV_check(SV* point_sv, Vec2d* point);
void from_SV_check(SV* surface_sv, Surface* THIS);
SV* to_SV(TriangleMesh* THIS);
}
// Defined in wxPerlIface.cpp
// Return a pointer to the associated wxWidgets object instance given by classname.
extern void* wxPli_sv_2_object( pTHX_ SV* scalar, const char* classname );
inline void confess_at(const char *file, int line, const char *func, const char *pat, ...)
{
#ifdef SLIC3RXS
va_list args;
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
file, line);
va_start(args, pat);
sv_vcatpvf(error_sv, pat, &args);
va_end(args);
sv_catpvn(error_sv, "\n\t", 2);
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(error_sv) );
PUTBACK;
call_pv("Carp::confess", G_DISCARD);
FREETMPS;
LEAVE;
#endif
}
#ifndef CONFESS
/* Implementation of CONFESS("foo"): */
#ifdef _MSC_VER
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#else
#define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)
#endif
/* End implementation of CONFESS("foo"): */
#endif /* CONFESS */
using namespace Slic3r;
#endif

35
xs/t/01_trianglemesh.t Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 5;
my $cube = {
vertices => [ [20,20,0], [20,0,0], [0,0,0], [0,20,0], [20,20,20], [0,20,20], [0,0,20], [20,0,20] ],
facets => [ [0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5] ],
};
{
my $m = Slic3r::TriangleMesh->new;
$m->ReadFromPerl($cube->{vertices}, $cube->{facets});
my ($vertices, $facets) = ($m->vertices, $m->facets);
is_deeply $vertices, $cube->{vertices}, 'vertices arrayref roundtrip';
is_deeply $facets, $cube->{facets}, 'facets arrayref roundtrip';
{
my $m2 = $m->clone;
is_deeply $m2->vertices, $cube->{vertices}, 'cloned vertices arrayref roundtrip';
is_deeply $m2->facets, $cube->{facets}, 'cloned facets arrayref roundtrip';
$m2->scale(3); # check that it does not affect $m
}
{
my $stats = $m->stats;
is $stats->{number_of_facets}, scalar(@{ $cube->{facets} }), 'stats.number_of_facets';
}
}
__END__

84
xs/t/03_point.t Normal file
View file

@ -0,0 +1,84 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 24;
my $point = Slic3r::Point->new(10, 15);
is_deeply [ @$point ], [10, 15], 'point roundtrip';
my $point2 = $point->clone;
$point2->scale(2);
is_deeply [ @$point2 ], [20, 30], 'scale';
$point2->translate(10, -15);
is_deeply [ @$point2 ], [30, 15], 'translate';
ok $point->coincides_with($point->clone), 'coincides_with';
ok !$point->coincides_with($point2), 'coincides_with';
{
my $point3 = Slic3r::Point->new(4300000, -9880845);
is $point->[0], $point->x, 'x accessor';
is $point->[1], $point->y, 'y accessor'; #,,
}
{
my $nearest = $point->nearest_point([ $point2, Slic3r::Point->new(100, 200) ]);
ok $nearest->coincides_with($point2), 'nearest_point';
}
{
my $line = Slic3r::Line->new([0,0], [100,0]);
is +Slic3r::Point->new(0,0) ->distance_to_line($line), 0, 'distance_to_line()';
is +Slic3r::Point->new(100,0)->distance_to_line($line), 0, 'distance_to_line()';
is +Slic3r::Point->new(50,0) ->distance_to_line($line), 0, 'distance_to_line()';
is +Slic3r::Point->new(150,0)->distance_to_line($line), 50, 'distance_to_line()';
is +Slic3r::Point->new(0,50) ->distance_to_line($line), 50, 'distance_to_line()';
is +Slic3r::Point->new(50,50)->distance_to_line($line), 50, 'distance_to_line()';
is +Slic3r::Point->new(50,50) ->perp_distance_to_line($line), 50, 'perp_distance_to_line()';
is +Slic3r::Point->new(150,50)->perp_distance_to_line($line), 50, 'perp_distance_to_line()';
}
{
my $line = Slic3r::Line->new([50,50], [125,-25]);
cmp_ok(abs(Slic3r::Point->new(100,0)->distance_to_line($line)), '<=', 4e-15, 'distance_to_line()');
}
{
my $line = Slic3r::Line->new(
[18335846,18335845],
[18335846,1664160],
);
$point = Slic3r::Point->new(1664161,18335848);
is $point->perp_distance_to_line($line), 16671685, 'perp_distance_to_line() does not overflow';
}
{
my $p0 = Slic3r::Point->new(76975850,89989996);
my $p1 = Slic3r::Point->new(76989990,109989991);
my $p2 = Slic3r::Point->new(76989987,89989994);
ok $p0->ccw($p1, $p2) < 0, 'ccw() does not overflow';
}
{
my $point = Slic3r::Point->new(15,15);
my $line = Slic3r::Line->new([10,10], [20,10]);
is_deeply $point->projection_onto_line($line)->pp, [15,10], 'project_onto_line';
$point = Slic3r::Point->new(0, 15);
is_deeply $point->projection_onto_line($line)->pp, [10,10], 'project_onto_line';
$point = Slic3r::Point->new(25, 15);
is_deeply $point->projection_onto_line($line)->pp, [20,10], 'project_onto_line';
$point = Slic3r::Point->new(10,10);
is_deeply $point->projection_onto_line($line)->pp, [10,10], 'project_onto_line';
$point = Slic3r::Point->new(12, 10);
is_deeply $point->projection_onto_line($line)->pp, [12,10], 'project_onto_line';
}
__END__

108
xs/t/04_expolygon.t Normal file
View file

@ -0,0 +1,108 @@
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(first sum);
use Slic3r::XS;
use Test::More tests => 21;
use constant PI => 4 * atan2(1, 1);
my $square = [ # ccw
[100, 100],
[200, 100],
[200, 200],
[100, 200],
];
my $hole_in_square = [ # cw
[140, 140],
[140, 160],
[160, 160],
[160, 140],
];
my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
ok $expolygon->is_valid, 'is_valid';
is ref($expolygon->pp), 'ARRAY', 'expolygon pp is unblessed';
is_deeply $expolygon->pp, [$square, $hole_in_square], 'expolygon roundtrip';
is ref($expolygon->arrayref), 'ARRAY', 'expolygon arrayref is unblessed';
isa_ok $expolygon->[0], 'Slic3r::Polygon::Ref', 'expolygon polygon is blessed';
isa_ok $expolygon->contour, 'Slic3r::Polygon::Ref', 'expolygon contour is blessed';
isa_ok $expolygon->holes->[0], 'Slic3r::Polygon::Ref', 'expolygon hole is blessed';
isa_ok $expolygon->[0][0], 'Slic3r::Point::Ref', 'expolygon point is blessed';
{
my $expolygon2 = $expolygon->clone;
my $polygon = $expolygon2->[0];
$polygon->scale(2);
is $expolygon2->[0][0][0], $polygon->[0][0], 'polygons are returned by reference';
}
is_deeply $expolygon->clone->pp, [$square, $hole_in_square], 'clone';
is $expolygon->area, 100*100-20*20, 'area';
{
my $expolygon2 = $expolygon->clone;
$expolygon2->scale(2.5);
is_deeply $expolygon2->pp, [
[map [ 2.5*$_->[0], 2.5*$_->[1] ], @$square],
[map [ 2.5*$_->[0], 2.5*$_->[1] ], @$hole_in_square]
], 'scale';
}
{
my $expolygon2 = $expolygon->clone;
$expolygon2->translate(10, -5);
is_deeply $expolygon2->pp, [
[map [ $_->[0]+10, $_->[1]-5 ], @$square],
[map [ $_->[0]+10, $_->[1]-5 ], @$hole_in_square]
], 'translate';
}
{
my $expolygon2 = $expolygon->clone;
$expolygon2->rotate(PI/2, Slic3r::Point->new(150,150));
is_deeply $expolygon2->pp, [
[ @$square[1,2,3,0] ],
[ @$hole_in_square[3,0,1,2] ]
], 'rotate around Point';
}
{
my $expolygon2 = $expolygon->clone;
$expolygon2->rotate(PI/2, [150,150]);
is_deeply $expolygon2->pp, [
[ @$square[1,2,3,0] ],
[ @$hole_in_square[3,0,1,2] ]
], 'rotate around pure-Perl Point';
}
{
my $expolygon2 = $expolygon->clone;
$expolygon2->scale(2);
my $collection = Slic3r::ExPolygon::Collection->new($expolygon->pp, $expolygon2->pp);
is_deeply $collection->pp, [ $expolygon->pp, $expolygon2->pp ],
'expolygon collection (pure Perl) roundtrip';
my $collection2 = Slic3r::ExPolygon::Collection->new($expolygon, $expolygon2);
is_deeply $collection->pp, $collection2->pp,
'expolygon collection (XS) roundtrip';
$collection->clear;
is scalar(@$collection), 0, 'clear collection';
$collection->append($expolygon);
is scalar(@$collection), 1, 'append to collection';
my $exp = $collection->[0];
$exp->scale(3);
is $collection->[0][0][0][0], $exp->[0][0][0], 'collection items are returned by reference';
is_deeply $collection->[0]->clone->pp, $collection->[0]->pp, 'clone collection item';
}
__END__

76
xs/t/05_surface.t Normal file
View file

@ -0,0 +1,76 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 15;
my $square = [ # ccw
[100, 100],
[200, 100],
[200, 200],
[100, 200],
];
my $hole_in_square = [ # cw
[140, 140],
[140, 160],
[160, 160],
[160, 140],
];
my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
my $surface = Slic3r::Surface->new(
expolygon => $expolygon,
surface_type => Slic3r::Surface::S_TYPE_INTERNAL,
);
$surface = $surface->clone;
isa_ok $surface->expolygon, 'Slic3r::ExPolygon::Ref', 'expolygon';
is_deeply [ @{$surface->expolygon->pp} ], [$square, $hole_in_square], 'expolygon roundtrip';
is scalar(@{$surface->polygons}), 2, 'polygons roundtrip';
is $surface->surface_type, Slic3r::Surface::S_TYPE_INTERNAL, 'surface_type';
$surface->surface_type(Slic3r::Surface::S_TYPE_BOTTOM);
is $surface->surface_type, Slic3r::Surface::S_TYPE_BOTTOM, 'modify surface_type';
$surface->bridge_angle(30);
is $surface->bridge_angle, 30, 'bridge_angle';
$surface->extra_perimeters(2);
is $surface->extra_perimeters, 2, 'extra_perimeters';
{
my $surface2 = $surface->clone;
$surface2->expolygon->scale(2);
isnt $surface2->expolygon->area, $expolygon->area, 'expolygon is returned by reference';
}
{
my $collection = Slic3r::Surface::Collection->new;
$collection->append($_) for $surface, $surface->clone;
is scalar(@$collection), 2, 'collection has the right number of items';
is_deeply $collection->[0]->expolygon->pp, [$square, $hole_in_square],
'collection returns a correct surface expolygon';
$collection->clear;
is scalar(@$collection), 0, 'clear collection';
$collection->append($surface);
is scalar(@$collection), 1, 'append to collection';
my $item = $collection->[0];
isa_ok $item, 'Slic3r::Surface::Ref';
$item->surface_type(Slic3r::Surface::S_TYPE_INTERNAL);
is $item->surface_type, $collection->[0]->surface_type, 'collection returns items by reference';
}
{
my $collection = Slic3r::Surface::Collection->new;
$collection->append($_) for
Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_BOTTOM),
Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_BOTTOM),
Slic3r::Surface->new(expolygon => $expolygon, surface_type => Slic3r::Surface::S_TYPE_TOP);
is scalar(@{$collection->group}), 2, 'group() returns correct number of groups';
}
__END__

21
xs/t/06_polygon.t Normal file
View file

@ -0,0 +1,21 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 3;
my $square = [ # ccw
[100, 100],
[200, 100],
[200, 200],
[100, 200],
];
my $polygon = Slic3r::Polygon->new(@$square);
is ref($polygon->arrayref), 'ARRAY', 'polygon arrayref is unblessed';
isa_ok $polygon->[0], 'Slic3r::Point::Ref', 'polygon point is blessed';
ok ref($polygon->first_point) eq 'Slic3r::Point', 'first_point';
__END__

38
xs/t/07_extrusionpath.t Normal file
View file

@ -0,0 +1,38 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 7;
my $points = [
[100, 100],
[200, 100],
[200, 200],
];
my $path = Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new(@$points),
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
mm3_per_mm => 1,
);
isa_ok $path->polyline, 'Slic3r::Polyline::Ref', 'path polyline';
is_deeply $path->polyline->pp, $points, 'path points roundtrip';
$path->reverse;
is_deeply $path->polyline->pp, [ reverse @$points ], 'reverse path';
$path->append([ 150, 150 ]);
is scalar(@$path), 4, 'append to path';
$path->pop_back;
is scalar(@$path), 3, 'pop_back from path';
ok $path->first_point->coincides_with($path->polyline->[0]), 'first_point';
$path = $path->clone;
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'role';
__END__

158
xs/t/08_extrusionloop.t Normal file
View file

@ -0,0 +1,158 @@
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(sum);
use Slic3r::XS;
use Test::More tests => 47;
{
my $square = [
[100, 100],
[200, 100],
[200, 200],
[100, 200],
];
my $square_p = Slic3r::Polygon->new(@$square);
my $loop = Slic3r::ExtrusionLoop->new;
$loop->append(Slic3r::ExtrusionPath->new(
polyline => $square_p->split_at_first_point,
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
mm3_per_mm => 1,
));
isa_ok $loop, 'Slic3r::ExtrusionLoop';
isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon';
is $loop->polygon->area, $square_p->area, 'polygon area';
is $loop->length, $square_p->length(), 'loop length';
$loop = $loop->clone;
is scalar(@$loop), 1, 'loop contains one path';
{
my $path = $loop->[0];
isa_ok $path, 'Slic3r::ExtrusionPath::Ref';
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'role';
}
$loop->split_at_vertex($square_p->[2]);
is scalar(@$loop), 1, 'splitting a single-path loop results in a single path';
is scalar(@{$loop->[0]->polyline}), 5, 'path has correct number of points';
ok $loop->[0]->polyline->[0]->coincides_with($square_p->[2]), 'expected point order';
ok $loop->[0]->polyline->[1]->coincides_with($square_p->[3]), 'expected point order';
ok $loop->[0]->polyline->[2]->coincides_with($square_p->[0]), 'expected point order';
ok $loop->[0]->polyline->[3]->coincides_with($square_p->[1]), 'expected point order';
ok $loop->[0]->polyline->[4]->coincides_with($square_p->[2]), 'expected point order';
}
{
my $polyline1 = Slic3r::Polyline->new([100,100], [200,100], [200,200]);
my $polyline2 = Slic3r::Polyline->new([200,200], [100,200], [100,100]);
my $loop = Slic3r::ExtrusionLoop->new_from_paths(
Slic3r::ExtrusionPath->new(
polyline => $polyline1,
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
mm3_per_mm => 1,
),
Slic3r::ExtrusionPath->new(
polyline => $polyline2,
role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
mm3_per_mm => 1,
),
);
my $tot_len = sum($polyline1->length, $polyline2->length);
is $loop->length, $tot_len, 'length';
is scalar(@$loop), 2, 'loop contains two paths';
{
# check splitting at intermediate point
my $loop2 = $loop->clone;
isa_ok $loop2, 'Slic3r::ExtrusionLoop';
$loop2->split_at_vertex($polyline1->[1]);
is $loop2->length, $tot_len, 'length after splitting is unchanged';
is scalar(@$loop2), 3, 'loop contains three paths after splitting';
ok $loop2->[0]->polyline->[0]->coincides_with($polyline1->[1]), 'expected starting point';
ok $loop2->[-1]->polyline->[-1]->coincides_with($polyline1->[1]), 'expected ending point';
ok $loop2->[0]->polyline->[-1]->coincides_with($loop2->[1]->polyline->[0]), 'paths have common point';
ok $loop2->[1]->polyline->[-1]->coincides_with($loop2->[2]->polyline->[0]), 'paths have common point';
is $loop2->[0]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
is $loop2->[1]->role, Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, 'expected order after splitting';
is $loop2->[2]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
is scalar(@{$loop2->[0]->polyline}), 2, 'path has correct number of points';
is scalar(@{$loop2->[1]->polyline}), 3, 'path has correct number of points';
is scalar(@{$loop2->[2]->polyline}), 2, 'path has correct number of points';
my @paths = @{$loop2->clip_end(3)};
is sum(map $_->length, @paths), $loop2->length - 3, 'returned paths have expected length';
}
{
# check splitting at endpoint
my $loop2 = $loop->clone;
$loop2->split_at_vertex($polyline2->[0]);
is $loop2->length, $tot_len, 'length after splitting is unchanged';
is scalar(@$loop2), 2, 'loop contains two paths after splitting';
ok $loop2->[0]->polyline->[0]->coincides_with($polyline2->[0]), 'expected starting point';
ok $loop2->[-1]->polyline->[-1]->coincides_with($polyline2->[0]), 'expected ending point';
ok $loop2->[0]->polyline->[-1]->coincides_with($loop2->[1]->polyline->[0]), 'paths have common point';
ok $loop2->[1]->polyline->[-1]->coincides_with($loop2->[0]->polyline->[0]), 'paths have common point';
is $loop2->[0]->role, Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, 'expected order after splitting';
is $loop2->[1]->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'expected order after splitting';
is scalar(@{$loop2->[0]->polyline}), 3, 'path has correct number of points';
is scalar(@{$loop2->[1]->polyline}), 3, 'path has correct number of points';
}
{
my $loop2 = $loop->clone;
my $point = Slic3r::Point->new(250,150);
$loop2->split_at($point);
is $loop2->length, $tot_len, 'length after splitting is unchanged';
is scalar(@$loop2), 3, 'loop contains three paths after splitting';
my $expected_start_point = Slic3r::Point->new(200,150);
ok $loop2->[0]->polyline->[0]->coincides_with($expected_start_point), 'expected starting point';
ok $loop2->[-1]->polyline->[-1]->coincides_with($expected_start_point), 'expected ending point';
}
}
{
my @polylines = (
Slic3r::Polyline->new([59312736,4821067],[64321068,4821067],[64321068,4821067],[64321068,9321068],[59312736,9321068]),
Slic3r::Polyline->new([59312736,9321068],[9829401,9321068]),
Slic3r::Polyline->new([9829401,9321068],[4821067,9321068],[4821067,4821067],[9829401,4821067]),
Slic3r::Polyline->new([9829401,4821067],[59312736,4821067]),
);
my $loop = Slic3r::ExtrusionLoop->new;
$loop->append($_) for (
Slic3r::ExtrusionPath->new(polyline => $polylines[0], role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1),
Slic3r::ExtrusionPath->new(polyline => $polylines[1], role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, mm3_per_mm => 1),
Slic3r::ExtrusionPath->new(polyline => $polylines[2], role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1),
Slic3r::ExtrusionPath->new(polyline => $polylines[3], role => Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER, mm3_per_mm => 1),
);
my $len = $loop->length;
my $point = Slic3r::Point->new(4821067,9321068);
$loop->split_at_vertex($point) or $loop->split_at($point);
is $loop->length, $len, 'total length is preserved after splitting';
is_deeply [ map $_->role, @$loop ], [
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
Slic3r::ExtrusionPath::EXTR_ROLE_OVERHANG_PERIMETER,
Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
], 'order is correctly preserved after splitting';
}
{
my $loop = Slic3r::ExtrusionLoop->new;
$loop->append(Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new([15896783,15868739],[24842049,12117558],[33853238,15801279],[37591780,24780128],[37591780,24844970],[33853231,33825297],[24842049,37509013],[15896798,33757841],[12211841,24812544],[15896783,15868739]),
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, mm3_per_mm => 1
));
my $len = $loop->length;
$loop->split_at(Slic3r::Point->new(15896783,15868739));
is $loop->length, $len, 'split_at() preserves total length';
}
__END__

128
xs/t/09_polyline.t Normal file
View file

@ -0,0 +1,128 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 18;
my $points = [
[100, 100],
[200, 100],
[200, 200],
];
my $polyline = Slic3r::Polyline->new(@$points);
is_deeply $polyline->pp, $points, 'polyline roundtrip';
is ref($polyline->arrayref), 'ARRAY', 'polyline arrayref is unblessed';
isa_ok $polyline->[0], 'Slic3r::Point::Ref', 'polyline point is blessed';
my $lines = $polyline->lines;
is_deeply [ map $_->pp, @$lines ], [
[ [100, 100], [200, 100] ],
[ [200, 100], [200, 200] ],
], 'polyline lines';
$polyline->append_polyline($polyline->clone);
is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline';
{
my $len = $polyline->length;
$polyline->clip_end($len/3);
ok abs($polyline->length - ($len-($len/3))) < 1, 'clip_end';
}
{
my $polyline = Slic3r::Polyline->new(
[0,0], [20,0], [50,0], [80,0], [100,0],
);
$polyline->simplify(2);
is_deeply $polyline->pp, [ [0,0], [100,0] ], 'Douglas-Peucker';
}
{
my $polyline = Slic3r::Polyline->new(
[0,0], [50,50], [100,0], [125,-25], [150,50],
);
$polyline->simplify(25);
is_deeply $polyline->pp, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker';
}
{
my $polyline = Slic3r::Polyline->new(
[0,0], [100,0], [50,10],
);
$polyline->simplify(25);
is_deeply $polyline->pp, [ [0,0], [100,0], [50,10] ], 'Douglas-Peucker uses shortest distance instead of perpendicular distance';
}
{
my $polyline = Slic3r::Polyline->new(@$points);
is $polyline->length, 100*2, 'length';
$polyline->extend_end(50);
is $polyline->length, 100*2 + 50, 'extend_end';
$polyline->extend_start(50);
is $polyline->length, 100*2 + 50 + 50, 'extend_start';
}
{
my $polyline = Slic3r::Polyline->new(@$points);
my $p1 = Slic3r::Polyline->new;
my $p2 = Slic3r::Polyline->new;
my $point = Slic3r::Point->new(150, 100);
$polyline->split_at($point, $p1, $p2);
is scalar(@$p1), 2, 'split_at';
is scalar(@$p2), 3, 'split_at';
ok $p1->last_point->coincides_with($point), 'split_at';
ok $p2->first_point->coincides_with($point), 'split_at';
}
{
my $polyline = Slic3r::Polyline->new(@$points[0,1,2,0]);
my $p1 = Slic3r::Polyline->new;
my $p2 = Slic3r::Polyline->new;
$polyline->split_at($polyline->first_point, $p1, $p2);
is scalar(@$p1), 1, 'split_at';
is scalar(@$p2), 4, 'split_at';
}
# disabled because we now use a more efficient but incomplete algorithm
#if (0) {
# my $polyline = Slic3r::Polyline->new(
# map [$_,10], (0,10,20,30,40,50,60)
# );
# {
# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new(
# [25,0], [55,0], [55,30], [25,30],
# ));
# my $p = $polyline->clone;
# $p->simplify_by_visibility($expolygon);
# is_deeply $p->pp, [
# map [$_,10], (0,10,20,30,50,60)
# ], 'simplify_by_visibility()';
# }
# {
# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new(
# [-15,0], [75,0], [75,30], [-15,30],
# ));
# my $p = $polyline->clone;
# $p->simplify_by_visibility($expolygon);
# is_deeply $p->pp, [
# map [$_,10], (0,60)
# ], 'simplify_by_visibility()';
# }
# {
# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new(
# [-15,0], [25,0], [25,30], [-15,30],
# ));
# my $p = $polyline->clone;
# $p->simplify_by_visibility($expolygon);
# is_deeply $p->pp, [
# map [$_,10], (0,20,30,40,50,60)
# ], 'simplify_by_visibility()';
# }
#}
__END__

81
xs/t/10_line.t Normal file
View file

@ -0,0 +1,81 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 40;
use constant PI => 4 * atan2(1, 1);
use constant EPSILON => 1E-4;
my $points = [
[100, 100],
[200, 100],
];
my $line = Slic3r::Line->new(@$points);
is_deeply $line->pp, $points, 'line roundtrip';
is ref($line->arrayref), 'ARRAY', 'line arrayref is unblessed';
isa_ok $line->[0], 'Slic3r::Point::Ref', 'line point is blessed';
{
my $clone = $line->clone;
$clone->reverse;
is_deeply $clone->pp, [ reverse @$points ], 'reverse';
}
{
my $line2 = Slic3r::Line->new($line->a->clone, $line->b->clone);
is_deeply $line2->pp, $points, 'line roundtrip with cloned points';
}
{
my $clone = $line->clone;
$clone->translate(10, -5);
is_deeply $clone->pp, [
[110, 95],
[210, 95],
], 'translate';
}
{
ok +Slic3r::Line->new([0,0],[200,0])->parallel_to_line(Slic3r::Line->new([200,200],[0,200])), 'parallel_to';
}
foreach my $base_angle (0, PI/4, PI/2, PI) {
my $line = Slic3r::Line->new([0,0], [100,0]);
$line->rotate($base_angle, [0,0]);
my $clone = $line->clone;
ok $line->parallel_to_line($clone), 'line is parallel to self';
$clone->reverse;
ok $line->parallel_to_line($clone), 'line is parallel to self + PI';
ok $line->parallel_to($line->direction), 'line is parallel to its direction';
ok $line->parallel_to($line->direction + PI), 'line is parallel to its direction + PI';
ok $line->parallel_to($line->direction - PI), 'line is parallel to its direction - PI';
{
my $line2 = $line->clone;
$line2->reverse;
ok $line->parallel_to_line($line2), 'line is parallel to its opposite';
}
{
my $line2 = $line->clone;
$line2->rotate(+(EPSILON)/2, [0,0]);
ok $line->parallel_to_line($line2), 'line is parallel within epsilon';
}
{
my $line2 = $line->clone;
$line2->rotate(-(EPSILON)/2, [0,0]);
ok $line->parallel_to_line($line2), 'line is parallel within epsilon';
}
}
{
my $a = Slic3r::Line->new([100, 0], [200, 0]);
my $b = Slic3r::Line->new([300, 300], [300, 100]);
my $r = $a->intersection_infinite($b);
is_deeply $r->pp, [300, 0], 'intersection_infinite';
}
__END__

View file

@ -0,0 +1,97 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 18;
my $points = [
[100, 100],
[200, 100],
[200, 200],
];
my $path = Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new(@$points),
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
mm3_per_mm => 1,
);
my $loop = Slic3r::ExtrusionLoop->new_from_paths(
Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polygon->new(@$points)->split_at_first_point,
role => Slic3r::ExtrusionPath::EXTR_ROLE_FILL,
mm3_per_mm => 1,
),
);
my $collection = Slic3r::ExtrusionPath::Collection->new(
$path,
);
isa_ok $collection, 'Slic3r::ExtrusionPath::Collection', 'collection object with items in constructor';
ok !$collection->no_sort, 'no_sort is false by default';
$collection->append($collection);
is scalar(@$collection), 2, 'append ExtrusionPath::Collection';
$collection->append($path);
is scalar(@$collection), 3, 'append ExtrusionPath';
$collection->append($loop);
is scalar(@$collection), 4, 'append ExtrusionLoop';
isa_ok $collection->[1], 'Slic3r::ExtrusionPath::Collection::Ref', 'correct object returned for collection';
isa_ok $collection->[2], 'Slic3r::ExtrusionPath::Ref', 'correct object returned for path';
isa_ok $collection->[3], 'Slic3r::ExtrusionLoop::Ref', 'correct object returned for loop';
is ref($collection->[2]->clone), 'Slic3r::ExtrusionPath', 'correct object returned for cloned path';
is ref($collection->[3]->clone), 'Slic3r::ExtrusionLoop', 'correct object returned for cloned loop';
is scalar(@{$collection->[1]}), 1, 'appended collection was duplicated';
{
my $collection_loop = $collection->[3];
$collection_loop->polygon->scale(2);
is_deeply $collection->[3]->polygon->pp, $collection_loop->polygon->pp, 'items are returned by reference';
}
{
my $collection = Slic3r::ExtrusionPath::Collection->new(
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
);
is_deeply
[ map $_->y, map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
[20, 18, 15, 10, 8, 5],
'chained_path_from';
is_deeply
[ map $_->y, map @{$_->polyline}, @{$collection->chained_path(0)} ],
[15, 18, 20, 10, 8, 5],
'chained_path';
}
{
my $collection = Slic3r::ExtrusionPath::Collection->new(
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
);
is_deeply
[ map $_->x, map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
[reverse 4, 10, 15, 10, 15, 20],
'chained_path_from';
$collection->no_sort(1);
my @foo = @{$collection->chained_path(0)};
pass 'chained_path with no_sort';
}
{
my $coll2 = $collection->clone;
ok !$coll2->no_sort, 'expected no_sort value';
$coll2->no_sort(1);
ok $coll2->clone->no_sort, 'no_sort is kept after clone';
}
__END__

View file

@ -0,0 +1,35 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 3;
{
my $collection = Slic3r::Polyline::Collection->new(
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
);
is_deeply
[ map $_->y, map @$_, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
[20, 18, 15, 10, 8, 5],
'chained_path_from';
is_deeply
[ map $_->y, map @$_, @{$collection->chained_path(0)} ],
[15, 18, 20, 10, 8, 5],
'chained_path';
}
{
my $collection = Slic3r::Polyline::Collection->new(
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
);
is_deeply
[ map $_->x, map @$_, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
[reverse 4, 10, 15, 10, 15, 20],
'chained_path_from';
}
__END__

252
xs/t/15_config.t Normal file
View file

@ -0,0 +1,252 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 143;
foreach my $config (Slic3r::Config->new, Slic3r::Config::Static::new_FullPrintConfig) {
$config->set('layer_height', 0.3);
ok abs($config->get('layer_height') - 0.3) < 1e-4, 'set/get float';
is $config->opt_serialize('layer_height'), '0.3', 'serialize float';
$config->set('perimeters', 2);
is $config->get('perimeters'), 2, 'set/get int';
is $config->opt_serialize('perimeters'), '2', 'serialize int';
$config->set('extrusion_axis', 'A');
is $config->get('extrusion_axis'), 'A', 'set/get string';
is $config->opt_serialize('extrusion_axis'), 'A', 'serialize string';
$config->set('notes', "foo\nbar");
is $config->get('notes'), "foo\nbar", 'set/get string with newline';
is $config->opt_serialize('notes'), 'foo\nbar', 'serialize string with newline';
$config->set_deserialize('notes', 'bar\nbaz');
is $config->get('notes'), "bar\nbaz", 'deserialize string with newline';
foreach my $test_data (
{
name => 'empty',
values => [],
serialized => ''
},
{
name => 'single empty',
values => [''],
serialized => '""'
},
{
name => 'single noempty, simple',
values => ['RGB'],
serialized => 'RGB'
},
{
name => 'multiple noempty, simple',
values => ['ABC', 'DEF', '09182745@!#$*(&'],
serialized => 'ABC;DEF;09182745@!#$*(&'
},
{
name => 'multiple, simple, some empty',
values => ['ABC', 'DEF', '', '09182745@!#$*(&', ''],
serialized => 'ABC;DEF;;09182745@!#$*(&;'
},
{
name => 'complex',
values => ['some "quoted" notes', "yet\n some notes", "whatever \n notes", ''],
serialized => '"some \"quoted\" notes";"yet\n some notes";"whatever \n notes";'
}
)
{
$config->set('filament_notes', $test_data->{values});
is $config->opt_serialize('filament_notes'), $test_data->{serialized}, 'serialize multi-string value ' . $test_data->{name};
$config->set_deserialize('filament_notes', '');
is_deeply $config->get('filament_notes'), [], 'deserialize multi-string value - empty ' . $test_data->{name};
$config->set_deserialize('filament_notes', $test_data->{serialized});
is_deeply $config->get('filament_notes'), $test_data->{values}, 'deserialize complex multi-string value ' . $test_data->{name};
}
$config->set('first_layer_height', 0.3);
ok abs($config->get('first_layer_height') - 0.3) < 1e-4, 'set/get absolute floatOrPercent';
is $config->opt_serialize('first_layer_height'), '0.3', 'serialize absolute floatOrPercent';
# This is no more supported after first_layer_height was moved from PrintObjectConfig to PrintConfig.
# $config->set('first_layer_height', $config->get('layer_height'));
# $config->get_abs_value('first_layer_height');
# ok abs($config->get_abs_value('first_layer_height') - 0.15) < 1e-4, 'set/get relative floatOrPercent';
# is $config->opt_serialize('first_layer_height'), '50%', 'serialize relative floatOrPercent';
# Uh-oh, we have no point option to test at the moment
#ok $config->set('print_center', [50,80]), 'valid point coordinates';
#is_deeply $config->get('print_center'), [50,80], 'set/get point';
#is $config->serialize('print_center'), '50,80', 'serialize point';
#$config->set_deserialize('print_center', '20,10');
#is_deeply $config->get('print_center'), [20,10], 'deserialize point';
#ok !$config->set('print_center', ['t',80]), 'invalid point X';
#ok !$config->set('print_center', [50,'t']), 'invalid point Y';
$config->set('use_relative_e_distances', 1);
is $config->get('use_relative_e_distances'), 1, 'set/get bool';
is $config->opt_serialize('use_relative_e_distances'), '1', 'serialize bool';
$config->set('gcode_flavor', 'teacup');
is $config->get('gcode_flavor'), 'teacup', 'set/get enum';
is $config->opt_serialize('gcode_flavor'), 'teacup', 'serialize enum';
$config->set_deserialize('gcode_flavor', 'mach3');
is $config->get('gcode_flavor'), 'mach3', 'deserialize enum (gcode_flavor)';
$config->set_deserialize('gcode_flavor', 'machinekit');
is $config->get('gcode_flavor'), 'machinekit', 'deserialize enum (gcode_flavor)';
$config->set_deserialize('fill_pattern', 'line');
is $config->get('fill_pattern'), 'line', 'deserialize enum (fill_pattern)';
$config->set_deserialize('support_material_pattern', 'rectilinear');
is $config->get('support_material_pattern'), 'rectilinear', 'deserialize enum (support_material_pattern)';
$config->set('extruder_offset', [[10,20],[30,45]]);
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
$config->set('extruder_offset', [Slic3r::Pointf->new(10,20),Slic3r::Pointf->new(30,45)]);
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[10,20],[30,45]], 'set/get points';
is $config->opt_serialize('extruder_offset'), '10x20,30x45', 'serialize points';
$config->set_deserialize('extruder_offset', '20x10');
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[20,10]], 'deserialize points';
$config->set_deserialize('extruder_offset', '0x0');
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [[0,0]], 'deserialize points';
{
my @values = ([10,20]);
$values[2] = [10,20]; # implicitely extend array; this is not the same as explicitely assigning undef to second item
ok !$config->set('extruder_offset', \@values), 'reject undef points';
}
# truncate ->get() to first decimal digit
$config->set('nozzle_diameter', [0.2,3]);
is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.2,3], 'set/get floats';
is $config->opt_serialize('nozzle_diameter'), '0.2,3', 'serialize floats';
$config->set_deserialize('nozzle_diameter', '0.1,0.4');
is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [0.1,0.4], 'deserialize floats';
$config->set_deserialize('nozzle_diameter', '3');
is_deeply [ map int($_*10)/10, @{$config->get('nozzle_diameter')} ], [3], 'deserialize a single float';
{
my @values = (0.4);
$values[2] = 2; # implicitely extend array; this is not the same as explicitely assigning undef to second item
ok !$config->set('nozzle_diameter', \@values), 'reject undef floats';
}
$config->set('temperature', [180,210]);
is_deeply $config->get('temperature'), [180,210], 'set/get ints';
is $config->opt_serialize('temperature'), '180,210', 'serialize ints';
$config->set_deserialize('temperature', '195,220');
is_deeply $config->get('temperature'), [195,220], 'deserialize ints';
{
my @values = (180);
$values[2] = 200; # implicitely extend array; this is not the same as explicitely assigning undef to second item
ok !$config->set('temperature', \@values), 'reject undef ints';
}
$config->set('wipe', [1,0]);
is_deeply $config->get('wipe'), [1,0], 'set/get bools';
is $config->get_at('wipe', 0), 1, 'get_at bools';
is $config->get_at('wipe', 1), 0, 'get_at bools';
is $config->get_at('wipe', 9), 1, 'get_at bools';
is $config->opt_serialize('wipe'), '1,0', 'serialize bools';
$config->set_deserialize('wipe', '0,1,1');
is_deeply $config->get('wipe'), [0,1,1], 'deserialize bools';
$config->set_deserialize('wipe', '');
is_deeply $config->get('wipe'), [], 'deserialize bools from empty string';
$config->set_deserialize('retract_layer_change', 0);
is_deeply $config->get('retract_layer_change'), [0], 'deserialize bools from non-string value';
{
my @values = (1);
$values[2] = 1; # implicitely extend array; this is not the same as explicitely assigning undef to second item
ok !$config->set('wipe', \@values), 'reject undef bools';
}
$config->set('post_process', ['foo','bar']);
is_deeply $config->get('post_process'), ['foo','bar'], 'set/get strings';
is $config->opt_serialize('post_process'), 'foo;bar', 'serialize strings';
$config->set_deserialize('post_process', 'bar;baz');
is_deeply $config->get('post_process'), ['bar','baz'], 'deserialize strings';
{
my @values = ('foo');
$values[2] = 'bar'; # implicitely extend array; this is not the same as explicitely assigning undef to second item
ok !$config->set('post_process', \@values), 'reject undef strings';
}
is_deeply [ sort @{$config->get_keys} ], [ sort keys %{$config->as_hash} ], 'get_keys and as_hash';
}
{
my $config = Slic3r::Config->new;
$config->set('perimeters', 2);
# test that no crash happens when using set_deserialize() with a key that hasn't been set() yet
$config->set_deserialize('filament_diameter', '3');
my $config2 = Slic3r::Config::Static::new_FullPrintConfig;
$config2->apply_dynamic($config);
is $config2->get('perimeters'), 2, 'apply_dynamic';
}
{
my $config = Slic3r::Config::Static::new_FullPrintConfig;
my $config2 = Slic3r::Config->new;
$config2->apply_static($config);
is $config2->get('perimeters'), Slic3r::Config::print_config_def()->{perimeters}{default}, 'apply_static and print_config_def';
$config->set('top_solid_infill_speed', 70);
is $config->get_abs_value('top_solid_infill_speed'), 70, 'get_abs_value() works when ratio_over references a floatOrPercent option';
}
{
my $config = Slic3r::Config->new;
$config->set('fill_pattern', 'line');
my $config2 = Slic3r::Config->new;
$config2->set('fill_pattern', 'hilbertcurve');
is $config->get('fill_pattern'), 'line', 'no interferences between DynamicConfig objects';
}
{
my $config = Slic3r::Config->new;
# the pair [0,0] is part of the test, since it checks whether the 0x0 serialized value is correctly parsed
$config->set('extruder_offset', [ [0,0], [20,0], [0,20] ]);
my $config2 = Slic3r::Config->new;
$config2->apply($config);
is_deeply [ map $_->pp, @{$config->get('extruder_offset')} ], [ map $_->pp, @{$config2->get('extruder_offset')} ],
'apply dynamic over dynamic';
}
{
my $config = Slic3r::Config->new;
$config->set('extruder', 2);
$config->set('perimeter_extruder', 3);
$config->normalize_fdm;
ok !$config->has('extruder'), 'extruder option is removed after normalize()';
is $config->get('infill_extruder'), 2, 'undefined extruder is populated with default extruder';
is $config->get('perimeter_extruder'), 3, 'defined extruder is not overwritten by default extruder';
}
{
my $config = Slic3r::Config->new;
$config->set('infill_extruder', 2);
$config->normalize_fdm;
is $config->get('solid_infill_extruder'), 2, 'undefined solid infill extruder is populated with infill extruder';
}
{
my $config = Slic3r::Config->new;
$config->set('spiral_vase', 1);
$config->set('retract_layer_change', [1,0]);
$config->normalize_fdm;
is_deeply $config->get('retract_layer_change'), [0,0], 'retract_layer_change is disabled with spiral_vase';
}
{
use Cwd qw(abs_path);
use File::Basename qw(dirname);
my $path = abs_path($0);
my $config = Slic3r::Config::load(dirname($path)."/inc/22_config_bad_config_options.ini");
ok 1, 'did not crash on reading invalid items in config';
}
__END__

27
xs/t/17_boundingbox.t Normal file
View file

@ -0,0 +1,27 @@
#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 5;
{
my @points = (
Slic3r::Point->new(100, 200),
Slic3r::Point->new(500, -600),
);
my $bb = Slic3r::Geometry::BoundingBox->new_from_points(\@points);
isa_ok $bb, 'Slic3r::Geometry::BoundingBox', 'new_from_points';
is_deeply $bb->min_point->pp, [100,-600], 'min_point';
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

@ -0,0 +1,7 @@
# generated by Slic3r 1.1.7 on Tue Aug 19 21:49:50 2014
avoid_crossing_perimeters = 1
bed_size = 200,180
g0 = 0
perimeter_acceleration = 0
support_material_extruder = 1
support_material_extrusion_width = 0

118
xs/xsp/BoundingBox.xsp Normal file
View file

@ -0,0 +1,118 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/Point.hpp"
%}
%name{Slic3r::Geometry::BoundingBox} class BoundingBox {
BoundingBox();
~BoundingBox();
Clone<BoundingBox> clone()
%code{% RETVAL = THIS; %};
void merge(BoundingBox* bb) %code{% THIS->merge(*bb); %};
void merge_point(Point* point) %code{% THIS->merge(*point); %};
void scale(double factor);
void translate(double x, double y);
void offset(double delta);
bool contains_point(Point* point) %code{% RETVAL = THIS->contains(*point); %};
bool overlap(BoundingBox* bbox) %code{% RETVAL = THIS->overlap(*bbox); %};
Clone<Polygon> polygon();
Clone<Point> size();
Clone<Point> center();
bool empty() %code{% RETVAL = empty(*THIS); %};
double radius();
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
int x_min() %code{% RETVAL = THIS->min(0); %};
int x_max() %code{% RETVAL = THIS->max(0); %};
int y_min() %code{% RETVAL = THIS->min(1); %};
int y_max() %code{% RETVAL = THIS->max(1); %};
void set_x_min(double val) %code{% THIS->min(0) = val; %};
void set_x_max(double val) %code{% THIS->max(0) = val; %};
void set_y_min(double val) %code{% THIS->min(1) = val; %};
void set_y_max(double val) %code{% THIS->max(1) = val; %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min(0), THIS->min(1), THIS->max(0), THIS->max(1)); RETVAL = buf; %};
bool defined() %code{% RETVAL = THIS->defined; %};
%{
BoundingBox*
new_from_points(CLASS, points)
char* CLASS
Points points
CODE:
RETVAL = new BoundingBox(points);
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Geometry::BoundingBoxf} class BoundingBoxf {
BoundingBoxf();
~BoundingBoxf();
Clone<BoundingBoxf> clone()
%code{% RETVAL = THIS; %};
void merge(BoundingBoxf* bb) %code{% THIS->merge(*bb); %};
void merge_point(Vec2d* point) %code{% THIS->merge(*point); %};
void scale(double factor);
void translate(double x, double y);
Clone<Vec2d> size();
Clone<Vec2d> center();
double radius();
bool empty() %code{% RETVAL = empty(*THIS); %};
Clone<Vec2d> min_point() %code{% RETVAL = THIS->min; %};
Clone<Vec2d> max_point() %code{% RETVAL = THIS->max; %};
double x_min() %code{% RETVAL = THIS->min(0); %};
double x_max() %code{% RETVAL = THIS->max(0); %};
double y_min() %code{% RETVAL = THIS->min(1); %};
double y_max() %code{% RETVAL = THIS->max(1); %};
void set_x_min(double val) %code{% THIS->min(0) = val; %};
void set_x_max(double val) %code{% THIS->max(0) = val; %};
void set_y_min(double val) %code{% THIS->min(1) = val; %};
void set_y_max(double val) %code{% THIS->max(1) = val; %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf;%lf,%lf", THIS->min(0), THIS->min(1), THIS->max(0), THIS->max(1)); RETVAL = buf; %};
bool defined() %code{% RETVAL = THIS->defined; %};
%{
BoundingBoxf*
new_from_points(CLASS, points)
char* CLASS
Pointfs points
CODE:
RETVAL = new BoundingBoxf(points);
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Geometry::BoundingBoxf3} class BoundingBoxf3 {
BoundingBoxf3();
~BoundingBoxf3();
Clone<BoundingBoxf3> clone()
%code{% RETVAL = THIS; %};
void merge(BoundingBoxf3* bb) %code{% THIS->merge(*bb); %};
void merge_point(Vec3d* point) %code{% THIS->merge(*point); %};
void scale(double factor);
void translate(double x, double y, double z);
void offset(double delta);
bool contains_point(Vec3d* point) %code{% RETVAL = THIS->contains(*point); %};
Clone<Vec3d> size();
Clone<Vec3d> center();
double radius();
bool empty() %code{% RETVAL = empty(*THIS); %};
Clone<Vec3d> min_point() %code{% RETVAL = THIS->min; %};
Clone<Vec3d> max_point() %code{% RETVAL = THIS->max; %};
double x_min() %code{% RETVAL = THIS->min(0); %};
double x_max() %code{% RETVAL = THIS->max(0); %};
double y_min() %code{% RETVAL = THIS->min(1); %};
double y_max() %code{% RETVAL = THIS->max(1); %};
double z_min() %code{% RETVAL = THIS->min(2); %};
double z_max() %code{% RETVAL = THIS->max(2); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf;%lf,%lf,%lf", THIS->min(0), THIS->min(1), THIS->min(2), THIS->max(0), THIS->max(1), THIS->max(2)); RETVAL = buf; %};
bool defined() %code{% RETVAL = THIS->defined; %};
};

43
xs/xsp/BridgeDetector.xsp Normal file
View file

@ -0,0 +1,43 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/BridgeDetector.hpp"
%}
%name{Slic3r::BridgeDetector} class BridgeDetector {
~BridgeDetector();
bool detect_angle();
Polygons coverage();
%name{coverage_by_angle} Polygons coverage(double angle);
Polylines unsupported_edges();
%name{unsupported_edges_by_angle} Polylines unsupported_edges(double angle);
double angle()
%code{% RETVAL = THIS->angle; %};
double resolution()
%code{% RETVAL = THIS->resolution; %};
%{
BridgeDetector*
BridgeDetector::new(expolygon, lower_slices, extrusion_width)
ExPolygon* expolygon;
ExPolygonCollection* lower_slices;
int extrusion_width;
CODE:
RETVAL = new BridgeDetector(*expolygon, lower_slices->expolygons, extrusion_width);
OUTPUT:
RETVAL
BridgeDetector*
BridgeDetector::new_expolygons(expolygons, lower_slices, extrusion_width)
ExPolygonCollection* expolygons;
ExPolygonCollection* lower_slices;
int extrusion_width;
CODE:
RETVAL = new BridgeDetector(expolygons->expolygons, lower_slices->expolygons, extrusion_width);
OUTPUT:
RETVAL
%}
};

132
xs/xsp/Clipper.xsp Normal file
View file

@ -0,0 +1,132 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ClipperUtils.hpp"
%}
%package{Slic3r::Geometry::Clipper};
%{
IV
_constant()
ALIAS:
JT_MITER = jtMiter
JT_ROUND = jtRound
JT_SQUARE = jtSquare
CODE:
RETVAL = ix;
OUTPUT: RETVAL
Polygons
offset(polygons, delta, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta
Slic3r::ClipperLib::JoinType joinType
double miterLimit
CODE:
RETVAL = offset(polygons, delta, joinType, miterLimit);
OUTPUT:
RETVAL
ExPolygons
offset_ex(polygons, delta, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta
Slic3r::ClipperLib::JoinType joinType
double miterLimit
CODE:
RETVAL = offset_ex(polygons, delta, joinType, miterLimit);
OUTPUT:
RETVAL
ExPolygons
offset2_ex(polygons, delta1, delta2, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
Polygons polygons
const float delta1
const float delta2
Slic3r::ClipperLib::JoinType joinType
double miterLimit
CODE:
RETVAL = offset2_ex(union_ex(polygons), delta1, delta2, joinType, miterLimit);
OUTPUT:
RETVAL
Polygons
diff(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
RETVAL = diff(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
OUTPUT:
RETVAL
ExPolygons
diff_ex(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
RETVAL = diff_ex(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
OUTPUT:
RETVAL
Polylines
diff_pl(subject, clip)
Polylines subject
Polygons clip
CODE:
RETVAL = diff_pl(subject, clip);
OUTPUT:
RETVAL
Polygons
intersection(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
RETVAL = intersection(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
OUTPUT:
RETVAL
ExPolygons
intersection_ex(subject, clip, safety_offset = false)
Polygons subject
Polygons clip
bool safety_offset
CODE:
RETVAL = intersection_ex(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
OUTPUT:
RETVAL
Polylines
intersection_pl(subject, clip)
Polylines subject
Polygons clip
CODE:
RETVAL = intersection_pl(subject, clip);
OUTPUT:
RETVAL
Polygons
union(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
RETVAL = safety_offset ? union_safety_offset(subject) : union_(subject);
OUTPUT:
RETVAL
ExPolygons
union_ex(subject, safety_offset = false)
Polygons subject
bool safety_offset
CODE:
RETVAL = safety_offset ? union_safety_offset_ex(subject) : union_ex(subject);
OUTPUT:
RETVAL
%}

222
xs/xsp/Config.xsp Normal file
View file

@ -0,0 +1,222 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/PrintConfig.hpp"
%}
%name{Slic3r::Config} class DynamicPrintConfig {
DynamicPrintConfig();
~DynamicPrintConfig();
static DynamicPrintConfig* new_from_defaults()
%code{% RETVAL = DynamicPrintConfig::new_from_defaults_keys(FullPrintConfig::defaults().keys()); %};
static DynamicPrintConfig* new_from_defaults_keys(std::vector<std::string> keys);
DynamicPrintConfig* clone() %code{% RETVAL = new DynamicPrintConfig(*THIS); %};
DynamicPrintConfig* clone_only(std::vector<std::string> keys)
%code{% RETVAL = new DynamicPrintConfig(); RETVAL->apply_only(*THIS, keys, true); %};
bool has(t_config_option_key opt_key);
SV* as_hash()
%code{% RETVAL = ConfigBase__as_hash(THIS); %};
SV* get(t_config_option_key opt_key)
%code{% RETVAL = ConfigBase__get(THIS, opt_key); %};
SV* get_at(t_config_option_key opt_key, int i)
%code{% RETVAL = ConfigBase__get_at(THIS, opt_key, i); %};
SV* get_value(t_config_option_key opt_key)
%code{%
const ConfigOptionDef *def = THIS->def()->get(opt_key);
RETVAL = (def != nullptr && ! def->ratio_over.empty()) ?
newSVnv(THIS->get_abs_value(opt_key)) :
ConfigBase__get(THIS, opt_key);
%};
bool set(t_config_option_key opt_key, SV* value)
%code{% RETVAL = ConfigBase__set(THIS, opt_key, value); %};
bool set_deserialize(t_config_option_key opt_key, SV* str)
%code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %};
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false)
%code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %};
std::string opt_serialize(t_config_option_key opt_key);
double get_abs_value(t_config_option_key opt_key);
%name{get_abs_value_over}
double get_abs_value(t_config_option_key opt_key, double ratio_over);
void apply(DynamicPrintConfig* other)
%code{% THIS->apply(*other, true); %};
std::vector<std::string> diff(DynamicPrintConfig* other)
%code{% RETVAL = THIS->diff(*other); %};
bool equals(DynamicPrintConfig* other)
%code{% RETVAL = THIS->equals(*other); %};
void apply_static(StaticPrintConfig* other)
%code{% THIS->apply(*other, true); %};
%name{get_keys} std::vector<std::string> keys();
void erase(t_config_option_key opt_key);
void normalize_fdm();
%name{setenv} void setenv_();
double min_object_distance() %code{% RETVAL = Slic3r::min_object_distance(*THIS); %};
static DynamicPrintConfig* load(char *path)
%code%{
auto config = new DynamicPrintConfig();
try {
config->load(path, ForwardCompatibilitySubstitutionRule::Disable);
RETVAL = config;
} catch (std::exception& e) {
delete config;
croak("Error extracting configuration from %s:\n%s\n", path, e.what());
}
%};
void save(std::string file);
int validate() %code%{
std::string err = THIS->validate();
if (! err.empty())
croak("Configuration is not valid: %s\n", err.c_str());
RETVAL = 1;
%};
};
%name{Slic3r::Config::Static} class StaticPrintConfig {
static StaticPrintConfig* new_GCodeConfig()
%code{% RETVAL = new GCodeConfig(); %};
static StaticPrintConfig* new_PrintConfig()
%code{% RETVAL = static_cast<GCodeConfig*>(new PrintConfig()); %};
static StaticPrintConfig* new_PrintObjectConfig()
%code{% RETVAL = new PrintObjectConfig(); %};
static StaticPrintConfig* new_PrintRegionConfig()
%code{% RETVAL = new PrintRegionConfig(); %};
static StaticPrintConfig* new_FullPrintConfig()
%code{% RETVAL = static_cast<GCodeConfig*>(new FullPrintConfig()); %};
~StaticPrintConfig();
bool has(t_config_option_key opt_key);
SV* as_hash()
%code{% RETVAL = ConfigBase__as_hash(THIS); %};
SV* get(t_config_option_key opt_key)
%code{% RETVAL = ConfigBase__get(THIS, opt_key); %};
SV* get_at(t_config_option_key opt_key, int i)
%code{% RETVAL = ConfigBase__get_at(THIS, opt_key, i); %};
bool set(t_config_option_key opt_key, SV* value)
%code{% RETVAL = StaticConfig__set(THIS, opt_key, value); %};
bool set_deserialize(t_config_option_key opt_key, SV* str)
%code{% RETVAL = ConfigBase__set_deserialize(THIS, opt_key, str); %};
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false)
%code{% ConfigBase__set_ifndef(THIS, opt_key, value, deserialize); %};
std::string opt_serialize(t_config_option_key opt_key);
double get_abs_value(t_config_option_key opt_key);
%name{get_abs_value_over}
double get_abs_value(t_config_option_key opt_key, double ratio_over);
void apply_static(StaticPrintConfig* other)
%code{% THIS->apply(*other, true); %};
void apply_dynamic(DynamicPrintConfig* other)
%code{% THIS->apply(*other, true); %};
%name{get_keys} std::vector<std::string> keys();
std::string get_extrusion_axis()
%code{%
if (GCodeConfig* config = dynamic_cast<GCodeConfig*>(THIS)) {
RETVAL = get_extrusion_axis(*config);
} else {
CONFESS("This StaticConfig object does not provide get_extrusion_axis()");
}
%};
%name{setenv} void setenv_();
double min_object_distance() %code{% RETVAL = Slic3r::min_object_distance(*THIS); %};
static StaticPrintConfig* load(char *path)
%code%{
auto config = new FullPrintConfig();
try {
config->load(path, ForwardCompatibilitySubstitutionRule::Disable);
RETVAL = static_cast<GCodeConfig*>(config);
} catch (std::exception& e) {
delete config;
croak("Error extracting configuration from %s:\n%s\n", path, e.what());
}
%};
void save(std::string file);
};
%package{Slic3r::Config};
%{
PROTOTYPES: DISABLE
SV*
print_config_def()
CODE:
t_optiondef_map &def = *const_cast<t_optiondef_map*>(&Slic3r::print_config_def.options);
HV* options_hv = newHV();
for (t_optiondef_map::iterator oit = def.begin(); oit != def.end(); ++oit) {
HV* hv = newHV();
t_config_option_key opt_key = oit->first;
ConfigOptionDef* optdef = &oit->second;
const char* opt_type;
if (optdef->type == coFloat || optdef->type == coFloats || optdef->type == coFloatOrPercent) {
opt_type = "f";
} else if (optdef->type == coPercent || optdef->type == coPercents) {
opt_type = "percent";
} else if (optdef->type == coInt || optdef->type == coInts) {
opt_type = "i";
} else if (optdef->type == coString) {
opt_type = "s";
} else if (optdef->type == coStrings) {
opt_type = "s@";
} else if (optdef->type == coPoint || optdef->type == coPoints) {
opt_type = "point";
} else if (optdef->type == coPoint3) {
opt_type = "point3";
} else if (optdef->type == coBool || optdef->type == coBools) {
opt_type = "bool";
} else if (optdef->type == coEnum) {
opt_type = "select";
} else {
throw "Unknown option type";
}
(void)hv_stores( hv, "type", newSVpv(opt_type, 0) );
(void)hv_stores( hv, "height", newSViv(optdef->height) );
(void)hv_stores( hv, "width", newSViv(optdef->width) );
(void)hv_stores( hv, "min", newSViv(optdef->min) );
(void)hv_stores( hv, "max", newSViv(optdef->max) );
// aliases
if (!optdef->aliases.empty()) {
AV* av = newAV();
av_fill(av, optdef->aliases.size()-1);
for (std::vector<t_config_option_key>::iterator it = optdef->aliases.begin(); it != optdef->aliases.end(); ++it)
av_store(av, it - optdef->aliases.begin(), newSVpvn(it->c_str(), it->length()));
(void)hv_stores( hv, "aliases", newRV_noinc((SV*)av) );
}
// shortcut
if (!optdef->shortcut.empty()) {
AV* av = newAV();
av_fill(av, optdef->shortcut.size()-1);
for (std::vector<t_config_option_key>::iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it)
av_store(av, it - optdef->shortcut.begin(), newSVpvn(it->c_str(), it->length()));
(void)hv_stores( hv, "shortcut", newRV_noinc((SV*)av) );
}
// enum_values
if (!optdef->enum_values.empty()) {
AV* av = newAV();
av_fill(av, optdef->enum_values.size()-1);
for (std::vector<std::string>::iterator it = optdef->enum_values.begin(); it != optdef->enum_values.end(); ++it)
av_store(av, it - optdef->enum_values.begin(), newSVpvn(it->c_str(), it->length()));
(void)hv_stores( hv, "values", newRV_noinc((SV*)av) );
}
// enum_labels
if (!optdef->enum_labels.empty()) {
AV* av = newAV();
av_fill(av, optdef->enum_labels.size()-1);
for (std::vector<std::string>::iterator it = optdef->enum_labels.begin(); it != optdef->enum_labels.end(); ++it)
av_store(av, it - optdef->enum_labels.begin(), newSVpvn_utf8(it->c_str(), it->length(), true));
(void)hv_stores( hv, "labels", newRV_noinc((SV*)av) );
}
if (optdef->default_value)
(void)hv_stores( hv, "default", ConfigOption_to_SV(*optdef->default_value.get(), *optdef) );
(void)hv_store( options_hv, opt_key.c_str(), opt_key.length(), newRV_noinc((SV*)hv), 0 );
}
RETVAL = newRV_noinc((SV*)options_hv);
OUTPUT:
RETVAL
%}

59
xs/xsp/ExPolygon.xsp Normal file
View file

@ -0,0 +1,59 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExPolygon.hpp"
%}
%name{Slic3r::ExPolygon} class ExPolygon {
~ExPolygon();
Clone<ExPolygon> clone()
%code{% RETVAL = THIS; %};
SV* arrayref()
%code{% RETVAL = to_AV(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
Ref<Polygon> contour()
%code{% RETVAL = &(THIS->contour); %};
Polygons* holes()
%code{% RETVAL = &(THIS->holes); %};
void scale(double factor);
void translate(double x, double y);
double area();
bool is_valid();
bool contains_line(Line* line)
%code{% RETVAL = THIS->contains(*line); %};
bool contains_polyline(Polyline* polyline)
%code{% RETVAL = THIS->contains(*polyline); %};
bool contains_point(Point* point)
%code{% RETVAL = THIS->contains(*point); %};
ExPolygons simplify(double tolerance);
Polygons simplify_p(double tolerance);
Polylines medial_axis(double max_width, double min_width)
%code{% THIS->medial_axis(max_width, min_width, &RETVAL); %};
%{
ExPolygon*
ExPolygon::new(...)
CODE:
RETVAL = new ExPolygon ();
// ST(0) is class name, ST(1) is contour and others are holes
from_SV_check(ST(1), &RETVAL->contour);
RETVAL->holes.resize(items-2);
for (unsigned int i = 2; i < items; i++) {
from_SV_check(ST(i), &RETVAL->holes[i-2]);
}
OUTPUT:
RETVAL
void
ExPolygon::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
from_SV_check(center_sv, &center);
THIS->rotate(angle, center);
%}
};

View file

@ -0,0 +1,81 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExPolygonCollection.hpp"
%}
%name{Slic3r::ExPolygon::Collection} class ExPolygonCollection {
~ExPolygonCollection();
Clone<ExPolygonCollection> clone()
%code{% RETVAL = THIS; %};
void clear()
%code{% THIS->expolygons.clear(); %};
void scale(double factor);
void translate(double x, double y);
void rotate(double angle, Point* center)
%code{% THIS->rotate(angle, *center); %};
int count()
%code{% RETVAL = THIS->expolygons.size(); %};
bool contains_point(Point* point)
%code{% RETVAL = THIS->contains(*point); %};
bool contains_line(Line* line)
%code{% RETVAL = THIS->contains(*line); %};
bool contains_polyline(Polyline* polyline)
%code{% RETVAL = THIS->contains(*polyline); %};
void simplify(double tolerance);
Polygons polygons()
%code{% RETVAL = (Polygons)*THIS; %};
Clone<Polygon> convex_hull();
%{
ExPolygonCollection*
ExPolygonCollection::new(...)
CODE:
RETVAL = new ExPolygonCollection ();
// ST(0) is class name, others are expolygons
RETVAL->expolygons.resize(items-1);
for (unsigned int i = 1; i < items; i++) {
// Note: a COPY of the input is stored
from_SV_check(ST(i), &RETVAL->expolygons[i-1]);
}
OUTPUT:
RETVAL
SV*
ExPolygonCollection::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->expolygons.size()-1);
int i = 0;
for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) {
av_store(av, i++, perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
SV*
ExPolygonCollection::pp()
CODE:
AV* av = newAV();
av_fill(av, THIS->expolygons.size()-1);
int i = 0;
for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) {
av_store(av, i++, to_SV_pureperl(&*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
void
ExPolygonCollection::append(...)
CODE:
for (unsigned int i = 1; i < items; i++) {
ExPolygon expolygon;
from_SV_check(ST(i), &expolygon);
THIS->expolygons.push_back(expolygon);
}
%}
};

View file

@ -0,0 +1,106 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExtrusionEntityCollection.hpp"
%}
%name{Slic3r::ExtrusionPath::Collection} class ExtrusionEntityCollection {
%name{_new} ExtrusionEntityCollection();
~ExtrusionEntityCollection();
Clone<ExtrusionEntityCollection> clone()
%code{% RETVAL = (ExtrusionEntityCollection*)THIS->clone(); %};
void reverse();
void clear();
ExtrusionEntityCollection* chained_path(bool no_reverse, ExtrusionRole role = erMixed)
%code{%
if (no_reverse)
croak("no_reverse must be false");
RETVAL = new ExtrusionEntityCollection();
*RETVAL = THIS->chained_path_from(THIS->entities.front()->first_point());
%};
ExtrusionEntityCollection* chained_path_from(Point* start_near, bool no_reverse, ExtrusionRole role = erMixed)
%code{%
if (no_reverse)
croak("no_reverse must be false");
RETVAL = new ExtrusionEntityCollection();
*RETVAL = THIS->chained_path_from(*start_near, role);
%};
Clone<Point> first_point();
Clone<Point> last_point();
int count()
%code{% RETVAL = THIS->entities.size(); %};
int items_count()
%code{% RETVAL = THIS->items_count(); %};
ExtrusionEntityCollection* flatten()
%code{%
RETVAL = new ExtrusionEntityCollection();
*RETVAL = THIS->flatten();
%};
double min_mm3_per_mm();
bool empty()
%code{% RETVAL = THIS->entities.empty(); %};
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
%{
SV*
ExtrusionEntityCollection::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->entities.size()-1);
int i = 0;
for (ExtrusionEntitiesPtr::iterator it = THIS->entities.begin(); it != THIS->entities.end(); ++it) {
SV* sv = newSV(0);
// return our item by reference
if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(*it)) {
sv_setref_pv( sv, perl_class_name_ref(path), path );
} else if (ExtrusionMultiPath* multipath = dynamic_cast<ExtrusionMultiPath*>(*it)) {
sv_setref_pv( sv, perl_class_name_ref(multipath), multipath );
} else if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(*it)) {
sv_setref_pv( sv, perl_class_name_ref(loop), loop );
} else if (ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(*it)) {
sv_setref_pv( sv, perl_class_name_ref(collection), collection );
} else {
croak("Unexpected type in ExtrusionEntityCollection");
}
av_store(av, i++, sv);
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
void
ExtrusionEntityCollection::append(...)
CODE:
for (unsigned int i = 1; i < items; i++) {
if(!sv_isobject( ST(i) ) || (SvTYPE(SvRV( ST(i) )) != SVt_PVMG)) {
croak("Argument %d is not object", i);
}
ExtrusionEntity* entity = (ExtrusionEntity *)SvIV((SV*)SvRV( ST(i) ));
// append COPIES
if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(entity)) {
THIS->entities.push_back( new ExtrusionPath(*path) );
} else if (ExtrusionMultiPath* multipath = dynamic_cast<ExtrusionMultiPath*>(entity)) {
THIS->entities.push_back( new ExtrusionMultiPath(*multipath) );
} else if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(entity)) {
THIS->entities.push_back( new ExtrusionLoop(*loop) );
} else if(ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(entity)) {
THIS->entities.push_back( collection->clone() );
} else {
croak("Argument %d is of unknown type", i);
}
}
bool
ExtrusionEntityCollection::no_sort(...)
CODE:
if (items > 1) {
THIS->no_sort = SvTRUE(ST(1));
}
RETVAL = THIS->no_sort;
OUTPUT:
RETVAL
%}
};

65
xs/xsp/ExtrusionLoop.xsp Normal file
View file

@ -0,0 +1,65 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExtrusionEntity.hpp"
%}
%name{Slic3r::ExtrusionLoop} class ExtrusionLoop {
ExtrusionLoop();
~ExtrusionLoop();
Clone<ExtrusionLoop> clone()
%code{% RETVAL = THIS; %};
void reverse();
bool make_clockwise();
bool make_counter_clockwise();
Clone<Point> first_point();
Clone<Point> last_point();
Clone<Polygon> polygon();
void append(ExtrusionPath* path)
%code{% THIS->paths.push_back(*path); %};
double length();
bool split_at_vertex(Point* point)
%code{% RETVAL = THIS->split_at_vertex(*point); %};
void split_at(Point* point, int prefer_non_overhang = 0)
%code{% THIS->split_at(*point, prefer_non_overhang != 0); %};
ExtrusionPaths clip_end(double distance)
%code{% THIS->clip_end(distance, &RETVAL); %};
bool has_overhang_point(Point* point)
%code{% RETVAL = THIS->has_overhang_point(*point); %};
ExtrusionRole role() const;
ExtrusionLoopRole loop_role() const;
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
%{
SV*
ExtrusionLoop::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->paths.size()-1);
for (ExtrusionPaths::iterator it = THIS->paths.begin(); it != THIS->paths.end(); ++it) {
av_store(av, it - THIS->paths.begin(), perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
%}
};
%package{Slic3r::ExtrusionLoop};
%{
IV
_constant()
ALIAS:
EXTRL_ROLE_DEFAULT = elrDefault
EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER = elrContourInternalPerimeter
EXTRL_ROLE_SKIRT = elrSkirt
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

View file

@ -0,0 +1,38 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExtrusionEntity.hpp"
%}
%name{Slic3r::ExtrusionMultiPath} class ExtrusionMultiPath {
ExtrusionMultiPath();
~ExtrusionMultiPath();
Clone<ExtrusionMultiPath> clone()
%code{% RETVAL = THIS; %};
void reverse();
Clone<Point> first_point();
Clone<Point> last_point();
void append(ExtrusionPath* path)
%code{% THIS->paths.push_back(*path); %};
double length();
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
Clone<Polyline> polyline()
%code{% RETVAL = THIS->as_polyline(); %};
%{
SV*
ExtrusionMultiPath::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->paths.size()-1);
for (ExtrusionPaths::iterator it = THIS->paths.begin(); it != THIS->paths.end(); ++it) {
av_store(av, it - THIS->paths.begin(), perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
%}
};

142
xs/xsp/ExtrusionPath.xsp Normal file
View file

@ -0,0 +1,142 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp"
%}
%name{Slic3r::ExtrusionPath} class ExtrusionPath {
~ExtrusionPath();
SV* arrayref()
%code{% RETVAL = to_AV(&THIS->polyline); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(&THIS->polyline); %};
void pop_back()
%code{% THIS->polyline.points.pop_back(); %};
void reverse();
Lines lines()
%code{% RETVAL = THIS->polyline.lines(); %};
Clone<Point> first_point();
Clone<Point> last_point();
void clip_end(double distance);
void simplify(double tolerance);
double length();
ExtrusionRole role() const;
bool is_bridge()
%code{% RETVAL = is_bridge(THIS->role()); %};
Polygons polygons_covered_by_width();
Polygons polygons_covered_by_spacing();
%{
ExtrusionPath*
_new(CLASS, polyline_sv, role, mm3_per_mm, width, height)
char* CLASS;
SV* polyline_sv;
ExtrusionRole role;
double mm3_per_mm;
float width;
float height;
CODE:
RETVAL = new ExtrusionPath (role);
from_SV_check(polyline_sv, &RETVAL->polyline);
RETVAL->mm3_per_mm = mm3_per_mm;
RETVAL->width = width;
RETVAL->height = height;
OUTPUT:
RETVAL
Ref<Polyline>
ExtrusionPath::polyline(...)
CODE:
if (items > 1) {
from_SV_check(ST(1), &THIS->polyline);
}
RETVAL = &(THIS->polyline);
OUTPUT:
RETVAL
double
ExtrusionPath::mm3_per_mm(...)
CODE:
if (items > 1) {
THIS->mm3_per_mm = (double)SvNV(ST(1));
}
RETVAL = THIS->mm3_per_mm;
OUTPUT:
RETVAL
float
ExtrusionPath::width(...)
CODE:
if (items > 1) {
THIS->width = (float)SvNV(ST(1));
}
RETVAL = THIS->width;
OUTPUT:
RETVAL
float
ExtrusionPath::height(...)
CODE:
if (items > 1) {
THIS->height = (float)SvNV(ST(1));
}
RETVAL = THIS->height;
OUTPUT:
RETVAL
void
ExtrusionPath::append(...)
CODE:
for (unsigned int i = 1; i < items; i++) {
Point p;
from_SV_check(ST(i), &p);
THIS->polyline.points.push_back(p);
}
ExtrusionEntityCollection*
ExtrusionPath::intersect_expolygons(ExPolygonCollection* collection)
CODE:
RETVAL = new ExtrusionEntityCollection ();
THIS->intersect_expolygons(*collection, RETVAL);
OUTPUT:
RETVAL
ExtrusionEntityCollection*
ExtrusionPath::subtract_expolygons(ExPolygonCollection* collection)
CODE:
RETVAL = new ExtrusionEntityCollection ();
THIS->subtract_expolygons(*collection, RETVAL);
OUTPUT:
RETVAL
%}
};
%package{Slic3r::ExtrusionPath};
%{
IV
_constant()
ALIAS:
EXTR_ROLE_NONE = erNone
EXTR_ROLE_PERIMETER = erPerimeter
EXTR_ROLE_EXTERNAL_PERIMETER = erExternalPerimeter
EXTR_ROLE_OVERHANG_PERIMETER = erOverhangPerimeter
EXTR_ROLE_FILL = erInternalInfill
EXTR_ROLE_SOLIDFILL = erSolidInfill
EXTR_ROLE_TOPSOLIDFILL = erTopSolidInfill
EXTR_ROLE_BRIDGE = erBridgeInfill
EXTR_ROLE_GAPFILL = erGapFill
EXTR_ROLE_SKIRT = erSkirt
EXTR_ROLE_SUPPORTMATERIAL = erSupportMaterial
EXTR_ROLE_SUPPORTMATERIAL_INTERFACE = erSupportMaterialInterface
EXTR_ROLE_MIXED = erMixed
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

View file

@ -0,0 +1,50 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/ExtrusionSimulator.hpp"
%}
%name{Slic3r::ExtrusionSimulator} class ExtrusionSimulator {
~ExtrusionSimulator();
%name{_new} ExtrusionSimulator();
Clone<ExtrusionSimulator> clone()
%code{% RETVAL = THIS; %};
void set_image_size(Point *image_size)
%code{% THIS->set_image_size(*image_size); %};
void set_viewport(BoundingBox *viewport)
%code{% THIS->set_viewport(*viewport); %};
void set_bounding_box(BoundingBox *bbox)
%code{% THIS->set_bounding_box(*bbox); %};
void reset_accumulator();
void extrude_to_accumulator(ExtrusionPath *path, Point *shift, ExtrusionSimulationType simulationType)
%code{% THIS->extrude_to_accumulator(*path, *shift, simulationType); %};
void evaluate_accumulator(ExtrusionSimulationType simulationType);
void* image_ptr()
%code{% RETVAL = const_cast<void*>(const_cast<Slic3r::ExtrusionSimulator*>(THIS)->image_ptr()); %};
%{
%}
};
%package{Slic3r::ExtrusionSimulator};
%{
IV
_constant()
ALIAS:
EXTRSIM_SIMPLE = ExtrusionSimulationSimple
EXTRSIM_DONT_SPREAD = ExtrusionSimulationDontSpread
EXTRSIM_SPREAD_NFULL = ExtrisopmSimulationSpreadNotOverfilled
EXTRSIM_SPREAD_FULL = ExtrusionSimulationSpreadFull
EXTRSIM_SPREAD_EXCESS = ExtrusionSimulationSpreadExcess
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

65
xs/xsp/Filler.xsp Normal file
View file

@ -0,0 +1,65 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Fill/Fill.hpp"
#include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp"
%}
%name{Slic3r::Filler} class Filler {
~Filler();
void set_bounding_box(BoundingBox *bbox)
%code{% THIS->fill->set_bounding_box(*bbox); %};
void set_spacing(coordf_t spacing)
%code{% THIS->fill->spacing = spacing; %};
coordf_t spacing()
%code{% RETVAL = THIS->fill->spacing; %};
void set_layer_id(size_t layer_id)
%code{% THIS->fill->layer_id = layer_id; %};
void set_z(coordf_t z)
%code{% THIS->fill->z = z; %};
void set_angle(float angle)
%code{% THIS->fill->angle = angle; %};
void set_link_max_length(coordf_t len)
%code{% THIS->fill->link_max_length = len; %};
void set_loop_clipping(coordf_t clipping)
%code{% THIS->fill->loop_clipping = clipping; %};
bool use_bridge_flow()
%code{% RETVAL = THIS->fill->use_bridge_flow(); %};
bool no_sort()
%code{% RETVAL = THIS->fill->no_sort(); %};
void set_density(float density)
%code{% THIS->params.density = density; %};
void set_dont_adjust(bool dont_adjust)
%code{% THIS->params.dont_adjust = dont_adjust; %};
PolylineCollection* _fill_surface(Surface *surface)
%code{%
PolylineCollection *pc = NULL;
if (THIS->fill != NULL) {
pc = new PolylineCollection();
pc->polylines = THIS->fill->fill_surface(surface, THIS->params);
}
RETVAL = pc;
%};
%{
Filler*
new_from_type(CLASS, type)
char* CLASS;
std::string type;
CODE:
Filler *filler = new Filler();
filler->fill = Fill::new_from_type(type);
RETVAL = filler;
OUTPUT:
RETVAL
%}
};

60
xs/xsp/Flow.xsp Normal file
View file

@ -0,0 +1,60 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Flow.hpp"
%}
%name{Slic3r::Flow} class Flow {
~Flow();
%name{_new} Flow(float width, float height, float nozzle_diameter);
Clone<Flow> clone()
%code{% RETVAL = THIS; %};
float width();
float height();
float nozzle_diameter();
bool bridge();
float spacing();
int scaled_width();
int scaled_spacing();
double mm3_per_mm();
%{
Flow*
_new_from_width(CLASS, role, width, nozzle_diameter, height)
char* CLASS;
FlowRole role;
std::string width;
float nozzle_diameter;
float height;
CODE:
ConfigOptionFloatOrPercent optwidth;
optwidth.deserialize(width, ForwardCompatibilitySubstitutionRule::Disable);
RETVAL = new Flow(Flow::new_from_config_width(role, optwidth, nozzle_diameter, height));
OUTPUT:
RETVAL
%}
};
%package{Slic3r::Flow};
%{
IV
_constant()
ALIAS:
FLOW_ROLE_EXTERNAL_PERIMETER = frExternalPerimeter
FLOW_ROLE_PERIMETER = frPerimeter
FLOW_ROLE_INFILL = frInfill
FLOW_ROLE_SOLID_INFILL = frSolidInfill
FLOW_ROLE_TOP_SOLID_INFILL = frTopSolidInfill
FLOW_ROLE_SUPPORT_MATERIAL = frSupportMaterial
FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE = frSupportMaterialInterface
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

53
xs/xsp/GCode.xsp Normal file
View file

@ -0,0 +1,53 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/GCode.hpp"
#include "libslic3r/GCode/CoolingBuffer.hpp"
%}
%name{Slic3r::GCode::CoolingBuffer} class CoolingBuffer {
CoolingBuffer(GCode* gcode)
%code{% RETVAL = new CoolingBuffer(*gcode); %};
~CoolingBuffer();
std::string process_layer(std::string gcode, size_t layer_id)
%code{% RETVAL = THIS->process_layer(std::move(gcode), layer_id, true); %};
};
%name{Slic3r::GCode} class GCode {
GCode();
~GCode();
void do_export(Print *print, const char *path)
%code%{
try {
THIS->do_export(print, path);
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
Ref<Vec2d> origin()
%code{% RETVAL = &(THIS->origin()); %};
void set_origin(Vec2d* pointf)
%code{% THIS->set_origin(*pointf); %};
Ref<Point> last_pos()
%code{% RETVAL = &(THIS->last_pos()); %};
unsigned int layer_count() const;
void set_layer_count(unsigned int value);
void set_extruders(std::vector<unsigned int> extruders)
%code{% THIS->writer().set_extruders(extruders); THIS->writer().set_extruder(0); %};
void apply_print_config(StaticPrintConfig* print_config)
%code{%
if (const PrintConfig* config = dynamic_cast<PrintConfig*>(print_config)) {
THIS->apply_print_config(*config);
} else {
CONFESS("A PrintConfig object was not supplied to apply_print_config()");
}
%};
Ref<StaticPrintConfig> config()
%code{% RETVAL = const_cast<StaticPrintConfig*>(static_cast<const StaticPrintConfig*>(static_cast<const PrintObjectConfig*>(&THIS->config()))); %};
};

24
xs/xsp/GCodeSender.xsp Normal file
View file

@ -0,0 +1,24 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/GCodeSender.hpp"
%}
%name{Slic3r::GCode::Sender} class GCodeSender {
GCodeSender();
~GCodeSender();
bool connect(std::string port, unsigned int baud_rate);
void disconnect();
bool is_connected();
bool wait_connected(unsigned int timeout = 3);
int queue_size();
void send(std::string s, bool priority = false);
void pause_queue();
void resume_queue();
void purge_queue(bool priority = false);
std::vector<std::string> purge_log();
std::string getT();
std::string getB();
};

113
xs/xsp/Geometry.xsp Normal file
View file

@ -0,0 +1,113 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Geometry.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp"
#include "libslic3r/ShortestPath.hpp"
%}
%package{Slic3r::Geometry};
Pointfs arrange(size_t total_parts, Vec2d* part, coordf_t dist, BoundingBoxf* bb = NULL)
%code{%
Pointfs points;
if (! Slic3r::Geometry::arrange(total_parts, *part, dist, bb, points))
CONFESS("%zu parts won't fit in your print area!\n", total_parts);
RETVAL = points;
%};
%{
bool
directions_parallel(angle1, angle2)
double angle1
double angle2
CODE:
RETVAL = Slic3r::Geometry::directions_parallel(angle1, angle2);
OUTPUT:
RETVAL
bool
directions_parallel_within(angle1, angle2, max_diff)
double angle1
double angle2
double max_diff
CODE:
RETVAL = Slic3r::Geometry::directions_parallel(angle1, angle2, max_diff);
OUTPUT:
RETVAL
Clone<Polygon>
convex_hull(points)
Points points
CODE:
RETVAL = Slic3r::Geometry::convex_hull(points);
OUTPUT:
RETVAL
std::vector<Points::size_type>
chained_path(points)
Points points
CODE:
RETVAL = chain_points(points);
OUTPUT:
RETVAL
std::vector<Points::size_type>
chained_path_from(points, start_from)
Points points
Point* start_from
CODE:
RETVAL = chain_points(points, start_from);
OUTPUT:
RETVAL
double
rad2deg(angle)
double angle
CODE:
RETVAL = Slic3r::Geometry::rad2deg(angle);
OUTPUT:
RETVAL
double
rad2deg_dir(angle)
double angle
CODE:
RETVAL = Slic3r::Geometry::rad2deg_dir(angle);
OUTPUT:
RETVAL
double
deg2rad(angle)
double angle
CODE:
RETVAL = Slic3r::Geometry::deg2rad(angle);
OUTPUT:
RETVAL
Polygons
simplify_polygons(polygons, tolerance)
Polygons polygons
double tolerance
CODE:
Slic3r::Geometry::simplify_polygons(polygons, tolerance, &RETVAL);
OUTPUT:
RETVAL
IV
_constant()
ALIAS:
X = X
Y = Y
Z = Z
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

119
xs/xsp/Layer.xsp Normal file
View file

@ -0,0 +1,119 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Layer.hpp"
#include "libslic3r/ExPolygonCollection.hpp"
%}
%name{Slic3r::Layer::Region} class LayerRegion {
// owned by Layer, no constructor/destructor
Ref<Layer> layer();
Ref<PrintRegion> region()
%code%{ RETVAL = &THIS->region(); %};
Ref<SurfaceCollection> slices()
%code%{ RETVAL = &THIS->slices; %};
Ref<ExtrusionEntityCollection> thin_fills()
%code%{ RETVAL = &THIS->thin_fills; %};
Ref<SurfaceCollection> fill_surfaces()
%code%{ RETVAL = &THIS->fill_surfaces; %};
Ref<ExtrusionEntityCollection> perimeters()
%code%{ RETVAL = &THIS->perimeters; %};
Ref<ExtrusionEntityCollection> fills()
%code%{ RETVAL = &THIS->fills; %};
Clone<Flow> flow(FlowRole role)
%code%{ RETVAL = THIS->flow(role); %};
void prepare_fill_surfaces();
void make_perimeters(SurfaceCollection* slices, SurfaceCollection* fill_surfaces)
%code%{ THIS->make_perimeters(*slices, fill_surfaces); %};
double infill_area_threshold();
void export_region_slices_to_svg(const char *path) const;
void export_region_fill_surfaces_to_svg(const char *path) const;
void export_region_slices_to_svg_debug(const char *name) const;
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
};
%name{Slic3r::Layer} class Layer {
// owned by PrintObject, no constructor/destructor
Ref<Layer> as_layer()
%code%{ RETVAL = THIS; %};
int id();
void set_id(int id);
Ref<PrintObject> object();
bool slicing_errors()
%code%{ RETVAL = THIS->slicing_errors; %};
coordf_t slice_z()
%code%{ RETVAL = THIS->slice_z; %};
coordf_t print_z()
%code%{ RETVAL = THIS->print_z; %};
coordf_t height()
%code%{ RETVAL = THIS->height; %};
size_t region_count();
Ref<LayerRegion> get_region(int idx);
Ref<LayerRegion> add_region(PrintRegion* print_region);
ExPolygonCollection* slices()
%code%{ RETVAL = new ExPolygonCollection(THIS->lslices); %};
int ptr()
%code%{ RETVAL = (int)(intptr_t)THIS; %};
Ref<SupportLayer> as_support_layer()
%code%{ RETVAL = dynamic_cast<SupportLayer*>(THIS); %};
void make_slices();
void backup_untyped_slices();
void restore_untyped_slices();
void make_perimeters();
void make_fills();
void export_region_slices_to_svg(const char *path);
void export_region_fill_surfaces_to_svg(const char *path);
void export_region_slices_to_svg_debug(const char *name);
void export_region_fill_surfaces_to_svg_debug(const char *name);
};
%name{Slic3r::Layer::Support} class SupportLayer {
// owned by PrintObject, no constructor/destructor
Ref<Layer> as_layer()
%code%{ RETVAL = THIS; %};
Ref<ExPolygonCollection> support_islands()
%code%{ RETVAL = &THIS->support_islands; %};
Ref<ExtrusionEntityCollection> support_fills()
%code%{ RETVAL = &THIS->support_fills; %};
// copies of some Layer methods, because the parameter wrapper code
// gets confused about getting a Layer::Support instead of a Layer
int id();
void set_id(int id);
Ref<PrintObject> object();
bool slicing_errors()
%code%{ RETVAL = THIS->slicing_errors; %};
coordf_t slice_z()
%code%{ RETVAL = THIS->slice_z; %};
coordf_t print_z()
%code%{ RETVAL = THIS->print_z; %};
coordf_t height()
%code%{ RETVAL = THIS->height; %};
size_t region_count();
Ref<LayerRegion> get_region(int idx);
Ref<LayerRegion> add_region(PrintRegion* print_region);
ExPolygonCollection* slices()
%code%{ RETVAL = new ExPolygonCollection(THIS->lslices); %};
void export_region_slices_to_svg(const char *path);
void export_region_fill_surfaces_to_svg(const char *path);
void export_region_slices_to_svg_debug(const char *name);
void export_region_fill_surfaces_to_svg_debug(const char *name);
};

92
xs/xsp/Line.xsp Normal file
View file

@ -0,0 +1,92 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Line.hpp"
#include "libslic3r/Polyline.hpp"
%}
%name{Slic3r::Line} class Line {
~Line();
Clone<Line> clone()
%code{% RETVAL = THIS; %};
SV* arrayref()
%code{% RETVAL = to_AV(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
Ref<Point> a()
%code{% RETVAL=&THIS->a; %};
Ref<Point> b()
%code{% RETVAL=&THIS->b; %};
void reverse();
void scale(double factor);
void translate(double x, double y);
double length();
double atan2_();
double orientation();
double direction();
bool parallel_to(double angle);
bool parallel_to_line(Line* line)
%code{% RETVAL = THIS->parallel_to(*line); %};
Clone<Point> midpoint();
Clone<Point> intersection_infinite(Line* other)
%code{%
Point p;
bool res = THIS->intersection_infinite(*other, &p);
if (!res) CONFESS("Intersection failed");
RETVAL = p;
%};
Polyline* as_polyline()
%code{% RETVAL = new Polyline(THIS->a, THIS->b); %};
Clone<Point> normal();
Clone<Point> vector();
double ccw(Point* point)
%code{% RETVAL = THIS->ccw(*point); %};
%{
Line*
Line::new(...)
CODE:
RETVAL = new Line ();
// ST(0) is class name, ST(1) and ST(2) are endpoints
from_SV_check(ST(1), &RETVAL->a);
from_SV_check(ST(2), &RETVAL->b);
OUTPUT:
RETVAL
void
Line::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
from_SV_check(center_sv, &center);
THIS->rotate(angle, center);
bool
Line::coincides_with(line_sv)
SV* line_sv;
CODE:
Line line;
from_SV_check(line_sv, &line);
RETVAL = (*THIS) == line;
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Linef3} class Linef3 {
Linef3(Vec3d* a, Vec3d* b)
%code{% RETVAL = new Linef3(*a, *b); %};
~Linef3();
Clone<Linef3> clone()
%code{% RETVAL = THIS; %};
Ref<Vec3d> a()
%code{% RETVAL = &THIS->a; %};
Ref<Vec3d> b()
%code{% RETVAL = &THIS->b; %};
Clone<Vec3d> intersect_plane(double z);
void scale(double factor);
};

296
xs/xsp/Model.xsp Normal file
View file

@ -0,0 +1,296 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Model.hpp"
#include "libslic3r/ModelArrange.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/Slicing.hpp"
#include "libslic3r/Format/AMF.hpp"
#include "libslic3r/Format/3mf.hpp"
#include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/STL.hpp"
#include "libslic3r/PresetBundle.hpp"
%}
%name{Slic3r::Model} class Model {
Model();
~Model();
%name{read_from_file} Model(std::string input_file, bool add_default_instances = true)
%code%{
try {
RETVAL = new Model(Model::read_from_file(input_file, nullptr, nullptr, only_if(add_default_instances, Model::LoadAttribute::AddDefaultInstances)));
} catch (std::exception& e) {
croak("Error while opening %s: %s\n", input_file.c_str(), e.what());
}
%};
Clone<Model> clone()
%code%{ RETVAL = THIS; %};
%name{_add_object} Ref<ModelObject> add_object();
Ref<ModelObject> _add_object_clone(ModelObject* other, bool copy_volumes = true)
%code%{ auto ptr = THIS->add_object(*other); if (! copy_volumes) ptr->clear_volumes(); RETVAL = ptr; %};
void delete_object(size_t idx);
void clear_objects();
size_t objects_count()
%code%{ RETVAL = THIS->objects.size(); %};
Ref<ModelObject> get_object(int idx)
%code%{ RETVAL = THIS->objects.at(idx); %};
Ref<ModelMaterial> get_material(t_model_material_id material_id)
%code%{
RETVAL = THIS->get_material(material_id);
if (RETVAL == NULL) {
XSRETURN_UNDEF;
}
%};
%name{add_material} Ref<ModelMaterial> add_material(t_model_material_id material_id);
Ref<ModelMaterial> add_material_clone(t_model_material_id material_id, ModelMaterial* other)
%code%{ RETVAL = THIS->add_material(material_id, *other); %};
bool has_material(t_model_material_id material_id) const
%code%{
RETVAL = (THIS->get_material(material_id) != NULL);
%};
void delete_material(t_model_material_id material_id);
void clear_materials();
std::vector<std::string> material_names() const
%code%{
for (ModelMaterialMap::iterator i = THIS->materials.begin();
i != THIS->materials.end(); ++i)
{
RETVAL.push_back(i->first);
}
%};
size_t material_count() const
%code%{ RETVAL = THIS->materials.size(); %};
bool add_default_instances();
Clone<BoundingBoxf3> bounding_box();
void center_instances_around_point(Vec2d* point)
%code%{ THIS->center_instances_around_point(*point); %};
void translate(double x, double y, double z);
Clone<TriangleMesh> mesh();
ModelObjectPtrs* objects()
%code%{ RETVAL = &THIS->objects; %};
bool arrange_objects(double dist, BoundingBoxf* bb = NULL) %code%{ ArrangeParams ap{scaled(dist)}; if (bb) arrange_objects(*THIS, scaled(*bb), ap); else arrange_objects(*THIS, InfiniteBed{}, ap); %};
void duplicate(unsigned int copies_num, double dist, BoundingBoxf* bb = NULL) %code%{ ArrangeParams ap{scaled(dist)}; if (bb) duplicate(*THIS, copies_num, scaled(*bb), ap); else duplicate(*THIS, copies_num, InfiniteBed{}, ap); %};
void duplicate_objects(unsigned int copies_num, double dist, BoundingBoxf* bb = NULL) %code%{ ArrangeParams ap{scaled(dist)}; if (bb) duplicate_objects(*THIS, copies_num, scaled(*bb), ap); else duplicate_objects(*THIS, copies_num, InfiniteBed{}, ap); %};
void duplicate_objects_grid(unsigned int x, unsigned int y, double dist);
bool looks_like_multipart_object() const;
void convert_multipart_object(unsigned int max_extruders);
bool store_stl(char *path, bool binary)
%code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %};
%{
Model*
load_stl(CLASS, path, object_name)
char* CLASS;
char* path;
char* object_name;
CODE:
RETVAL = new Model();
if (! load_stl(path, RETVAL, object_name)) {
delete RETVAL;
RETVAL = NULL;
}
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Model::Material} class ModelMaterial {
Ref<Model> model()
%code%{ RETVAL = THIS->get_model(); %};
Ref<DynamicPrintConfig> config()
%code%{ RETVAL = &const_cast<DynamicPrintConfig&>(THIS->config.get()); %};
std::string get_attribute(std::string name)
%code%{ if (THIS->attributes.find(name) != THIS->attributes.end()) RETVAL = THIS->attributes[name]; %};
void set_attribute(std::string name, std::string value)
%code%{ THIS->attributes[name] = value; %};
%{
SV*
ModelMaterial::attributes()
CODE:
HV* hv = newHV();
for (t_model_material_attributes::const_iterator attr = THIS->attributes.begin(); attr != THIS->attributes.end(); ++attr) {
(void)hv_store( hv, attr->first.c_str(), attr->first.length(), newSVpv(attr->second.c_str(), attr->second.length()), 0 );
}
RETVAL = (SV*)newRV_noinc((SV*)hv);
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Model::Object} class ModelObject {
ModelVolumePtrs* volumes()
%code%{ RETVAL = &THIS->volumes; %};
ModelInstancePtrs* instances()
%code%{ RETVAL = &THIS->instances; %};
void invalidate_bounding_box();
Clone<TriangleMesh> mesh();
Clone<TriangleMesh> raw_mesh();
Clone<BoundingBoxf3> instance_bounding_box(int idx)
%code%{ RETVAL = THIS->instance_bounding_box(idx, true); %};
Clone<BoundingBoxf3> bounding_box();
%name{_add_volume} Ref<ModelVolume> add_volume(TriangleMesh* mesh)
%code%{ RETVAL = THIS->add_volume(*mesh); %};
Ref<ModelVolume> _add_volume_clone(ModelVolume* other)
%code%{ RETVAL = THIS->add_volume(*other); %};
void delete_volume(size_t idx);
void clear_volumes();
int volumes_count()
%code%{ RETVAL = THIS->volumes.size(); %};
Ref<ModelVolume> get_volume(int idx)
%code%{ RETVAL = THIS->volumes.at(idx); %};
bool move_volume_up(int idx)
%code%{
if (idx > 0 && idx < int(THIS->volumes.size())) {
std::swap(THIS->volumes[idx-1], THIS->volumes[idx]);
RETVAL = true;
} else
RETVAL = false;
%};
bool move_volume_down(int idx)
%code%{
if (idx >= 0 && idx + 1 < int(THIS->volumes.size())) {
std::swap(THIS->volumes[idx+1], THIS->volumes[idx]);
RETVAL = true;
} else
RETVAL = false;
%};
%name{_add_instance} Ref<ModelInstance> add_instance();
Ref<ModelInstance> _add_instance_clone(ModelInstance* other)
%code%{ RETVAL = THIS->add_instance(*other); %};
void delete_last_instance();
void clear_instances();
int instances_count()
%code%{ RETVAL = THIS->instances.size(); %};
std::string name()
%code%{ RETVAL = THIS->name; %};
void set_name(std::string value)
%code%{ THIS->name = value; %};
std::string input_file()
%code%{ RETVAL = THIS->input_file; %};
void set_input_file(std::string value)
%code%{ THIS->input_file = value; %};
Ref<DynamicPrintConfig> config()
%code%{ RETVAL = &const_cast<DynamicPrintConfig&>(THIS->config.get()); %};
Ref<Model> model()
%code%{ RETVAL = THIS->get_model(); %};
Ref<Vec3d> origin_translation()
%code%{ RETVAL = &THIS->origin_translation; %};
void set_origin_translation(Vec3d* point)
%code%{ THIS->origin_translation = *point; %};
void ensure_on_bed();
int materials_count() const;
int facets_count();
void center_around_origin();
void translate(double x, double y, double z);
void scale_xyz(Vec3d* versor)
%code{% THIS->scale(*versor); %};
void rotate(float angle, Vec3d* axis)
%code{% THIS->rotate(angle, *axis); %};
void mirror(Axis axis);
};
%name{Slic3r::Model::Volume} class ModelVolume {
Ref<ModelObject> object()
%code%{ RETVAL = THIS->get_object(); %};
std::string name()
%code%{ RETVAL = THIS->name; %};
void set_name(std::string value)
%code%{ THIS->name = value; %};
t_model_material_id material_id();
void set_material_id(t_model_material_id material_id)
%code%{ THIS->set_material_id(material_id); %};
Ref<ModelMaterial> material();
Ref<DynamicPrintConfig> config()
%code%{ RETVAL = &const_cast<DynamicPrintConfig&>(THIS->config.get()); %};
Ref<TriangleMesh> mesh()
%code%{ RETVAL = &THIS->mesh(); %};
bool modifier()
%code%{ RETVAL = THIS->is_modifier(); %};
void set_modifier(bool modifier)
%code%{ THIS->set_type(modifier ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART); %};
bool model_part()
%code%{ RETVAL = THIS->is_model_part(); %};
bool support_enforcer()
%code%{ RETVAL = THIS->is_support_enforcer(); %};
void set_support_enforcer()
%code%{ THIS->set_type(ModelVolumeType::SUPPORT_ENFORCER); %};
bool support_blocker()
%code%{ RETVAL = THIS->is_support_blocker(); %};
void set_support_blocker()
%code%{ THIS->set_type(ModelVolumeType::SUPPORT_BLOCKER); %};
size_t split(unsigned int max_extruders);
};
%name{Slic3r::Model::Instance} class ModelInstance {
Ref<ModelObject> object()
%code%{ RETVAL = THIS->get_object(); %};
Vec3d* rotation()
%code%{ RETVAL = new Vec3d(THIS->get_rotation(X), THIS->get_rotation(Y), THIS->get_rotation(Z)); %};
Vec3d* scaling_factor()
%code%{ RETVAL = new Vec3d(THIS->get_scaling_factor(X), THIS->get_scaling_factor(Y), THIS->get_scaling_factor(Z)); %};
Vec2d* offset()
%code%{ RETVAL = new Vec2d(THIS->get_offset(X), THIS->get_offset(Y)); %};
void set_rotation(double val)
%code%{ THIS->set_rotation(Z, val); THIS->get_object()->invalidate_bounding_box(); %};
void set_rotations(Vec3d *rotation)
%code%{ THIS->set_rotation(*rotation); THIS->get_object()->invalidate_bounding_box(); %};
void set_scaling_factor(double val)
%code%{ THIS->set_scaling_factor(X, val); THIS->set_scaling_factor(Y, val); THIS->set_scaling_factor(Z, val); THIS->get_object()->invalidate_bounding_box(); %};
void set_scaling_factors(Vec3d *scale)
%code%{ THIS->set_scaling_factor(*scale); THIS->get_object()->invalidate_bounding_box(); %};
void set_offset(Vec2d *offset)
%code%{
THIS->set_offset(X, (*offset)(0));
THIS->set_offset(Y, (*offset)(1));
%};
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
void transform_polygon(Polygon* polygon) const;
};

View file

@ -0,0 +1,40 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/PerimeterGenerator.hpp"
#include "libslic3r/Layer.hpp"
%}
%name{Slic3r::Layer::PerimeterGenerator} class PerimeterGenerator {
PerimeterGenerator(SurfaceCollection* slices, double layer_height, Flow* flow,
StaticPrintConfig* region_config, StaticPrintConfig* object_config,
StaticPrintConfig* print_config, ExtrusionEntityCollection* loops,
ExtrusionEntityCollection* gap_fill,
SurfaceCollection* fill_surfaces)
%code{% RETVAL = new PerimeterGenerator(slices, layer_height, *flow,
dynamic_cast<PrintRegionConfig*>(region_config),
dynamic_cast<PrintObjectConfig*>(object_config),
dynamic_cast<PrintConfig*>(print_config),
false,
loops, gap_fill, fill_surfaces); %};
~PerimeterGenerator();
void set_lower_slices(ExPolygonCollection* lower_slices)
%code{% THIS->lower_slices = &lower_slices->expolygons; %};
void set_layer_id(int layer_id)
%code{% THIS->layer_id = layer_id; %};
void set_perimeter_flow(Flow* flow)
%code{% THIS->perimeter_flow = *flow; %};
void set_ext_perimeter_flow(Flow* flow)
%code{% THIS->ext_perimeter_flow = *flow; %};
void set_overhang_flow(Flow* flow)
%code{% THIS->overhang_flow = *flow; %};
void set_solid_infill_flow(Flow* flow)
%code{% THIS->solid_infill_flow = *flow; %};
Ref<StaticPrintConfig> config()
%code{% RETVAL = THIS->config; %};
void process();
};

View file

@ -0,0 +1,33 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include <vector>
#include "libslic3r/PlaceholderParser.hpp"
%}
%name{Slic3r::GCode::PlaceholderParser} class PlaceholderParser {
PlaceholderParser();
~PlaceholderParser();
void apply_config(DynamicPrintConfig *config)
%code%{ THIS->apply_config(*config); %};
void set(std::string key, int value);
std::string process(std::string str) const
%code%{
try {
RETVAL = THIS->process(str, 0);
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
bool evaluate_boolean_expression(const char *str) const
%code%{
try {
RETVAL = THIS->evaluate_boolean_expression(str, THIS->config());
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
};

138
xs/xsp/Point.xsp Normal file
View file

@ -0,0 +1,138 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Point.hpp"
#include "libslic3r/Line.hpp"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/Polyline.hpp"
%}
%name{Slic3r::Point} class Point {
Point(int _x = 0, int _y = 0);
~Point();
Clone<Point> clone()
%code{% RETVAL=THIS; %};
void scale(double factor)
%code{% *THIS *= factor; %};
void translate(double x, double y)
%code{% *THIS += Point(x, y); %};
SV* arrayref()
%code{% RETVAL = to_SV_pureperl(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
int x()
%code{% RETVAL = (*THIS)(0); %};
int y()
%code{% RETVAL = (*THIS)(1); %};
void set_x(int val)
%code{% (*THIS)(0) = val; %};
void set_y(int val)
%code{% (*THIS)(1) = val; %};
int nearest_point_index(Points points);
Clone<Point> nearest_point(Points points)
%code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %};
double distance_to(Point* point)
%code{% RETVAL = (*point - *THIS).cast<double>().norm(); %};
double distance_to_line(Line* line)
%code{% RETVAL = line->distance_to(*THIS); %};
double perp_distance_to_line(Line* line)
%code{% RETVAL = line->perp_distance_to(*THIS); %};
double ccw(Point* p1, Point* p2)
%code{% RETVAL = THIS->ccw(*p1, *p2); %};
double ccw_angle(Point* p1, Point* p2)
%code{% RETVAL = THIS->ccw_angle(*p1, *p2); %};
Point* projection_onto_polygon(Polygon* polygon)
%code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %};
Point* projection_onto_polyline(Polyline* polyline)
%code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %};
Point* projection_onto_line(Line* line)
%code{% RETVAL = new Point(THIS->projection_onto(*line)); %};
Point* negative()
%code{% RETVAL = new Point(- *THIS); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", (*THIS)(0), (*THIS)(1)); RETVAL = buf; %};
%{
void
Point::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
from_SV_check(center_sv, &center);
THIS->rotate(angle, center);
bool
Point::coincides_with(point_sv)
SV* point_sv;
CODE:
Point point;
from_SV_check(point_sv, &point);
RETVAL = (*THIS) == point;
OUTPUT:
RETVAL
%}
};
%name{Slic3r::Pointf} class Vec2d {
Vec2d(double _x = 0, double _y = 0);
~Vec2d();
Clone<Vec2d> clone()
%code{% RETVAL = THIS; %};
SV* arrayref()
%code{% RETVAL = to_SV_pureperl(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
double x()
%code{% RETVAL = (*THIS)(0); %};
double y()
%code{% RETVAL = (*THIS)(1); %};
void set_x(double val)
%code{% (*THIS)(0) = val; %};
void set_y(double val)
%code{% (*THIS)(1) = val; %};
void translate(double x, double y)
%code{% *THIS += Vec2d(x, y); %};
void scale(double factor)
%code{% *THIS *= factor; %};
void rotate(double angle, Vec2d* center)
%code{% *THIS = Eigen::Translation2d(*center) * Eigen::Rotation2Dd(angle) * Eigen::Translation2d(- *center) * Eigen::Vector2d((*THIS)(0), (*THIS)(1)); %};
Vec2d* negative()
%code{% RETVAL = new Vec2d(- *THIS); %};
Vec2d* vector_to(Vec2d* point)
%code{% RETVAL = new Vec2d(*point - *THIS); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", (*THIS)(0), (*THIS)(1)); RETVAL = buf; %};
};
%name{Slic3r::Pointf3} class Vec3d {
Vec3d(double _x = 0, double _y = 0, double _z = 0);
~Vec3d();
Clone<Vec3d> clone()
%code{% RETVAL = THIS; %};
double x()
%code{% RETVAL = (*THIS)(0); %};
double y()
%code{% RETVAL = (*THIS)(1); %};
double z()
%code{% RETVAL = (*THIS)(2); %};
void set_x(double val)
%code{% (*THIS)(0) = val; %};
void set_y(double val)
%code{% (*THIS)(1) = val; %};
void set_z(double val)
%code{% (*THIS)(2) = val; %};
void translate(double x, double y, double z)
%code{% *THIS += Vec3d(x, y, z); %};
void scale(double factor)
%code{% *THIS *= factor; %};
double distance_to(Vec3d* point)
%code{% RETVAL = (*point - *THIS).norm(); %};
Vec3d* negative()
%code{% RETVAL = new Vec3d(- *THIS); %};
Vec3d* vector_to(Vec3d* point)
%code{% RETVAL = new Vec3d(*point - *THIS); %};
std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", (*THIS)(0), (*THIS)(1), (*THIS)(2)); RETVAL = buf; %};
};

82
xs/xsp/Polygon.xsp Normal file
View file

@ -0,0 +1,82 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/BoundingBox.hpp"
%}
%name{Slic3r::Polygon} class Polygon {
~Polygon();
Clone<Polygon> clone()
%code{% RETVAL = THIS; %};
SV* arrayref()
%code{% RETVAL = to_AV(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
void scale(double factor);
void translate(double x, double y);
void reverse();
Lines lines();
Clone<Polyline> split_at_vertex(Point* point)
%code{% RETVAL = THIS->split_at_vertex(*point); %};
Clone<Polyline> split_at_index(int index);
Clone<Polyline> split_at_first_point();
Points equally_spaced_points(double distance);
double length();
double area();
bool is_counter_clockwise();
bool is_clockwise();
bool make_counter_clockwise();
bool make_clockwise();
bool is_valid();
Clone<Point> first_point();
bool contains_point(Point* point)
%code{% RETVAL = THIS->contains(*point); %};
Polygons simplify(double tolerance);
Polygons triangulate_convex()
%code{% THIS->triangulate_convex(&RETVAL); %};
Clone<Point> centroid();
Clone<BoundingBox> bounding_box();
Points concave_points(double angle);
Points convex_points(double angle);
Clone<Point> point_projection(Point* point)
%code{% RETVAL = THIS->point_projection(*point); %};
Clone<Point> intersection(Line* line)
%code{%
Point p;
(void)THIS->intersection(*line, &p);
RETVAL = p;
%};
Clone<Point> first_intersection(Line* line)
%code{%
Point p;
(void)THIS->first_intersection(*line, &p);
RETVAL = p;
%};
%{
Polygon*
Polygon::new(...)
CODE:
RETVAL = new Polygon ();
// ST(0) is class name, ST(1) is first point
RETVAL->points.resize(items-1);
for (unsigned int i = 1; i < items; i++) {
from_SV_check(ST(i), &RETVAL->points[i-1]);
}
OUTPUT:
RETVAL
void
Polygon::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
from_SV_check(center_sv, &center);
THIS->rotate(angle, center);
%}
};

90
xs/xsp/Polyline.xsp Normal file
View file

@ -0,0 +1,90 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/Polyline.hpp"
%}
%name{Slic3r::Polyline} class Polyline {
~Polyline();
Clone<Polyline> clone()
%code{% RETVAL = THIS; %};
SV* arrayref()
%code{% RETVAL = to_AV(THIS); %};
SV* pp()
%code{% RETVAL = to_SV_pureperl(THIS); %};
void scale(double factor);
void translate(double x, double y);
void pop_back()
%code{% THIS->points.pop_back(); %};
void reverse();
Lines lines();
Clone<Point> first_point();
Clone<Point> last_point();
Points equally_spaced_points(double distance);
double length();
bool is_valid();
void clip_end(double distance);
void clip_start(double distance);
void extend_end(double distance);
void extend_start(double distance);
void simplify(double tolerance);
void split_at(Point* point, Polyline* p1, Polyline* p2)
%code{% THIS->split_at(*point, p1, p2); %};
bool is_straight();
Clone<BoundingBox> bounding_box();
void remove_duplicate_points();
%{
Polyline*
Polyline::new(...)
CODE:
RETVAL = new Polyline ();
// ST(0) is class name, ST(1) is first point
RETVAL->points.resize(items-1);
for (unsigned int i = 1; i < items; i++) {
from_SV_check(ST(i), &RETVAL->points[i-1]);
}
OUTPUT:
RETVAL
void
Polyline::append(...)
CODE:
for (unsigned int i = 1; i < items; i++) {
Point p;
from_SV_check(ST(i), &p);
THIS->points.push_back(p);
}
void
Polyline::append_polyline(polyline)
Polyline* polyline;
CODE:
for (Points::const_iterator it = polyline->points.begin(); it != polyline->points.end(); ++it) {
THIS->points.push_back((*it));
}
void
Polyline::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
from_SV_check(center_sv, &center);
THIS->rotate(angle, center);
Polygons
Polyline::grow(delta, joinType = Slic3r::ClipperLib::jtSquare, miterLimit = 3)
const float delta
Slic3r::ClipperLib::JoinType joinType
double miterLimit
CODE:
RETVAL = offset(*THIS, delta, joinType, miterLimit);
OUTPUT:
RETVAL
%}
};

View file

@ -0,0 +1,81 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r.h"
#include "Polyline.hpp"
#include "ShortestPath.hpp"
%}
%name{Slic3r::Polyline::Collection} class PolylineCollection {
~PolylineCollection();
Clone<PolylineCollection> clone()
%code{% RETVAL = THIS; %};
void clear()
%code{% THIS->polylines.clear(); %};
PolylineCollection* chained_path(bool no_reverse)
%code{%
RETVAL = new PolylineCollection();
RETVAL->polylines = chain_polylines(THIS->polylines, &THIS->polylines.front().first_point());
%};
PolylineCollection* chained_path_from(Point* start_near, bool no_reverse)
%code{%
RETVAL = new PolylineCollection();
RETVAL->polylines = chain_polylines(THIS->polylines, start_near);
%};
int count()
%code{% RETVAL = THIS->polylines.size(); %};
%{
PolylineCollection*
PolylineCollection::new(...)
CODE:
RETVAL = new PolylineCollection ();
// ST(0) is class name, others are Polylines
RETVAL->polylines.resize(items-1);
for (unsigned int i = 1; i < items; i++) {
// Note: a COPY of the input is stored
from_SV_check(ST(i), &RETVAL->polylines[i-1]);
}
OUTPUT:
RETVAL
SV*
PolylineCollection::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->polylines.size()-1);
int i = 0;
for (Polylines::iterator it = THIS->polylines.begin(); it != THIS->polylines.end(); ++it) {
av_store(av, i++, perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
SV*
PolylineCollection::pp()
CODE:
AV* av = newAV();
av_fill(av, THIS->polylines.size()-1);
int i = 0;
for (Polylines::iterator it = THIS->polylines.begin(); it != THIS->polylines.end(); ++it) {
av_store(av, i++, to_SV_pureperl(&*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
void
PolylineCollection::append(...)
CODE:
for (unsigned int i = 1; i < items; i++) {
Polyline polyline;
from_SV_check(ST(i), &polyline);
THIS->polylines.push_back(polyline);
}
%}
};

171
xs/xsp/Print.xsp Normal file
View file

@ -0,0 +1,171 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Print.hpp"
#include "libslic3r/PlaceholderParser.hpp"
%}
%package{Slic3r::Print::State};
%{
IV
_constant()
ALIAS:
STEP_SLICE = posSlice
STEP_PERIMETERS = posPerimeters
STEP_PREPARE_INFILL = posPrepareInfill
STEP_INFILL = posInfill
STEP_SUPPORTMATERIAL = posSupportMaterial
STEP_SKIRTBRIM = psSkirtBrim
STEP_WIPE_TOWER = psWipeTower
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}
%name{Slic3r::Print::Region} class PrintRegion {
// owned by Print, no constructor/destructor
Ref<StaticPrintConfig> config()
%code%{ RETVAL = &THIS->config(); %};
};
%name{Slic3r::Print::Object} class PrintObject {
// owned by Print, no constructor/destructor
Ref<Print> print();
Ref<ModelObject> model_object();
Ref<StaticPrintConfig> config()
%code%{ RETVAL = &THIS->config(); %};
Clone<BoundingBox> bounding_box();
size_t layer_count();
Ref<Layer> get_layer(int idx);
size_t support_layer_count();
Ref<SupportLayer> get_support_layer(int idx);
bool step_done(PrintObjectStep step)
%code%{ RETVAL = THIS->is_step_done(step); %};
void slice();
};
%name{Slic3r::Print} class Print {
Print();
~Print();
Ref<Model> model()
%code%{ RETVAL = const_cast<Model*>(&THIS->model()); %};
Ref<StaticPrintConfig> config()
%code%{ RETVAL = const_cast<GCodeConfig*>(static_cast<const GCodeConfig*>(&THIS->config())); %};
Ref<PlaceholderParser> placeholder_parser()
%code%{ RETVAL = const_cast<PlaceholderParser*>(&THIS->placeholder_parser()); %};
Ref<ExtrusionEntityCollection> skirt()
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->skirt()); %};
Ref<ExtrusionEntityCollection> brim()
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->brim()); %};
// std::string estimated_normal_print_time()
// %code%{ RETVAL = THIS->print_statistics().estimated_normal_print_time; %};
// std::string estimated_silent_print_time()
// %code%{ RETVAL = THIS->print_statistics().estimated_silent_print_time; %};
double total_used_filament()
%code%{ RETVAL = THIS->print_statistics().total_used_filament; %};
double total_extruded_volume()
%code%{ RETVAL = THIS->print_statistics().total_extruded_volume; %};
double total_weight()
%code%{ RETVAL = THIS->print_statistics().total_weight; %};
double total_cost()
%code%{ RETVAL = THIS->print_statistics().total_cost; %};
double total_wipe_tower_cost()
%code%{ RETVAL = THIS->print_statistics().total_wipe_tower_cost; %};
double total_wipe_tower_filament()
%code%{ RETVAL = THIS->print_statistics().total_wipe_tower_filament; %};
int wipe_tower_number_of_toolchanges()
%code%{ RETVAL = THIS->wipe_tower_data().number_of_toolchanges; %};
PrintObjectPtrs* objects()
%code%{ RETVAL = const_cast<PrintObjectPtrs*>(&THIS->objects_mutable()); %};
Ref<PrintObject> get_object(int idx)
%code%{ RETVAL = THIS->objects_mutable()[idx]; %};
size_t object_count()
%code%{ RETVAL = THIS->objects().size(); %};
PrintRegionPtrs* regions()
%code%{ RETVAL = const_cast<PrintRegionPtrs*>(&THIS->print_regions_mutable()); %};
bool step_done(PrintStep step)
%code%{ RETVAL = THIS->is_step_done(step); %};
bool object_step_done(PrintObjectStep step)
%code%{ RETVAL = THIS->is_step_done(step); %};
SV* filament_stats()
%code%{
HV* hv = newHV();
for (std::map<size_t,double>::const_iterator it = THIS->print_statistics().filament_stats.begin(); it != THIS->print_statistics().filament_stats.end(); ++it) {
// stringify extruder_id
std::ostringstream ss;
ss << it->first;
std::string str = ss.str();
(void)hv_store( hv, str.c_str(), str.length(), newSViv(it->second), 0 );
RETVAL = newRV_noinc((SV*)hv);
}
%};
bool has_support_material() const;
void auto_assign_extruders(ModelObject* model_object);
std::string output_filepath(std::string path = "")
%code%{
try {
RETVAL = THIS->output_filepath(path);
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
bool apply(Model *model, DynamicPrintConfig* config)
%code%{
// Touching every config as the Perl bindings does not correctly export ModelConfig,
// therefore the configs have often invalid timestamps.
for (auto obj : model->objects) {
obj->config.touch();
for (auto vol : obj->volumes)
vol->config.touch();
}
for (auto mat : model->materials)
mat.second->config.touch();
RETVAL = THIS->apply(*model, *config);
%};
bool has_infinite_skirt();
std::vector<unsigned int> extruders() const;
int validate() %code%{
std::string err = THIS->validate();
if (! err.empty())
croak("Configuration is not valid: %s\n", err.c_str());
RETVAL = 1;
%};
void set_callback_event(int evt) %code%{
%};
void set_status_silent();
void set_status(int percent, const char *message);
void process() %code%{
try {
THIS->process();
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
void export_gcode(char *path_template) %code%{
try {
THIS->export_gcode(path_template, nullptr);
} catch (std::exception& e) {
croak("%s\n", e.what());
}
%};
};

118
xs/xsp/Surface.xsp Normal file
View file

@ -0,0 +1,118 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/Surface.hpp"
#include "libslic3r/ClipperUtils.hpp"
%}
%name{Slic3r::Surface} class Surface {
~Surface();
Ref<ExPolygon> expolygon()
%code{% RETVAL = &(THIS->expolygon); %};
double thickness()
%code{% RETVAL = THIS->thickness; %};
unsigned short thickness_layers()
%code{% RETVAL = THIS->thickness_layers; %};
double area();
bool is_solid() const;
bool is_external() const;
bool is_internal() const;
bool is_bottom() const;
bool is_bridge() const;
%{
Surface*
_new(CLASS, expolygon, surface_type, thickness, thickness_layers, bridge_angle, extra_perimeters)
char* CLASS;
ExPolygon* expolygon;
SurfaceType surface_type;
double thickness;
unsigned short thickness_layers;
double bridge_angle;
unsigned short extra_perimeters;
CODE:
RETVAL = new Surface (surface_type, *expolygon);
RETVAL->thickness = thickness;
RETVAL->thickness_layers = thickness_layers;
RETVAL->bridge_angle = bridge_angle;
RETVAL->extra_perimeters = extra_perimeters;
// we don't delete expolygon here because it's referenced by a Perl SV
// whose DESTROY will take care of destruction
OUTPUT:
RETVAL
SurfaceType
Surface::surface_type(...)
CODE:
if (items > 1) {
THIS->surface_type = (SurfaceType)SvUV(ST(1));
}
RETVAL = THIS->surface_type;
OUTPUT:
RETVAL
double
Surface::bridge_angle(...)
CODE:
if (items > 1) {
THIS->bridge_angle = (double)SvNV(ST(1));
}
RETVAL = THIS->bridge_angle;
OUTPUT:
RETVAL
unsigned short
Surface::extra_perimeters(...)
CODE:
if (items > 1) {
THIS->extra_perimeters = (double)SvUV(ST(1));
}
RETVAL = THIS->extra_perimeters;
OUTPUT:
RETVAL
Polygons
Surface::polygons()
CODE:
RETVAL.push_back(THIS->expolygon.contour);
for (Polygons::iterator it = THIS->expolygon.holes.begin(); it != THIS->expolygon.holes.end(); ++it) {
RETVAL.push_back((*it));
}
OUTPUT:
RETVAL
Surfaces
Surface::offset(delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
const float delta
Slic3r::ClipperLib::JoinType joinType
double miterLimit
CODE:
surfaces_append(RETVAL, offset_ex(THIS->expolygon, delta, joinType, miterLimit), *THIS);
OUTPUT:
RETVAL
%}
};
%package{Slic3r::Surface};
%{
IV
_constant()
ALIAS:
S_TYPE_TOP = stTop
S_TYPE_BOTTOM = stBottom
S_TYPE_BOTTOMBRIDGE = stBottomBridge
S_TYPE_INTERNAL = stInternal
S_TYPE_INTERNALSOLID = stInternalSolid
S_TYPE_INTERNALBRIDGE = stInternalBridge
S_TYPE_INTERNALVOID = stInternalVoid
S_TYPW_PERIMETER = stPerimeter
PROTOTYPE:
CODE:
RETVAL = ix;
OUTPUT: RETVAL
%}

View file

@ -0,0 +1,84 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/SurfaceCollection.hpp"
%}
%name{Slic3r::Surface::Collection} class SurfaceCollection {
%name{_new} SurfaceCollection();
~SurfaceCollection();
void clear()
%code{% THIS->surfaces.clear(); %};
void append(Surface* surface)
%code{% THIS->surfaces.push_back(*surface); %};
int count()
%code{% RETVAL = THIS->surfaces.size(); %};
void simplify(double tolerance);
%{
SV*
SurfaceCollection::arrayref()
CODE:
AV* av = newAV();
av_fill(av, THIS->surfaces.size()-1);
int i = 0;
for (Surfaces::iterator it = THIS->surfaces.begin(); it != THIS->surfaces.end(); ++it) {
av_store(av, i++, perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
SV*
SurfaceCollection::filter_by_type(surface_type)
SurfaceType surface_type;
CODE:
AV* av = newAV();
for (Surfaces::iterator it = THIS->surfaces.begin(); it != THIS->surfaces.end(); ++it) {
if ((*it).surface_type == surface_type) av_push(av, perl_to_SV_ref(*it));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
void
SurfaceCollection::replace(index, surface)
int index
Surface* surface
CODE:
THIS->surfaces[index] = *surface;
void
SurfaceCollection::set_surface_type(index, surface_type)
int index
SurfaceType surface_type;
CODE:
THIS->surfaces[index].surface_type = surface_type;
SV*
SurfaceCollection::group()
CODE:
// perform grouping
std::vector<SurfacesPtr> groups;
THIS->group(&groups);
// build return arrayref
AV* av = newAV();
av_fill(av, groups.size()-1);
size_t i = 0;
for (std::vector<SurfacesPtr>::iterator it = groups.begin(); it != groups.end(); ++it) {
AV* innerav = newAV();
av_fill(innerav, it->size()-1);
size_t j = 0;
for (SurfacesPtr::iterator it_s = it->begin(); it_s != it->end(); ++it_s) {
av_store(innerav, j++, perl_to_SV_clone_ref(**it_s));
}
av_store(av, i++, newRV_noinc((SV*)innerav));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
%}
};

205
xs/xsp/TriangleMesh.xsp Normal file
View file

@ -0,0 +1,205 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/TriangleMeshSlicer.hpp"
%}
%name{Slic3r::TriangleMesh} class TriangleMesh {
TriangleMesh();
~TriangleMesh();
Clone<TriangleMesh> clone()
%code{% RETVAL = THIS; %};
void write_ascii(char* output_file);
void write_binary(char* output_file);
void scale(float factor);
void scale_xyz(Vec3d* versor)
%code{% THIS->scale(versor->cast<float>()); %};
void translate(float x, float y, float z);
void rotate_x(float angle);
void rotate_y(float angle);
void rotate_z(float angle);
void mirror_x();
void mirror_y();
void mirror_z();
void align_to_origin();
void rotate(double angle, Point* center);
void merge(TriangleMesh* mesh)
%code{% THIS->merge(*mesh); %};
Clone<Polygon> convex_hull();
Clone<BoundingBoxf3> bounding_box();
Clone<Vec3d> center()
%code{% RETVAL = THIS->bounding_box().center(); %};
int facets_count();
%{
void
TriangleMesh::ReadFromPerl(vertices, facets)
SV* vertices
SV* facets
CODE:
std::vector<Slic3r::Vec3f> out_vertices;
{
AV* vertices_av = (AV*)SvRV(vertices);
int number_of_vertices = av_len(vertices_av) + 1;
out_vertices.reserve(number_of_vertices);
for (int i = 0; i < number_of_vertices; ++ i) {
AV* vertex_av = (AV*)SvRV(*av_fetch(vertices_av, i, 0));
out_vertices.push_back(Slic3r::Vec3f(SvNV(*av_fetch(vertex_av, 0, 0)), SvNV(*av_fetch(vertex_av, 1, 0)), SvNV(*av_fetch(vertex_av, 2, 0))));
}
}
std::vector<Slic3r::Vec3i> out_indices;
{
AV* facets_av = (AV*)SvRV(facets);
int number_of_facets = av_len(facets_av) + 1;
out_indices.reserve(number_of_facets);
for (int i = 0; i < number_of_facets; ++ i) {
AV* facet_av = (AV*)SvRV(*av_fetch(facets_av, i, 0));
out_indices.push_back(Slic3r::Vec3i(SvIV(*av_fetch(facet_av, 0, 0)), SvIV(*av_fetch(facet_av, 1, 0)), SvIV(*av_fetch(facet_av, 2, 0))));
}
}
*THIS = TriangleMesh(std::move(out_vertices), std::move(out_indices));
SV*
TriangleMesh::stats()
CODE:
HV* hv = newHV();
(void)hv_stores( hv, "number_of_facets", newSViv(THIS->facets_count()) );
(void)hv_stores( hv, "number_of_parts", newSViv(THIS->stats().number_of_parts) );
(void)hv_stores( hv, "volume", newSVnv(THIS->stats().volume) );
(void)hv_stores( hv, "degenerate_facets", newSViv(THIS->stats().repaired_errors.degenerate_facets) );
(void)hv_stores( hv, "edges_fixed", newSViv(THIS->stats().repaired_errors.edges_fixed) );
(void)hv_stores( hv, "facets_removed", newSViv(THIS->stats().repaired_errors.facets_removed) );
(void)hv_stores( hv, "facets_reversed", newSViv(THIS->stats().repaired_errors.facets_reversed) );
(void)hv_stores( hv, "backwards_edges", newSViv(THIS->stats().repaired_errors.backwards_edges) );
RETVAL = (SV*)newRV_noinc((SV*)hv);
OUTPUT:
RETVAL
SV*
TriangleMesh::vertices()
CODE:
// vertices
AV* vertices = newAV();
av_extend(vertices, THIS->its.vertices.size());
for (size_t i = 0; i < THIS->its.vertices.size(); i++) {
AV* vertex = newAV();
av_store(vertices, i, newRV_noinc((SV*)vertex));
av_extend(vertex, 2);
av_store(vertex, 0, newSVnv(THIS->its.vertices[i](0)));
av_store(vertex, 1, newSVnv(THIS->its.vertices[i](1)));
av_store(vertex, 2, newSVnv(THIS->its.vertices[i](2)));
}
RETVAL = newRV_noinc((SV*)vertices);
OUTPUT:
RETVAL
SV*
TriangleMesh::facets()
CODE:
// facets
AV* facets = newAV();
av_extend(facets, THIS->facets_count());
for (int i = 0; i < THIS->facets_count(); i++) {
AV* facet = newAV();
av_store(facets, i, newRV_noinc((SV*)facet));
av_extend(facet, 2);
av_store(facet, 0, newSVnv(THIS->its.indices[i][0]));
av_store(facet, 1, newSVnv(THIS->its.indices[i][1]));
av_store(facet, 2, newSVnv(THIS->its.indices[i][2]));
}
RETVAL = newRV_noinc((SV*)facets);
OUTPUT:
RETVAL
SV*
TriangleMesh::size()
CODE:
AV* size = newAV();
av_extend(size, 2);
av_store(size, 0, newSVnv(THIS->stats().size(0)));
av_store(size, 1, newSVnv(THIS->stats().size(1)));
av_store(size, 2, newSVnv(THIS->stats().size(2)));
RETVAL = newRV_noinc((SV*)size);
OUTPUT:
RETVAL
SV*
TriangleMesh::slice(z)
std::vector<double> z
CODE:
// convert doubles to floats
std::vector<float> z_f = cast<float>(z);
std::vector<ExPolygons> layers = slice_mesh_ex(THIS->its, z_f, 0.049f);
AV* layers_av = newAV();
size_t len = layers.size();
if (len > 0) av_extend(layers_av, len-1);
for (unsigned int i = 0; i < layers.size(); i++) {
AV* expolygons_av = newAV();
len = layers[i].size();
if (len > 0) av_extend(expolygons_av, len-1);
unsigned int j = 0;
for (ExPolygons::iterator it = layers[i].begin(); it != layers[i].end(); ++it) {
av_store(expolygons_av, j++, perl_to_SV_clone_ref(*it));
}
av_store(layers_av, i, newRV_noinc((SV*)expolygons_av));
}
RETVAL = (SV*)newRV_noinc((SV*)layers_av);
OUTPUT:
RETVAL
void
TriangleMesh::cut(z, upper_mesh, lower_mesh)
float z;
TriangleMesh* upper_mesh;
TriangleMesh* lower_mesh;
CODE:
indexed_triangle_set upper, lower;
cut_mesh(THIS->its, z, upper_mesh ? &upper : nullptr, lower_mesh ? &lower : nullptr);
if (upper_mesh)
*upper_mesh = TriangleMesh(upper);
if (lower_mesh)
*lower_mesh = TriangleMesh(lower);
std::vector<double>
TriangleMesh::bb3()
CODE:
RETVAL.push_back(THIS->stats().min(0));
RETVAL.push_back(THIS->stats().min(1));
RETVAL.push_back(THIS->stats().max(0));
RETVAL.push_back(THIS->stats().max(1));
RETVAL.push_back(THIS->stats().min(2));
RETVAL.push_back(THIS->stats().max(2));
OUTPUT:
RETVAL
Clone<TriangleMesh>
cube(double x, double y, double z)
CODE:
RETVAL = make_cube(x,y,z);
OUTPUT:
RETVAL
Clone<TriangleMesh>
cylinder(double r, double h)
CODE:
RETVAL = make_cylinder(r, h);
OUTPUT:
RETVAL
Clone<TriangleMesh>
sphere(double rho)
CODE:
RETVAL = make_sphere(rho);
OUTPUT:
RETVAL
%}
};

163
xs/xsp/XS.xsp Normal file
View file

@ -0,0 +1,163 @@
%module{Slic3r::XS};
%package{Slic3r::XS};
#include <xsinit.h>
#include "Utils.hpp"
%{
%}
%package{Slic3r};
%{
SV*
VERSION()
CODE:
RETVAL = newSVpv(SLIC3R_VERSION, 0);
OUTPUT: RETVAL
SV*
BUILD()
CODE:
RETVAL = newSVpv(SLIC3R_BUILD_ID, 0);
OUTPUT: RETVAL
SV*
FORK_NAME()
CODE:
RETVAL = newSVpv(SLIC3R_APP_NAME, 0);
OUTPUT: RETVAL
void
set_logging_level(level)
unsigned int level;
CODE:
Slic3r::set_logging_level(level);
void
trace(level, message)
unsigned int level;
char *message;
CODE:
Slic3r::trace(level, message);
void
disable_multi_threading()
CODE:
Slic3r::disable_multi_threading();
void
set_var_dir(dir)
char *dir;
CODE:
Slic3r::set_var_dir(dir);
void
set_local_dir(dir)
char *dir;
CODE:
Slic3r::set_local_dir(dir);
char*
var_dir()
CODE:
RETVAL = const_cast<char*>(Slic3r::var_dir().c_str());
OUTPUT: RETVAL
void
set_resources_dir(dir)
char *dir;
CODE:
Slic3r::set_resources_dir(dir);
char*
resources_dir()
CODE:
RETVAL = const_cast<char*>(Slic3r::resources_dir().c_str());
OUTPUT: RETVAL
std::string
var(file_name)
const char *file_name;
CODE:
RETVAL = Slic3r::var(file_name);
OUTPUT: RETVAL
void
set_data_dir(dir)
char *dir;
CODE:
Slic3r::set_data_dir(dir);
char*
data_dir()
CODE:
RETVAL = const_cast<char*>(Slic3r::data_dir().c_str());
OUTPUT: RETVAL
local_encoded_string
encode_path(src)
const char *src;
CODE:
RETVAL = Slic3r::encode_path(src);
OUTPUT: RETVAL
std::string
decode_path(src)
const char *src;
CODE:
RETVAL = Slic3r::decode_path(src);
OUTPUT: RETVAL
std::string
normalize_utf8_nfc(src)
const char *src;
CODE:
RETVAL = Slic3r::normalize_utf8_nfc(src);
OUTPUT: RETVAL
std::string
path_to_filename(src)
const char *src;
CODE:
RETVAL = Slic3r::PerlUtils::path_to_filename(src);
OUTPUT: RETVAL
local_encoded_string
path_to_filename_raw(src)
const char *src;
CODE:
RETVAL = Slic3r::PerlUtils::path_to_filename(src);
OUTPUT: RETVAL
std::string
path_to_stem(src)
const char *src;
CODE:
RETVAL = Slic3r::PerlUtils::path_to_stem(src);
OUTPUT: RETVAL
std::string
path_to_extension(src)
const char *src;
CODE:
RETVAL = Slic3r::PerlUtils::path_to_extension(src);
OUTPUT: RETVAL
std::string
path_to_parent_path(src)
const char *src;
CODE:
RETVAL = Slic3r::PerlUtils::path_to_parent_path(src);
OUTPUT: RETVAL
void
xspp_test_croak_hangs_on_strawberry()
CODE:
try {
throw 1;
} catch (...) {
croak("xspp_test_croak_hangs_on_strawberry: exception catched\n");
}
%}

550
xs/xsp/my.map Normal file
View file

@ -0,0 +1,550 @@
coordf_t T_NV
std::string T_STD_STRING
local_encoded_string T_STD_STRING_LOCAL_ENCODING
t_config_option_key T_STD_STRING
t_model_material_id T_STD_STRING
std::vector<std::string> T_STD_VECTOR_STD_STRING
std::vector<int> T_STD_VECTOR_INT
std::vector<Points::size_type> T_STD_VECTOR_INT
std::vector<size_t> T_STD_VECTOR_INT
std::vector<unsigned int> T_STD_VECTOR_UINT
std::vector<double> T_STD_VECTOR_DOUBLE
t_layer_height_ranges T_LAYER_HEIGHT_RANGES
BoundingBox* O_OBJECT_SLIC3R
Ref<BoundingBox> O_OBJECT_SLIC3R_T
Clone<BoundingBox> O_OBJECT_SLIC3R_T
BoundingBoxf* O_OBJECT_SLIC3R
Ref<BoundingBoxf> O_OBJECT_SLIC3R_T
Clone<BoundingBoxf> O_OBJECT_SLIC3R_T
BoundingBoxf3* O_OBJECT_SLIC3R
Ref<BoundingBoxf3> O_OBJECT_SLIC3R_T
Clone<BoundingBoxf3> O_OBJECT_SLIC3R_T
DynamicPrintConfig* O_OBJECT_SLIC3R
Ref<DynamicPrintConfig> O_OBJECT_SLIC3R_T
Clone<DynamicPrintConfig> O_OBJECT_SLIC3R_T
StaticPrintConfig* O_OBJECT_SLIC3R
Ref<StaticPrintConfig> O_OBJECT_SLIC3R_T
PrintObjectConfig* O_OBJECT_SLIC3R
Ref<PrintObjectConfig> O_OBJECT_SLIC3R_T
PrintRegionConfig* O_OBJECT_SLIC3R
Ref<PrintRegionConfig> O_OBJECT_SLIC3R_T
GCodeConfig* O_OBJECT_SLIC3R
Ref<GCodeConfig> O_OBJECT_SLIC3R_T
PrintConfig* O_OBJECT_SLIC3R
Ref<PrintConfig> O_OBJECT_SLIC3R_T
FullPrintConfig* O_OBJECT_SLIC3R
Ref<FullPrintConfig> O_OBJECT_SLIC3R_T
ZTable* O_OBJECT
TriangleMesh* O_OBJECT_SLIC3R
Ref<TriangleMesh> O_OBJECT_SLIC3R_T
Clone<TriangleMesh> O_OBJECT_SLIC3R_T
Point* O_OBJECT_SLIC3R
Ref<Point> O_OBJECT_SLIC3R_T
Clone<Point> O_OBJECT_SLIC3R_T
Point3* O_OBJECT_SLIC3R
Ref<Point3> O_OBJECT_SLIC3R_T
Clone<Point3> O_OBJECT_SLIC3R_T
Vec2d* O_OBJECT_SLIC3R
Ref<Vec2d> O_OBJECT_SLIC3R_T
Clone<Vec2d> O_OBJECT_SLIC3R_T
Vec3d* O_OBJECT_SLIC3R
Ref<Vec3d> O_OBJECT_SLIC3R_T
Clone<Vec3d> O_OBJECT_SLIC3R_T
Line* O_OBJECT_SLIC3R
Ref<Line> O_OBJECT_SLIC3R_T
Clone<Line> O_OBJECT_SLIC3R_T
Linef3* O_OBJECT_SLIC3R
Ref<Linef3> O_OBJECT_SLIC3R_T
Clone<Linef3> O_OBJECT_SLIC3R_T
Polyline* O_OBJECT_SLIC3R
Ref<Polyline> O_OBJECT_SLIC3R_T
Clone<Polyline> O_OBJECT_SLIC3R_T
PolylineCollection* O_OBJECT_SLIC3R
Ref<PolylineCollection> O_OBJECT_SLIC3R_T
Clone<PolylineCollection> O_OBJECT_SLIC3R_T
Polygon* O_OBJECT_SLIC3R
Ref<Polygon> O_OBJECT_SLIC3R_T
Clone<Polygon> O_OBJECT_SLIC3R_T
ExPolygon* O_OBJECT_SLIC3R
Ref<ExPolygon> O_OBJECT_SLIC3R_T
Clone<ExPolygon> O_OBJECT_SLIC3R_T
ExPolygonCollection* O_OBJECT_SLIC3R
Ref<ExPolygonCollection> O_OBJECT_SLIC3R_T
Clone<ExPolygonCollection> O_OBJECT_SLIC3R_T
ExtrusionEntityCollection* O_OBJECT_SLIC3R
Ref<ExtrusionEntityCollection> O_OBJECT_SLIC3R_T
Clone<ExtrusionEntityCollection> O_OBJECT_SLIC3R_T
ExtrusionMultiPath* O_OBJECT_SLIC3R
Ref<ExtrusionMultiPath> O_OBJECT_SLIC3R_T
Clone<ExtrusionMultiPath> O_OBJECT_SLIC3R_T
ExtrusionPath* O_OBJECT_SLIC3R
Ref<ExtrusionPath> O_OBJECT_SLIC3R_T
Clone<ExtrusionPath> O_OBJECT_SLIC3R_T
ExtrusionLoop* O_OBJECT_SLIC3R
Ref<ExtrusionLoop> O_OBJECT_SLIC3R_T
Clone<ExtrusionLoop> O_OBJECT_SLIC3R_T
ExtrusionSimulator* O_OBJECT_SLIC3R
Ref<ExtrusionSimulator> O_OBJECT_SLIC3R_T
Clone<ExtrusionSimulator> O_OBJECT_SLIC3R_T
Filler* O_OBJECT_SLIC3R
Ref<Filler> O_OBJECT_SLIC3R_T
Clone<Filler> O_OBJECT_SLIC3R_T
Flow* O_OBJECT_SLIC3R
Ref<Flow> O_OBJECT_SLIC3R_T
Clone<Flow> O_OBJECT_SLIC3R_T
PrintState* O_OBJECT_SLIC3R
Ref<PrintState> O_OBJECT_SLIC3R_T
Surface* O_OBJECT_SLIC3R
Ref<Surface> O_OBJECT_SLIC3R_T
Clone<Surface> O_OBJECT_SLIC3R_T
SurfaceCollection* O_OBJECT_SLIC3R
Ref<SurfaceCollection> O_OBJECT_SLIC3R_T
Model* O_OBJECT_SLIC3R
Ref<Model> O_OBJECT_SLIC3R_T
Clone<Model> O_OBJECT_SLIC3R_T
ModelMaterial* O_OBJECT_SLIC3R
Ref<ModelMaterial> O_OBJECT_SLIC3R_T
Clone<ModelMaterial> O_OBJECT_SLIC3R_T
ModelObject* O_OBJECT_SLIC3R
Ref<ModelObject> O_OBJECT_SLIC3R_T
Clone<ModelObject> O_OBJECT_SLIC3R_T
ModelVolume* O_OBJECT_SLIC3R
Ref<ModelVolume> O_OBJECT_SLIC3R_T
Clone<ModelVolume> O_OBJECT_SLIC3R_T
ModelInstance* O_OBJECT_SLIC3R
Ref<ModelInstance> O_OBJECT_SLIC3R_T
Clone<ModelInstance> O_OBJECT_SLIC3R_T
PrintRegion* O_OBJECT_SLIC3R
Ref<PrintRegion> O_OBJECT_SLIC3R_T
PrintObject* O_OBJECT_SLIC3R
Ref<PrintObject> O_OBJECT_SLIC3R_T
Print* O_OBJECT_SLIC3R
Ref<Print> O_OBJECT_SLIC3R_T
Clone<Print> O_OBJECT_SLIC3R_T
LayerRegion* O_OBJECT_SLIC3R
Ref<LayerRegion> O_OBJECT_SLIC3R_T
Layer* O_OBJECT_SLIC3R
Ref<Layer> O_OBJECT_SLIC3R_T
SupportLayer* O_OBJECT_SLIC3R
Ref<SupportLayer> O_OBJECT_SLIC3R_T
PlaceholderParser* O_OBJECT_SLIC3R
Ref<PlaceholderParser> O_OBJECT_SLIC3R_T
Clone<PlaceholderParser> O_OBJECT_SLIC3R_T
CoolingBuffer* O_OBJECT_SLIC3R
Ref<CoolingBuffer> O_OBJECT_SLIC3R_T
Clone<CoolingBuffer> O_OBJECT_SLIC3R_T
GCode* O_OBJECT_SLIC3R
Ref<GCode> O_OBJECT_SLIC3R_T
Clone<GCode> O_OBJECT_SLIC3R_T
BridgeDetector* O_OBJECT_SLIC3R
Ref<BridgeDetector> O_OBJECT_SLIC3R_T
Clone<BridgeDetector> O_OBJECT_SLIC3R_T
PerimeterGenerator* O_OBJECT_SLIC3R
Ref<PerimeterGenerator> O_OBJECT_SLIC3R_T
Clone<PerimeterGenerator> O_OBJECT_SLIC3R_T
PrintObjectSupportMaterial* O_OBJECT_SLIC3R
Ref<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
Clone<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
Axis T_UV
ExtrusionLoopRole T_UV
ExtrusionRole T_UV
ExtrusionSimulationType T_UV
FlowRole T_UV
PrintStep T_UV
PrintObjectStep T_UV
SurfaceType T_UV
Slic3r::ClipperLib::JoinType T_UV
Slic3r::ClipperLib::PolyFillType T_UV
# we return these types whenever we want the items to be cloned
Points T_ARRAYREF
Pointfs T_ARRAYREF
Lines T_ARRAYREF
Polygons T_ARRAYREF
Polylines T_ARRAYREF
ExPolygons T_ARRAYREF
ExtrusionPaths T_ARRAYREF
Surfaces T_ARRAYREF
# we return these types whenever we want the items to be returned
# by reference and marked ::Ref because they're contained in another
# Perl object
Polygons* T_ARRAYREF_PTR
ModelObjectPtrs* T_PTR_ARRAYREF_PTR
ModelVolumePtrs* T_PTR_ARRAYREF_PTR
ModelInstancePtrs* T_PTR_ARRAYREF_PTR
PrintRegionPtrs* T_PTR_ARRAYREF_PTR
PrintObjectPtrs* T_PTR_ARRAYREF_PTR
LayerPtrs* T_PTR_ARRAYREF_PTR
SupportLayerPtrs* T_PTR_ARRAYREF_PTR
# we return these types whenever we want the items to be returned
# by reference and not marked ::Ref because they're newly allocated
# and not referenced by any Perl object
INPUT
T_STD_STRING
{
size_t len;
// const char * c = SvPV($arg, len);
// Always convert strings to UTF-8 before passing them to XS
const char * c = SvPVutf8($arg, len);
$var = std::string(c, len);
}
INPUT
T_STD_STRING_LOCAL_ENCODING
{
size_t len;
const char * c = SvPV($arg, len);
$var = std::string(c, len);
}
T_STD_VECTOR_STD_STRING
if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) {
AV* av = (AV*)SvRV($arg);
const unsigned int alen = av_len(av)+1;
$var = std::vector<std::string>(alen);
STRLEN len;
char* tmp;
SV** elem;
for (unsigned int i = 0; i < alen; i++) {
elem = av_fetch(av, i, 0);
if (elem != NULL) {
tmp = SvPV(*elem, len);
${var}[i] = std::string(tmp, len);
}
else
${var}[i] = std::string(\"\");
}
}
else
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
T_STD_VECTOR_INT
if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) {
AV* av = (AV*)SvRV($arg);
const unsigned int len = av_len(av)+1;
$var = std::vector<int>(len);
SV** elem;
for (unsigned int i = 0; i < len; i++) {
elem = av_fetch(av, i, 0);
if (elem != NULL)
${var}[i] = SvIV(*elem);
else
${var}[i] = 0;
}
}
else
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
T_STD_VECTOR_UINT
if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) {
AV* av = (AV*)SvRV($arg);
const unsigned int len = av_len(av)+1;
$var = std::vector<unsigned int>(len);
SV** elem;
for (unsigned int i = 0; i < len; i++) {
elem = av_fetch(av, i, 0);
if (elem != NULL)
${var}[i] = SvUV(*elem);
else
${var}[i] = 0;
}
}
else
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
T_STD_VECTOR_DOUBLE
if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) {
AV* av = (AV*)SvRV($arg);
const unsigned int len = av_len(av)+1;
$var = std::vector<double>(len);
SV** elem;
for (unsigned int i = 0; i < len; i++) {
elem = av_fetch(av, i, 0);
if (elem != NULL)
${var}[i] = SvNV(*elem);
else
${var}[i] = 0.;
}
}
else
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
O_OBJECT_SLIC3R
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) {
if ( sv_isa($arg, Slic3r::perl_class_name($var) ) || sv_isa($arg, Slic3r::perl_class_name_ref($var) )) {
$var = ($type)SvIV((SV*)SvRV( $arg ));
} else {
croak(\"$var is not of type %s (got %s)\", Slic3r::perl_class_name($var), HvNAME(SvSTASH(SvRV($arg))));
XSRETURN_UNDEF;
}
} else {
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
XSRETURN_UNDEF;
}
T_ARRAYREF
if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV) {
AV* av = (AV*)SvRV($arg);
const unsigned int len = av_len(av)+1;
$var.resize(len);
for (unsigned int i = 0; i < len; i++) {
SV** elem = av_fetch(av, i, 0);
from_SV_check(*elem, &$var\[i]);
}
} else
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
T_LAYER_HEIGHT_RANGES
{
if (!SvROK($arg) || SvTYPE(SvRV($arg)) != SVt_PVAV) {
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
}
AV* av = (AV*)SvRV($arg);
const unsigned int len = av_len(av)+1;
t_layer_height_ranges tmp_ranges;
for (unsigned int i = 0; i < len; i++) {
SV* elem = *av_fetch(av, i, 0);
if (!SvROK(elem) || SvTYPE(SvRV(elem)) != SVt_PVAV) {
Perl_croak(
aTHX_ \"%s: %s contains something that is not an array reference\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
}
AV* elemAV = (AV*)SvRV(elem);
if (av_len(elemAV) + 1 != 3) {
Perl_croak(
aTHX_ \"%s: %s contains an array that isn't 3 elements long\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
\"$var\");
}
coordf_t vals[3];
for (unsigned int j = 0; j < 3; ++j) {
SV *elem_elem = *av_fetch(elemAV, j, 0);
if (!looks_like_number(elem_elem)) {
Perl_croak(
aTHX_ \"%s: layer ranges and heights must be numbers\",
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]});
}
vals[j] = SvNV(elem_elem);
}
tmp_ranges[t_layer_height_range(vals[0], vals[1])] = vals[2];
}
$var = tmp_ranges;
}
OUTPUT
T_STD_STRING
$arg = newSVpvn_utf8( $var.c_str(), $var.length(), true );
T_STD_STRING_LOCAL_ENCODING
$arg = newSVpvn( $var.c_str(), $var.length() );
T_STD_VECTOR_STD_STRING
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len)
av_extend(av, len-1);
for (unsigned int i = 0; i < len; i++) {
const std::string& str = ${var}[i];
STRLEN len = str.length();
av_store(av, i, newSVpvn_utf8(str.c_str(), len, true));
}
T_STD_VECTOR_INT
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len)
av_extend(av, len-1);
for (unsigned int i = 0; i < len; i++) {
av_store(av, i, newSViv(${var}[i]));
}
T_STD_VECTOR_UINT
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len)
av_extend(av, len-1);
for (unsigned int i = 0; i < len; i++) {
av_store(av, i, newSVuv(${var}[i]));
}
T_STD_VECTOR_DOUBLE
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len)
av_extend(av, len-1);
for (unsigned int i = 0; i < len; i++) {
av_store(av, i, newSVnv(${var}[i]));
}
# return object from pointer
O_OBJECT_SLIC3R
if ($var == NULL)
XSRETURN_UNDEF;
sv_setref_pv( $arg, Slic3r::perl_class_name($var), (void*)$var );
# return value handled by template class
O_OBJECT_SLIC3R_T
if ($var == NULL)
XSRETURN_UNDEF;
sv_setref_pv( $arg, $type\::CLASS(), (void*)$var );
T_ARRAYREF
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len > 0) av_extend(av, len-1);
int i = 0;
for (${type}::const_iterator it = $var.begin(); it != $var.end(); ++it) {
av_store(av, i++, perl_to_SV_clone_ref(*it));
}
T_ARRAYREF_PTR
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var->size();
if (len > 0) av_extend(av, len-1);
int i = 0;
for (${ my $t = $type; $t =~ s/\*$//; \$t }::iterator it = $var->begin(); it != $var->end(); ++it) {
av_store(av, i++, perl_to_SV_ref(*it));
}
T_PTR_ARRAYREF_PTR
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var->size();
if (len > 0) av_extend(av, len-1);
int i = 0;
for (${ my $t = $type; $t =~ s/\*$//; \$t }::iterator it = $var->begin(); it != $var->end(); ++it) {
av_store(av, i++, perl_to_SV_ref(**it));
}
T_PTR_ARRAYREF
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len > 0) av_extend(av, len-1);
int i = 0;
for (${type}::iterator it = $var.begin(); it != $var.end(); ++it) {
av_store(av, i++, to_SV(*it));
}
T_LAYER_HEIGHT_RANGES
AV* av = newAV();
$arg = newRV_noinc((SV*)av);
sv_2mortal($arg);
const unsigned int len = $var.size();
if (len > 0) av_extend(av, len-1);
// map is sorted, so we can just copy it in order
int i = 0;
for (${type}::iterator it = $var.begin(); it != $var.end(); ++it) {
const coordf_t range_values[] = {
it->first.first, // key's first = minz
it->first.second, // key's second = maxz
it->second, // value = height
};
AV *rangeAV = newAV();
av_extend(rangeAV, 2);
for (int j = 0; j < 3; ++j) {
av_store(rangeAV, j, newSVnv(range_values[j]));
}
av_store(av, i++, (SV*)newRV_noinc((SV*)rangeAV));
}

0
xs/xsp/mytype.map Normal file
View file

245
xs/xsp/typemap.xspt Normal file
View file

@ -0,0 +1,245 @@
%typemap{bool}{simple};
%typemap{size_t}{simple};
%typemap{coordf_t}{simple};
%typemap{std::string};
%typemap{t_config_option_key};
%typemap{t_model_material_id};
%typemap{std::vector<int>};
%typemap{std::vector<size_t>};
%typemap{std::vector<unsigned int>*};
%typemap{std::vector<double>};
%typemap{std::vector<double>*};
%typemap{std::vector<unsigned int>};
%typemap{std::vector<unsigned int>*};
%typemap{std::vector<std::string>};
%typemap{t_layer_height_ranges};
%typemap{void*};
%typemap{SV*};
%typemap{AV*};
%typemap{Point*};
%typemap{Ref<Point>}{simple};
%typemap{Clone<Point>}{simple};
%typemap{Point3*};
%typemap{Ref<Point3>}{simple};
%typemap{Clone<Point3>}{simple};
%typemap{Vec2d*};
%typemap{Ref<Vec2d>}{simple};
%typemap{Clone<Vec2d>}{simple};
%typemap{Vec3d*};
%typemap{Ref<Vec3d>}{simple};
%typemap{Clone<Vec3d>}{simple};
%typemap{BoundingBox*};
%typemap{Ref<BoundingBox>}{simple};
%typemap{Clone<BoundingBox>}{simple};
%typemap{BoundingBoxf*};
%typemap{Ref<BoundingBoxf>}{simple};
%typemap{Clone<BoundingBoxf>}{simple};
%typemap{BoundingBoxf3*};
%typemap{Ref<BoundingBoxf3>}{simple};
%typemap{Clone<BoundingBoxf3>}{simple};
%typemap{DynamicPrintConfig*};
%typemap{Ref<DynamicPrintConfig>}{simple};
%typemap{Clone<DynamicPrintConfig>}{simple};
%typemap{StaticPrintConfig*};
%typemap{Ref<StaticPrintConfig>}{simple};
%typemap{PrintObjectConfig*};
%typemap{Ref<PrintObjectConfig>}{simple};
%typemap{PrintRegionConfig*};
%typemap{Ref<PrintRegionConfig>}{simple};
%typemap{GCodeConfig*};
%typemap{Ref<GCodeConfig>}{simple};
%typemap{PrintConfig*};
%typemap{Ref<PrintConfig>}{simple};
%typemap{FullPrintConfig*};
%typemap{Ref<FullPrintConfig>}{simple};
%typemap{ExPolygon*};
%typemap{Ref<ExPolygon>}{simple};
%typemap{Clone<ExPolygon>}{simple};
%typemap{ExPolygonCollection*};
%typemap{Ref<ExPolygonCollection>}{simple};
%typemap{Clone<ExPolygonCollection>}{simple};
%typemap{Filler*};
%typemap{Ref<Filler>}{simple};
%typemap{Clone<Filler>}{simple};
%typemap{Flow*};
%typemap{Ref<Flow>}{simple};
%typemap{Clone<Flow>}{simple};
%typemap{Line*};
%typemap{Ref<Line>}{simple};
%typemap{Clone<Line>}{simple};
%typemap{Linef3*};
%typemap{Ref<Linef3>}{simple};
%typemap{Clone<Linef3>}{simple};
%typemap{Polyline*};
%typemap{Ref<Polyline>}{simple};
%typemap{Clone<Polyline>}{simple};
%typemap{Polygon*};
%typemap{Ref<Polygon>}{simple};
%typemap{Clone<Polygon>}{simple};
%typemap{ExtrusionEntityCollection*};
%typemap{Ref<ExtrusionEntityCollection>}{simple};
%typemap{Clone<ExtrusionEntityCollection>}{simple};
%typemap{ExtrusionMultiPath*};
%typemap{Ref<ExtrusionMultiPath>}{simple};
%typemap{Clone<ExtrusionMultiPath>}{simple};
%typemap{ExtrusionPath*};
%typemap{Ref<ExtrusionPath>}{simple};
%typemap{Clone<ExtrusionPath>}{simple};
%typemap{ExtrusionLoop*};
%typemap{Ref<ExtrusionLoop>}{simple};
%typemap{Clone<ExtrusionLoop>}{simple};
%typemap{ExtrusionSimulator*};
%typemap{Ref<ExtrusionSimulator>}{simple};
%typemap{Clone<ExtrusionSimulator>}{simple};
%typemap{TriangleMesh*};
%typemap{Ref<TriangleMesh>}{simple};
%typemap{Clone<TriangleMesh>}{simple};
%typemap{PolylineCollection*};
%typemap{Ref<PolylineCollection>}{simple};
%typemap{Clone<PolylineCollection>}{simple};
%typemap{BridgeDetector*};
%typemap{Ref<BridgeDetector>}{simple};
%typemap{Clone<BridgeDetector>}{simple};
%typemap{SurfaceCollection*};
%typemap{Ref<SurfaceCollection>}{simple};
%typemap{Clone<SurfaceCollection>}{simple};
%typemap{PerimeterGenerator*};
%typemap{Ref<PerimeterGenerator>}{simple};
%typemap{Clone<PerimeterGenerator>}{simple};
%typemap{Surface*};
%typemap{Ref<Surface>}{simple};
%typemap{Clone<Surface>}{simple};
%typemap{PrintState*};
%typemap{Ref<PrintState>}{simple};
%typemap{PrintRegion*};
%typemap{Ref<PrintRegion>}{simple};
%typemap{PrintObject*};
%typemap{Ref<PrintObject>}{simple};
%typemap{Print*};
%typemap{Ref<Print>}{simple};
%typemap{Clone<Print>}{simple};
%typemap{LayerRegion*};
%typemap{Ref<LayerRegion>}{simple};
%typemap{Layer*};
%typemap{Ref<Layer>}{simple};
%typemap{SupportLayer*};
%typemap{Ref<SupportLayer>}{simple};
%typemap{PrintObjectSupportMaterial*};
%typemap{Ref<PrintObjectSupportMaterial>}{simple};
%typemap{Clone<PrintObjectSupportMaterial>}{simple};
%typemap{PlaceholderParser*};
%typemap{Ref<PlaceholderParser>}{simple};
%typemap{Clone<PlaceholderParser>}{simple};
%typemap{CoolingBuffer*};
%typemap{Ref<CoolingBuffer>}{simple};
%typemap{Clone<CoolingBuffer>}{simple};
%typemap{GCode*};
%typemap{Ref<GCode>}{simple};
%typemap{Clone<GCode>}{simple};
//%typemap{GCodePreviewData*};
//%typemap{Ref<GCodePreviewData>}{simple};
//%typemap{Clone<GCodePreviewData>}{simple};
%typemap{Points};
%typemap{Pointfs};
%typemap{Lines};
%typemap{Polygons};
%typemap{Polylines};
%typemap{ExPolygons};
%typemap{ExtrusionPaths};
%typemap{Surfaces};
%typemap{Polygons*};
%typemap{TriangleMesh*};
%typemap{Model*};
%typemap{Ref<Model>}{simple};
%typemap{Clone<Model>}{simple};
%typemap{ModelMaterial*};
%typemap{Ref<ModelMaterial>}{simple};
%typemap{Clone<ModelMaterial>}{simple};
%typemap{ModelObject*};
%typemap{Ref<ModelObject>}{simple};
%typemap{Clone<ModelObject>}{simple};
%typemap{ModelObjectPtrs*};
%typemap{Ref<ModelObjectPtrs>}{simple};
%typemap{Clone<ModelObjectPtrs>}{simple};
%typemap{ModelVolume*};
%typemap{Ref<ModelVolume>}{simple};
%typemap{Clone<ModelVolume>}{simple};
%typemap{ModelVolumePtrs*};
%typemap{Ref<ModelVolumePtrs>}{simple};
%typemap{Clone<ModelVolumePtrs>}{simple};
%typemap{ModelInstance*};
%typemap{Ref<ModelInstance>}{simple};
%typemap{Clone<ModelInstance>}{simple};
%typemap{ModelInstancePtrs*};
%typemap{Ref<ModelInstancePtrs>}{simple};
%typemap{Clone<ModelInstancePtrs>}{simple};
%typemap{PresetHints*};
%typemap{Ref<PresetHints>}{simple};
%typemap{PrintRegionPtrs*};
%typemap{PrintObjectPtrs*};
%typemap{LayerPtrs*};
%typemap{SupportLayerPtrs*};
%typemap{Axis}{parsed}{
%cpp_type{Axis};
%precall_code{%
$CVar = (Axis)SvUV($PerlVar);
%};
};
%typemap{SurfaceType}{parsed}{
%cpp_type{SurfaceType};
%precall_code{%
$CVar = (SurfaceType)SvUV($PerlVar);
%};
};
%typemap{ExtrusionLoopRole}{parsed}{
%cpp_type{ExtrusionLoopRole};
%precall_code{%
$CVar = (ExtrusionLoopRole)SvUV($PerlVar);
%};
};
%typemap{ExtrusionRole}{parsed}{
%cpp_type{ExtrusionRole};
%precall_code{%
$CVar = (ExtrusionRole)SvUV($PerlVar);
%};
};
%typemap{ExtrusionSimulationType}{parsed}{
%cpp_type{ExtrusionSimulationType};
%precall_code{%
$CVar = (ExtrusionSimulationType)SvUV($PerlVar);
%};
};
%typemap{FlowRole}{parsed}{
%cpp_type{FlowRole};
%precall_code{%
$CVar = (FlowRole)SvUV($PerlVar);
%};
};
%typemap{PrintStep}{parsed}{
%cpp_type{PrintStep};
%precall_code{%
$CVar = (PrintStep)SvUV($PerlVar);
%};
};
%typemap{PrintObjectStep}{parsed}{
%cpp_type{PrintObjectStep};
%precall_code{%
$CVar = (PrintObjectStep)SvUV($PerlVar);
%};
};