mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-10 07:15:08 -06:00
Add the full source of BambuStudio
using version 1.0.10
This commit is contained in:
parent
30bcadab3e
commit
1555904bef
3771 changed files with 1251328 additions and 0 deletions
212
xs/CMakeLists.txt
Normal file
212
xs/CMakeLists.txt
Normal 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
303
xs/lib/Slic3r/XS.pm
Normal 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
27
xs/main.xs.in
Normal 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
549
xs/src/perlglue.cpp
Normal 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
7063
xs/src/ppport.h
Normal file
File diff suppressed because it is too large
Load diff
259
xs/src/xsinit.h
Normal file
259
xs/src/xsinit.h
Normal 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
35
xs/t/01_trianglemesh.t
Normal 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
84
xs/t/03_point.t
Normal 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
108
xs/t/04_expolygon.t
Normal 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
76
xs/t/05_surface.t
Normal 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
21
xs/t/06_polygon.t
Normal 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
38
xs/t/07_extrusionpath.t
Normal 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
158
xs/t/08_extrusionloop.t
Normal 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
128
xs/t/09_polyline.t
Normal 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
81
xs/t/10_line.t
Normal 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__
|
97
xs/t/12_extrusionpathcollection.t
Normal file
97
xs/t/12_extrusionpathcollection.t
Normal 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__
|
35
xs/t/13_polylinecollection.t
Normal file
35
xs/t/13_polylinecollection.t
Normal 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
252
xs/t/15_config.t
Normal 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
27
xs/t/17_boundingbox.t
Normal 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__
|
7
xs/t/inc/22_config_bad_config_options.ini
Normal file
7
xs/t/inc/22_config_bad_config_options.ini
Normal 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
118
xs/xsp/BoundingBox.xsp
Normal 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
43
xs/xsp/BridgeDetector.xsp
Normal 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
132
xs/xsp/Clipper.xsp
Normal 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
222
xs/xsp/Config.xsp
Normal 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
59
xs/xsp/ExPolygon.xsp
Normal 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, ¢er);
|
||||
THIS->rotate(angle, center);
|
||||
|
||||
%}
|
||||
};
|
81
xs/xsp/ExPolygonCollection.xsp
Normal file
81
xs/xsp/ExPolygonCollection.xsp
Normal 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);
|
||||
}
|
||||
|
||||
%}
|
||||
};
|
106
xs/xsp/ExtrusionEntityCollection.xsp
Normal file
106
xs/xsp/ExtrusionEntityCollection.xsp
Normal 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
65
xs/xsp/ExtrusionLoop.xsp
Normal 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
|
||||
|
||||
%}
|
38
xs/xsp/ExtrusionMultiPath.xsp
Normal file
38
xs/xsp/ExtrusionMultiPath.xsp
Normal 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
142
xs/xsp/ExtrusionPath.xsp
Normal 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
|
||||
|
||||
%}
|
||||
|
50
xs/xsp/ExtrusionSimulator.xsp
Normal file
50
xs/xsp/ExtrusionSimulator.xsp
Normal 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
65
xs/xsp/Filler.xsp
Normal 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
60
xs/xsp/Flow.xsp
Normal 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
53
xs/xsp/GCode.xsp
Normal 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
24
xs/xsp/GCodeSender.xsp
Normal 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
113
xs/xsp/Geometry.xsp
Normal 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
119
xs/xsp/Layer.xsp
Normal 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
92
xs/xsp/Line.xsp
Normal 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, ¢er);
|
||||
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
296
xs/xsp/Model.xsp
Normal 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;
|
||||
};
|
40
xs/xsp/PerimeterGenerator.xsp
Normal file
40
xs/xsp/PerimeterGenerator.xsp
Normal 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();
|
||||
};
|
33
xs/xsp/PlaceholderParser.xsp
Normal file
33
xs/xsp/PlaceholderParser.xsp
Normal 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
138
xs/xsp/Point.xsp
Normal 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, ¢er);
|
||||
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
82
xs/xsp/Polygon.xsp
Normal 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, ¢er);
|
||||
THIS->rotate(angle, center);
|
||||
|
||||
%}
|
||||
};
|
90
xs/xsp/Polyline.xsp
Normal file
90
xs/xsp/Polyline.xsp
Normal 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, ¢er);
|
||||
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
|
||||
|
||||
%}
|
||||
};
|
81
xs/xsp/PolylineCollection.xsp
Normal file
81
xs/xsp/PolylineCollection.xsp
Normal 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
171
xs/xsp/Print.xsp
Normal 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
118
xs/xsp/Surface.xsp
Normal 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
|
||||
|
||||
%}
|
||||
|
84
xs/xsp/SurfaceCollection.xsp
Normal file
84
xs/xsp/SurfaceCollection.xsp
Normal 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
205
xs/xsp/TriangleMesh.xsp
Normal 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
163
xs/xsp/XS.xsp
Normal 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
550
xs/xsp/my.map
Normal 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
0
xs/xsp/mytype.map
Normal file
245
xs/xsp/typemap.xspt
Normal file
245
xs/xsp/typemap.xspt
Normal 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);
|
||||
%};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue