Merge remote-tracking branch 'origin/master' into gsoc2016-refactored

This commit is contained in:
Marius Kintel 2016-10-29 18:50:57 -04:00
commit 38f107f6d5
52 changed files with 2901 additions and 31 deletions

View file

@ -26,8 +26,8 @@ notifications:
skip_join: true
before_install:
- if [[ "$DIST" == "trusty" ]]; then wget -qO - http://files.openscad.org/OBS-Repository-Key.pub | sudo apt-key add - ; echo 'yes' | sudo add-apt-repository 'deb http://download.opensuse.org/repositories/home:/t-paul:/lib3mf/xUbuntu_14.04/ ./' ; sudo apt-get update -qq ; sudo apt-get purge -qq fglrx ; sudo apt-get install -qq build-essential libqt4-dev libqt4-opengl-dev libxmu-dev cmake bison flex git-core libboost-all-dev libXi-dev libmpfr-dev libboost-dev libglew-dev libeigen3-dev libcgal-dev libgmp3-dev libgmp-dev curl imagemagick libfontconfig-dev libopencsg-dev libharfbuzz-dev lib3mf-dev ; fi
- if [[ "$DIST" == "precise" ]]; then echo 'yes' | sudo add-apt-repository ppa:chrysn/openscad ; sudo apt-get update -qq ; sudo apt-get purge -qq fglrx ; sudo apt-get install -qq build-essential libqt4-dev libqt4-opengl-dev libxmu-dev cmake bison flex git-core libboost-all-dev libXi-dev libmpfr-dev libboost-dev libglew-dev libeigen3-dev libcgal-dev libgmp3-dev libgmp-dev curl imagemagick libfontconfig-dev ; sudo apt-get install -qq libopencsg-dev ; echo 'yes' | sudo add-apt-repository ppa:mapnik/nightly-trunk ; sudo apt-get update -qq ; sudo apt-get install -qq libharfbuzz-dev ; echo 'yes' | sudo add-apt-repository ppa:oibaf/graphics-drivers ; sudo apt-get update -qq ; sudo apt-get install --install-recommends libgl1-mesa-dev-lts-quantal ; fi
- if [[ "$DIST" == "trusty" ]]; then wget -qO - http://files.openscad.org/OBS-Repository-Key.pub | sudo apt-key add - ; echo 'yes' | sudo add-apt-repository 'deb http://download.opensuse.org/repositories/home:/t-paul:/lib3mf/xUbuntu_14.04/ ./' ; sudo apt-get update -qq ; sudo apt-get purge -qq fglrx ; sudo apt-get install -qq build-essential libqt4-dev libqt4-opengl-dev libxmu-dev cmake bison flex git-core libboost-all-dev libXi-dev libmpfr-dev libboost-dev libglew-dev libeigen3-dev libcgal-dev libgmp3-dev libgmp-dev curl imagemagick libfontconfig-dev libopencsg-dev libharfbuzz-dev libzip-dev lib3mf-dev ; fi
- if [[ "$DIST" == "precise" ]]; then echo 'yes' | sudo add-apt-repository ppa:chrysn/openscad ; sudo apt-get update -qq ; sudo apt-get purge -qq fglrx ; sudo apt-get install -qq build-essential libqt4-dev libqt4-opengl-dev libxmu-dev cmake bison flex git-core libboost-all-dev libXi-dev libmpfr-dev libboost-dev libglew-dev libeigen3-dev libcgal-dev libgmp3-dev libgmp-dev curl imagemagick libfontconfig-dev ; sudo apt-get install -qq libopencsg-dev ; echo 'yes' | sudo add-apt-repository ppa:mapnik/nightly-trunk ; sudo apt-get update -qq ; sudo apt-get install -qq libharfbuzz-dev libzip-dev ; echo 'yes' | sudo add-apt-repository ppa:oibaf/graphics-drivers ; sudo apt-get update -qq ; sudo apt-get install --install-recommends libgl1-mesa-dev-lts-quantal ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; ./scripts/macosx-build-homebrew.sh ; fi
branches:

View file

@ -83,6 +83,16 @@
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>amf</string>
</array>
<key>CFBundleTypeName</key>
<string>AMF file</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>NSAppleScriptEnabled</key>
<true/>

View file

@ -21,3 +21,4 @@ include(freetype.pri)
include(fontconfig.pri)
include(scintilla.pri)
include(c++11.pri)
include(libzip.pri)

38
libzip.pri Normal file
View file

@ -0,0 +1,38 @@
# Detect libzip, then use this priority list to determine
# which library to use:
#
# Priority
# 1. LIBZIP_INCLUDEPATH / LIBZIP_LIBPATH (qmake parameter, not checked it given on commandline)
# 3. system's standard include paths from pkg-config
libzip {
exists($$LIBZIP_INCLUDEPATH/zip.h) {
ENABLE_LIBZIP=yes
} else {
LIBZIP_INCLUDEPATH =
LIBZIP_LIBPATH =
}
isEmpty(LIBZIP_INCLUDEPATH) {
LIBZIP_CFLAGS = $$system("pkg-config --cflags libzip")
!isEmpty(LIBZIP_CFLAGS) {
ENABLE_LIBZIP=yes
}
} else {
LIBZIP_CFLAGS = -I$$LIBZIP_INCLUDEPATH
}
isEmpty(LIBZIP_LIBPATH) {
LIBZIP_LIBS = $$system("pkg-config --libs libzip")
} else {
LIBZIP_LIBS = -L$$LIBZIP_LIBPATH -lzip
}
!isEmpty(ENABLE_LIBZIP) {
DEFINES += ENABLE_LIBZIP
QMAKE_CXXFLAGS += $$LIBZIP_CFLAGS
LIBS += $$LIBZIP_LIBS
}
}

View file

@ -184,6 +184,7 @@ CONFIG += freetype
CONFIG += fontconfig
CONFIG += gettext
CONFIG += libxml2
CONFIG += libzip
#Uncomment the following line to enable the QScintilla editor
!nogui {
@ -503,6 +504,7 @@ SOURCES += \
src/import_stl.cc \
src/import_off.cc \
src/import_svg.cc \
src/import_amf.cc \
src/renderer.cc \
src/colormap.cc \
src/ThrownTogetherRenderer.cc \

View file

@ -48,6 +48,7 @@ PACKAGES=(
"freetype 2.6.3"
"ragel 6.9"
"harfbuzz 1.2.7"
"libzip 1.1.3"
"libxml2 2.9.4"
"fontconfig 2.12.0"
)
@ -272,7 +273,7 @@ build_gmp()
fi
tar xjf gmp-$version.tar.bz2
cd gmp-$version
./configure --prefix=$DEPLOYDIR CXXFLAGS="$CXXSTDFLAGS" CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS="$LDSTDFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" ABI=64 --enable-cxx
./configure --prefix=$DEPLOYDIR CXXFLAGS="$CXXSTDFLAGS" CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN" LDFLAGS="$LDSTDFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN" --enable-cxx
make -j"$NUMCPU" install
install_name_tool -id @rpath/libgmp.dylib $DEPLOYDIR/lib/libgmp.dylib
@ -554,6 +555,29 @@ build_freetype()
install_name_tool -id @rpath/libfreetype.dylib $DEPLOYDIR/lib/libfreetype.dylib
}
check_libzip()
{
check_file lib/libzip.dylib
}
build_libzip()
{
version="$1"
echo "Building libzip $version..."
cd "$BASEDIR"/src
rm -rf "libzip-$version"
if [ ! -f "libxml2-$version.tar.gz" ]; then
curl --insecure -LO "https://nih.at/libzip/libzip-1.1.3.tar.gz"
fi
tar xzf "libzip-$version.tar.gz"
cd "libzip-$version"
./configure --prefix="$DEPLOYDIR" CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN
make -j$NUMCPU
make install
install_name_tool -id @rpath/libzip.dylib $DEPLOYDIR/lib/libzip.dylib
}
check_libxml2()
{
check_file lib/libxml2.dylib
@ -571,7 +595,7 @@ build_libxml2()
fi
tar xzf "libxml2-$version.tar.gz"
cd "libxml2-$version"
./configure --prefix="$DEPLOYDIR" --with-zlib=/usr -without-lzma --without-ftp --without-http --without-python CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN
./configure --prefix="$DEPLOYDIR" --with-zlib=/usr -with-lzma --without-ftp --without-http --without-python CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN
make -j$NUMCPU
make install
install_name_tool -id @rpath/libxml2.dylib $DEPLOYDIR/lib/libxml2.dylib

View file

@ -15,21 +15,44 @@ printUsage()
echo "Usage: $0"
}
log()
{
echo "$(date):" "$@"
}
if [ ! -f $OPENSCADDIR/openscad.pro ]; then
echo "Must be run from the OpenSCAD source root directory"
exit 0
fi
log "Listing homebrew configuration"
brew config
log "Updating homebrew"
brew update
# Install special packages not yet in upstream homebrew repo.
# Check if there's already an active openscad tap and skip
# tap/untap in that case.
TAP=:
if ! brew tap | grep ^openscad/ >/dev/null 2>/dev/null
then
log "Tapping openscad homebrew repo"
TAP=brew
fi
$TAP tap openscad/homebrew-tap
# FIXME: We used to require unlinking boost, but doing so also causes us to lose boost.
# Disabling until we can figure out why we unlinked in the first place
# brew unlink boost
for formula in eigen boost cgal glew glib opencsg freetype libxml2 fontconfig harfbuzz qt5 qscintilla2 imagemagick; do
for formula in eigen boost cgal glew glib opencsg freetype libzip libxml2 fontconfig harfbuzz qt5 qscintilla2 imagemagick; do
log "Installing formula $formula"
brew ls --versions $formula
brew install $formula
brew outdated $formula || brew upgrade $formula
time brew install $formula
done
brew link --force gettext
brew link --force qt5
brew link --force qscintilla2
for formula in gettext qt5 qscintilla2; do
log "Linking formula $formula"
brew link --force $formula
done
$TAP untap openscad/homebrew-tap

View file

@ -1,4 +1,5 @@
export OPENSCAD_LIBRARIES=$PWD/../libraries/install
export PKG_CONFIG_PATH=$OPENSCAD_LIBRARIES/lib/pkgconfig
export DYLD_LIBRARY_PATH=$OPENSCAD_LIBRARIES/lib
export DYLD_FRAMEWORK_PATH=$OPENSCAD_LIBRARIES/lib

View file

@ -100,15 +100,17 @@ void CSGTreeEvaluator::applyToChildren(State &state, const AbstractNode &node, O
}
break;
case OPENSCAD_INTERSECTION:
if (t != t1 && t != t2 &&
if (t && t != t1 && t != t2 &&
t1->isHighlight() && t2->isHighlight()) {
t->setHighlight(true);
}
else if (t != t1 && t1->isHighlight()) {
this->highlightNodes.push_back(t1);
}
else if (t != t2 && t2->isHighlight()) {
this->highlightNodes.push_back(t2);
else {
if (t != t1 && t1->isHighlight()) {
this->highlightNodes.push_back(t1);
}
if (t != t2 && t2->isHighlight()) {
this->highlightNodes.push_back(t2);
}
}
break;
case OPENSCAD_UNION:

View file

@ -23,6 +23,12 @@
#endif // GNUG
#endif // ENABLE_CGAL
#ifdef ENABLE_LIBZIP
#include <zip.h>
#else
#define LIBZIP_VERSION "<not enabled>"
#endif
extern std::vector<std::string> librarypath;
extern std::vector<std::string> fontpath;
@ -101,6 +107,7 @@ std::string LibraryInfo::info()
#endif
<< "\nMingW build: " << mingwstatus
<< "\nGLib version: " << GLIB_MAJOR_VERSION << "." << GLIB_MINOR_VERSION << "." << GLIB_MICRO_VERSION
<< "\nlibzip version: " << LIBZIP_VERSION
<< "\nApplication Path: " << PlatformUtils::applicationPath()
<< "\nDocuments Path: " << PlatformUtils::documentsPath()
<< "\nResource Path: " << PlatformUtils::resourceBasePath()

View file

@ -23,6 +23,7 @@ const Feature Feature::ExperimentalAssertExpression("assert", "Enable <code>asse
const Feature Feature::ExperimentalEachExpression("lc-each", "Enable <code>each</code> expression in list comprehensions.");
const Feature Feature::ExperimentalElseExpression("lc-else", "Enable <code>else</code> expression in list comprehensions.");
const Feature Feature::ExperimentalForCExpression("lc-for-c", "Enable C-style <code>for</code> expression in list comprehensions.");
const Feature Feature::ExperimentalAmfImport("amf-import", "Enable AMF import.");
const Feature Feature::ExperimentalSvgImport("svg-import", "Enable SVG import.");
const Feature Feature::ExperimentalCustomizer("customizer", "Enable Customizer");

View file

@ -18,6 +18,7 @@ public:
static const Feature ExperimentalEachExpression;
static const Feature ExperimentalElseExpression;
static const Feature ExperimentalForCExpression;
static const Feature ExperimentalAmfImport;
static const Feature ExperimentalSvgImport;
static const Feature ExperimentalCustomizer;

View file

@ -49,6 +49,8 @@ using namespace boost::assign; // bring 'operator+=()' into scope
#include <boost/detail/endian.hpp>
#include <cstdint>
extern PolySet * import_amf(std::string);
class ImportModule : public AbstractModule
{
public:
@ -99,6 +101,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti
if (ext == ".stl") actualtype = TYPE_STL;
else if (ext == ".off") actualtype = TYPE_OFF;
else if (ext == ".dxf") actualtype = TYPE_DXF;
else if (Feature::ExperimentalAmfImport.is_enabled() && ext == ".amf") actualtype = TYPE_AMF;
else if (Feature::ExperimentalSvgImport.is_enabled() && ext == ".svg") actualtype = TYPE_SVG;
}
@ -146,13 +149,15 @@ const Geometry *ImportNode::createGeometry() const
switch (this->type) {
case TYPE_STL: {
PolySet *p = import_stl(this->filename);
g = p;
g = import_stl(this->filename);
break;
}
case TYPE_AMF: {
g = import_amf(this->filename);
break;
}
case TYPE_OFF: {
PolySet *p = import_off(this->filename);
g = p;
g = import_off(this->filename);
break;
}
case TYPE_SVG: {

363
src/import_amf.cc Normal file
View file

@ -0,0 +1,363 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "importnode.h"
#include "polyset.h"
#include "printutils.h"
#ifdef ENABLE_CGAL
#include "cgalutils.h"
#endif
#include <sys/types.h>
#include <map>
#include <fstream>
#include <assert.h>
#include <libxml/xmlreader.h>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
static const std::string text_node("#text");
static const std::string object("/amf/object");
static const std::string coordinates("/amf/object/mesh/vertices/vertex/coordinates");
static const std::string coordinates_x = coordinates + "/x";
static const std::string coordinates_y = coordinates + "/y";
static const std::string coordinates_z = coordinates + "/z";
static const std::string triangle("/amf/object/mesh/volume/triangle");
static const std::string triangle_v1 = triangle + "/v1";
static const std::string triangle_v2 = triangle + "/v2";
static const std::string triangle_v3 = triangle + "/v3";
class AmfImporter {
private:
fs::path path;
typedef void (*cb_func)(AmfImporter *, const xmlChar *);
PolySet *polySet;
std::vector<PolySet *> polySets;
double x, y, z;
int idx_v1, idx_v2, idx_v3;
std::vector<Eigen::Vector3d> vertex_list;
std::map<const std::string, cb_func> funcs;
std::map<const std::string, cb_func> start_funcs;
std::map<const std::string, cb_func> end_funcs;
static void set_x(AmfImporter *importer, const xmlChar *value);
static void set_y(AmfImporter *importer, const xmlChar *value);
static void set_z(AmfImporter *importer, const xmlChar *value);
static void set_v1(AmfImporter *importer, const xmlChar *value);
static void set_v2(AmfImporter *importer, const xmlChar *value);
static void set_v3(AmfImporter *importer, const xmlChar *value);
static void start_object(AmfImporter *importer, const xmlChar *value);
static void end_object(AmfImporter *importer, const xmlChar *value);
static void end_triangle(AmfImporter *importer, const xmlChar *vlue);
static void end_vertex(AmfImporter *importer, const xmlChar *value);
int streamFile(const char *filename);
void processNode(xmlTextReaderPtr reader);
public:
AmfImporter();
virtual ~AmfImporter();
PolySet *read(const std::string filename);
virtual xmlTextReaderPtr createXmlReader(const char *filename);
};
AmfImporter::AmfImporter() : path("/")
{
}
AmfImporter::~AmfImporter()
{
}
void AmfImporter::set_x(AmfImporter *importer, const xmlChar *value)
{
importer->x = boost::lexical_cast<double>(std::string((const char *)value));
}
void AmfImporter::set_y(AmfImporter *importer, const xmlChar *value)
{
importer->y = boost::lexical_cast<double>(std::string((const char *)value));
}
void AmfImporter::set_z(AmfImporter *importer, const xmlChar *value)
{
importer->z = boost::lexical_cast<double>(std::string((const char *)value));
}
void AmfImporter::set_v1(AmfImporter *importer, const xmlChar *value)
{
importer->idx_v1 = boost::lexical_cast<int>(std::string((const char *)value));
}
void AmfImporter::set_v2(AmfImporter *importer, const xmlChar *value)
{
importer->idx_v2 = boost::lexical_cast<int>(std::string((const char *)value));
}
void AmfImporter::set_v3(AmfImporter *importer, const xmlChar *value)
{
importer->idx_v3 = boost::lexical_cast<int>(std::string((const char *)value));
}
void AmfImporter::start_object(AmfImporter *importer, const xmlChar *)
{
importer->polySet = new PolySet(3);
}
void AmfImporter::end_object(AmfImporter *importer, const xmlChar *)
{
PRINTDB("AMF: add object %d", importer->polySets.size());
importer->polySets.push_back(importer->polySet);
importer->vertex_list.clear();
importer->polySet = NULL;
}
void AmfImporter::end_vertex(AmfImporter *importer, const xmlChar *)
{
PRINTDB("AMF: add vertex %d - (%.2f, %.2f, %.2f)", importer->vertex_list.size() % importer->x % importer->y % importer->z);
importer->vertex_list.push_back(Eigen::Vector3d(importer->x, importer->y, importer->z));
}
void AmfImporter::end_triangle(AmfImporter *importer, const xmlChar *)
{
int idx_v1 = importer->idx_v1;
int idx_v2 = importer->idx_v2;
int idx_v3 = importer->idx_v3;
PRINTDB("AMF: add triangle %d - (%.2f, %.2f, %.2f)", importer->vertex_list.size() % idx_v1 % idx_v2 % idx_v3);
std::vector<Eigen::Vector3d> &v = importer->vertex_list;
importer->polySet->append_poly();
importer->polySet->append_vertex(v[idx_v1].x(), v[idx_v1].y(), v[idx_v1].z());
importer->polySet->append_vertex(v[idx_v2].x(), v[idx_v2].y(), v[idx_v2].z());
importer->polySet->append_vertex(v[idx_v3].x(), v[idx_v3].y(), v[idx_v3].z());
}
void AmfImporter::processNode(xmlTextReaderPtr reader)
{
const char *name = reinterpret_cast<const char *> (xmlTextReaderName(reader));
if (name == NULL)
name = reinterpret_cast<const char *> (xmlStrdup(BAD_CAST "--"));
xmlChar *value = xmlTextReaderValue(reader);
int node_type = xmlTextReaderNodeType(reader);
switch (node_type) {
case XML_READER_TYPE_ELEMENT:
{
path /= name;
cb_func startFunc = start_funcs[path.string()];
if (startFunc) {
PRINTDB("AMF: start %s", path.string());
startFunc(this, NULL);
}
}
break;
case XML_READER_TYPE_END_ELEMENT:
{
cb_func endFunc = end_funcs[path.string()];
if (endFunc) {
PRINTDB("AMF: end %s", path.string());
endFunc(this, value);
}
path = path.parent_path();
}
break;
case XML_READER_TYPE_TEXT:
{
cb_func textFunc = funcs[path.string()];
if (textFunc) {
PRINTDB("AMF: text %s - '%s'", path.string() % value);
textFunc(this, value);
}
}
break;
}
xmlFree(value);
xmlFree((void *) (name));
}
xmlTextReaderPtr AmfImporter::createXmlReader(const char *filename)
{
return xmlReaderForFile(filename, NULL, XML_PARSE_NOENT | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
}
int AmfImporter::streamFile(const char *filename)
{
int ret;
xmlTextReaderPtr reader = createXmlReader(filename);
if (reader == NULL) {
PRINTB("WARNING: Can't open import file '%s'.", filename);
return 1;
}
try {
xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1);
ret = xmlTextReaderRead(reader);
while (ret == 1) {
processNode(reader);
ret = xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
} catch (boost::bad_lexical_cast &) {
ret = -1;
}
if (ret != 0) {
PRINTB("WARNING: Failed to parse file '%s'.", filename);
}
return ret;
}
PolySet * AmfImporter::read(const std::string filename)
{
funcs[coordinates_x] = set_x;
funcs[coordinates_y] = set_y;
funcs[coordinates_z] = set_z;
funcs[triangle_v1] = set_v1;
funcs[triangle_v2] = set_v2;
funcs[triangle_v3] = set_v3;
start_funcs[object] = start_object;
end_funcs[coordinates] = end_vertex;
end_funcs[triangle] = end_triangle;
end_funcs[object] = end_object;
streamFile(filename.c_str());
vertex_list.clear();
PolySet *p = NULL;
#ifdef ENABLE_CGAL
if (polySets.size() == 1) {
p = polySets[0];
} if (polySets.size() > 1) {
Geometry::Geometries children;
for (std::vector<PolySet *>::iterator it = polySets.begin();it != polySets.end();it++) {
children.push_back(std::make_pair((const AbstractNode*)NULL, shared_ptr<const Geometry>(*it)));
}
CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(children, OPENSCAD_UNION);
PolySet *result = new PolySet(3);
if (CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *result)) {
delete result;
p = new PolySet(3);
PRINTB("ERROR: Error importing multi-object AMF file '%s'", filename);
} else {
p = result;
}
}
#endif
if (!p) {
p = new PolySet(3);
}
polySets.clear();
return p;
}
#if ENABLE_LIBZIP
#include <zip.h>
class AmfImporterZIP : public AmfImporter
{
private:
struct zip *archive;
struct zip_file *zipfile;
static int read_callback(void *context, char *buffer, int len);
static int close_callback(void *context);
public:
AmfImporterZIP();
virtual ~AmfImporterZIP();
virtual xmlTextReaderPtr createXmlReader(const char *filename);
};
AmfImporterZIP::AmfImporterZIP()
{
}
AmfImporterZIP::~AmfImporterZIP()
{
}
int AmfImporterZIP::read_callback(void *context, char *buffer, int len)
{
AmfImporterZIP *importer = (AmfImporterZIP *)context;
return zip_fread(importer->zipfile, buffer, len);
}
int AmfImporterZIP::close_callback(void *context)
{
AmfImporterZIP *importer = (AmfImporterZIP *)context;
return zip_fclose(importer->zipfile);
}
xmlTextReaderPtr AmfImporterZIP::createXmlReader(const char *filename)
{
archive = zip_open(filename, 0, NULL);
if (archive) {
fs::path f(filename);
zipfile = zip_fopen(archive, f.filename().c_str(), ZIP_FL_NODIR);
if (zipfile == NULL) {
PRINTB("WARNING: Can't read file '%s' from zipped AMF '%s'", f.filename().c_str() % filename);
}
if ((zipfile == NULL) && (zip_get_num_files(archive) == 1)) {
PRINTB("WARNING: Trying to read single entry '%s'", zip_get_name(archive, 0, 0));
zipfile = zip_fopen_index(archive, 0, 0);
}
if (zipfile) {
return xmlReaderForIO(read_callback, close_callback, this, f.filename().c_str(), NULL,
XML_PARSE_NOENT | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
} else {
zip_close(archive);
zipfile = NULL;
return NULL;
}
} else {
return AmfImporter::createXmlReader(filename);
}
}
PolySet *import_amf(const std::string filename) {
AmfImporterZIP importer;
return importer.read(filename);
}
#else
PolySet *import_amf(const std::string filename) {
AmfImporter importer;
return importer.read(filename);
}
#endif

View file

@ -5,6 +5,7 @@
enum import_type_e {
TYPE_UNKNOWN,
TYPE_AMF,
TYPE_STL,
TYPE_OFF,
TYPE_SVG,

View file

@ -260,6 +260,7 @@ MainWindow::MainWindow(const QString &filename)
knownFileExtensions["off"] = importStatement;
knownFileExtensions["dxf"] = importStatement;
if (Feature::ExperimentalSvgImport.is_enabled()) knownFileExtensions["svg"] = importStatement;
if (Feature::ExperimentalAmfImport.is_enabled()) knownFileExtensions["amf"] = importStatement;
knownFileExtensions["dat"] = surfaceStatement;
knownFileExtensions["png"] = surfaceStatement;
knownFileExtensions["scad"] = "";

2059
testdata/amf/cube-with-hole.amf vendored Normal file

File diff suppressed because it is too large Load diff

BIN
testdata/amf/multi-volume-binary.amf vendored Normal file

Binary file not shown.

257
testdata/amf/sphere20face.amf vendored Normal file
View file

@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<!--AMF generated by Jonathan Hiller's XmlStream class, originally written for AMF file format (http://amf.wikispaces.com/)-->
<amf unit="inch" version="1.1">
<metadata type="name">Sphere20</metadata>
<object id="3">
<mesh>
<vertices>
<vertex>
<coordinates>
<x>-2.62866</x>
<y>4.25325</y>
<z>0</z>
</coordinates>
<normal>
<nx>-0.525731</nx>
<ny>0.850651</ny>
<nz>0</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>2.62866</x>
<y>4.25325</y>
<z>0</z>
</coordinates>
<normal>
<nx>0.525731</nx>
<ny>0.850651</ny>
<nz>0</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>-2.62866</x>
<y>-4.25325</y>
<z>0</z>
</coordinates>
<normal>
<nx>-0.525731</nx>
<ny>-0.850651</ny>
<nz>0</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>2.62866</x>
<y>-4.25325</y>
<z>0</z>
</coordinates>
<normal>
<nx>0.525731</nx>
<ny>-0.850651</ny>
<nz>0</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>0</x>
<y>-2.62866</y>
<z>4.25325</z>
</coordinates>
<normal>
<nx>0</nx>
<ny>-0.525731</ny>
<nz>0.850651</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>0</x>
<y>2.62866</y>
<z>4.25325</z>
</coordinates>
<normal>
<nx>0</nx>
<ny>0.525731</ny>
<nz>0.850651</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>0</x>
<y>-2.62866</y>
<z>-4.25325</z>
</coordinates>
<normal>
<nx>0</nx>
<ny>-0.525731</ny>
<nz>-0.850651</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>0</x>
<y>2.62866</y>
<z>-4.25325</z>
</coordinates>
<normal>
<nx>0</nx>
<ny>0.525731</ny>
<nz>-0.850651</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>4.25325</x>
<y>0</y>
<z>-2.62866</z>
</coordinates>
<normal>
<nx>0.850651</nx>
<ny>0</ny>
<nz>-0.525731</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>4.25325</x>
<y>0</y>
<z>2.62866</z>
</coordinates>
<normal>
<nx>0.850651</nx>
<ny>0</ny>
<nz>0.525731</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>-4.25325</x>
<y>0</y>
<z>-2.62866</z>
</coordinates>
<normal>
<nx>-0.850651</nx>
<ny>0</ny>
<nz>-0.525731</nz>
</normal>
</vertex>
<vertex>
<coordinates>
<x>-4.25325</x>
<y>0</y>
<z>2.62866</z>
</coordinates>
<normal>
<nx>-0.850651</nx>
<ny>0</ny>
<nz>0.525731</nz>
</normal>
</vertex>
</vertices>
<volume>
<triangle>
<v1>0</v1>
<v2>11</v2>
<v3>5</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>5</v2>
<v3>1</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>1</v2>
<v3>7</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>7</v2>
<v3>10</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>10</v2>
<v3>11</v3>
</triangle>
<triangle>
<v1>1</v1>
<v2>5</v2>
<v3>9</v3>
</triangle>
<triangle>
<v1>5</v1>
<v2>11</v2>
<v3>4</v3>
</triangle>
<triangle>
<v1>11</v1>
<v2>10</v2>
<v3>2</v3>
</triangle>
<triangle>
<v1>10</v1>
<v2>7</v2>
<v3>6</v3>
</triangle>
<triangle>
<v1>7</v1>
<v2>1</v2>
<v3>8</v3>
</triangle>
<triangle>
<v1>3</v1>
<v2>9</v2>
<v3>4</v3>
</triangle>
<triangle>
<v1>3</v1>
<v2>4</v2>
<v3>2</v3>
</triangle>
<triangle>
<v1>3</v1>
<v2>2</v2>
<v3>6</v3>
</triangle>
<triangle>
<v1>3</v1>
<v2>6</v2>
<v3>8</v3>
</triangle>
<triangle>
<v1>3</v1>
<v2>8</v2>
<v3>9</v3>
</triangle>
<triangle>
<v1>4</v1>
<v2>9</v2>
<v3>5</v3>
</triangle>
<triangle>
<v1>2</v1>
<v2>4</v2>
<v3>11</v3>
</triangle>
<triangle>
<v1>6</v1>
<v2>2</v2>
<v3>10</v3>
</triangle>
<triangle>
<v1>8</v1>
<v2>6</v2>
<v3>7</v3>
</triangle>
<triangle>
<v1>9</v1>
<v2>8</v2>
<v3>1</v3>
</triangle>
</volume>
</mesh>
</object>
</amf>

BIN
testdata/amf/split_pyramid.amf vendored Normal file

Binary file not shown.

22
testdata/amf/tetra_multicolor.amf vendored Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<amf unit="inch" version="1.1">
<metadata type="name">Color Tetrahedron</metadata>
<object id="1">
<color><r>1</r><g>1</g><b>1</b></color>
<mesh>
<vertices>
<vertex><coordinates><x>0</x><y>0</y><z>0</z></coordinates></vertex>
<vertex><coordinates><x>1</x><y>0.25</y><z>0</z></coordinates></vertex>
<vertex><coordinates><x>0.25</x><y>1</y><z>0</z></coordinates></vertex>
<vertex><coordinates><x>0.4</x><y>0.4</y><z>0.5</z></coordinates></vertex>
</vertices>
<volume>
<metadata type="name">Hard side</metadata>
<triangle><v1>2</v1><v2>1</v2><v3>0</v3><color><r>1</r><g>0</g><b>0</b></color></triangle>
<triangle><v1>0</v1><v2>1</v2><v3>3</v3><color><r>0</r><g>1</g><b>0</b></color></triangle>
<triangle><v1>3</v1><v2>1</v2><v3>2</v3><color><r>0</r><g>0</g><b>1</b></color></triangle>
<triangle><v1>0</v1><v2>3</v2><v3>2</v3></triangle>
</volume>
</mesh>
</object>
</amf>

View file

@ -0,0 +1,4 @@
intersection() {
#translate([2,0,0]) cube(1);
#cube(1);
}

3
testdata/scad/amf/cube-with-hole.scad vendored Normal file
View file

@ -0,0 +1,3 @@
// converted from STL by cura, unzipped
import("../../amf/cube-with-hole.amf");

View file

@ -0,0 +1,3 @@
// converted from STL and split by cura, zipped
import("../../amf/multi-volume-binary.amf");

3
testdata/scad/amf/sphere20face.scad vendored Normal file
View file

@ -0,0 +1,3 @@
// example file from http://amf.wikispaces.com/AMF+test+files
import("../../amf/sphere20face.amf");

3
testdata/scad/amf/split_pyramid.scad vendored Normal file
View file

@ -0,0 +1,3 @@
// example file from http://amf.wikispaces.com/AMF+test+files
import("../../amf/split_pyramid.amf");

View file

@ -0,0 +1,3 @@
// example file from http://amf.wikispaces.com/AMF+test+files
import("../../amf/tetra_multicolor.amf");

View file

@ -23,3 +23,10 @@ echo(t5 = t5);
d = c + 9;
t6 = assert(condition = d + 5 > 15, message = str("value: ", d + 5)) a*b*c*d;
echo(t6 = t6);
t7 = assert(true) [a,b];
echo(t7 = t7);
t8 = assert(true) [for (i=[1:a]) [i,b]];
echo(t8 = t8);

View file

@ -0,0 +1,2 @@
c = let(c=1) [c];
echo(c);

View file

@ -12,3 +12,6 @@ echo(let($a=2,b=$a*3) $a*b);
echo(let($a=2*b,b=3) $a*b);
echo(let($a=2*b,b=$a*3) $a*b);
echo(let(b=$a*3,$a=2*b) $a*b);
echo(let(b=$a,$a=b) [$a, b]);
echo(let(b=2*$a,$a=b) [for (i=[1:b]) [i,$a]]);

View file

@ -759,6 +759,7 @@ set(NOCGAL_SOURCES
../src/builtin.cc
../src/import.cc
../src/import_stl.cc
../src/import_amf.cc
../src/import_off.cc
../src/import_svg.cc
../src/export.cc
@ -773,7 +774,6 @@ set(NOCGAL_SOURCES
../src/polyset-utils.cc
../src/GeometryUtils.cc)
set(CGAL_SOURCES
${NOCGAL_SOURCES}
../src/CSGTreeEvaluator.cc
@ -1034,7 +1034,7 @@ function(add_cmdline_test TESTCMD_BASENAME)
if (${EXPERIMENTAL} EQUAL -1)
set(EXPERIMENTAL_OPTION "")
else()
set(EXPERIMENTAL_OPTION "--enable=lc-each" "--enable=lc-else" "--enable=lc-for-c")
set(EXPERIMENTAL_OPTION "--enable=assert" "--enable=lc-each" "--enable=lc-else" "--enable=lc-for-c" "--enable=amf-import")
endif()
# 2D tests should be viewed from the top, not an angle.
@ -1140,6 +1140,7 @@ file(GLOB FEATURES_2D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/2D/features/*.s
file(GLOB DEPRECATED_3D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/deprecated/*.scad)
file(GLOB ISSUES_3D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/issues/*.scad)
file(GLOB SCAD_DXF_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/dxf/*.scad)
file(GLOB SCAD_AMF_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/amf/*.scad)
file(GLOB FUNCTION_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/functions/*.scad)
file(GLOB_RECURSE EXAMPLE_3D_FILES ${CMAKE_SOURCE_DIR}/../examples/*.scad)
@ -1220,7 +1221,7 @@ list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad)
list(APPEND CGALPNGTEST_2D_FILES ${FEATURES_2D_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_2D_FILES})
list(APPEND CGALPNGTEST_3D_FILES ${FEATURES_3D_FILES} ${DEPRECATED_3D_FILES} ${ISSUES_3D_FILES} ${EXAMPLE_3D_FILES})
list(APPEND CGALPNGTEST_3D_FILES ${FEATURES_3D_FILES} ${SCAD_AMF_FILES} ${DEPRECATED_3D_FILES} ${ISSUES_3D_FILES} ${EXAMPLE_3D_FILES})
list(APPEND CGALPNGTEST_3D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/assert-tests.scad
@ -1359,6 +1360,26 @@ disable_tests(csgpngtest_primitive-inf-tests
csgpngtest_issue1258)
experimental_tests(echotest_list-comprehensions-experimental
cgalpngtest_cube-with-hole
cgalpngtest_multi-volume-binary
cgalpngtest_sphere20face
cgalpngtest_split_pyramid
cgalpngtest_tetra_multicolor
opencsgtest_cube-with-hole
opencsgtest_multi-volume-binary
opencsgtest_sphere20face
opencsgtest_split_pyramid
opencsgtest_tetra_multicolor
csgpngtest_cube-with-hole
csgpngtest_multi-volume-binary
csgpngtest_sphere20face
csgpngtest_split_pyramid
csgpngtest_tetra_multicolor
throwntogethertest_cube-with-hole
throwntogethertest_multi-volume-binary
throwntogethertest_sphere20face
throwntogethertest_split_pyramid
throwntogethertest_tetra_multicolor
echotest_assert-tests
cgalpngtest_assert-tests
opencsgtest_assert-tests
@ -1607,6 +1628,7 @@ list(APPEND TRIVIAL_IMPORT_EXPORT_3D_FILES
add_cmdline_test(monotonepngtest EXE ${OPENSCAD_BINPATH} ARGS --colorscheme=Monotone --render -o SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_2D_FILES} ${TRIVIAL_IMPORT_EXPORT_3D_FILES})
add_cmdline_test(stlpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL EXPECTEDDIR monotonepngtest SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_3D_FILES})
add_cmdline_test(offpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=OFF EXPECTEDDIR monotonepngtest SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_3D_FILES})
add_cmdline_test(amfpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=AMF --enable=amf-import EXPECTEDDIR monotonepngtest SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_3D_FILES})
add_cmdline_test(dxfpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=DXF --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_2D_FILES})
add_cmdline_test(svgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=SVG --enable=svg-import --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${TRIVIAL_IMPORT_EXPORT_2D_FILES})
@ -1633,7 +1655,6 @@ add_cmdline_test(dxfpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/
add_cmdline_test(svgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=SVG --render=cgal --enable=svg-import EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D})
#
# Failing tests
#

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -1,7 +1,4 @@
ECHO: t0 = undef
ECHO: t1 = undef
ECHO: t2 = undef
ECHO: t3 = undef
ECHO: t4 = 18
ECHO: t5 = 36
ECHO: t6 = 396
ERROR: Parser error in file "/Users/kintel/code/OpenSCAD/openscad/testdata/scad/functions/assert-expression-tests.scad", line 16: syntax error
Can't parse file 'testdata/scad/functions/assert-expression-tests.scad'!

View file

@ -0,0 +1 @@
ECHO: [1]

View file

@ -14,3 +14,5 @@ ECHO: 12
ECHO: 6
ECHO: 12
ECHO: 18
ECHO: [1, 1]
ECHO: [[1, 2], [2, 2]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB