Merge remote-tracking branch 'origin/master' into c++11

This commit is contained in:
Marius Kintel 2014-06-21 16:15:56 -04:00
commit a0875c845c
42 changed files with 679 additions and 360 deletions

View file

@ -86,16 +86,16 @@ libraries from aptitude. If you're using Mac, or an older Linux/BSD, there
are build scripts that download and compile the libraries from source.
Follow the instructions for the platform you're compiling on below.
* [Qt4 (4.4 - 5.2)](http://www.qt.nokia.com/)
* [CGAL (3.6 - 4.1)](http://www.cgal.org/)
* [Qt4 (4.4 - 5.3)](http://www.qt.nokia.com/)
* [CGAL (3.6 - 4.4)](http://www.cgal.org/)
* [GMP (5.x)](http://www.gmplib.org/)
* [MPFR (3.x)](http://www.mpfr.org/)
* [cmake (2.8, required by CGAL and the test framework)](http://www.cmake.org/)
* [boost (1.35 - 1.55)](http://www.boost.org/)
* [OpenCSG (1.3.2)](http://www.opencsg.org/)
* [OpenCSG (1.3.2 ->)](http://www.opencsg.org/)
* [GLEW (1.5.4 ->)](http://glew.sourceforge.net/)
* [Eigen (3.0 - 3.2)](http://eigen.tuxfamily.org/)
* [glib2 (2.2.0)](https://developer.gnome.org/glib/)
* [Eigen (3.x)](http://eigen.tuxfamily.org/)
* [glib2 (2.x)](https://developer.gnome.org/glib/)
* [fontconfig (2.10)](http://fontconfig.org/)
* [freetype2 (2.4)](http://freetype.org/)
* [harfbuzz (0.9.19)](http://harfbuzz.org/)

View file

@ -317,6 +317,7 @@ SOURCES += src/version_check.cc \
src/ProgressWidget.cc \
src/mathc99.cc \
src/linalg.cc \
src/Camera.cc \
src/handle_dep.cc \
src/value.cc \
src/expr.cc \

View file

@ -13,7 +13,7 @@ if [[ $? != 0 ]]; then
fi
# Exclude tests known the cause issues on Travis
# opencsgtest_rotate_extrude-tests - Fails on Ubuntu 12.04 using Gallium 0.4 drivers
ctest -j8 -E opencsgtest_rotate_extrude-tests
ctest -j8 -E "opencsgtest_rotate_extrude-tests|opencsgtest_render-tests"
if [[ $? != 0 ]]; then
echo "Test failure"
exit 1

View file

@ -113,3 +113,20 @@ void CGALRenderer::draw(bool showfaces, bool showedges) const
this->polyhedron->draw(showfaces && showedges);
}
}
BoundingBox CGALRenderer::getBoundingBox() const
{
BoundingBox bbox;
if (this->polyhedron) {
CGAL::Bbox_3 cgalbbox = this->polyhedron->bbox();
bbox = BoundingBox(
Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()) );
}
else if (this->polyset) {
bbox = this->polyset->getBoundingBox();
}
return bbox;
}

View file

@ -6,8 +6,9 @@ class CGALRenderer : public Renderer
{
public:
CGALRenderer(shared_ptr<const class Geometry> geom);
~CGALRenderer();
void draw(bool showfaces, bool showedges) const;
virtual ~CGALRenderer();
virtual void draw(bool showfaces, bool showedges) const;
virtual BoundingBox getBoundingBox() const;
public:
shared_ptr<class Polyhedron> polyhedron;

80
src/Camera.cc Normal file
View file

@ -0,0 +1,80 @@
#include "Camera.h"
#include "rendersettings.h"
Camera::Camera(enum CameraType camtype) :
type(camtype), projection(Camera::PERSPECTIVE), fov(45), height(60), viewall(false)
{
if (this->type == Camera::GIMBAL) {
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
} else if (this->type == Camera::VECTOR) {
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
}
pixel_width = RenderSettings::inst()->img_width;
pixel_height = RenderSettings::inst()->img_height;
}
void Camera::setup(std::vector<double> params)
{
if (params.size() == 7) {
type = Camera::GIMBAL;
object_trans << params[0], params[1], params[2];
object_rot << params[3], params[4], params[5];
viewer_distance = params[6];
} else if (params.size() == 6) {
type = Camera::VECTOR;
eye << params[0], params[1], params[2];
center << params[3], params[4], params[5];
} else {
assert("Gimbal cam needs 7 numbers, Vector camera needs 6");
}
}
void Camera::gimbalDefaultTranslate()
{ // match the GUI viewport numbers (historical reasons)
object_trans.x() *= -1;
object_trans.y() *= -1;
object_trans.z() *= -1;
object_rot.x() = fmodf(360 - object_rot.x() + 90, 360);
object_rot.y() = fmodf(360 - object_rot.y(), 360);
object_rot.z() = fmodf(360 - object_rot.z(), 360);
}
/*!
Moves camera so that the given bbox is fully visible.
FIXME: The scalefactor is a temporary hack to be compatible with
earlier ways of showing the whole scene.
*/
void Camera::viewAll(const BoundingBox &bbox, float scalefactor)
{
if (this->type == Camera::NONE) {
this->type = Camera::VECTOR;
this->center = bbox.center();
this->eye = this->center - Vector3d(1,1,-0.5);
}
switch (this->projection) {
case Camera::ORTHOGONAL:
this->height = bbox.diagonal().norm();
break;
case Camera::PERSPECTIVE: {
double radius = bbox.diagonal().norm()/2;
switch (this->type) {
case Camera::GIMBAL:
this->viewer_distance = radius / tan(this->fov*M_PI/360);
break;
case Camera::VECTOR: {
Vector3d cameradir = (this->center - this->eye).normalized();
this->eye = this->center - radius*scalefactor*cameradir;
break;
}
default:
assert(false && "Camera type not specified");
}
}
break;
}
}

View file

@ -16,61 +16,19 @@ projection, Perspective and Orthogonal.
*/
#include "linalg.h"
#include <vector>
#include <Eigen/Geometry>
#include "rendersettings.h"
class Camera
{
public:
enum CameraType { NONE, GIMBAL, VECTOR } type;
enum ProjectionType { ORTHOGONAL, PERSPECTIVE } projection;
Camera() {
type = Camera::NONE;
projection = Camera::PERSPECTIVE;
}
Camera( enum CameraType e )
{
type = e;
if ( e == Camera::GIMBAL ) {
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
} else if ( e == Camera::VECTOR ) {
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
}
pixel_width = RenderSettings::inst()->img_width;
pixel_height = RenderSettings::inst()->img_height;
projection = Camera::PERSPECTIVE;
}
void setup( std::vector<double> params )
{
if ( params.size() == 7 ) {
type = Camera::GIMBAL;
object_trans << params[0], params[1], params[2];
object_rot << params[3], params[4], params[5];
viewer_distance = params[6];
} else if ( params.size() == 6 ) {
type = Camera::VECTOR;
eye << params[0], params[1], params[2];
center << params[3], params[4], params[5];
} else {
assert( "Gimbal cam needs 7 numbers, Vector camera needs 6" );
}
}
void gimbalDefaultTranslate()
{ // match the GUI viewport numbers (historical reasons)
object_trans.x() *= -1;
object_trans.y() *= -1;
object_trans.z() *= -1;
object_rot.x() = fmodf(360 - object_rot.x() + 90, 360 );
object_rot.y() = fmodf(360 - object_rot.y(), 360);
object_rot.z() = fmodf(360 - object_rot.z(), 360);
}
Camera(enum CameraType camtype = NONE);
void setup(std::vector<double> params);
void gimbalDefaultTranslate();
void viewAll(const BoundingBox &bbox, float scalefactor = 1.0f);
// Vectorcam
Eigen::Vector3d eye;
@ -82,6 +40,14 @@ public:
Eigen::Vector3d object_rot;
double viewer_distance;
// Perspective settings
double fov; // Field of view
// Orthographic settings
double height; // world-space height of viewport
bool viewall;
unsigned int pixel_width;
unsigned int pixel_height;
};

View file

@ -3,6 +3,7 @@
#include "stdio.h"
#include "rendersettings.h"
#include "mathc99.h"
#include "renderer.h"
#ifdef _WIN32
#include <GL/wglew.h>
@ -47,60 +48,107 @@ void GLView::resizeGL(int w, int h)
cam.pixel_width = w;
cam.pixel_height = h;
glViewport(0, 0, w, h);
w_h_ratio = sqrt((double)w / (double)h);
aspectratio = 1.0*w/h;
}
void GLView::setupGimbalCamPerspective()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +far_far_away);
gluLookAt(0.0, -cam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}
void GLView::setupGimbalCamOrtho(double distance, bool offset)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (offset) glTranslated(-0.8, -0.8, 0);
double l = distance/10;
glOrtho(-w_h_ratio*l, +w_h_ratio*l,
-(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
-far_far_away, +far_far_away);
gluLookAt(0.0, -cam.viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}
void GLView::setupVectorCamPerspective()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double dist = (cam.center - cam.eye).norm();
gluPerspective(45, pow(w_h_ratio,2), 0.1*dist, 100*dist);
}
void GLView::setupVectorCamOrtho(bool offset)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (offset) glTranslated(-0.8, -0.8, 0);
double l = (cam.center - cam.eye).norm() / 10;
glOrtho(-pow(w_h_ratio,2)*l, +pow(w_h_ratio,2)*l,
-(1/pow(w_h_ratio,2))*l, +(1/pow(w_h_ratio,2))*l,
-far_far_away, +far_far_away);
}
void GLView::setCamera( Camera &cam )
void GLView::setCamera(const Camera &cam)
{
this->cam = cam;
}
void GLView::setupCamera()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
switch (this->cam.type) {
case Camera::GIMBAL:
switch (this->cam.projection) {
case Camera::PERSPECTIVE: {
double dist = cam.viewer_distance;
gluPerspective(cam.fov, aspectratio, 0.1*dist, 100*dist);
break;
}
case Camera::ORTHOGONAL: {
glOrtho(-cam.height/2*aspectratio, cam.height*aspectratio/2,
-cam.height/2, cam.height/2,
-far_far_away, +far_far_away);
break;
}
}
gluLookAt(0.0, -cam.viewer_distance, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated(cam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(cam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(cam.object_rot.z(), 0.0, 0.0, 1.0);
glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z() );
break;
case Camera::VECTOR: {
switch (this->cam.projection) {
case Camera::PERSPECTIVE: {
double dist = (cam.center - cam.eye).norm();
gluPerspective(cam.fov, aspectratio, 0.1*dist, 100*dist);
break;
}
case Camera::ORTHOGONAL: {
glOrtho(-cam.height/2*aspectratio, cam.height*aspectratio/2,
-cam.height/2, cam.height/2,
-far_far_away, +far_far_away);
break;
}
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Vector3d dir(cam.eye - cam.center);
Vector3d up(0.0,0.0,1.0);
if (dir.cross(up).norm() < 0.001) { // View direction is ~parallel with up vector
up << 0.0,1.0,0.0;
}
gluLookAt(cam.eye[0], cam.eye[1], cam.eye[2],
cam.center[0], cam.center[1], cam.center[2],
up[0], up[1], up[2]);
break;
}
default:
break;
}
}
void GLView::paintGL()
{
if (cam.type == Camera::GIMBAL) gimbalCamPaintGL();
else if (cam.type == Camera::VECTOR) vectorCamPaintGL();
else if (cam.type == Camera::NONE) {
fprintf(stderr,"paintGL with null camera\n");
}
glEnable(GL_LIGHTING);
setupCamera();
Color4f bgcol = RenderSettings::inst()->color(RenderSettings::BACKGROUND_COLOR);
glClearColor(bgcol[0], bgcol[1], bgcol[2], 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Only for GIMBAL cam
if (showcrosshairs) GLView::showCrosshairs();
if (showaxes) GLView::showAxes();
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
glLineWidth(2);
glColor3d(1.0, 0.0, 0.0);
if (this->renderer) {
#if defined(ENABLE_OPENCSG)
// FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet
OpenCSG::setContext(this->opencsg_id);
#endif
this->renderer->draw(showfaces, showedges);
}
// Only for GIMBAL
if (showaxes) GLView::showSmallaxes();
}
#ifdef ENABLE_OPENCSG
@ -279,86 +327,6 @@ void GLView::initializeGL()
#endif
}
void GLView::vectorCamPaintGL()
{
glEnable(GL_LIGHTING);
if (cam.projection==Camera::ORTHOGONAL) setupVectorCamOrtho();
else setupVectorCamPerspective();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(1.0f, 1.0f, 0.92f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
gluLookAt(cam.eye[0], cam.eye[1], cam.eye[2],
cam.center[0], cam.center[1], cam.center[2],
0.0, 0.0, 1.0);
// fixme - showcrosshairs doesnt work with vector camera
// if (showcrosshairs) GLView::showCrosshairs();
if (showaxes) GLView::showAxes();
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
glLineWidth(2);
glColor3d(1.0, 0.0, 0.0);
//FIXME showSmallAxes wont work with vector camera
//if (showaxes) GLView::showSmallaxes();
if (this->renderer) {
this->renderer->draw(showfaces, showedges);
}
}
void GLView::gimbalCamPaintGL()
{
glEnable(GL_LIGHTING);
if (cam.projection == Camera::ORTHOGONAL)
GLView::setupGimbalCamOrtho(cam.viewer_distance);
else
GLView::setupGimbalCamPerspective();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Color4f bgcol = RenderSettings::inst()->color(RenderSettings::BACKGROUND_COLOR);
glClearColor(bgcol[0], bgcol[1], bgcol[2], 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glRotated(cam.object_rot.x(), 1.0, 0.0, 0.0);
glRotated(cam.object_rot.y(), 0.0, 1.0, 0.0);
glRotated(cam.object_rot.z(), 0.0, 0.0, 1.0);
if (showcrosshairs) GLView::showCrosshairs();
glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z() );
if (showaxes) GLView::showAxes();
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
glLineWidth(2);
glColor3d(1.0, 0.0, 0.0);
if (this->renderer) {
#if defined(ENABLE_OPENCSG)
// FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet
OpenCSG::setContext(this->opencsg_id);
#endif
this->renderer->draw(showfaces, showedges);
}
// Small axis cross in the lower left corner
if (showaxes) GLView::showSmallaxes();
}
void GLView::showSmallaxes()
{
// Fixme - this doesnt work in Vector Camera mode
@ -367,8 +335,18 @@ void GLView::showSmallaxes()
// Small axis cross in the lower left corner
glDepthFunc(GL_ALWAYS);
GLView::setupGimbalCamOrtho(1000,true);
// Set up an orthographic projection of the axis cross in the corner
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(-0.8f, -0.8f, 0.0f);
double scale = 90;
glOrtho(-scale*dpi*aspectratio,scale*dpi*aspectratio,
-scale*dpi,scale*dpi,
-scale*dpi,scale*dpi);
gluLookAt(0.0, -1.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated(cam.object_rot.x(), 1.0, 0.0, 0.0);
@ -436,10 +414,6 @@ void GLView::showSmallaxes()
// FIXME - depends on gimbal camera 'viewer distance'.. how to fix this
// for VectorCamera?
glEnd();
//Restore perspective for next paint
if(cam.projection==Camera::PERSPECTIVE)
GLView::setupGimbalCamPerspective();
}
void GLView::showAxes()
@ -447,11 +421,10 @@ void GLView::showAxes()
// FIXME: doesn't work under Vector Camera
// Large gray axis cross inline with the model
// FIXME: This is always gray - adjust color to keep contrast with background
float dpi = this->getDPI();
glLineWidth(1*dpi);
glLineWidth(this->getDPI());
glColor3d(0.5, 0.5, 0.5);
glBegin(GL_LINES);
double l = cam.viewer_distance*dpi/10;
double l = cam.viewer_distance;
glVertex3d(-l, 0, 0);
glVertex3d(+l, 0, 0);
glVertex3d(0, -l, 0);

View file

@ -25,28 +25,21 @@ Some actions (showCrossHairs) only work properly on Gimbal Camera.
#endif
#include "system-gl.h"
#include <iostream>
#include "renderer.h"
#include "Camera.h"
class GLView
{
public:
GLView();
void setRenderer(Renderer* r);
void setRenderer(class Renderer* r);
Renderer *getRenderer() const { return this->renderer; }
void initializeGL();
void resizeGL(int w, int h);
virtual void paintGL();
void setCamera( Camera &cam );
void setupGimbalCamPerspective();
void setupGimbalCamOrtho(double distance, bool offset=false);
void gimbalCamPaintGL();
void setupVectorCamPerspective();
void setupVectorCamOrtho(bool offset=false);
void vectorCamPaintGL();
void setCamera(const Camera &cam);
void setupCamera();
void showCrosshairs();
void showAxes();
@ -61,7 +54,7 @@ public:
double far_far_away;
size_t width;
size_t height;
double w_h_ratio;
double aspectratio;
bool orthomode;
bool showaxes;
bool showfaces;

View file

@ -86,6 +86,7 @@ private:
void openFile(const QString &filename);
void handleFileDrop(const QString &filename);
void refreshDocument();
void updateCamera();
void updateTemporalVariables();
bool fileChangedOnDisk();
void compileTopLevelDocument();
@ -202,6 +203,7 @@ public slots:
void viewPerspective();
void viewOrthogonal();
void viewResetView();
void viewAll();
void hideConsole();
void animateUpdateDocChanged();
void animateUpdate();
@ -224,6 +226,7 @@ private:
char const * afterCompileSlot;
bool procevents;
bool isClosing;
class QTemporaryFile *tempFile;
class ProgressWidget *progresswidget;
class CGALWorker *cgalworker;

View file

@ -120,7 +120,7 @@
<x>0</x>
<y>0</y>
<width>936</width>
<height>34</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
@ -234,6 +234,7 @@
<addaction name="viewActionBack"/>
<addaction name="viewActionDiagonal"/>
<addaction name="viewActionCenter"/>
<addaction name="viewActionViewAll"/>
<addaction name="separator"/>
<addaction name="viewActionZoomIn"/>
<addaction name="viewActionZoomOut"/>
@ -961,6 +962,11 @@
<string>Ctrl+[</string>
</property>
</action>
<action name="viewActionViewAll">
<property name="text">
<string>View All</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View file

@ -147,3 +147,10 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
}
std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>());
}
BoundingBox OpenCSGRenderer::getBoundingBox() const
{
BoundingBox bbox;
if (this->root_chain) bbox = this->root_chain->getBoundingBox();
return bbox;
}

View file

@ -8,7 +8,8 @@ class OpenCSGRenderer : public Renderer
public:
OpenCSGRenderer(class CSGChain *root_chain, CSGChain *highlights_chain,
CSGChain *background_chain, GLint *shaderinfo);
void draw(bool showfaces, bool showedges) const;
virtual void draw(bool showfaces, bool showedges) const;
virtual BoundingBox getBoundingBox() const;
private:
void renderCSGChain(class CSGChain *chain, GLint *shaderinfo,
bool highlight, bool background) const;

View file

@ -85,7 +85,16 @@ void QGLView::resetView()
{
cam.object_rot << 35, 0, -25;
cam.object_trans << 0, 0, 0;
cam.viewer_distance = 500;
cam.viewer_distance = 140;
}
void QGLView::viewAll()
{
if (Renderer *r = this->getRenderer()) {
BoundingBox bbox = r->getBoundingBox();
cam.object_trans = -bbox.center();
cam.viewAll(r->getBoundingBox());
}
}
void QGLView::initializeGL()
@ -147,17 +156,16 @@ void QGLView::display_opencsg_warning_dialog()
void QGLView::resizeGL(int w, int h)
{
GLView::resizeGL(w,h);
GLView::setupGimbalCamPerspective();
}
void QGLView::paintGL()
{
GLView::gimbalCamPaintGL();
GLView::paintGL();
if (statusLabel) {
QString msg;
Camera nc( cam );
Camera nc(cam);
nc.gimbalDefaultTranslate();
msg.sprintf("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f",
nc.object_trans.x(), nc.object_trans.y(), nc.object_trans.z(),

View file

@ -44,6 +44,7 @@ public:
#endif
bool save(const char *filename);
void resetView();
void viewAll();
public slots:
void ZoomIn(void);

View file

@ -123,3 +123,10 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
glPopMatrix();
}
}
BoundingBox ThrownTogetherRenderer::getBoundingBox() const
{
BoundingBox bbox;
if (this->root_chain) bbox = this->root_chain->getBoundingBox();
return bbox;
}

View file

@ -7,7 +7,8 @@ class ThrownTogetherRenderer : public Renderer
public:
ThrownTogetherRenderer(class CSGChain *root_chain,
CSGChain *highlights_chain, CSGChain *background_chain);
void draw(bool showfaces, bool showedges) const;
virtual void draw(bool showfaces, bool showedges) const;
virtual BoundingBox getBoundingBox() const;
private:
void renderCSGChain(CSGChain *chain, bool highlight, bool background, bool showedges,
bool fberror) const;

View file

@ -106,6 +106,7 @@ Builtins::Builtins()
Value zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(500))));
}
Builtins::~Builtins()

View file

@ -13,11 +13,17 @@
#include "cgalutils.h"
#include "CGAL_Nef_polyhedron.h"
static void setupCamera(Camera &cam, const BoundingBox &bbox, float scalefactor)
{
if (cam.type == Camera::NONE) cam.viewall = true;
if (cam.viewall) cam.viewAll(bbox, scalefactor);
}
void export_png(const Geometry *root_geom, Camera &cam, std::ostream &output)
{
OffscreenView *glview;
try {
glview = new OffscreenView( cam.pixel_width, cam.pixel_height );
glview = new OffscreenView(cam.pixel_width, cam.pixel_height);
} catch (int error) {
fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i.\n", error);
return;
@ -25,32 +31,16 @@ void export_png(const Geometry *root_geom, Camera &cam, std::ostream &output)
shared_ptr<const Geometry> ptr(root_geom);
CGALRenderer cgalRenderer(ptr);
BoundingBox bbox;
if (cgalRenderer.polyhedron) {
CGAL::Bbox_3 cgalbbox = cgalRenderer.polyhedron->bbox();
bbox = BoundingBox(
Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()) );
}
else if (cgalRenderer.polyset) {
bbox = cgalRenderer.polyset->getBoundingBox();
}
BoundingBox bbox = cgalRenderer.getBoundingBox();
setupCamera(cam, bbox, 3);
if (cam.type == Camera::NONE) {
cam.type = Camera::VECTOR;
cam.center = getBoundingCenter(bbox);
double radius = getBoundingRadius(bbox);
Vector3d cameradir(1, 1, -0.5);
cam.eye = cam.center - radius*2*cameradir;
}
glview->setCamera( cam );
glview->setCamera(cam);
glview->setRenderer(&cgalRenderer);
glview->paintGL();
glview->save(output);
}
enum Previewer { OPENCSG, THROWN } previewer;
enum Previewer { OPENCSG, THROWNTOGETHER } previewer;
#ifdef ENABLE_OPENCSG
#include "OpenCSGRenderer.h"
@ -58,16 +48,16 @@ enum Previewer { OPENCSG, THROWN } previewer;
#endif
#include "ThrownTogetherRenderer.h"
void export_png_preview_common( Tree &tree, Camera &cam, std::ostream &output, Previewer previewer = OPENCSG )
void export_png_preview_common(Tree &tree, Camera &cam, std::ostream &output, Previewer previewer = OPENCSG)
{
CsgInfo csgInfo = CsgInfo();
if ( !csgInfo.compile_chains( tree ) ) {
if (!csgInfo.compile_chains(tree)) {
fprintf(stderr,"Couldn't initialize CSG chains\n");
return;
}
try {
csgInfo.glview = new OffscreenView( cam.pixel_width, cam.pixel_height );
csgInfo.glview = new OffscreenView(cam.pixel_width, cam.pixel_height);
} catch (int error) {
fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i.\n", error);
return;
@ -76,39 +66,30 @@ void export_png_preview_common( Tree &tree, Camera &cam, std::ostream &output, P
#ifdef ENABLE_OPENCSG
OpenCSGRenderer openCSGRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo);
#endif
ThrownTogetherRenderer thrownTogetherRenderer( csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain );
ThrownTogetherRenderer thrownTogetherRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain);
if (cam.type == Camera::NONE) {
cam.type = Camera::VECTOR;
double radius = 1.0;
if (csgInfo.root_chain) {
BoundingBox bbox = csgInfo.root_chain->getBoundingBox();
cam.center = (bbox.min() + bbox.max()) / 2;
radius = (bbox.max() - bbox.min()).norm() / 2;
}
Vector3d cameradir(1, 1, -0.5);
cam.eye = cam.center - radius*1.8*cameradir;
}
csgInfo.glview->setCamera( cam );
#ifdef ENABLE_OPENCSG
if ( previewer == OPENCSG )
csgInfo.glview->setRenderer( &openCSGRenderer );
if (previewer == OPENCSG)
csgInfo.glview->setRenderer(&openCSGRenderer);
else
#endif
csgInfo.glview->setRenderer( &thrownTogetherRenderer );
csgInfo.glview->setRenderer(&thrownTogetherRenderer);
#ifdef ENABLE_OPENCSG
OpenCSG::setContext( 0 );
OpenCSG::setOption( OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject );
BoundingBox bbox = csgInfo.glview->getRenderer()->getBoundingBox();
setupCamera(cam, bbox, 2.7);
csgInfo.glview->setCamera(cam);
OpenCSG::setContext(0);
OpenCSG::setOption(OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject);
#endif
csgInfo.glview->paintGL();
csgInfo.glview->save( output );
csgInfo.glview->save(output);
}
void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output)
{
#ifdef ENABLE_OPENCSG
export_png_preview_common( tree, cam, output, OPENCSG );
export_png_preview_common(tree, cam, output, OPENCSG);
#else
fprintf(stderr,"This openscad was built without OpenCSG support\n");
#endif
@ -116,8 +97,7 @@ void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output)
void export_png_with_throwntogether(Tree &tree, Camera &cam, std::ostream &output)
{
export_png_preview_common( tree, cam, output, THROWN );
export_png_preview_common(tree, cam, output, THROWNTOGETHER);
}
#endif // ENABLE_CGAL

View file

@ -225,7 +225,7 @@ Highlighter::Highlighter(QTextDocument *parent)
tokentypes["prim3d"] << "cube" << "cylinder" << "sphere" << "polyhedron";
tokentypes["prim2d"] << "square" << "polygon" << "circle";
tokentypes["import"] << "include" << "use" << "import_stl" << "import" << "import_dxf" << "dxf_dim" << "dxf_cross" << "surface";
tokentypes["special"] << "$children" << "child" << "children" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr";
tokentypes["special"] << "$children" << "child" << "children" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr" << "$vpd";
tokentypes["extrude"] << "linear_extrude" << "rotate_extrude";
tokentypes["bracket"] << "[" << "]" << "(" << ")";
tokentypes["curlies"] << "{" << "}";

View file

@ -46,18 +46,3 @@ bool matrix_contains_nan( const Transform3d &m )
}
return false;
}
double getBoundingRadius(BoundingBox bbox)
{
// FIXME: For eigen3, we can use bbox.diagonal().norm()/2;
double radius = (bbox.max() - bbox.min()).norm() / 2;
return radius; // 0;
}
Vector3d getBoundingCenter(BoundingBox bbox)
{
// FIXME: For eigen3, we can use bbox.center();
Vector3d center = (bbox.min() + bbox.max()) / 2;
return center; // Vector3d(0,0,0);
}

View file

@ -21,9 +21,6 @@ bool matrix_contains_infinity( const Transform3d &m );
bool matrix_contains_nan( const Transform3d &m );
BoundingBox operator*(const Transform3d &m, const BoundingBox &box);
Vector3d getBoundingCenter(BoundingBox bbox);
double getBoundingRadius(BoundingBox bbox);
class Color4f : public Eigen::Vector4f
{

View file

@ -36,6 +36,7 @@
#include "highlighter.h"
#include "export.h"
#include "builtin.h"
#include "expression.h"
#include "progress.h"
#include "dxfdim.h"
#include "AboutDialog.h"
@ -204,6 +205,7 @@ MainWindow::MainWindow(const QString &filename)
tval = 0;
fps = 0;
fsteps = 1;
isClosing = false;
const QString importStatement = "import(\"%1\");\n";
const QString surfaceStatement = "surface(\"%1\");\n";
@ -370,6 +372,7 @@ MainWindow::MainWindow(const QString &filename)
connect(this->viewActionDiagonal, SIGNAL(triggered()), this, SLOT(viewAngleDiagonal()));
connect(this->viewActionCenter, SIGNAL(triggered()), this, SLOT(viewCenter()));
connect(this->viewActionResetView, SIGNAL(triggered()), this, SLOT(viewResetView()));
connect(this->viewActionViewAll, SIGNAL(triggered()), this, SLOT(viewAll()));
connect(this->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective()));
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole()));
@ -485,14 +488,10 @@ MainWindow::loadViewSettings(){
} else {
viewPerspective();
}
if (settings.value("view/hideConsole").toBool()) {
viewActionHide->setChecked(true);
hideConsole();
}
if (settings.value("view/hideEditor").toBool()) {
editActionHide->setChecked(true);
hideEditor();
}
viewActionHide->setChecked(settings.value("view/hideConsole").toBool());
hideConsole();
editActionHide->setChecked(settings.value("view/hideEditor").toBool());
hideEditor();
updateMdiMode(settings.value("advanced/mdi").toBool());
updateUndockMode(settings.value("advanced/undockableWindows").toBool());
}
@ -1366,6 +1365,68 @@ void MainWindow::updateTemporalVariables()
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360)));
top_ctx.set_variable("$vpr", Value(vpr));
top_ctx.set_variable("$vpd", Value(qglview->cam.viewer_distance));
}
/*!
* Update the viewport camera by evaluating the special variables. If they
* are assigned on top-level, the values are used to change the camera
* rotation, translation and distance.
*/
void MainWindow::updateCamera()
{
if (!root_module)
return;
bool camera_set = false;
double tx = qglview->cam.object_trans.x();
double ty = qglview->cam.object_trans.y();
double tz = qglview->cam.object_trans.z();
double rx = qglview->cam.object_rot.x();
double ry = qglview->cam.object_rot.y();
double rz = qglview->cam.object_rot.z();
double d = qglview->cam.viewer_distance;
BOOST_FOREACH(const Assignment &a, root_module->scope.assignments) {
double x, y, z;
if ("$vpr" == a.first) {
const Value vpr = a.second.get()->evaluate(&top_ctx);
if (vpr.getVec3(x, y, z)) {
rx = x;
ry = y;
rz = z;
camera_set = true;
}
} else if ("$vpt" == a.first) {
const Value vpt = a.second.get()->evaluate(&top_ctx);
if (vpt.getVec3(x, y, z)) {
tx = x;
ty = y;
tz = z;
camera_set = true;
}
} else if ("$vpd" == a.first) {
const Value vpd = a.second.get()->evaluate(&top_ctx);
if (vpd.type() == Value::NUMBER) {
d = vpd.toDouble();
camera_set = true;
}
}
}
if (camera_set) {
std::vector<double> params;
params.push_back(tx);
params.push_back(ty);
params.push_back(tz);
params.push_back(rx);
params.push_back(ry);
params.push_back(rz);
params.push_back(d);
qglview->cam.setup(params);
qglview->updateGL();
}
}
/*!
@ -1413,6 +1474,7 @@ void MainWindow::compileTopLevelDocument()
QFileInfo(this->fileName).absolutePath().toLocal8Bit(),
false);
updateCamera();
}
void MainWindow::checkAutoReload()
@ -2080,8 +2142,17 @@ void MainWindow::viewResetView()
this->qglview->updateGL();
}
void MainWindow::viewAll()
{
this->qglview->viewAll();
this->qglview->updateGL();
}
void MainWindow::on_editorDock_visibilityChanged(bool visible)
{
if (isClosing) {
return;
}
QSettings settings;
settings.setValue("view/hideEditor", !visible);
editActionHide->setChecked(!visible);
@ -2090,6 +2161,9 @@ void MainWindow::on_editorDock_visibilityChanged(bool visible)
void MainWindow::on_consoleDock_visibilityChanged(bool visible)
{
if (isClosing) {
return;
}
QSettings settings;
settings.setValue("view/hideConsole", !visible);
viewActionHide->setChecked(!visible);
@ -2257,6 +2331,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
delete this->tempFile;
this->tempFile = NULL;
}
isClosing = true;
event->accept();
} else {
event->ignore();

View file

@ -109,6 +109,7 @@ static void help(const char *progname)
"%2%[ --version ] [ --info ] \\\n"
"%2%[ --camera=translatex,y,z,rotx,y,z,dist | \\\n"
"%2% --camera=eyex,y,z,centerx,y,z ] \\\n"
"%2%[ --viewall ] \\\n"
"%2%[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n"
"%2%[ --render | --preview[=throwntogether] ] \\\n"
"%2%[ --csglimit=num ]"
@ -172,6 +173,10 @@ Camera get_camera( po::variables_map vm )
camera.gimbalDefaultTranslate();
}
if (vm.count("viewall")) {
camera.viewall = true;
}
if (vm.count("projection")) {
string proj = vm["projection"].as<string>();
if (proj=="o" || proj=="ortho" || proj=="orthogonal")
@ -430,7 +435,6 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
} else {
export_png_with_opencsg(tree, camera, fstream);
}
PRINTB("Camera eye: %f %f %f\n", camera.eye[0] % camera.eye[1] % camera.eye[2]);
fstream.close();
}
}
@ -609,6 +613,7 @@ int main(int argc, char **argv)
("preview", po::value<string>(), "if exporting a png image, do an OpenCSG(default) or ThrownTogether preview")
("csglimit", po::value<unsigned int>(), "if exporting a png image, stop rendering at the given number of CSG elements")
("camera", po::value<string>(), "parameters for camera when exporting png")
("viewall", "adjust camera to fit object")
("imgsize", po::value<string>(), "=width,height for exporting png")
("projection", po::value<string>(), "(o)rtho or (p)erspective when exporting png")
("debug", po::value<string>(), "special debug info")
@ -713,7 +718,7 @@ int main(int argc, char **argv)
currentdir = boosty::stringy(fs::current_path());
Camera camera = get_camera( vm );
Camera camera = get_camera(vm);
// Initialize global visitors
NodeCache nodecache;

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.1.2 *
* Date : 15 December 2013 *
* Version : 6.1.3a *
* Date : 22 January 2014 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* Copyright : Angus Johnson 2010-2014 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
@ -491,7 +491,52 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
}
//------------------------------------------------------------------------------
int PointInPolygon (const IntPoint& pt, OutPt* op)
int PointInPolygon (const IntPoint &pt, const Path &path)
{
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int result = 0;
size_t cnt = path.size();
if (cnt < 3) return 0;
IntPoint ip = path[0];
for(size_t i = 1; i <= cnt; ++i)
{
IntPoint ipNext = (i == cnt ? path[0] : path[i]);
if (ipNext.Y == pt.Y)
{
if ((ipNext.X == pt.X) || (ip.Y == pt.Y &&
((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1;
}
if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y))
{
if (ip.X >= pt.X)
{
if (ipNext.X > pt.X) result = 1 - result;
else
{
double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) -
(double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
if (!d) return -1;
if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
}
} else
{
if (ipNext.X > pt.X)
{
double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) -
(double)(ipNext.X - pt.X) * (ip.Y - pt.Y);
if (!d) return -1;
if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result;
}
}
}
ip = ipNext;
}
return result;
}
//------------------------------------------------------------------------------
int PointInPolygon (const IntPoint &pt, OutPt *op)
{
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
@ -534,7 +579,7 @@ int PointInPolygon (const IntPoint& pt, OutPt* op)
}
//------------------------------------------------------------------------------
bool Poly2ContainsPoly1(OutPt* OutPt1, OutPt* OutPt2)
bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
{
OutPt* op = OutPt1;
do
@ -1126,11 +1171,9 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
catch(...)
{
delete [] edges;
return false; //almost certainly a vertex has exceeded range
throw; //range test fails
}
TEdge *eStart = &edges[0];
if (!Closed) eStart->Prev->OutIdx = Skip;
//2. Remove duplicate vertices, and (when closed) collinear edges ...
TEdge *E = eStart, *eLoopStop = eStart;
@ -1171,7 +1214,11 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
return false;
}
if (!Closed) m_HasOpenPaths = true;
if (!Closed)
{
m_HasOpenPaths = true;
eStart->Prev->OutIdx = Skip;
}
//3. Do second stage of edge initialization ...
E = eStart;
@ -1431,21 +1478,12 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc)
//------------------------------------------------------------------------------
#endif
void Clipper::Clear()
{
if (m_edges.empty()) return; //avoids problems with ClipperBase destructor
DisposeAllOutRecs();
ClipperBase::Clear();
}
//------------------------------------------------------------------------------
void Clipper::Reset()
{
ClipperBase::Reset();
m_Scanbeam.clear();
m_ActiveEdges = 0;
m_SortedEdges = 0;
DisposeAllOutRecs();
LocalMinima* lm = m_MinimaList;
while (lm)
{
@ -1469,6 +1507,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
m_UsingPolyTree = false;
bool succeeded = ExecuteInternal();
if (succeeded) BuildResult(solution);
DisposeAllOutRecs();
m_ExecuteLocked = false;
return succeeded;
}
@ -1485,6 +1524,7 @@ bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
m_UsingPolyTree = true;
bool succeeded = ExecuteInternal();
if (succeeded) BuildResult2(polytree);
DisposeAllOutRecs();
m_ExecuteLocked = false;
return succeeded;
}
@ -2674,12 +2714,13 @@ void Clipper::PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam)
//First, match up overlapping horizontal edges (eg when one polygon's
//intermediate horz edge overlaps an intermediate horz edge of another, or
//when one polygon sits on top of another) ...
for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
{
Join* j = m_GhostJoins[i];
if (HorzSegmentsOverlap(j->OutPt1->Pt, j->OffPt, horzEdge->Bot, horzEdge->Top))
AddJoin(j->OutPt1, outPt, j->OffPt);
}
//for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
//{
// Join* j = m_GhostJoins[i];
// if (HorzSegmentsOverlap(j->OutPt1->Pt, j->OffPt, horzEdge->Bot, horzEdge->Top))
// AddJoin(j->OutPt1, outPt, j->OffPt);
//}
//Also, since horizontal edges at the top of one SB are often removed from
//the AEL before we process the horizontal edges at the bottom of the next,
//we need to create 'ghost' Join records of 'contrubuting' horizontals that
@ -4255,6 +4296,15 @@ void ReversePaths(Paths& p)
}
//------------------------------------------------------------------------------
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType)
{
Clipper c;
c.StrictlySimple(true);
c.AddPath(in_poly, ptSubject, true);
c.Execute(ctUnion, out_polys, fillType, fillType);
}
//------------------------------------------------------------------------------
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType)
{
Clipper c;
@ -4428,8 +4478,8 @@ void Minkowski(const Path& poly, const Path& path,
Paths quads;
quads.reserve((pathCnt + delta) * (polyCnt + 1));
for (size_t i = 0; i <= pathCnt - 2 + delta; ++i)
for (size_t j = 0; j <= polyCnt - 1; ++j)
for (size_t i = 0; i < pathCnt - 1 + delta; ++i)
for (size_t j = 0; j < polyCnt; ++j)
{
Path quad;
quad.reserve(4);
@ -4447,15 +4497,30 @@ void Minkowski(const Path& poly, const Path& path,
}
//------------------------------------------------------------------------------
void MinkowskiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed)
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed)
{
Minkowski(poly, path, solution, true, isClosed);
Minkowski(pattern, path, solution, true, pathIsClosed);
}
//------------------------------------------------------------------------------
void MinkowskiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed)
void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution,
PolyFillType pathFillType, bool pathIsClosed)
{
Minkowski(poly, path, solution, false, isClosed);
Clipper c;
for (size_t i = 0; i < paths.size(); ++i)
{
Paths tmp;
Minkowski(pattern, paths[i], tmp, true, pathIsClosed);
c.AddPaths(tmp, ptSubject, true);
}
if (pathIsClosed) c.AddPaths(paths, ptClip, true);
c.Execute(ctUnion, solution, pathFillType, pathFillType);
}
//------------------------------------------------------------------------------
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution)
{
Minkowski(poly1, poly2, solution, false, true);
}
//------------------------------------------------------------------------------

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.1.2 *
* Date : 15 December 2013 *
* Version : 6.1.3a *
* Date : 22 January 2014 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 *
* Copyright : Angus Johnson 2010-2014 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
@ -34,7 +34,7 @@
#ifndef clipper_hpp
#define clipper_hpp
#define CLIPPER_VERSION "6.1.2"
#define CLIPPER_VERSION "6.1.3"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
@ -166,6 +166,7 @@ private:
bool Orientation(const Path &poly);
double Area(const Path &poly);
int PointInPolygon(const IntPoint &pt, const Path &path);
#ifdef use_deprecated
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
@ -181,8 +182,10 @@ void CleanPolygon(Path& poly, double distance = 1.415);
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
void CleanPolygons(Paths& polys, double distance = 1.415);
void MinkowskiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void MinkowskiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
void MinkowskiSum(const Path& pattern, const Paths& paths,
Paths& solution, PolyFillType pathFillType, bool pathIsClosed);
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
@ -259,7 +262,6 @@ public:
PolyTree &polytree,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
void Clear();
bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;};
bool StrictlySimple() {return m_StrictSimple;};

View file

@ -13,7 +13,8 @@ class Renderer
public:
virtual ~Renderer() {}
virtual void draw(bool showfaces, bool showedges) const = 0;
virtual BoundingBox getBoundingBox() const = 0;
#define CSGMODE_DIFFERENCE_FLAG 0x10
enum csgmode_e {
CSGMODE_NONE = 0x00,

View file

@ -138,7 +138,6 @@ if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-extensions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")
endif()
@ -153,27 +152,34 @@ function(inclusion user_set_path found_paths)
# their set_paths to be a priority.
if (DEBUG_OSCD)
message(STATUS "inclusion ${user_set_path} ${found_paths}")
message(STATUS "inclusion ${${user_set_path}} ${${found_paths}}")
message(STATUS "inclusion:")
message(STATUS " ${user_set_path}: ${${user_set_path}}")
message(STATUS " ${found_paths}: ${${found_paths}}")
endif()
set( inclusion_match 0 )
foreach( found_path ${${found_paths}} )
if (${found_path} MATCHES ${${user_set_path}}.*)
set( inclusion_match 1 )
set(inclusion_match 0)
if (${user_set_path})
foreach(found_path ${${found_paths}})
string(FIND ${found_path} ${${user_set_path}} INDEX)
if (DEFINED INDEX)
if (${INDEX} EQUAL 0)
set(inclusion_match 1)
endif()
endif()
endforeach()
if (inclusion_match)
include_directories(BEFORE ${${found_paths}})
if (DEBUG_OSCD)
message(STATUS "inclusion prepend ${${found_paths}} for ${user_set_path}")
endif()
set(inclusion_match 0)
endif()
endforeach()
if (user_set_path AND inclusion_match)
include_directories(BEFORE ${${found_paths}})
if (DEBUG_OSCD)
message(STATUS "inclusion prepend ${${found_paths}} for ${user_set_path}")
endif()
else()
endif()
if (NOT inclusion_match)
include_directories(AFTER ${${found_paths}})
if (DEBUG_OSCD)
message(STATUS "inclusion append ${${found_paths}} for ${user_set_path}")
endif()
endif()
set( inclusion_match 0 )
endfunction()
# Boost
@ -208,14 +214,26 @@ if (NOT $ENV{BOOSTDIR} STREQUAL "")
endif()
find_package( Boost 1.35.0 COMPONENTS thread program_options filesystem system regex REQUIRED)
message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
message(STATUS "Boost ${Boost_VERSION} includes found: " ${Boost_INCLUDE_DIRS})
message(STATUS "Boost libraries found:")
foreach(boostlib ${Boost_LIBRARIES})
message(STATUS " " ${boostlib})
endforeach()
inclusion(BOOST_ROOT Boost_INCLUDE_DIRS)
add_definitions(-DBOOST_FILESYSTEM_VERSION=3) # Use V3 for boost 1.44-1.45
if (${Boost_VERSION} LESS 104600)
add_definitions(-DBOOST_FILESYSTEM_VERSION=3) # Use V3 for boost 1.44-1.45
endif()
# On Mac, we need to link against the correct C++ library. We choose the same one
# as Boost uses.
if(APPLE)
execute_process(COMMAND grep -q __112basic_string ${Boost_LIBRARIES}
RESULT_VARIABLE BOOST_USE_STDLIBCPP)
if (NOT BOOST_USE_STDLIBCPP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
endif()
# Mac OS X
if(APPLE)
@ -570,6 +588,7 @@ set(CORE_SOURCES
../src/parsersettings.cc
../src/mathc99.cc
../src/linalg.cc
../src/Camera.cc
../src/handle_dep.cc
../src/value.cc
../src/calc.cc
@ -1095,7 +1114,7 @@ add_cmdline_test(dumptest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX csg FILES ${DUM
add_cmdline_test(dumptest-examples EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX csg FILES ${EXAMPLE_FILES})
add_cmdline_test(cgalpngtest EXE ${OPENSCAD_BINPATH} ARGS --render -o SUFFIX png FILES ${CGALPNGTEST_FILES})
add_cmdline_test(opencsgtest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX png FILES ${OPENCSGTEST_FILES})
add_cmdline_test(csgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT csg-import-test.py ARGS ${OPENSCAD_BINPATH} EXPECTEDDIR cgalpngtest SUFFIX png FILES ${CGALPNGTEST_FILES})
add_cmdline_test(csgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=csg EXPECTEDDIR cgalpngtest SUFFIX png FILES ${CGALPNGTEST_FILES})
add_cmdline_test(throwntogethertest EXE ${OPENSCAD_BINPATH} ARGS --preview=throwntogether -o SUFFIX png FILES ${THROWNTOGETHERTEST_FILES})
# FIXME: We don't actually need to compare the output of cgalstlsanitytest
# with anything. It's self-contained and returns != 0 on error
@ -1148,36 +1167,64 @@ add_cmdline_test(openscad-imgstretch2 EXE ${OPENSCAD_BINPATH}
ARGS --imgsize 100,500 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective gimbal cam
add_cmdline_test(openscad-camdist EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=0,0,0,90,0,90,300 -o
ARGS --imgsize=500,500 --camera=0,0,0,90,0,90,100 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective gimbal cam
add_cmdline_test(openscad-camrot EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=0,0,0,440,337.5,315,300 -o
ARGS --imgsize=500,500 --camera=0,0,0,440,337.5,315,100 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective gimbal cam
add_cmdline_test(openscad-camtrans EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 -o
ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,100 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective gimbal cam, viewall
add_cmdline_test(openscad-camtrans-viewall EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,3000 --viewall -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Orthographic gimbal cam
add_cmdline_test(openscad-camortho EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,300 --projection=o -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Orthographic gimbal cam viewall
add_cmdline_test(openscad-camortho-viewall EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=100,-20,-10,90,0,90,3000 --viewall --projection=o -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective vector cam
add_cmdline_test(openscad-cameye EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=60,40,30,0,0,0 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective vector cam
add_cmdline_test(openscad-cameye2 EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective vector cam
add_cmdline_test(openscad-camcenter EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=60,40,30,20,10,30 -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Perspective vector cam viewall
add_cmdline_test(openscad-camcenter-viewall EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=60,40,30,20,10,30 --viewall -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
# Orthographic vector cam
add_cmdline_test(openscad-cameyeortho EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=160,140,130,0,0,0 --projection=o -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
add_cmdline_test(openscad-camcenter EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=60,40,30,20,10,30 -o
# Orthographic vector cam viewall
add_cmdline_test(openscad-cameyeortho-viewall EXE ${OPENSCAD_BINPATH}
ARGS --imgsize=500,500 --camera=16,14,13,0,0,0 --viewall --projection=o -o
SUFFIX png
FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/camera-tests.scad)
@ -1187,3 +1234,5 @@ message("Available test configurations: ${TEST_CONFIGS}")
#foreach(CONF ${TEST_CONFIGS})
# message("${CONF}: ${${CONF}_TEST_CONFIG}")
#endforeach()
message("CPPFLAGS: ${CMAKE_CXX_FLAGS}")

View file

@ -1,14 +0,0 @@
#!/usr/bin/env python
import sys, os, re, subprocess
scad = sys.argv[1]
bin = sys.argv[2]
png = sys.argv[3]
csg = re.sub(r"\.scad$", ".csg", scad)
print(bin, scad, csg, png);
subprocess.call([bin, scad, '-o', csg])
subprocess.call([bin, csg, '--render', '-o', png])
os.remove(csg);

View file

@ -0,0 +1,108 @@
#!/usr/bin/env python
# Export-import test
#
#
# Usage: <script> <inputfile> --openscad=<executable-path> --format=<format> file.png
#
#
# step 1. If the input file is _not_ and .scad file, create a temporary .scad file importing the input file.
# step 2. process the .scad file, output an export format (csg, stl, off, dxf, svg, amf)
# step 3. If the export format is _not_ .csg, create a temporary new .scad file importing the exported file
# step 4. render the .csg or .scad file to the given .png file
# step 5. (done in CTest) - compare the generated .png file to expected output
# of the original .scad file. they should be the same!
#
# This script should return 0 on success, not-0 on error.
#
# Authors: Torsten Paul, Don Bright, Marius Kintel
import sys, os, re, subprocess, argparse
def failquit(*args):
if len(args)!=0: print(args)
print('test_3d_export args:',str(sys.argv))
print('exiting test_3d_export.py with failure')
sys.exit(1)
def createImport(inputfile, scadfile):
print ('createImport: ' + inputfile + " " + scadfile)
outputdir = os.path.dirname(scadfile)
try:
if not os.path.exists(outputdir): os.mkdir(outputdir)
f = open(scadfile,'w')
f.write('import("'+inputfile+'");'+os.linesep)
f.close()
except:
failquit('failure while opening/writing ' + scadfile)
#
# Parse arguments
#
formats = ['csg', 'stl','off', 'amf', 'dxf', 'svg']
parser = argparse.ArgumentParser()
parser.add_argument('--openscad', required=True, help='Specify OpenSCAD executable')
parser.add_argument('--format', required=True, choices=[item for sublist in [(f,f.upper()) for f in formats] for item in sublist], help='Specify 3d export format')
args,remaining_args = parser.parse_known_args()
args.format = args.format.lower()
inputfile = remaining_args[0] # Can be .scad file or a file to be imported
pngfile = remaining_args[-1]
remaining_args = remaining_args[1:-1] # Passed on to the OpenSCAD executable
if not os.path.exists(inputfile):
failquit('cant find input file named: ' + inputfile)
if not os.path.exists(args.openscad):
failquit('cant find openscad executable named: ' + args.openscad)
outputdir = os.path.dirname(pngfile)
inputpath, inputfilename = os.path.split(inputfile)
inputbasename,inputsuffix = os.path.splitext(inputfilename)
if args.format == 'csg':
# Must export to same folder for include/use/import to work
exportfile = inputfile + '.' + args.format
else:
exportfile = os.path.join(outputdir, inputfilename)
if args.format != inputsuffix[1:]: exportfile += '.' + args.format
# If we're not reading an .scad or .csg file, we need to import it.
if inputsuffix != '.scad' and inputsuffix != '.csg':
# FIXME: Remove tempfile if created
tempfile = os.path.join(outputdir, inputfilename + '.scad')
createImport(inputfile, tempfile)
inputfile = tempfile
#
# First run: Just export the given filetype
#
export_cmd = [args.openscad, inputfile, '-o', exportfile] + remaining_args
print('Running OpenSCAD #1:')
print(' '.join(export_cmd))
result = subprocess.call(export_cmd)
if result != 0:
failquit('OpenSCAD #1 failed with return code ' + str(result))
#
# Second run: Import the exported file and render as png
#
newscadfile = exportfile
# If we didn't export a .csg file, we need to import it
if args.format != 'csg':
newscadfile += '.scad'
createImport(exportfile, newscadfile)
create_png_cmd = [args.openscad, newscadfile, '--render', '-o', pngfile] + remaining_args
print('Running OpenSCAD #2:')
print(' '.join(create_png_cmd))
result = subprocess.call(create_png_cmd)
if result != 0:
failquit('OpenSCAD #2 failed with return code ' + str(result))
try: os.remove(exportfile)
except: failquit('failure at os.remove('+exportfile+')')
if newscadfile != exportfile:
try: os.remove(newscadfile)
except: failquit('failure at os.remove('+newscadfile+')')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB