forked from bartvdbraak/blender
Another "insanely" big code clean-up patch by Bastien Montagne, many thanks!
This commit is contained in:
parent
8b57a67f3e
commit
fa0211df26
@ -1,141 +1,154 @@
|
|||||||
//
|
/*
|
||||||
// Filename : BBox.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : A class to hold a bounding box
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 22/05/2003
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BBOX_H__
|
||||||
|
#define __BBOX_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/BBox.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief A class to hold a bounding box
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 22/05/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef BBOX_H
|
|
||||||
# define BBOX_H
|
|
||||||
|
|
||||||
template <class Point>
|
template <class Point>
|
||||||
class BBox
|
class BBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
inline BBox()
|
||||||
|
{
|
||||||
|
_empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
inline BBox() {
|
template <class T>
|
||||||
_empty = true;
|
inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in)
|
||||||
}
|
{
|
||||||
|
_empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in) {
|
inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax())
|
||||||
_empty = false;
|
{
|
||||||
}
|
_empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax()) {
|
inline void extendToContain(const T& p)
|
||||||
_empty = false;
|
{
|
||||||
}
|
if (_empty) {
|
||||||
|
_min = p;
|
||||||
|
_max = p;
|
||||||
|
_empty = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < Point::dim(); i++) {
|
||||||
|
if (p[i] < _min[i])
|
||||||
|
_min[i] = p[i];
|
||||||
|
else if (p[i] > _max[i])
|
||||||
|
_max[i] = p[i];
|
||||||
|
}
|
||||||
|
_empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
inline void clear()
|
||||||
inline void extendToContain(const T& p) {
|
{
|
||||||
if (_empty) {
|
_empty = true;
|
||||||
_min = p;
|
}
|
||||||
_max = p;
|
|
||||||
_empty = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < Point::dim(); i++) {
|
|
||||||
if (p[i] < _min[i])
|
|
||||||
_min[i] = p[i];
|
|
||||||
else if (p[i] > _max[i])
|
|
||||||
_max[i] = p[i];
|
|
||||||
}
|
|
||||||
_empty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void clear() {
|
inline bool empty() const
|
||||||
_empty = true;
|
{
|
||||||
}
|
return _empty;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool empty() const {
|
inline const Point& getMin() const
|
||||||
return _empty;
|
{
|
||||||
}
|
return _min;
|
||||||
|
}
|
||||||
|
|
||||||
inline const Point& getMin() const {
|
inline const Point& getMax() const
|
||||||
return _min;
|
{
|
||||||
}
|
return _max;
|
||||||
|
}
|
||||||
|
|
||||||
inline const Point& getMax() const {
|
inline BBox<Point>& operator=(const BBox<Point>& b)
|
||||||
return _max;
|
{
|
||||||
}
|
_min = b.getMin();
|
||||||
|
_max = b.getMax();
|
||||||
|
_empty = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline BBox<Point>& operator=(const BBox<Point>& b) {
|
inline BBox<Point>& operator+=(const BBox<Point>& b)
|
||||||
_min = b.getMin();
|
{
|
||||||
_max = b.getMax();
|
if (_empty) {
|
||||||
_empty = false;
|
_min = b.getMin();
|
||||||
return *this;
|
_max = b.getMax();
|
||||||
}
|
_empty = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (unsigned int i = 0; i < Point::dim(); i++) {
|
||||||
|
if (b.getMin()[i] < _min[i])
|
||||||
|
_min[i] = b.getMin()[i];
|
||||||
|
if (b.getMax()[i] > _max[i])
|
||||||
|
_max[i] = b.getMax()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline BBox<Point>& operator+=(const BBox<Point>& b) {
|
inline bool inside(const Point& p)
|
||||||
if (_empty) {
|
{
|
||||||
_min = b.getMin();
|
if (empty())
|
||||||
_max = b.getMax();
|
return false;
|
||||||
_empty = false;
|
for (unsigned int i = 0; i < Point::dim(); i++) {
|
||||||
}
|
if ((_min[i]>p[i]) || (_max[i]<p[i]))
|
||||||
else {
|
return false;
|
||||||
for (unsigned i = 0; i < Point::dim(); i++) {
|
}
|
||||||
if (b.getMin()[i] < _min[i])
|
return true;
|
||||||
_min[i] = b.getMin()[i];
|
}
|
||||||
if (b.getMax()[i] > _max[i])
|
|
||||||
_max[i] = b.getMax()[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool inside(const Point& p){
|
|
||||||
if(empty())
|
|
||||||
return false;
|
|
||||||
for (unsigned i = 0; i < Point::dim(); i++) {
|
|
||||||
if((_min[i]>p[i]) || (_max[i]<p[i]))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Point _min;
|
||||||
Point _min;
|
Point _max;
|
||||||
Point _max;
|
bool _empty;
|
||||||
bool _empty;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Point>
|
template <class Point>
|
||||||
BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
|
BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
|
||||||
{
|
{
|
||||||
Point new_min;
|
Point new_min;
|
||||||
Point new_max;
|
Point new_max;
|
||||||
|
|
||||||
for (unsigned i = 0; i < Point::dim(); i++) {
|
for (unsigned int i = 0; i < Point::dim(); i++) {
|
||||||
new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
|
new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
|
||||||
new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
|
new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return BBox<Point>(new_min, new_max);
|
return BBox<Point>(new_min, new_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BBOX_H
|
#endif // __BBOX_H__
|
||||||
|
@ -1,23 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Bezier.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a Bezier curve of order 4.
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 04/06/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "Bezier.h"
|
#include "Bezier.h"
|
||||||
#include "FitCurve.h"
|
#include "FitCurve.h"
|
||||||
@ -34,85 +47,81 @@ BezierCurveSegment::~BezierCurveSegment()
|
|||||||
|
|
||||||
void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
|
void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
|
||||||
{
|
{
|
||||||
_ControlPolygon.push_back(iPoint);
|
_ControlPolygon.push_back(iPoint);
|
||||||
if(_ControlPolygon.size() == 4)
|
if (_ControlPolygon.size() == 4)
|
||||||
Build();
|
Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BezierCurveSegment::Build()
|
void BezierCurveSegment::Build()
|
||||||
{
|
{
|
||||||
if(_ControlPolygon.size() != 4)
|
if (_ControlPolygon.size() != 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Compute the rightmost part of the matrix:
|
// Compute the rightmost part of the matrix:
|
||||||
vector<Vec2d>::const_iterator p0,p1,p2,p3;
|
vector<Vec2d>::const_iterator p0,p1,p2,p3;
|
||||||
p0 = _ControlPolygon.begin();
|
p0 = _ControlPolygon.begin();
|
||||||
p1 = p0;++p1;
|
p1 = p0;
|
||||||
p2 = p1;++p2;
|
++p1;
|
||||||
p3 = p2;++p3;
|
p2 = p1;
|
||||||
float x[4], y[4];
|
++p2;
|
||||||
|
p3 = p2;
|
||||||
x[0] = -p0->x()+3*p1->x()-3*p2->x()+p3->x();
|
++p3;
|
||||||
x[1] = 3*p0->x()-6*p1->x()+3*p2->x();
|
float x[4], y[4];
|
||||||
x[2] = -3*p0->x()+3*p1->x();
|
|
||||||
x[3] = p0->x();
|
|
||||||
|
|
||||||
y[0] = -p0->y()+3*p1->y()-3*p2->y()+p3->y();
|
x[0] = -p0->x() + 3 * p1->x() - 3 * p2->x() + p3->x();
|
||||||
y[1] = 3*p0->y()-6*p1->y()+3*p2->y();
|
x[1] = 3 * p0->x() - 6 * p1->x() + 3 * p2->x();
|
||||||
y[2] = -3*p0->y()+3*p1->y();
|
x[2] = -3 * p0->x() + 3 * p1->x();
|
||||||
y[3] = p0->y();
|
x[3] = p0->x();
|
||||||
|
|
||||||
int nvertices = 12;
|
y[0] = -p0->y() + 3 * p1->y() - 3 * p2->y() + p3->y();
|
||||||
float increment = 1.0/(float)nvertices;
|
y[1] = 3 * p0->y() - 6 * p1->y() + 3 * p2->y();
|
||||||
float t = 0.f;
|
y[2] = -3 * p0->y() + 3 * p1->y();
|
||||||
for(int i=0; i<=nvertices; ++i)
|
y[3] = p0->y();
|
||||||
{
|
|
||||||
_Vertices.push_back(Vec2d((x[3] + t*(x[2] + t*(x[1] + t*x[0]))),
|
int nvertices = 12;
|
||||||
(y[3] + t*(y[2] + t*(y[1] + t*y[0])))));
|
float increment = 1.0 / (float)nvertices;
|
||||||
t+=increment;
|
float t = 0.0f;
|
||||||
}
|
for (int i = 0; i <= nvertices; ++i) {
|
||||||
|
_Vertices.push_back(Vec2d((x[3] + t * (x[2] + t * (x[1] + t * x[0]))),
|
||||||
|
(y[3] + t * (y[2] + t * (y[1] + t * y[0])))));
|
||||||
|
t += increment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BezierCurve::BezierCurve()
|
BezierCurve::BezierCurve()
|
||||||
{
|
{
|
||||||
_currentSegment = new BezierCurveSegment;
|
_currentSegment = new BezierCurveSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
|
BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
|
||||||
{
|
{
|
||||||
FitCurveWrapper fitcurve;
|
FitCurveWrapper fitcurve;
|
||||||
_currentSegment = new BezierCurveSegment;
|
_currentSegment = new BezierCurveSegment;
|
||||||
vector<Vec2d> curve;
|
vector<Vec2d> curve;
|
||||||
|
|
||||||
fitcurve.FitCurve(iPoints, curve, error);
|
fitcurve.FitCurve(iPoints, curve, error);
|
||||||
int i=0;
|
int i = 0;
|
||||||
vector<Vec2d>::iterator v,vend;
|
vector<Vec2d>::iterator v,vend;
|
||||||
for(v=curve.begin(),vend=curve.end();
|
for (v = curve.begin(), vend = curve.end(); v != vend; ++v) {
|
||||||
v!=vend;
|
if ((i == 0) || (i % 4 != 0))
|
||||||
++v)
|
AddControlPoint(*v);
|
||||||
{
|
++i;
|
||||||
if((i == 0) || (i%4 != 0))
|
}
|
||||||
AddControlPoint(*v);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BezierCurve::~BezierCurve()
|
BezierCurve::~BezierCurve()
|
||||||
{
|
{
|
||||||
if(_currentSegment)
|
if(_currentSegment)
|
||||||
delete _currentSegment;
|
delete _currentSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BezierCurve::AddControlPoint(const Vec2d& iPoint)
|
void BezierCurve::AddControlPoint(const Vec2d& iPoint)
|
||||||
{
|
{
|
||||||
_ControlPolygon.push_back(iPoint);
|
_ControlPolygon.push_back(iPoint);
|
||||||
_currentSegment->AddControlPoint(iPoint);
|
_currentSegment->AddControlPoint(iPoint);
|
||||||
if(_currentSegment->size() == 4)
|
if (_currentSegment->size() == 4) {
|
||||||
{
|
_Segments.push_back(_currentSegment);
|
||||||
_Segments.push_back(_currentSegment);
|
_currentSegment = new BezierCurveSegment;
|
||||||
_currentSegment = new BezierCurveSegment;
|
_currentSegment->AddControlPoint(iPoint);
|
||||||
_currentSegment->AddControlPoint(iPoint);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,73 +1,96 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Bezier.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a Bezier curve of order 4.
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 04/06/2003
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BEZIER_H__
|
||||||
|
#define __BEZIER_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Bezier.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a Bezier curve of order 4.
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 04/06/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef BEZIER_H
|
|
||||||
# define BEZIER_H
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../system/FreestyleConfig.h"
|
|
||||||
#include "Geom.h"
|
#include "Geom.h"
|
||||||
|
|
||||||
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT BezierCurveSegment
|
class LIB_GEOMETRY_EXPORT BezierCurveSegment
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<Vec2d> _ControlPolygon;
|
std::vector<Vec2d> _ControlPolygon;
|
||||||
std::vector<Vec2d> _Vertices;
|
std::vector<Vec2d> _Vertices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BezierCurveSegment();
|
BezierCurveSegment();
|
||||||
virtual ~BezierCurveSegment();
|
virtual ~BezierCurveSegment();
|
||||||
|
|
||||||
void AddControlPoint(const Vec2d& iPoint);
|
void AddControlPoint(const Vec2d& iPoint);
|
||||||
void Build();
|
void Build();
|
||||||
inline int size() const {return _ControlPolygon.size();}
|
|
||||||
inline std::vector<Vec2d>& vertices() {return _Vertices;}
|
inline int size() const
|
||||||
|
{
|
||||||
|
return _ControlPolygon.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<Vec2d>& vertices()
|
||||||
|
{
|
||||||
|
return _Vertices;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT BezierCurve
|
class LIB_GEOMETRY_EXPORT BezierCurve
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<Vec2d> _ControlPolygon;
|
std::vector<Vec2d> _ControlPolygon;
|
||||||
std::vector<BezierCurveSegment*> _Segments;
|
std::vector<BezierCurveSegment*> _Segments;
|
||||||
BezierCurveSegment *_currentSegment;
|
BezierCurveSegment *_currentSegment;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BezierCurve();
|
BezierCurve();
|
||||||
BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
|
BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
|
||||||
virtual ~BezierCurve();
|
virtual ~BezierCurve();
|
||||||
|
|
||||||
void AddControlPoint(const Vec2d& iPoint);
|
void AddControlPoint(const Vec2d& iPoint);
|
||||||
std::vector<Vec2d>& controlPolygon() {return _ControlPolygon;}
|
|
||||||
std::vector<BezierCurveSegment*>& segments() {return _Segments;}
|
std::vector<Vec2d>& controlPolygon()
|
||||||
|
{
|
||||||
|
return _ControlPolygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BezierCurveSegment*>& segments()
|
||||||
|
{
|
||||||
|
return _Segments;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BEZIER_H
|
#endif // __BEZIER_H__
|
||||||
|
@ -1,62 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/FastGrid.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cell grid surrounding the bounding box of the scene
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "FastGrid.h"
|
#include "FastGrid.h"
|
||||||
|
|
||||||
void FastGrid::clear() {
|
void FastGrid::clear()
|
||||||
if(!_cells)
|
{
|
||||||
return;
|
if (!_cells)
|
||||||
|
return;
|
||||||
|
|
||||||
for(unsigned i = 0; i < _cells_size; i++)
|
for (unsigned int i = 0; i < _cells_size; i++) {
|
||||||
if (_cells[i])
|
if (_cells[i])
|
||||||
delete _cells[i];
|
delete _cells[i];
|
||||||
delete[] _cells;
|
}
|
||||||
_cells = NULL;
|
delete[] _cells;
|
||||||
_cells_size = 0;
|
_cells = NULL;
|
||||||
|
_cells_size = 0;
|
||||||
|
|
||||||
Grid::clear();
|
Grid::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
|
void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
|
||||||
Grid::configure(orig, size, nb);
|
{
|
||||||
_cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
|
Grid::configure(orig, size, nb);
|
||||||
_cells = new Cell*[_cells_size];
|
_cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
|
||||||
memset(_cells, 0, _cells_size * sizeof(*_cells));
|
_cells = new Cell*[_cells_size];
|
||||||
|
memset(_cells, 0, _cells_size * sizeof(*_cells));
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell* FastGrid::getCell(const Vec3u& p) {
|
Cell *FastGrid::getCell(const Vec3u& p)
|
||||||
//cout << _cells<< " "<< p << " " <<_cells_nb[0]<<"-"<< _cells_nb[1]<<"-"<< _cells_nb[2]<< " "<<_cells_size<< endl;
|
{
|
||||||
assert(_cells||("_cells is a null pointer"));
|
#if 0
|
||||||
assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
|
cout << _cells << " " << p << " " << _cells_nb[0] << "-" << _cells_nb[1] << "-" << _cells_nb[2]
|
||||||
assert(p[0]<_cells_nb[0]);
|
<< " " << _cells_size << endl;
|
||||||
assert(p[1]<_cells_nb[1]);
|
#endif
|
||||||
assert(p[2]<_cells_nb[2]);
|
assert(_cells || ("_cells is a null pointer"));
|
||||||
return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
|
assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
|
||||||
|
assert(p[0] < _cells_nb[0]);
|
||||||
|
assert(p[1] < _cells_nb[1]);
|
||||||
|
assert(p[2] < _cells_nb[2]);
|
||||||
|
return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastGrid::fillCell(const Vec3u& p, Cell& cell) {
|
void FastGrid::fillCell(const Vec3u& p, Cell& cell)
|
||||||
assert(_cells||("_cells is a null pointer"));
|
{
|
||||||
assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
|
assert(_cells || ("_cells is a null pointer"));
|
||||||
assert(p[0]<_cells_nb[0]);
|
assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
|
||||||
assert(p[1]<_cells_nb[1]);
|
assert(p[0] < _cells_nb[0]);
|
||||||
assert(p[2]<_cells_nb[2]);
|
assert(p[1] < _cells_nb[1]);
|
||||||
_cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
|
assert(p[2] < _cells_nb[2]);
|
||||||
|
_cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
|
||||||
}
|
}
|
||||||
|
@ -1,85 +1,86 @@
|
|||||||
//
|
/*
|
||||||
// Filename : FastGrid.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a cell grid surrounding the
|
* This program is free software; you can redistribute it and/or
|
||||||
// bounding box of the scene
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 30/07/2002
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* GNU General Public License for more details.
|
||||||
// with this source distribution.
|
*
|
||||||
//
|
* You should have received a copy of the GNU General Public License
|
||||||
// This program is free software; you can redistribute it and/or
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
// modify it under the terms of the GNU General Public License
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
// as published by the Free Software Foundation; either version 2
|
*
|
||||||
// of the License, or (at your option) any later version.
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
//
|
* All rights reserved.
|
||||||
// This program is distributed in the hope that it will be useful,
|
*
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* The Original Code is: all of this file.
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
*
|
||||||
// GNU General Public License for more details.
|
* Contributor(s): none yet.
|
||||||
//
|
*
|
||||||
// You should have received a copy of the GNU General Public License
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef FASTGRID_H
|
|
||||||
# define FASTGRID_H
|
|
||||||
|
|
||||||
# include "Grid.h"
|
|
||||||
# include <cassert>
|
|
||||||
/*! Class to define a regular grid used for ray
|
|
||||||
* casting computations
|
|
||||||
* We don't use a hashtable here. The grid is
|
|
||||||
* explicitly stored for faster computations.
|
|
||||||
* However, this might result in significant
|
|
||||||
* increase in memory usage (compared to the regular grid)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __FASTGRID_H__
|
||||||
|
#define __FASTGRID_H__
|
||||||
|
|
||||||
|
/** \file blender/freestyle/intern/geometry/FastGrid.h
|
||||||
|
* \ingroup freestyle
|
||||||
|
* \brief Class to define a cell grid surrounding the bounding box of the scene
|
||||||
|
* \author Stephane Grabli
|
||||||
|
* \date 30/07/2002
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "Grid.h"
|
||||||
|
|
||||||
|
/*! Class to define a regular grid used for ray casting computations
|
||||||
|
* We don't use a hashtable here. The grid is explicitly stored for faster computations.
|
||||||
|
* However, this might result in significant increase in memory usage (compared to the regular grid)
|
||||||
|
*/
|
||||||
class LIB_GEOMETRY_EXPORT FastGrid : public Grid
|
class LIB_GEOMETRY_EXPORT FastGrid : public Grid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
FastGrid() : Grid()
|
||||||
|
{
|
||||||
|
_cells = NULL;
|
||||||
|
_cells_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
FastGrid() : Grid() {
|
virtual ~FastGrid()
|
||||||
_cells = NULL;
|
{
|
||||||
_cells_size = 0;
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FastGrid() {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! clears the grid
|
/*! clears the grid
|
||||||
* Deletes all the cells, clears the hashtable,
|
* Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
|
||||||
* resets size, size of cell, number of cells.
|
*/
|
||||||
*/
|
virtual void clear();
|
||||||
virtual void clear();
|
|
||||||
|
/*! Sets the different parameters of the grid
|
||||||
/*! Sets the different parameters of the grid
|
* orig
|
||||||
* orig
|
* The grid origin
|
||||||
* The grid origin
|
* size
|
||||||
* size
|
* The grid's dimensions
|
||||||
* The grid's dimensions
|
* nb
|
||||||
* nb
|
* The number of cells of the grid
|
||||||
* The number of cells of the grid
|
*/
|
||||||
*/
|
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
||||||
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
|
||||||
|
/*! returns the cell whose coordinates are pased as argument */
|
||||||
/*! returns the cell whose coordinates are pased as argument */
|
Cell* getCell(const Vec3u& p);
|
||||||
Cell* getCell(const Vec3u& p) ;
|
|
||||||
|
/*! Fills the case p with the cell iCell */
|
||||||
/*! Fills the case p with the cell iCell */
|
virtual void fillCell(const Vec3u& p, Cell& cell);
|
||||||
virtual void fillCell(const Vec3u& p, Cell& cell);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Cell **_cells;
|
||||||
Cell** _cells;
|
unsigned _cells_size;
|
||||||
unsigned _cells_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FASTGRID_H
|
#endif // __FASTGRID_H__
|
||||||
|
@ -1,33 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/FitCurve.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
|
||||||
//
|
* \brief from "Graphics Gems", Academic Press, 1990
|
||||||
// This program is free software; you can redistribute it and/or
|
* \author Stephane Grabli
|
||||||
// modify it under the terms of the GNU General Public License
|
* \date 06/06/2003
|
||||||
// as published by the Free Software Foundation; either version 2
|
*/
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// 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 <cstdlib> // for malloc and free
|
#include <cstdlib> // for malloc and free
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "FitCurve.h"
|
#include "FitCurve.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
typedef Vector2 *BezierCurve;
|
typedef Vector2 *BezierCurve;
|
||||||
|
|
||||||
|
// XXX Do we need "#ifdef __cplusplus" at all here???
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -46,379 +62,367 @@ static Vector2 ComputeLeftTangent(Vector2 *d, int end);
|
|||||||
static Vector2 ComputeLeftTangent(Vector2 *d, int end);
|
static Vector2 ComputeLeftTangent(Vector2 *d, int end);
|
||||||
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
|
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
|
||||||
static double *ChordLengthParameterize(Vector2 *d, int first, int last);
|
static double *ChordLengthParameterize(Vector2 *d, int first, int last);
|
||||||
static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
|
static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
|
||||||
static Vector2 V2AddII(Vector2 a, Vector2 b);
|
static Vector2 V2AddII(Vector2 a, Vector2 b);
|
||||||
static Vector2 V2ScaleIII(Vector2 v, double s);
|
static Vector2 V2ScaleIII(Vector2 v, double s);
|
||||||
static Vector2 V2SubII(Vector2 a, Vector2 b);
|
static Vector2 V2SubII(Vector2 a, Vector2 b);
|
||||||
|
|
||||||
|
#define MAXPOINTS 1000 /* The most points you can have */
|
||||||
|
|
||||||
#define MAXPOINTS 1000 /* The most points you can have */
|
/* returns squared length of input vector */
|
||||||
|
static double V2SquaredLength(Vector2 *a)
|
||||||
/* returns squared length of input vector */
|
{
|
||||||
static double V2SquaredLength(Vector2 *a)
|
return (((*a)[0] * (*a)[0]) + ((*a)[1] * (*a)[1]));
|
||||||
{ return(((*a)[0] * (*a)[0])+((*a)[1] * (*a)[1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns length of input vector */
|
/* returns length of input vector */
|
||||||
static double V2Length(Vector2 *a)
|
static double V2Length(Vector2 *a)
|
||||||
{
|
{
|
||||||
return(sqrt(V2SquaredLength(a)));
|
return (sqrt(V2SquaredLength(a)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector2 *V2Scale(Vector2 *v, double newlen)
|
static Vector2 *V2Scale(Vector2 *v, double newlen)
|
||||||
{
|
{
|
||||||
double len = V2Length(v);
|
double len = V2Length(v);
|
||||||
if (len != 0.0) { (*v)[0] *= newlen/len; (*v)[1] *= newlen/len; }
|
if (len != 0.0) {
|
||||||
return(v);
|
(*v)[0] *= newlen / len;
|
||||||
|
(*v)[1] *= newlen / len;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the dot product of vectors a and b */
|
/* return the dot product of vectors a and b */
|
||||||
static double V2Dot(Vector2 *a, Vector2 *b)
|
static double V2Dot(Vector2 *a, Vector2 *b)
|
||||||
{
|
{
|
||||||
return(((*a)[0]*(*b)[0])+((*a)[1]*(*b)[1]));
|
return (((*a)[0] * (*b)[0]) + ((*a)[1] * (*b)[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the distance between two points */
|
/* return the distance between two points */
|
||||||
static double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
|
static double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
|
||||||
{
|
{
|
||||||
double dx = (*a)[0] - (*b)[0];
|
double dx = (*a)[0] - (*b)[0];
|
||||||
double dy = (*a)[1] - (*b)[1];
|
double dy = (*a)[1] - (*b)[1];
|
||||||
return(sqrt((dx*dx)+(dy*dy)));
|
return (sqrt((dx * dx) + (dy * dy)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return vector sum c = a+b */
|
/* return vector sum c = a+b */
|
||||||
static Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
|
static Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
|
||||||
{
|
{
|
||||||
(*c)[0] = (*a)[0]+(*b)[0]; (*c)[1] = (*a)[1]+(*b)[1];
|
(*c)[0] = (*a)[0] + (*b)[0];
|
||||||
return(c);
|
(*c)[1] = (*a)[1] + (*b)[1];
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* normalizes the input vector and returns it */
|
/* normalizes the input vector and returns it */
|
||||||
static Vector2 *V2Normalize(Vector2 *v)
|
static Vector2 *V2Normalize(Vector2 *v)
|
||||||
{
|
{
|
||||||
double len = V2Length(v);
|
double len = V2Length(v);
|
||||||
if (len != 0.0) { (*v)[0] /= len; (*v)[1] /= len; }
|
if (len != 0.0) {
|
||||||
return(v);
|
(*v)[0] /= len;
|
||||||
|
(*v)[1] /= len;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* negates the input vector and returns it */
|
/* negates the input vector and returns it */
|
||||||
static Vector2 *V2Negate(Vector2 *v)
|
static Vector2 *V2Negate(Vector2 *v)
|
||||||
{
|
{
|
||||||
(*v)[0] = -(*v)[0]; (*v)[1] = -(*v)[1];
|
(*v)[0] = -(*v)[0];
|
||||||
return(v);
|
(*v)[1] = -(*v)[1];
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GenerateBezier:
|
||||||
/*
|
|
||||||
* GenerateBezier :
|
|
||||||
* Use least-squares method to find Bezier control points for region.
|
* Use least-squares method to find Bezier control points for region.
|
||||||
*
|
* Vector2 *d; Array of digitized points
|
||||||
|
* int first, last; Indices defining region
|
||||||
|
* double *uPrime; Parameter values for region
|
||||||
|
* Vector2 tHat1, tHat2; Unit tangents at endpoints
|
||||||
*/
|
*/
|
||||||
static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
|
static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
|
||||||
// Vector2 *d; /* Array of digitized points */
|
|
||||||
// int first, last; /* Indices defining region */
|
|
||||||
// double *uPrime; /* Parameter values for region */
|
|
||||||
// Vector2 tHat1, tHat2; /* Unit tangents at endpoints */
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
|
Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
|
||||||
int nPts; /* Number of pts in sub-curve */
|
int nPts; /* Number of pts in sub-curve */
|
||||||
double C[2][2]; /* Matrix C */
|
double C[2][2]; /* Matrix C */
|
||||||
double X[2]; /* Matrix X */
|
double X[2]; /* Matrix X */
|
||||||
double det_C0_C1, /* Determinants of matrices */
|
double det_C0_C1; /* Determinants of matrices */
|
||||||
det_C0_X,
|
double det_C0_X;
|
||||||
det_X_C1;
|
double det_X_C1;
|
||||||
double alpha_l, /* Alpha values, left and right */
|
double alpha_l; /* Alpha values, left and right */
|
||||||
alpha_r;
|
double alpha_r;
|
||||||
Vector2 tmp; /* Utility variable */
|
Vector2 tmp; /* Utility variable */
|
||||||
BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
|
BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
|
||||||
|
|
||||||
bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
|
bezCurve = (Vector2*)malloc(4 * sizeof(Vector2));
|
||||||
nPts = last - first + 1;
|
nPts = last - first + 1;
|
||||||
|
|
||||||
|
/* Compute the A's */
|
||||||
/* Compute the A's */
|
for (i = 0; i < nPts; i++) {
|
||||||
for (i = 0; i < nPts; i++) {
|
Vector2 v1, v2;
|
||||||
Vector2 v1, v2;
|
|
||||||
v1 = tHat1;
|
v1 = tHat1;
|
||||||
v2 = tHat2;
|
v2 = tHat2;
|
||||||
V2Scale(&v1, B1(uPrime[i]));
|
V2Scale(&v1, B1(uPrime[i]));
|
||||||
V2Scale(&v2, B2(uPrime[i]));
|
V2Scale(&v2, B2(uPrime[i]));
|
||||||
A[i][0] = v1;
|
A[i][0] = v1;
|
||||||
A[i][1] = v2;
|
A[i][1] = v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the C and X matrices */
|
/* Create the C and X matrices */
|
||||||
C[0][0] = 0.0;
|
C[0][0] = 0.0;
|
||||||
C[0][1] = 0.0;
|
C[0][1] = 0.0;
|
||||||
C[1][0] = 0.0;
|
C[1][0] = 0.0;
|
||||||
C[1][1] = 0.0;
|
C[1][1] = 0.0;
|
||||||
X[0] = 0.0;
|
X[0] = 0.0;
|
||||||
X[1] = 0.0;
|
X[1] = 0.0;
|
||||||
|
for (i = 0; i < nPts; i++) {
|
||||||
for (i = 0; i < nPts; i++) {
|
C[0][0] += V2Dot(&A[i][0], &A[i][0]);
|
||||||
C[0][0] += V2Dot(&A[i][0], &A[i][0]);
|
|
||||||
C[0][1] += V2Dot(&A[i][0], &A[i][1]);
|
C[0][1] += V2Dot(&A[i][0], &A[i][1]);
|
||||||
/* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/
|
// C[1][0] += V2Dot(&A[i][0], &A[i][1]);
|
||||||
C[1][0] = C[0][1];
|
C[1][0] = C[0][1];
|
||||||
C[1][1] += V2Dot(&A[i][1], &A[i][1]);
|
C[1][1] += V2Dot(&A[i][1], &A[i][1]);
|
||||||
|
|
||||||
tmp = V2SubII(d[first + i],
|
tmp = V2SubII(d[first + i],
|
||||||
V2AddII(
|
V2AddII(V2ScaleIII(d[first], B0(uPrime[i])),
|
||||||
V2ScaleIII(d[first], B0(uPrime[i])),
|
V2AddII(V2ScaleIII(d[first], B1(uPrime[i])),
|
||||||
V2AddII(
|
V2AddII(V2ScaleIII(d[last], B2(uPrime[i])),
|
||||||
V2ScaleIII(d[first], B1(uPrime[i])),
|
V2ScaleIII(d[last], B3(uPrime[i]))
|
||||||
V2AddII(
|
)
|
||||||
V2ScaleIII(d[last], B2(uPrime[i])),
|
)
|
||||||
V2ScaleIII(d[last], B3(uPrime[i]))))));
|
)
|
||||||
|
);
|
||||||
|
|
||||||
X[0] += V2Dot(&((A[i])[0]), &tmp);
|
X[0] += V2Dot(&((A[i])[0]), &tmp);
|
||||||
X[1] += V2Dot(&((A[i])[1]), &tmp);
|
X[1] += V2Dot(&((A[i])[1]), &tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the determinants of C and X */
|
/* Compute the determinants of C and X */
|
||||||
det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
|
det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
|
||||||
det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
|
det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
|
||||||
det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
|
det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
|
||||||
|
|
||||||
/* Finally, derive alpha values */
|
/* Finally, derive alpha values */
|
||||||
if (det_C0_C1 == 0.0) {
|
if (det_C0_C1 == 0.0) {
|
||||||
det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
|
det_C0_C1 = (C[0][0] * C[1][1]) * 10.0e-12;
|
||||||
}
|
}
|
||||||
alpha_l = det_X_C1 / det_C0_C1;
|
alpha_l = det_X_C1 / det_C0_C1;
|
||||||
alpha_r = det_C0_X / det_C0_C1;
|
alpha_r = det_C0_X / det_C0_C1;
|
||||||
|
|
||||||
|
|
||||||
/* If alpha negative, use the Wu/Barsky heuristic (see text) */
|
/* If alpha negative, use the Wu/Barsky heuristic (see text) (if alpha is 0, you get coincident control points
|
||||||
/* (if alpha is 0, you get coincident control points that lead to
|
* that lead to divide by zero in any subsequent NewtonRaphsonRootFind() call).
|
||||||
* divide by zero in any subsequent NewtonRaphsonRootFind() call. */
|
*/
|
||||||
if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
|
if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
|
||||||
double dist = V2DistanceBetween2Points(&d[last], &d[first]) /
|
double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
|
||||||
3.0;
|
|
||||||
|
|
||||||
bezCurve[0] = d[first];
|
bezCurve[0] = d[first];
|
||||||
bezCurve[3] = d[last];
|
bezCurve[3] = d[last];
|
||||||
V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
|
V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
|
||||||
V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
|
V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
|
||||||
return (bezCurve);
|
return bezCurve;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First and last control points of the Bezier curve are */
|
/* First and last control points of the Bezier curve are positioned exactly at the first and last data points
|
||||||
/* positioned exactly at the first and last data points */
|
* Control points 1 and 2 are positioned an alpha distance out on the tangent vectors, left and right, respectively
|
||||||
/* Control points 1 and 2 are positioned an alpha distance out */
|
*/
|
||||||
/* on the tangent vectors, left and right, respectively */
|
bezCurve[0] = d[first];
|
||||||
bezCurve[0] = d[first];
|
bezCurve[3] = d[last];
|
||||||
bezCurve[3] = d[last];
|
V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
|
||||||
V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
|
V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
|
||||||
V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
|
return (bezCurve);
|
||||||
return (bezCurve);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reparameterize:
|
* Reparameterize:
|
||||||
* Given set of points and their parameterization, try to find
|
* Given set of points and their parameterization, try to find a better parameterization.
|
||||||
* a better parameterization.
|
* Vector2 *d; Array of digitized points
|
||||||
*
|
* int first, last; Indices defining region
|
||||||
|
* double *u; Current parameter values
|
||||||
|
* BezierCurve bezCurve; Current fitted curve
|
||||||
*/
|
*/
|
||||||
static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
|
static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
|
||||||
// Vector2 *d; /* Array of digitized points */
|
|
||||||
// int first, last; /* Indices defining region */
|
|
||||||
// double *u; /* Current parameter values */
|
|
||||||
// BezierCurve bezCurve; /* Current fitted curve */
|
|
||||||
{
|
{
|
||||||
int nPts = last-first+1;
|
int nPts = last - first + 1;
|
||||||
int i;
|
int i;
|
||||||
double *uPrime; /* New parameter values */
|
double *uPrime; /* New parameter values */
|
||||||
|
|
||||||
uPrime = (double *)malloc(nPts * sizeof(double));
|
uPrime = (double*)malloc(nPts * sizeof(double));
|
||||||
for (i = first; i <= last; i++) {
|
for (i = first; i <= last; i++) {
|
||||||
uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-
|
uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i - first]);
|
||||||
first]);
|
}
|
||||||
}
|
return (uPrime);
|
||||||
return (uPrime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NewtonRaphsonRootFind :
|
* NewtonRaphsonRootFind:
|
||||||
* Use Newton-Raphson iteration to find better root.
|
* Use Newton-Raphson iteration to find better root.
|
||||||
|
* BezierCurve Q; Current fitted curve
|
||||||
|
* Vector2 P; Digitized point
|
||||||
|
* double u; Parameter value for "P"
|
||||||
*/
|
*/
|
||||||
static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
|
static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
|
||||||
// BezierCurve Q; /* Current fitted curve */
|
|
||||||
// Vector2 P; /* Digitized point */
|
|
||||||
// double u; /* Parameter value for "P" */
|
|
||||||
{
|
{
|
||||||
double numerator, denominator;
|
double numerator, denominator;
|
||||||
Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
|
Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
|
||||||
Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
|
Vector2 Q_u, Q1_u, Q2_u; /* u evaluated at Q, Q', & Q'' */
|
||||||
double uPrime; /* Improved u */
|
double uPrime; /* Improved u */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Compute Q(u) */
|
/* Compute Q(u) */
|
||||||
Q_u = BezierII(3, Q, u);
|
Q_u = BezierII(3, Q, u);
|
||||||
|
|
||||||
/* Generate control vertices for Q' */
|
/* Generate control vertices for Q' */
|
||||||
for (i = 0; i <= 2; i++) {
|
for (i = 0; i <= 2; i++) {
|
||||||
Q1[i][0] = (Q[i+1][0] - Q[i][0]) * 3.0;
|
Q1[i][0] = (Q[i + 1][0] - Q[i][0]) * 3.0;
|
||||||
Q1[i][1] = (Q[i+1][1] - Q[i][1]) * 3.0;
|
Q1[i][1] = (Q[i + 1][1] - Q[i][1]) * 3.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate control vertices for Q'' */
|
/* Generate control vertices for Q'' */
|
||||||
for (i = 0; i <= 1; i++) {
|
for (i = 0; i <= 1; i++) {
|
||||||
Q2[i][0] = (Q1[i+1][0] - Q1[i][0]) * 2.0;
|
Q2[i][0] = (Q1[i + 1][0] - Q1[i][0]) * 2.0;
|
||||||
Q2[i][1] = (Q1[i+1][1] - Q1[i][1]) * 2.0;
|
Q2[i][1] = (Q1[i + 1][1] - Q1[i][1]) * 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute Q'(u) and Q''(u) */
|
/* Compute Q'(u) and Q''(u) */
|
||||||
Q1_u = BezierII(2, Q1, u);
|
Q1_u = BezierII(2, Q1, u);
|
||||||
Q2_u = BezierII(1, Q2, u);
|
Q2_u = BezierII(1, Q2, u);
|
||||||
|
|
||||||
/* Compute f(u)/f'(u) */
|
/* Compute f(u)/f'(u) */
|
||||||
numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
|
numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
|
||||||
denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
|
denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
|
||||||
(Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
|
(Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
|
||||||
|
|
||||||
/* u = u - f(u)/f'(u) */
|
/* u = u - f(u)/f'(u) */
|
||||||
if(denominator == 0) // FIXME
|
if (denominator == 0) // FIXME
|
||||||
return u;
|
return u;
|
||||||
uPrime = u - (numerator/denominator);
|
uPrime = u - (numerator / denominator);
|
||||||
return (uPrime);
|
return uPrime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bezier :
|
* Bezier:
|
||||||
* Evaluate a Bezier curve at a particular parameter value
|
* Evaluate a Bezier curve at a particular parameter value
|
||||||
*
|
* int degree; The degree of the bezier curve
|
||||||
|
* Vector2 *V; Array of control points
|
||||||
|
* double t; Parametric value to find point for
|
||||||
*/
|
*/
|
||||||
static Vector2 BezierII(int degree, Vector2 *V, double t)
|
static Vector2 BezierII(int degree, Vector2 *V, double t)
|
||||||
// int degree; /* The degree of the bezier curve */
|
|
||||||
// Vector2 *V; /* Array of control points */
|
|
||||||
// double t; /* Parametric value to find point for */
|
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
Vector2 Q; /* Point on curve at parameter t */
|
Vector2 Q; /* Point on curve at parameter t */
|
||||||
Vector2 *Vtemp; /* Local copy of control points */
|
Vector2 *Vtemp; /* Local copy of control points */
|
||||||
|
|
||||||
/* Copy array */
|
/* Copy array */
|
||||||
Vtemp = (Vector2 *)malloc((unsigned)((degree+1)
|
Vtemp = (Vector2*)malloc((unsigned)((degree + 1) * sizeof (Vector2)));
|
||||||
* sizeof (Vector2)));
|
for (i = 0; i <= degree; i++) {
|
||||||
for (i = 0; i <= degree; i++) {
|
|
||||||
Vtemp[i] = V[i];
|
Vtemp[i] = V[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Triangle computation */
|
/* Triangle computation */
|
||||||
for (i = 1; i <= degree; i++) {
|
for (i = 1; i <= degree; i++) {
|
||||||
for (j = 0; j <= degree-i; j++) {
|
for (j = 0; j <= degree-i; j++) {
|
||||||
Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j+1][0];
|
Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j + 1][0];
|
||||||
Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j+1][1];
|
Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j + 1][1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q = Vtemp[0];
|
Q = Vtemp[0];
|
||||||
free((void *)Vtemp);
|
free((void*)Vtemp);
|
||||||
return Q;
|
return Q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* B0, B1, B2, B3 :
|
* B0, B1, B2, B3:
|
||||||
* Bezier multipliers
|
* Bezier multipliers
|
||||||
*/
|
*/
|
||||||
static double B0(double u)
|
static double B0(double u)
|
||||||
{
|
{
|
||||||
double tmp = 1.0 - u;
|
double tmp = 1.0 - u;
|
||||||
return (tmp * tmp * tmp);
|
return (tmp * tmp * tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static double B1(double u)
|
static double B1(double u)
|
||||||
{
|
{
|
||||||
double tmp = 1.0 - u;
|
double tmp = 1.0 - u;
|
||||||
return (3 * u * (tmp * tmp));
|
return (3 * u * (tmp * tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static double B2(double u)
|
static double B2(double u)
|
||||||
{
|
{
|
||||||
double tmp = 1.0 - u;
|
double tmp = 1.0 - u;
|
||||||
return (3 * u * u * tmp);
|
return (3 * u * u * tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double B3(double u)
|
static double B3(double u)
|
||||||
{
|
{
|
||||||
return (u * u * u);
|
return (u * u * u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
|
* ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent:
|
||||||
*Approximate unit tangents at endpoints and "center" of digitized curve
|
* Approximate unit tangents at endpoints and "center" of digitized curve
|
||||||
|
*/
|
||||||
|
/* Vector2 *d; Digitized points
|
||||||
|
* int end; Index to "left" end of region
|
||||||
*/
|
*/
|
||||||
static Vector2 ComputeLeftTangent(Vector2 *d, int end)
|
static Vector2 ComputeLeftTangent(Vector2 *d, int end)
|
||||||
// Vector2 *d; /* Digitized points*/
|
|
||||||
// int end; /* Index to "left" end of region */
|
|
||||||
{
|
{
|
||||||
Vector2 tHat1;
|
Vector2 tHat1;
|
||||||
tHat1 = V2SubII(d[end+1], d[end]);
|
tHat1 = V2SubII(d[end + 1], d[end]);
|
||||||
tHat1 = *V2Normalize(&tHat1);
|
tHat1 = *V2Normalize(&tHat1);
|
||||||
return tHat1;
|
return tHat1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Vector2 *d; Digitized points
|
||||||
|
* int end; Index to "right" end of region
|
||||||
|
*/
|
||||||
static Vector2 ComputeRightTangent(Vector2 *d, int end)
|
static Vector2 ComputeRightTangent(Vector2 *d, int end)
|
||||||
// Vector2 *d; /* Digitized points */
|
|
||||||
// int end; /* Index to "right" end of region */
|
|
||||||
{
|
{
|
||||||
Vector2 tHat2;
|
Vector2 tHat2;
|
||||||
tHat2 = V2SubII(d[end-1], d[end]);
|
tHat2 = V2SubII(d[end - 1], d[end]);
|
||||||
tHat2 = *V2Normalize(&tHat2);
|
tHat2 = *V2Normalize(&tHat2);
|
||||||
return tHat2;
|
return tHat2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Vector2 *d; Digitized points
|
||||||
|
* int end; Index to point inside region
|
||||||
|
*/
|
||||||
static Vector2 ComputeCenterTangent(Vector2 *d, int center)
|
static Vector2 ComputeCenterTangent(Vector2 *d, int center)
|
||||||
// Vector2 *d; /* Digitized points */
|
|
||||||
// int center; /* Index to point inside region */
|
|
||||||
{
|
{
|
||||||
Vector2 V1, V2, tHatCenter;
|
Vector2 V1, V2, tHatCenter;
|
||||||
|
|
||||||
V1 = V2SubII(d[center-1], d[center]);
|
V1 = V2SubII(d[center - 1], d[center]);
|
||||||
V2 = V2SubII(d[center], d[center+1]);
|
V2 = V2SubII(d[center], d[center + 1]);
|
||||||
tHatCenter[0] = (V1[0] + V2[0])/2.0;
|
tHatCenter[0] = (V1[0] + V2[0]) / 2.0;
|
||||||
tHatCenter[1] = (V1[1] + V2[1])/2.0;
|
tHatCenter[1] = (V1[1] + V2[1]) / 2.0;
|
||||||
tHatCenter = *V2Normalize(&tHatCenter);
|
tHatCenter = *V2Normalize(&tHatCenter);
|
||||||
return tHatCenter;
|
return tHatCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ChordLengthParameterize :
|
* ChordLengthParameterize:
|
||||||
* Assign parameter values to digitized points
|
* Assign parameter values to digitized points using relative distances between points.
|
||||||
* using relative distances between points.
|
* Vector2 *d; Array of digitized points
|
||||||
|
* int first, last; Indices defining region
|
||||||
*/
|
*/
|
||||||
static double *ChordLengthParameterize(Vector2 *d, int first, int last)
|
static double *ChordLengthParameterize(Vector2 *d, int first, int last)
|
||||||
// Vector2 *d; /* Array of digitized points */
|
|
||||||
// int first, last; /* Indices defining region */
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double *u; /* Parameterization */
|
double *u; /* Parameterization */
|
||||||
|
|
||||||
u = (double *)malloc((unsigned)(last-first+1) * sizeof(double));
|
u = (double*)malloc((unsigned)(last - first + 1) * sizeof(double));
|
||||||
|
|
||||||
u[0] = 0.0;
|
u[0] = 0.0;
|
||||||
for (i = first+1; i <= last; i++) {
|
for (i = first + 1; i <= last; i++) {
|
||||||
u[i-first] = u[i-first-1] +
|
u[i - first] = u[i - first - 1] + V2DistanceBetween2Points(&d[i], &d[i - 1]);
|
||||||
V2DistanceBetween2Points(&d[i], &d[i-1]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i = first + 1; i <= last; i++) {
|
for (i = first + 1; i <= last; i++) {
|
||||||
u[i-first] = u[i-first] / u[last-first];
|
u[i - first] = u[i - first] / u[last - first];
|
||||||
}
|
}
|
||||||
|
|
||||||
return(u);
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -426,53 +430,57 @@ static double *ChordLengthParameterize(Vector2 *d, int first, int last)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ComputeMaxError :
|
* ComputeMaxError :
|
||||||
* Find the maximum squared distance of digitized points
|
* Find the maximum squared distance of digitized points to fitted curve.
|
||||||
* to fitted curve.
|
* Vector2 *d; Array of digitized points
|
||||||
*/
|
* int first, last; Indices defining region
|
||||||
|
* BezierCurve bezCurve; Fitted Bezier curve
|
||||||
|
* double *u; Parameterization of points
|
||||||
|
* int *splitPoint; Point of maximum error
|
||||||
|
*/
|
||||||
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
|
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
|
||||||
// Vector2 *d; /* Array of digitized points */
|
|
||||||
// int first, last; /* Indices defining region */
|
|
||||||
// BezierCurve bezCurve; /* Fitted Bezier curve */
|
|
||||||
// double *u; /* Parameterization of points */
|
|
||||||
// int *splitPoint; /* Point of maximum error */
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double maxDist; /* Maximum error */
|
double maxDist; /* Maximum error */
|
||||||
double dist; /* Current error */
|
double dist; /* Current error */
|
||||||
Vector2 P; /* Point on curve */
|
Vector2 P; /* Point on curve */
|
||||||
Vector2 v; /* Vector from point to curve */
|
Vector2 v; /* Vector from point to curve */
|
||||||
|
|
||||||
*splitPoint = (last - first + 1)/2;
|
*splitPoint = (last - first + 1) / 2;
|
||||||
maxDist = 0.0;
|
maxDist = 0.0;
|
||||||
for (i = first + 1; i < last; i++) {
|
for (i = first + 1; i < last; i++) {
|
||||||
P = BezierII(3, bezCurve, u[i-first]);
|
P = BezierII(3, bezCurve, u[i - first]);
|
||||||
v = V2SubII(P, d[i]);
|
v = V2SubII(P, d[i]);
|
||||||
dist = V2SquaredLength(&v);
|
dist = V2SquaredLength(&v);
|
||||||
if (dist >= maxDist) {
|
if (dist >= maxDist) {
|
||||||
maxDist = dist;
|
maxDist = dist;
|
||||||
*splitPoint = i;
|
*splitPoint = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (maxDist);
|
return maxDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector2 V2AddII(Vector2 a, Vector2 b)
|
static Vector2 V2AddII(Vector2 a, Vector2 b)
|
||||||
{
|
{
|
||||||
Vector2 c;
|
Vector2 c;
|
||||||
c[0] = a[0] + b[0]; c[1] = a[1] + b[1];
|
c[0] = a[0] + b[0];
|
||||||
return (c);
|
c[1] = a[1] + b[1];
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector2 V2ScaleIII(Vector2 v, double s)
|
static Vector2 V2ScaleIII(Vector2 v, double s)
|
||||||
{
|
{
|
||||||
Vector2 result;
|
Vector2 result;
|
||||||
result[0] = v[0] * s; result[1] = v[1] * s;
|
result[0] = v[0] * s;
|
||||||
return (result);
|
result[1] = v[1] * s;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector2 V2SubII(Vector2 a, Vector2 b)
|
static Vector2 V2SubII(Vector2 a, Vector2 b)
|
||||||
{
|
{
|
||||||
Vector2 c;
|
Vector2 c;
|
||||||
c[0] = a[0] - b[0]; c[1] = a[1] - b[1];
|
c[0] = a[0] - b[0];
|
||||||
return (c);
|
c[1] = a[1] - b[1];
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -488,116 +496,107 @@ FitCurveWrapper::FitCurveWrapper()
|
|||||||
|
|
||||||
FitCurveWrapper::~FitCurveWrapper()
|
FitCurveWrapper::~FitCurveWrapper()
|
||||||
{
|
{
|
||||||
_vertices.clear();
|
_vertices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve )
|
void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve)
|
||||||
{
|
{
|
||||||
for(int i=0; i<n+1; ++i)
|
for (int i = 0; i < n + 1; ++i)
|
||||||
_vertices.push_back(curve[i]);
|
_vertices.push_back(curve[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
|
void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
|
||||||
{
|
{
|
||||||
int size = data.size();
|
int size = data.size();
|
||||||
Vector2 *d = new Vector2[size];
|
Vector2 *d = new Vector2[size];
|
||||||
for(int i=0; i<size; ++i)
|
for (int i = 0; i < size; ++i) {
|
||||||
{
|
d[i][0] = data[i][0];
|
||||||
d[i][0] = data[i][0];
|
d[i][1] = data[i][1];
|
||||||
d[i][1] = data[i][1];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FitCurve(d,size,error);
|
FitCurve(d, size, error);
|
||||||
|
|
||||||
// copy results
|
// copy results
|
||||||
for(vector<Vector2>::iterator v=_vertices.begin(), vend=_vertices.end();
|
for (vector<Vector2>::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
|
||||||
v!=vend;
|
oCurve.push_back(Vec2d(v->x(), v->y())) ;
|
||||||
++v)
|
}
|
||||||
{
|
|
||||||
oCurve.push_back(Vec2d(v->x(), v->y())) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
|
void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
|
||||||
{
|
{
|
||||||
Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
|
Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
|
||||||
|
|
||||||
tHat1 = ComputeLeftTangent(d, 0);
|
tHat1 = ComputeLeftTangent(d, 0);
|
||||||
tHat2 = ComputeRightTangent(d, nPts - 1);
|
tHat2 = ComputeRightTangent(d, nPts - 1);
|
||||||
FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
|
FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
|
void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
|
||||||
{
|
{
|
||||||
BezierCurve bezCurve; /*Control points of fitted Bezier curve*/
|
BezierCurve bezCurve; /* Control points of fitted Bezier curve */
|
||||||
double *u; /* Parameter values for point */
|
double *u; /* Parameter values for point */
|
||||||
double *uPrime; /* Improved parameter values */
|
double *uPrime; /* Improved parameter values */
|
||||||
double maxError; /* Maximum fitting error */
|
double maxError; /* Maximum fitting error */
|
||||||
int splitPoint; /* Point to split point set at */
|
int splitPoint; /* Point to split point set at */
|
||||||
int nPts; /* Number of points in subset */
|
int nPts; /* Number of points in subset */
|
||||||
double iterationError; /*Error below which you try iterating */
|
double iterationError; /* Error below which you try iterating */
|
||||||
int maxIterations = 4; /* Max times to try iterating */
|
int maxIterations = 4; /* Max times to try iterating */
|
||||||
Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
|
Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
iterationError = error * error;
|
iterationError = error * error;
|
||||||
nPts = last - first + 1;
|
nPts = last - first + 1;
|
||||||
|
|
||||||
/* Use heuristic if region only has two points in it */
|
/* Use heuristic if region only has two points in it */
|
||||||
if (nPts == 2) {
|
if (nPts == 2) {
|
||||||
double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
|
double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
|
||||||
|
|
||||||
bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
|
bezCurve = (Vector2*)malloc(4 * sizeof(Vector2));
|
||||||
bezCurve[0] = d[first];
|
bezCurve[0] = d[first];
|
||||||
bezCurve[3] = d[last];
|
bezCurve[3] = d[last];
|
||||||
V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
|
V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
|
||||||
V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
|
V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
|
||||||
DrawBezierCurve(3, bezCurve);
|
DrawBezierCurve(3, bezCurve);
|
||||||
free((void *)bezCurve);
|
free((void*)bezCurve);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* Parameterize points, and attempt to fit curve */
|
|
||||||
u = ChordLengthParameterize(d, first, last);
|
|
||||||
bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
|
|
||||||
|
|
||||||
/* Find max deviation of points to fitted curve */
|
|
||||||
maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
|
|
||||||
if (maxError < error) {
|
|
||||||
DrawBezierCurve(3, bezCurve);
|
|
||||||
free((void *)u);
|
|
||||||
free((void *)bezCurve);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If error not too large, try some reparameterization */
|
|
||||||
/* and iteration */
|
|
||||||
if (maxError < iterationError) {
|
|
||||||
for (i = 0; i < maxIterations; i++) {
|
|
||||||
uPrime = Reparameterize(d, first, last, u, bezCurve);
|
|
||||||
bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
|
|
||||||
maxError = ComputeMaxError(d, first, last,
|
|
||||||
bezCurve, uPrime, &splitPoint);
|
|
||||||
if (maxError < error) {
|
|
||||||
DrawBezierCurve(3, bezCurve);
|
|
||||||
free((void *)u);
|
|
||||||
free((void *)bezCurve);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free((void *)u);
|
|
||||||
u = uPrime;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Fitting failed -- split at max error point and fit recursively */
|
/* Parameterize points, and attempt to fit curve */
|
||||||
free((void *)u);
|
u = ChordLengthParameterize(d, first, last);
|
||||||
free((void *)bezCurve);
|
bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
|
||||||
tHatCenter = ComputeCenterTangent(d, splitPoint);
|
|
||||||
FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
|
|
||||||
V2Negate(&tHatCenter);
|
|
||||||
FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
|
|
||||||
|
|
||||||
|
/* Find max deviation of points to fitted curve */
|
||||||
|
maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
|
||||||
|
if (maxError < error) {
|
||||||
|
DrawBezierCurve(3, bezCurve);
|
||||||
|
free((void*)u);
|
||||||
|
free((void*)bezCurve);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If error not too large, try some reparameterization and iteration */
|
||||||
|
if (maxError < iterationError) {
|
||||||
|
for (i = 0; i < maxIterations; i++) {
|
||||||
|
uPrime = Reparameterize(d, first, last, u, bezCurve);
|
||||||
|
bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
|
||||||
|
maxError = ComputeMaxError(d, first, last,
|
||||||
|
bezCurve, uPrime, &splitPoint);
|
||||||
|
if (maxError < error) {
|
||||||
|
DrawBezierCurve(3, bezCurve);
|
||||||
|
free((void*)u);
|
||||||
|
free((void*)bezCurve);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free((void*)u);
|
||||||
|
u = uPrime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fitting failed -- split at max error point and fit recursively */
|
||||||
|
free((void*)u);
|
||||||
|
free((void*)bezCurve);
|
||||||
|
tHatCenter = ComputeCenterTangent(d, splitPoint);
|
||||||
|
FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
|
||||||
|
V2Negate(&tHatCenter);
|
||||||
|
FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,101 +1,125 @@
|
|||||||
//
|
/*
|
||||||
// Filename : FitCurve.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : An Algorithm for Automatically Fitting Digitized Curves
|
* This program is free software; you can redistribute it and/or
|
||||||
// by Philip J. Schneider
|
* modify it under the terms of the GNU General Public License
|
||||||
// from "Graphics Gems", Academic Press, 1990
|
* as published by the Free Software Foundation; either version 2
|
||||||
// Date of creation : 06/06/2003
|
* of the License, or (at your option) any later version.
|
||||||
//
|
*
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FITCURVE_H__
|
||||||
|
#define __FITCURVE_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/FitCurve.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
|
||||||
//
|
* \brief from "Graphics Gems", Academic Press, 1990
|
||||||
// This program is free software; you can redistribute it and/or
|
* \author Stephane Grabli
|
||||||
// modify it under the terms of the GNU General Public License
|
* \date 06/06/2003
|
||||||
// as published by the Free Software Foundation; either version 2
|
*/
|
||||||
// of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef FITCURVE_H
|
|
||||||
# define FITCURVE_H
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../system/FreestyleConfig.h"
|
|
||||||
#include "Geom.h"
|
#include "Geom.h"
|
||||||
|
|
||||||
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
typedef struct Point2Struct { /* 2d point */
|
/* 2d point */
|
||||||
|
typedef struct Point2Struct
|
||||||
|
{
|
||||||
double coordinates[2];
|
double coordinates[2];
|
||||||
Point2Struct() {coordinates[0]=0;coordinates[1]=0;}
|
|
||||||
inline double operator[](const int i) const
|
Point2Struct()
|
||||||
{
|
{
|
||||||
return coordinates[i];
|
coordinates[0] = 0;
|
||||||
}
|
coordinates[1] = 0;
|
||||||
inline double& operator[](const int i)
|
}
|
||||||
{
|
|
||||||
return coordinates[i];
|
inline double operator[](const int i) const
|
||||||
}
|
{
|
||||||
inline double x() const {return coordinates[0];}
|
return coordinates[i];
|
||||||
inline double y() const {return coordinates[1];}
|
}
|
||||||
} Point2;
|
|
||||||
|
inline double& operator[](const int i)
|
||||||
|
{
|
||||||
|
return coordinates[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double x() const
|
||||||
|
{
|
||||||
|
return coordinates[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double y() const
|
||||||
|
{
|
||||||
|
return coordinates[1];
|
||||||
|
}
|
||||||
|
} Point2;
|
||||||
|
|
||||||
typedef Point2 Vector2;
|
typedef Point2 Vector2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT FitCurveWrapper
|
class LIB_GEOMETRY_EXPORT FitCurveWrapper
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<Vector2> _vertices;
|
std::vector<Vector2> _vertices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FitCurveWrapper();
|
FitCurveWrapper();
|
||||||
~FitCurveWrapper();
|
~FitCurveWrapper();
|
||||||
|
|
||||||
|
/*! Fits a set of 2D data points to a set of Bezier Curve segments
|
||||||
|
* data
|
||||||
|
* Input data points
|
||||||
|
* oCurve
|
||||||
|
* Control points of the sets of bezier curve segments.
|
||||||
|
* Each segment is made of 4 points (polynomial degree of curve = 3)
|
||||||
|
* error
|
||||||
|
* max error tolerance between resulting curve and input data
|
||||||
|
*/
|
||||||
|
void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
|
||||||
|
|
||||||
/*! Fits a set of 2D data points to a set of Bezier Curve segments
|
|
||||||
* data
|
|
||||||
* Input data points
|
|
||||||
* oCurve
|
|
||||||
* Control points of the sets of bezier curve segments.
|
|
||||||
* Each segment is made of 4 points (polynomial degree of curve = 3)
|
|
||||||
* error
|
|
||||||
* max error tolerance between resulting curve and input data
|
|
||||||
*/
|
|
||||||
void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
|
|
||||||
protected:
|
protected:
|
||||||
/* Vec2d *d; Array of digitized points */
|
/* Vec2d *d; Array of digitized points
|
||||||
/* int nPts; Number of digitized points */
|
* int nPts; Number of digitized points
|
||||||
/* double error; User-defined error squared */
|
* double error; User-defined error squared
|
||||||
void FitCurve(Vector2 *d, int nPts, double error);
|
*/
|
||||||
|
void FitCurve(Vector2 *d, int nPts, double error);
|
||||||
/*! Draws a Bezier curve segment
|
|
||||||
* n
|
/*! Draws a Bezier curve segment
|
||||||
* degree of curve (=3)
|
* n
|
||||||
* curve
|
* degree of curve (=3)
|
||||||
* bezier segments control points
|
* curve
|
||||||
*/
|
* bezier segments control points
|
||||||
void DrawBezierCurve(int n, Vector2 *curve);
|
*/
|
||||||
|
void DrawBezierCurve(int n, Vector2 *curve);
|
||||||
/* Vec2d *d; Array of digitized points */
|
|
||||||
/* int first, last; Indices of first and last pts in region */
|
/* Vec2d *d; Array of digitized points
|
||||||
/* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints */
|
* int first, last; Indices of first and last pts in region
|
||||||
/* double error; User-defined error squared */
|
* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints
|
||||||
void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
|
* double error; User-defined error squared
|
||||||
|
*/
|
||||||
|
void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FITCURVE_H
|
#endif // __FITCURVE_H__
|
||||||
|
@ -1,78 +1,84 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Geom.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Sylvain Paris
|
*
|
||||||
// Emmanuel Turquin
|
* This program is free software; you can redistribute it and/or
|
||||||
// Stephane Grabli
|
* modify it under the terms of the GNU General Public License
|
||||||
// Purpose : Vectors and Matrices (useful type definitions)
|
* as published by the Free Software Foundation; either version 2
|
||||||
// Date of creation : 20/05/2003
|
* of the License, or (at your option) any later version.
|
||||||
//
|
*
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GEOM_H__
|
||||||
|
#define __GEOM_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Geom.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Vectors and Matrices (useful type definitions)
|
||||||
//
|
* \author Sylvain Paris
|
||||||
// This program is free software; you can redistribute it and/or
|
* \author Emmanuel Turquin
|
||||||
// modify it under the terms of the GNU General Public License
|
* \author Stephane Grabli
|
||||||
// as published by the Free Software Foundation; either version 2
|
* \date 20/05/2003
|
||||||
// of the License, or (at your option) any later version.
|
*/
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GEOM_H
|
#include "VecMat.h"
|
||||||
# define GEOM_H
|
|
||||||
|
|
||||||
# include "VecMat.h"
|
#include "../system/Precision.h"
|
||||||
# include "../system/Precision.h"
|
|
||||||
|
|
||||||
namespace Geometry {
|
namespace Geometry {
|
||||||
|
|
||||||
typedef VecMat::Vec2<unsigned> Vec2u;
|
typedef VecMat::Vec2<unsigned> Vec2u;
|
||||||
typedef VecMat::Vec2<int> Vec2i;
|
typedef VecMat::Vec2<int> Vec2i;
|
||||||
typedef VecMat::Vec2<float> Vec2f;
|
typedef VecMat::Vec2<float> Vec2f;
|
||||||
typedef VecMat::Vec2<double> Vec2d;
|
typedef VecMat::Vec2<double> Vec2d;
|
||||||
typedef VecMat::Vec2<real> Vec2r;
|
typedef VecMat::Vec2<real> Vec2r;
|
||||||
|
|
||||||
typedef VecMat::Vec3<unsigned> Vec3u;
|
typedef VecMat::Vec3<unsigned> Vec3u;
|
||||||
typedef VecMat::Vec3<int> Vec3i;
|
typedef VecMat::Vec3<int> Vec3i;
|
||||||
typedef VecMat::Vec3<float> Vec3f;
|
typedef VecMat::Vec3<float> Vec3f;
|
||||||
typedef VecMat::Vec3<double> Vec3d;
|
typedef VecMat::Vec3<double> Vec3d;
|
||||||
typedef VecMat::Vec3<real> Vec3r;
|
typedef VecMat::Vec3<real> Vec3r;
|
||||||
|
|
||||||
typedef VecMat::HVec3<unsigned> HVec3u;
|
typedef VecMat::HVec3<unsigned> HVec3u;
|
||||||
typedef VecMat::HVec3<int> HVec3i;
|
typedef VecMat::HVec3<int> HVec3i;
|
||||||
typedef VecMat::HVec3<float> HVec3f;
|
typedef VecMat::HVec3<float> HVec3f;
|
||||||
typedef VecMat::HVec3<double> HVec3d;
|
typedef VecMat::HVec3<double> HVec3d;
|
||||||
typedef VecMat::HVec3<real> HVec3r;
|
typedef VecMat::HVec3<real> HVec3r;
|
||||||
|
|
||||||
typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
|
typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
|
||||||
typedef VecMat::SquareMatrix<int, 2> Matrix22i;
|
typedef VecMat::SquareMatrix<int, 2> Matrix22i;
|
||||||
typedef VecMat::SquareMatrix<float, 2> Matrix22f;
|
typedef VecMat::SquareMatrix<float, 2> Matrix22f;
|
||||||
typedef VecMat::SquareMatrix<double, 2> Matrix22d;
|
typedef VecMat::SquareMatrix<double, 2> Matrix22d;
|
||||||
typedef VecMat::SquareMatrix<real, 2> Matrix22r;
|
typedef VecMat::SquareMatrix<real, 2> Matrix22r;
|
||||||
|
|
||||||
typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
|
typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
|
||||||
typedef VecMat::SquareMatrix<int, 3> Matrix33i;
|
typedef VecMat::SquareMatrix<int, 3> Matrix33i;
|
||||||
typedef VecMat::SquareMatrix<float, 3> Matrix33f;
|
typedef VecMat::SquareMatrix<float, 3> Matrix33f;
|
||||||
typedef VecMat::SquareMatrix<double, 3> Matrix33d;
|
typedef VecMat::SquareMatrix<double, 3> Matrix33d;
|
||||||
typedef VecMat::SquareMatrix<real, 3> Matrix33r;
|
typedef VecMat::SquareMatrix<real, 3> Matrix33r;
|
||||||
|
|
||||||
typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
|
typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
|
||||||
typedef VecMat::SquareMatrix<int, 4> Matrix44i;
|
typedef VecMat::SquareMatrix<int, 4> Matrix44i;
|
||||||
typedef VecMat::SquareMatrix<float, 4> Matrix44f;
|
typedef VecMat::SquareMatrix<float, 4> Matrix44f;
|
||||||
typedef VecMat::SquareMatrix<double, 4> Matrix44d;
|
typedef VecMat::SquareMatrix<double, 4> Matrix44d;
|
||||||
typedef VecMat::SquareMatrix<real, 4> Matrix44r;
|
typedef VecMat::SquareMatrix<real, 4> Matrix44r;
|
||||||
|
|
||||||
} // end of namespace Geometry
|
} // end of namespace Geometry
|
||||||
|
|
||||||
#endif // GEOM_H
|
#endif // __GEOM_H__
|
||||||
|
@ -1,240 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/GeomCleaner.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cleaner of geometry providing a set of useful tools
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 04/03/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//#if defined(__GNUC__) && (__GNUC__ >= 3)
|
#if 0
|
||||||
//// hash_map is not part of the C++ standard anymore;
|
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
//// hash_map.h has been kept though for backward compatibility
|
// hash_map is not part of the C++ standard anymore;
|
||||||
//# include <hash_map.h>
|
// hash_map.h has been kept though for backward compatibility
|
||||||
//#else
|
# include <hash_map.h>
|
||||||
//# include <hash_map>
|
#else
|
||||||
//#endif
|
# include <hash_map>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "../system/TimeUtils.h"
|
|
||||||
#include "GeomCleaner.h"
|
#include "GeomCleaner.h"
|
||||||
|
|
||||||
|
#include "../system/TimeUtils.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize,
|
void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
const unsigned *iIndices, unsigned iISize,
|
unsigned iISize, real **oVertices, unsigned **oIndices)
|
||||||
real **oVertices,
|
|
||||||
unsigned **oIndices)
|
|
||||||
{
|
{
|
||||||
// First, we build a list of IndexVertex:
|
// First, we build a list of IndexVertex:
|
||||||
list<IndexedVertex> indexedVertices;
|
list<IndexedVertex> indexedVertices;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for(i=0; i<iVSize; i+= 3)
|
for (i = 0; i < iVSize; i += 3) {
|
||||||
{
|
indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3));
|
||||||
indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// q-sort
|
// q-sort
|
||||||
indexedVertices.sort();
|
indexedVertices.sort();
|
||||||
|
|
||||||
// build the indices mapping array:
|
// build the indices mapping array:
|
||||||
unsigned *mapIndices = new unsigned[iVSize/3];
|
unsigned *mapIndices = new unsigned[iVSize / 3];
|
||||||
*oVertices = new real[iVSize];
|
*oVertices = new real[iVSize];
|
||||||
list<IndexedVertex>::iterator iv;
|
list<IndexedVertex>::iterator iv;
|
||||||
unsigned newIndex = 0;
|
unsigned newIndex = 0;
|
||||||
unsigned vIndex = 0;
|
unsigned vIndex = 0;
|
||||||
for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++)
|
for (iv = indexedVertices.begin(); iv != indexedVertices.end(); iv++) {
|
||||||
{
|
// Build the final results:
|
||||||
// Build the final results:
|
(*oVertices)[vIndex] = iv->x();
|
||||||
(*oVertices)[vIndex] = iv->x();
|
(*oVertices)[vIndex + 1] = iv->y();
|
||||||
(*oVertices)[vIndex+1] = iv->y();
|
(*oVertices)[vIndex + 2] = iv->z();
|
||||||
(*oVertices)[vIndex+2] = iv->z();
|
|
||||||
|
|
||||||
mapIndices[iv->index()] = newIndex;
|
mapIndices[iv->index()] = newIndex;
|
||||||
newIndex++;
|
newIndex++;
|
||||||
vIndex+=3;
|
vIndex += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the final index array:
|
||||||
// Build the final index array:
|
*oIndices = new unsigned[iISize];
|
||||||
*oIndices = new unsigned[iISize];
|
for (i = 0; i < iISize; i++) {
|
||||||
for(i=0; i<iISize; i++)
|
(*oIndices)[i] = 3 * mapIndices[iIndices[i] / 3];
|
||||||
{
|
}
|
||||||
(*oIndices)[i] = 3*mapIndices[iIndices[i]/3];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] mapIndices;
|
delete [] mapIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
|
void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
const unsigned *iIndices, unsigned iISize,
|
unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices)
|
|
||||||
{
|
{
|
||||||
// First, we build a list of IndexVertex:
|
// First, we build a list of IndexVertex:
|
||||||
vector<Vec3r> vertices;
|
vector<Vec3r> vertices;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for(i=0; i<iVSize; i+= 3)
|
for (i = 0; i < iVSize; i += 3) {
|
||||||
{
|
vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
|
||||||
vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
unsigned *mapVertex = new unsigned[iVSize];
|
unsigned *mapVertex = new unsigned[iVSize];
|
||||||
vector<Vec3r>::iterator v = vertices.begin();
|
vector<Vec3r>::iterator v = vertices.begin();
|
||||||
|
|
||||||
vector<Vec3r> compressedVertices;
|
|
||||||
Vec3r previous = *v;
|
|
||||||
mapVertex[0] = 0;
|
|
||||||
compressedVertices.push_back(vertices.front());
|
|
||||||
|
|
||||||
v++;
|
vector<Vec3r> compressedVertices;
|
||||||
Vec3r current;
|
Vec3r previous = *v;
|
||||||
i=1;
|
mapVertex[0] = 0;
|
||||||
for(; v!=vertices.end(); v++)
|
compressedVertices.push_back(vertices.front());
|
||||||
{
|
|
||||||
current = *v;
|
|
||||||
if(current == previous)
|
|
||||||
mapVertex[i] = compressedVertices.size()-1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compressedVertices.push_back(current);
|
|
||||||
mapVertex[i] = compressedVertices.size()-1;
|
|
||||||
}
|
|
||||||
previous = current;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builds the resulting vertex array:
|
v++;
|
||||||
*oVSize = 3*compressedVertices.size();
|
Vec3r current;
|
||||||
*oVertices = new real [*oVSize];
|
i = 1;
|
||||||
i=0;
|
for (; v != vertices.end(); v++) {
|
||||||
for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++)
|
current = *v;
|
||||||
{
|
if (current == previous)
|
||||||
(*oVertices)[i] = (*v)[0];
|
mapVertex[i] = compressedVertices.size() - 1;
|
||||||
(*oVertices)[i+1] = (*v)[1];
|
else {
|
||||||
(*oVertices)[i+2] = (*v)[2];
|
compressedVertices.push_back(current);
|
||||||
i += 3;
|
mapVertex[i] = compressedVertices.size() - 1;
|
||||||
}
|
}
|
||||||
|
previous = current;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
// Map the index array:
|
// Builds the resulting vertex array:
|
||||||
*oIndices = new unsigned[iISize];
|
*oVSize = 3 * compressedVertices.size();
|
||||||
for(i=0; i<iISize; i++)
|
*oVertices = new real[*oVSize];
|
||||||
{
|
i = 0;
|
||||||
(*oIndices)[i] = 3*mapVertex[iIndices[i]/3];
|
for (v = compressedVertices.begin(); v != compressedVertices.end(); v++) {
|
||||||
}
|
(*oVertices)[i] = (*v)[0];
|
||||||
|
(*oVertices)[i + 1] = (*v)[1];
|
||||||
|
(*oVertices)[i + 2] = (*v)[2];
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
delete [] mapVertex;
|
// Map the index array:
|
||||||
|
*oIndices = new unsigned[iISize];
|
||||||
|
for (i = 0; i < iISize; i++) {
|
||||||
|
(*oIndices)[i] = 3 * mapVertex[iIndices[i] / 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] mapVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
|
void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
const unsigned *iIndices, unsigned iISize,
|
unsigned iISize, real **oVertices, unsigned *oVSize,
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices)
|
unsigned **oIndices)
|
||||||
{
|
{
|
||||||
|
// tmp arrays used to store the sorted data:
|
||||||
|
real *tmpVertices;
|
||||||
|
unsigned *tmpIndices;
|
||||||
|
|
||||||
// tmp arrays used to store the sorted data:
|
Chronometer chrono;
|
||||||
real *tmpVertices;
|
// Sort data
|
||||||
unsigned *tmpIndices;
|
chrono.start();
|
||||||
|
GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
|
||||||
|
printf("Sorting: %lf\n", chrono.stop());
|
||||||
|
|
||||||
Chronometer chrono;
|
// compress data
|
||||||
// Sort data
|
chrono.start();
|
||||||
chrono.start();
|
GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
|
||||||
GeomCleaner::SortIndexedVertexArray(iVertices, iVSize,
|
printf("Merging: %lf\n", chrono.stop());
|
||||||
iIndices, iISize,
|
|
||||||
&tmpVertices, &tmpIndices
|
|
||||||
);
|
|
||||||
printf("Sorting: %lf\n", chrono.stop());
|
|
||||||
|
|
||||||
// compress data
|
// deallocates memory:
|
||||||
chrono.start();
|
delete [] tmpVertices;
|
||||||
GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize,
|
delete [] tmpIndices;
|
||||||
tmpIndices, iISize,
|
|
||||||
oVertices, oVSize,
|
|
||||||
oIndices);
|
|
||||||
printf("Merging: %lf\n", chrono.stop());
|
|
||||||
|
|
||||||
// deallocates memory:
|
|
||||||
delete [] tmpVertices;
|
|
||||||
delete [] tmpIndices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Defines a hash table used for searching the Cells */
|
/*! Defines a hash table used for searching the Cells */
|
||||||
struct GeomCleanerHasher{
|
struct GeomCleanerHasher{
|
||||||
#define _MUL 950706376UL
|
#define _MUL 950706376UL
|
||||||
#define _MOD 2147483647UL
|
#define _MOD 2147483647UL
|
||||||
inline size_t operator() (const Vec3r& p) const {
|
inline size_t operator() (const Vec3r& p) const
|
||||||
size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
|
{
|
||||||
res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
|
size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
|
||||||
return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
|
res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
|
||||||
}
|
return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
|
||||||
|
}
|
||||||
|
#undef _MUL
|
||||||
|
#undef _MOD
|
||||||
};
|
};
|
||||||
|
|
||||||
void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
|
void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
const unsigned *iIndices, unsigned iISize,
|
unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices)
|
|
||||||
{
|
{
|
||||||
typedef map<Vec3r, unsigned> cleanHashTable;
|
typedef map<Vec3r, unsigned> cleanHashTable;
|
||||||
vector<Vec3r> vertices;
|
vector<Vec3r> vertices;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for(i=0; i<iVSize; i+= 3)
|
for (i = 0; i < iVSize; i += 3)
|
||||||
vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
|
vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
|
||||||
|
|
||||||
cleanHashTable ht;
|
|
||||||
vector<unsigned> newIndices;
|
|
||||||
vector<Vec3r> newVertices;
|
|
||||||
|
|
||||||
// elimination of needless points
|
|
||||||
unsigned currentIndex = 0;
|
|
||||||
vector<Vec3r>::const_iterator v = vertices.begin();
|
|
||||||
vector<Vec3r>::const_iterator end = vertices.end();
|
|
||||||
cleanHashTable::const_iterator found;
|
|
||||||
for(; v!=end; v++)
|
|
||||||
{
|
|
||||||
found = ht.find(*v);
|
|
||||||
if(found != ht.end())
|
|
||||||
{
|
|
||||||
// The vertex is already in the new array.
|
|
||||||
newIndices.push_back((*found).second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newVertices.push_back(*v);
|
|
||||||
newIndices.push_back(currentIndex);
|
|
||||||
ht[*v] = currentIndex;
|
|
||||||
currentIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// creation of oVertices array:
|
cleanHashTable ht;
|
||||||
*oVSize = 3*newVertices.size();
|
vector<unsigned> newIndices;
|
||||||
*oVertices = new real[*oVSize];
|
vector<Vec3r> newVertices;
|
||||||
currentIndex = 0;
|
|
||||||
end = newVertices.end();
|
|
||||||
for(v=newVertices.begin(); v!=end ; v++)
|
|
||||||
{
|
|
||||||
(*oVertices)[currentIndex++] = (*v)[0];
|
|
||||||
(*oVertices)[currentIndex++] = (*v)[1];
|
|
||||||
(*oVertices)[currentIndex++] = (*v)[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// map new indices:
|
// elimination of needless points
|
||||||
*oIndices = new unsigned[iISize];
|
unsigned currentIndex = 0;
|
||||||
for(i=0; i<iISize; i++)
|
vector<Vec3r>::const_iterator v = vertices.begin();
|
||||||
(*oIndices)[i] = 3*newIndices[iIndices[i]/3];
|
vector<Vec3r>::const_iterator end = vertices.end();
|
||||||
|
cleanHashTable::const_iterator found;
|
||||||
|
for (; v != end; v++) {
|
||||||
|
found = ht.find(*v);
|
||||||
|
if (found != ht.end()) {
|
||||||
|
// The vertex is already in the new array.
|
||||||
|
newIndices.push_back((*found).second);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newVertices.push_back(*v);
|
||||||
|
newIndices.push_back(currentIndex);
|
||||||
|
ht[*v] = currentIndex;
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// creation of oVertices array:
|
||||||
|
*oVSize = 3 * newVertices.size();
|
||||||
|
*oVertices = new real[*oVSize];
|
||||||
|
currentIndex = 0;
|
||||||
|
end = newVertices.end();
|
||||||
|
for (v = newVertices.begin(); v != end ; v++) {
|
||||||
|
(*oVertices)[currentIndex++] = (*v)[0];
|
||||||
|
(*oVertices)[currentIndex++] = (*v)[1];
|
||||||
|
(*oVertices)[currentIndex++] = (*v)[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// map new indices:
|
||||||
|
*oIndices = new unsigned[iISize];
|
||||||
|
for (i = 0; i < iISize; i++)
|
||||||
|
(*oIndices)[i] = 3 * newIndices[iIndices[i] / 3];
|
||||||
}
|
}
|
||||||
|
@ -1,219 +1,227 @@
|
|||||||
//
|
/*
|
||||||
// Filename : GeomCleaner.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a cleaner of geometry providing
|
* This program is free software; you can redistribute it and/or
|
||||||
// a set of useful tools
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 04/03/2002
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GEOMCLEANER_H__
|
||||||
|
#define __GEOMCLEANER_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/GeomCleaner.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cleaner of geometry providing a set of useful tools
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 04/03/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GEOMCLEANER_H
|
#include "Geom.h"
|
||||||
# define GEOMCLEANER_H
|
|
||||||
|
|
||||||
# include "../system/FreestyleConfig.h"
|
#include "../system/FreestyleConfig.h"
|
||||||
# include "Geom.h"
|
|
||||||
|
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT GeomCleaner
|
class LIB_GEOMETRY_EXPORT GeomCleaner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
inline GeomCleaner() {}
|
||||||
|
inline ~GeomCleaner() {}
|
||||||
|
|
||||||
inline GeomCleaner() {}
|
/*! Sorts an array of Indexed vertices
|
||||||
inline ~GeomCleaner() {}
|
* iVertices
|
||||||
|
* Array of vertices to sort. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
|
||||||
|
* iVSize
|
||||||
|
* The size of iVertices array.
|
||||||
|
* iIndices
|
||||||
|
* The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face). Each
|
||||||
|
* element is an unsignedeger multiple of 3.
|
||||||
|
* iISize
|
||||||
|
* The size of iIndices array
|
||||||
|
* oVertices
|
||||||
|
* Output of sorted vertices. A vertex v1 precedes another one v2 in this array if v1.x<v2.x,
|
||||||
|
* or v1.x=v2.x && v1.y < v2.y or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
|
||||||
|
* The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
|
||||||
|
* oIndices
|
||||||
|
* Output corresponding to the iIndices array but reorganized in order to match the sorted vertex array.
|
||||||
|
*/
|
||||||
|
static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
|
unsigned iISize, real **oVertices, unsigned **oIndices);
|
||||||
|
|
||||||
/*! Sorts an array of Indexed vertices
|
/*! Compress a SORTED indexed vertex array by eliminating multiple appearing occurences of a single vertex.
|
||||||
* iVertices
|
* iVertices
|
||||||
* Array of vertices to sort. It is organized as a
|
* The SORTED vertex array to compress. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
|
||||||
* float series of vertex coordinates: XYZXYZXYZ...
|
* iVSize
|
||||||
* iVSize
|
* The size of iVertices array.
|
||||||
* The size of iVertices array.
|
* iIndices
|
||||||
* iIndices
|
* The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
|
||||||
* The array containing the vertex indices (used to refer
|
* Each element is an unsignedeger multiple of 3.
|
||||||
* to the vertex coordinates in an indexed face). Each
|
* iISize
|
||||||
* element is an unsignedeger multiple of 3.
|
* The size of iIndices array
|
||||||
* iISize
|
* oVertices
|
||||||
* The size of iIndices array
|
* The vertex array, result of the compression.
|
||||||
* oVertices
|
* The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
|
||||||
* Output of sorted vertices. A vertex v1 precedes another one
|
* oVSize
|
||||||
* v2 in this array if v1.x<v2.x, or v1.x=v2.x && v1.y < v2.y
|
* The size of oVertices.
|
||||||
* or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
|
* oIndices
|
||||||
* The array is organized as a 3-float serie giving
|
* The indices array, reorganized to match the compressed oVertices array.
|
||||||
* the vertices coordinates: XYZXYZXYZ...
|
*/
|
||||||
* oIndices
|
static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
* Output corresponding to the iIndices array but
|
unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
|
||||||
* reorganized in order to match the sorted vertex array.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize,
|
/*! Sorts and compress an array of indexed vertices.
|
||||||
const unsigned *iIndices, unsigned iISize,
|
* iVertices
|
||||||
real **oVertices,
|
* The vertex array to sort then compress. It is organized as a float series of
|
||||||
unsigned **oIndices);
|
* vertex coordinates: XYZXYZXYZ...
|
||||||
|
* iVSize
|
||||||
|
* The size of iVertices array.
|
||||||
|
* iIndices
|
||||||
|
* The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
|
||||||
|
* Each element is an unsignedeger multiple of 3.
|
||||||
|
* iISize
|
||||||
|
* The size of iIndices array
|
||||||
|
* oVertices
|
||||||
|
* The vertex array, result of the sorting-compression.
|
||||||
|
* The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
|
||||||
|
* oVSize
|
||||||
|
* The size of oVertices.
|
||||||
|
* oIndices
|
||||||
|
* The indices array, reorganized to match the sorted and compressed oVertices array.
|
||||||
|
*/
|
||||||
|
static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
|
unsigned iISize, real **oVertices, unsigned *oVSize,
|
||||||
|
unsigned **oIndices);
|
||||||
|
|
||||||
/*! Compress a SORTED indexed vertex array by eliminating
|
/*! Cleans an indexed vertex array. (Identical to SortAndCompress except that we use here a hash table
|
||||||
* multiple appearing occurences of a single vertex.
|
* to create the new array.)
|
||||||
* iVertices
|
* iVertices
|
||||||
* The SORTED vertex array to compress. It is organized as a
|
* The vertex array to sort then compress. It is organized as a float series of
|
||||||
* float series of vertex coordinates: XYZXYZXYZ...
|
* vertex coordinates: XYZXYZXYZ...
|
||||||
* iVSize
|
* iVSize
|
||||||
* The size of iVertices array.
|
* The size of iVertices array.
|
||||||
* iIndices
|
* iIndices
|
||||||
* The array containing the vertex indices (used to refer
|
* The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
|
||||||
* to the vertex coordinates in an indexed face). Each
|
* Each element is an unsignedeger multiple of 3.
|
||||||
* element is an unsignedeger multiple of 3.
|
* iISize
|
||||||
* iISize
|
* The size of iIndices array
|
||||||
* The size of iIndices array
|
* oVertices
|
||||||
* oVertices
|
* The vertex array, result of the sorting-compression.
|
||||||
* The vertex array, result of the compression.
|
* The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
|
||||||
* The array is organized as a 3-float serie giving
|
* oVSize
|
||||||
* the vertices coordinates: XYZXYZXYZ...
|
* The size of oVertices.
|
||||||
* oVSize
|
* oIndices
|
||||||
* The size of oVertices.
|
* The indices array, reorganized to match the sorted and compressed oVertices array.
|
||||||
* oIndices
|
*/
|
||||||
* The indices array, reorganized to match the compressed
|
static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
|
||||||
* oVertices array.
|
unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
|
||||||
*/
|
|
||||||
|
|
||||||
static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
|
|
||||||
const unsigned *iIndices, unsigned iISize,
|
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices);
|
|
||||||
|
|
||||||
/*! Sorts and compress an array of indexed vertices.
|
|
||||||
* iVertices
|
|
||||||
* The vertex array to sort then compress. It is organized as a
|
|
||||||
* float series of vertex coordinates: XYZXYZXYZ...
|
|
||||||
* iVSize
|
|
||||||
* The size of iVertices array.
|
|
||||||
* iIndices
|
|
||||||
* The array containing the vertex indices (used to refer
|
|
||||||
* to the vertex coordinates in an indexed face). Each
|
|
||||||
* element is an unsignedeger multiple of 3.
|
|
||||||
* iISize
|
|
||||||
* The size of iIndices array
|
|
||||||
* oVertices
|
|
||||||
* The vertex array, result of the sorting-compression.
|
|
||||||
* The array is organized as a 3-float serie giving
|
|
||||||
* the vertices coordinates: XYZXYZXYZ...
|
|
||||||
* oVSize
|
|
||||||
* The size of oVertices.
|
|
||||||
* oIndices
|
|
||||||
* The indices array, reorganized to match the sorted and compressed
|
|
||||||
* oVertices array.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
|
|
||||||
const unsigned *iIndices, unsigned iISize,
|
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices);
|
|
||||||
|
|
||||||
/*! Cleans an indexed vertex array. (Identical to
|
|
||||||
* SortAndCompress except that we use here a hash
|
|
||||||
* table to create the new array.)
|
|
||||||
* iVertices
|
|
||||||
* The vertex array to sort then compress. It is organized as a
|
|
||||||
* float series of vertex coordinates: XYZXYZXYZ...
|
|
||||||
* iVSize
|
|
||||||
* The size of iVertices array.
|
|
||||||
* iIndices
|
|
||||||
* The array containing the vertex indices (used to refer
|
|
||||||
* to the vertex coordinates in an indexed face). Each
|
|
||||||
* element is an unsignedeger multiple of 3.
|
|
||||||
* iISize
|
|
||||||
* The size of iIndices array
|
|
||||||
* oVertices
|
|
||||||
* The vertex array, result of the sorting-compression.
|
|
||||||
* The array is organized as a 3-float serie giving
|
|
||||||
* the vertices coordinates: XYZXYZXYZ...
|
|
||||||
* oVSize
|
|
||||||
* The size of oVertices.
|
|
||||||
* oIndices
|
|
||||||
* The indices array, reorganized to match the sorted and compressed
|
|
||||||
* oVertices array.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
|
|
||||||
const unsigned *iIndices, unsigned iISize,
|
|
||||||
real **oVertices, unsigned *oVSize,
|
|
||||||
unsigned **oIndices);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*! Binary operators */
|
/*! Binary operators */
|
||||||
//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
|
//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
|
||||||
|
|
||||||
/*! Class Indexed Vertex. Used to represent
|
/*! Class Indexed Vertex. Used to represent an indexed vertex by storing the vertex coordinates as well as its index */
|
||||||
* an indexed vertex by storing the vertex
|
|
||||||
* coordinates as well as its index
|
|
||||||
*/
|
|
||||||
class IndexedVertex
|
class IndexedVertex
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vec3r _Vector;
|
Vec3r _Vector;
|
||||||
unsigned _index;
|
unsigned _index;
|
||||||
public:
|
|
||||||
inline IndexedVertex() {}
|
|
||||||
inline IndexedVertex(Vec3r iVector, unsigned iIndex)
|
|
||||||
{
|
|
||||||
_Vector = iVector;
|
|
||||||
_index = iIndex;
|
|
||||||
}
|
|
||||||
/*! accessors */
|
|
||||||
inline const Vec3r& vector() const {return _Vector;}
|
|
||||||
inline unsigned index() {return _index;}
|
|
||||||
inline real x() {return _Vector[0];}
|
|
||||||
inline real y() {return _Vector[1];}
|
|
||||||
inline real z() {return _Vector[2];}
|
|
||||||
|
|
||||||
/*! modifiers */
|
|
||||||
inline void setVector(const Vec3r& iVector) {_Vector = iVector;}
|
|
||||||
inline void setIndex(unsigned iIndex) {_index = iIndex;}
|
|
||||||
|
|
||||||
/*! operators */
|
public:
|
||||||
IndexedVertex& operator=(const IndexedVertex& iv)
|
inline IndexedVertex() {}
|
||||||
{
|
|
||||||
_Vector = iv._Vector;
|
inline IndexedVertex(Vec3r iVector, unsigned iIndex)
|
||||||
_index = iv._index;
|
{
|
||||||
return *this;
|
_Vector = iVector;
|
||||||
}
|
_index = iIndex;
|
||||||
inline real operator[](const unsigned i) {return _Vector[i];}
|
}
|
||||||
//friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
|
|
||||||
inline bool operator<(const IndexedVertex& v) const
|
/*! accessors */
|
||||||
{
|
inline const Vec3r& vector() const
|
||||||
return (_Vector < v._Vector);
|
{
|
||||||
}
|
return _Vector;
|
||||||
inline bool operator==(const IndexedVertex& v)
|
}
|
||||||
{
|
|
||||||
return (_Vector == v._Vector);
|
inline unsigned index()
|
||||||
}
|
{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline real x()
|
||||||
|
{
|
||||||
|
return _Vector[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline real y()
|
||||||
|
{
|
||||||
|
return _Vector[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline real z()
|
||||||
|
{
|
||||||
|
return _Vector[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! modifiers */
|
||||||
|
inline void setVector(const Vec3r& iVector)
|
||||||
|
{
|
||||||
|
_Vector = iVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setIndex(unsigned iIndex)
|
||||||
|
{
|
||||||
|
_index = iIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! operators */
|
||||||
|
IndexedVertex& operator=(const IndexedVertex& iv)
|
||||||
|
{
|
||||||
|
_Vector = iv._Vector;
|
||||||
|
_index = iv._index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline real operator[](const unsigned i)
|
||||||
|
{
|
||||||
|
return _Vector[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
|
||||||
|
inline bool operator<(const IndexedVertex& v) const
|
||||||
|
{
|
||||||
|
return (_Vector < v._Vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const IndexedVertex& v)
|
||||||
|
{
|
||||||
|
return (_Vector == v._Vector);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
|
#if 0
|
||||||
//{
|
bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
|
||||||
// return iv1.operator<(iv2);
|
{
|
||||||
//}
|
return iv1.operator<(iv2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // GEOMCLEANER_H
|
#endif // __GEOMCLEANER_H__
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,310 +1,277 @@
|
|||||||
//
|
/*
|
||||||
// Filename : GeomUtils.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Various tools for geometry
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 12/04/2002
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GEOMUTILS_H__
|
||||||
|
#define __GEOMUTILS_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/GeomUtils.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Various tools for geometry
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 12/04/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GEOMUTILS_H
|
#include <vector>
|
||||||
# define GEOMUTILS_H
|
|
||||||
|
|
||||||
# include <vector>
|
#include "Geom.h"
|
||||||
# include "../system/FreestyleConfig.h"
|
|
||||||
# include "Geom.h"
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
namespace GeomUtils {
|
namespace GeomUtils {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Templated procedures
|
// Templated procedures
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*! Computes the distance from a point P to a segment AB */
|
/*! Computes the distance from a point P to a segment AB */
|
||||||
template<class T>
|
template<class T>
|
||||||
real distPointSegment( const T& P, const T& A , const T& B) {
|
real distPointSegment( const T& P, const T& A , const T& B)
|
||||||
T AB, AP, BP;
|
{
|
||||||
AB = B - A;
|
T AB, AP, BP;
|
||||||
AP = P - A;
|
AB = B - A;
|
||||||
BP = P - B;
|
AP = P - A;
|
||||||
|
BP = P - B;
|
||||||
|
|
||||||
real c1(AB * AP);
|
real c1(AB * AP);
|
||||||
if (c1 <= 0)
|
if (c1 <= 0)
|
||||||
return AP.norm();
|
return AP.norm();
|
||||||
|
|
||||||
real c2(AB * AB);
|
real c2(AB * AB);
|
||||||
if (c2 <= c1)
|
if (c2 <= c1)
|
||||||
return BP.norm();
|
return BP.norm();
|
||||||
|
|
||||||
real b = c1 / c2;
|
real b = c1 / c2;
|
||||||
T Pb, PPb;
|
T Pb, PPb;
|
||||||
Pb = A + b * AB;
|
Pb = A + b * AB;
|
||||||
PPb = P - Pb;
|
PPb = P - Pb;
|
||||||
|
|
||||||
return PPb.norm();
|
return PPb.norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Non-templated procedures
|
// Non-templated procedures
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef enum {
|
||||||
|
DONT_INTERSECT,
|
||||||
|
DO_INTERSECT,
|
||||||
|
COLINEAR,
|
||||||
|
COINCIDENT,
|
||||||
|
} intersection_test;
|
||||||
|
|
||||||
typedef enum {
|
LIB_GEOMETRY_EXPORT
|
||||||
DONT_INTERSECT,
|
intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
|
||||||
DO_INTERSECT,
|
const Vec2r& p3, const Vec2r& p4, // second segment
|
||||||
COLINEAR,
|
Vec2r& res); // found intersection point
|
||||||
COINCIDENT
|
|
||||||
} intersection_test;
|
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
|
intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
|
||||||
const Vec2r& p3, const Vec2r& p4, // second segment
|
const Vec2r& p3, const Vec2r& p4, // second segment
|
||||||
Vec2r& res); // found intersection point
|
Vec2r& res); // found intersection point
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
|
intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
|
||||||
const Vec2r& p3, const Vec2r& p4, // second segment
|
const Vec2r& p3, const Vec2r& p4, // second segment
|
||||||
Vec2r& res); // found intersection point
|
real& t, // I = P1 + t * P1P2)
|
||||||
|
real& u, // I = P3 + u * P3P4
|
||||||
|
real epsilon = M_EPSILON);
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
/*! check whether a 2D segment intersect a 2D region or not */
|
||||||
intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
|
LIB_GEOMETRY_EXPORT
|
||||||
const Vec2r& p3, const Vec2r& p4, // second segment
|
bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
|
||||||
real& t, // I = P1 + t * P1P2)
|
|
||||||
real& u, // I = P3 + u * P3P4
|
|
||||||
real epsilon = M_EPSILON);
|
|
||||||
|
|
||||||
/*! check whether a 2D segment intersect a 2D region or not */
|
/*! check whether a 2D segment is included in a 2D region or not */
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
bool intersect2dSeg2dArea(const Vec2r& min,
|
bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
|
||||||
const Vec2r& max,
|
|
||||||
const Vec2r& A,
|
|
||||||
const Vec2r& B);
|
|
||||||
|
|
||||||
/*! check whether a 2D segment is included in a 2D region or not */
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
bool include2dSeg2dArea(const Vec2r& min,
|
|
||||||
const Vec2r& max,
|
|
||||||
const Vec2r& A,
|
|
||||||
const Vec2r& B);
|
|
||||||
|
|
||||||
/*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
|
/*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
bool overlapTriangleBox(Vec3r& boxcenter,
|
bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3]);
|
||||||
Vec3r& boxhalfsize,
|
|
||||||
Vec3r triverts[3]);
|
|
||||||
|
|
||||||
/*! Fast, Minimum Storage Ray-Triangle Intersection,
|
/*! Fast, Minimum Storage Ray-Triangle Intersection, adapted from Tomas Möller and Ben Trumbore code. */
|
||||||
* adapted from Tomas Möller and Ben Trumbore code.
|
LIB_GEOMETRY_EXPORT
|
||||||
*/
|
bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
|
||||||
LIB_GEOMETRY_EXPORT
|
real& t, // I = orig + t * dir
|
||||||
bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
|
real& u, real& v, // I = (1 - u - v) * v0 + u * v1 + v * v2
|
||||||
const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
|
const real epsilon = M_EPSILON); // the epsilon to use
|
||||||
real& t, // I = orig + t * dir
|
|
||||||
real& u, real& v, // I = (1-u-v)*v0+u*v1+v*v2
|
|
||||||
const real epsilon = M_EPSILON); // the epsilon to use
|
|
||||||
|
|
||||||
/*! Intersection between plane and ray
|
/*! Intersection between plane and ray adapted from Graphics Gems, Didier Badouel */
|
||||||
* adapted from Graphics Gems, Didier Badouel
|
LIB_GEOMETRY_EXPORT
|
||||||
*/
|
intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
|
||||||
LIB_GEOMETRY_EXPORT
|
// plane's normal and offset (plane = { P / P.N + d = 0 })
|
||||||
intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
|
const Vec3r& norm, const real d,
|
||||||
const Vec3r& norm, const real d, // plane's normal and offset (plane = { P / P.N + d = 0 })
|
real& t, // I = orig + t * dir
|
||||||
real& t, // I = orig + t * dir
|
const real epsilon = M_EPSILON); // the epsilon to use
|
||||||
const real epsilon = M_EPSILON); // the epsilon to use
|
|
||||||
|
|
||||||
/*! Intersection Ray-Bounding box (axis aligned).
|
/*! Intersection Ray-Bounding box (axis aligned).
|
||||||
* Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm",
|
* Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm", JGT 10:1 (2005), pp. 49-54.
|
||||||
* JGT 10:1 (2005), pp. 49-54.
|
*/
|
||||||
* Returns
|
LIB_GEOMETRY_EXPORT
|
||||||
*/
|
bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
|
||||||
LIB_GEOMETRY_EXPORT
|
const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
|
||||||
bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
|
// the interval in which at least on of the intersections must happen
|
||||||
const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
|
real t0, real t1,
|
||||||
real t0, real t1, // the interval in which at least on of the intersections must happen
|
real& tmin, // Imin = orig + tmin * dir is the first intersection
|
||||||
real& tmin, real& tmax, // Imin=orig+tmin*dir is the first intersection, Imax=orig+tmax*dir is the second intersection
|
real& tmax, // Imax = orig + tmax * dir is the second intersection
|
||||||
real epsilon = M_EPSILON); // the epsilon to use
|
real epsilon = M_EPSILON); // the epsilon to use
|
||||||
|
|
||||||
|
/*! Checks whether 3D point P lies inside or outside of the triangle ABC */
|
||||||
|
LIB_GEOMETRY_EXPORT
|
||||||
|
bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C);
|
||||||
|
|
||||||
/*! Checks whether 3D point P lies inside or outside of the triangle ABC */
|
LIB_GEOMETRY_EXPORT
|
||||||
LIB_GEOMETRY_EXPORT
|
void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res);
|
||||||
bool includePointTriangle(const Vec3r& P,
|
|
||||||
const Vec3r& A,
|
|
||||||
const Vec3r& B,
|
|
||||||
const Vec3r& C);
|
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
void transformVertex(const Vec3r& vert,
|
void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res);
|
||||||
const Matrix44r& matrix,
|
|
||||||
Vec3r& res);
|
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
void transformVertices(const vector<Vec3r>& vertices,
|
|
||||||
const Matrix44r& trans,
|
|
||||||
vector<Vec3r>& res);
|
|
||||||
|
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
|
Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Coordinates systems changing procedures
|
// Coordinates systems changing procedures
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*! From world to image
|
/*! From world to image
|
||||||
* p
|
* p
|
||||||
* point's coordinates expressed in world coordinates system
|
* point's coordinates expressed in world coordinates system
|
||||||
* q
|
* q
|
||||||
* vector in which the result will be stored
|
* vector in which the result will be stored
|
||||||
* model_view_matrix
|
* model_view_matrix
|
||||||
* The model view matrix expressed in line major order (OpenGL
|
* The model view matrix expressed in line major order (OpenGL
|
||||||
* matrices are column major ordered)
|
* matrices are column major ordered)
|
||||||
* projection_matrix
|
* projection_matrix
|
||||||
* The projection matrix expressed in line major order (OpenGL
|
* The projection matrix expressed in line major order (OpenGL
|
||||||
* matrices are column major ordered)
|
* matrices are column major ordered)
|
||||||
* viewport
|
* viewport
|
||||||
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
|
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
|
||||||
*/
|
*/
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
void fromWorldToImage(const Vec3r& p,
|
void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4], const real projection_matrix[4][4],
|
||||||
Vec3r& q,
|
const int viewport[4]);
|
||||||
const real model_view_matrix[4][4],
|
|
||||||
const real projection_matrix[4][4],
|
|
||||||
const int viewport[4]);
|
|
||||||
|
|
||||||
/*! From world to image
|
/*! From world to image
|
||||||
* p
|
* p
|
||||||
* point's coordinates expressed in world coordinates system
|
* point's coordinates expressed in world coordinates system
|
||||||
* q
|
* q
|
||||||
* vector in which the result will be stored
|
* vector in which the result will be stored
|
||||||
* transform
|
* transform
|
||||||
* The transformation matrix (gathering model view and projection),
|
* The transformation matrix (gathering model view and projection),
|
||||||
* expressed in line major order (OpenGL matrices are column major ordered)
|
* expressed in line major order (OpenGL matrices are column major ordered)
|
||||||
* viewport
|
* viewport
|
||||||
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
|
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
|
||||||
*/
|
*/
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
void fromWorldToImage(const Vec3r& p,
|
void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4]);
|
||||||
Vec3r& q,
|
|
||||||
const real transform[4][4],
|
|
||||||
const int viewport[4]);
|
|
||||||
|
|
||||||
/*! Projects from world coordinates to camera coordinates
|
/*! Projects from world coordinates to camera coordinates
|
||||||
* Returns the point's coordinates expressed in the camera's
|
* Returns the point's coordinates expressed in the camera's
|
||||||
* coordinates system.
|
* coordinates system.
|
||||||
* p
|
* p
|
||||||
* point's coordinates expressed in world coordinates system
|
* point's coordinates expressed in world coordinates system
|
||||||
* q
|
* q
|
||||||
* vector in which the result will be stored
|
* vector in which the result will be stored
|
||||||
* model_view_matrix
|
* model_view_matrix
|
||||||
* The model view matrix expressed in line major order (OpenGL
|
* The model view matrix expressed in line major order (OpenGL
|
||||||
* matrices are column major ordered)
|
* matrices are column major ordered)
|
||||||
*/
|
*/
|
||||||
LIB_GEOMETRY_EXPORT
|
LIB_GEOMETRY_EXPORT
|
||||||
void fromWorldToCamera(const Vec3r& p,
|
void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
|
||||||
Vec3r& q,
|
|
||||||
const real model_view_matrix[4][4]);
|
|
||||||
|
|
||||||
/*! Projects from World Coordinates to retina coordinates
|
|
||||||
* Returns the point's coordinates expressed in Retina system.
|
|
||||||
* p
|
|
||||||
* point's coordinates expressed in camera system
|
|
||||||
* q
|
|
||||||
* vector in which the result will be stored
|
|
||||||
* projection_matrix
|
|
||||||
* The projection matrix expressed in line major order (OpenGL
|
|
||||||
* matrices are column major ordered)
|
|
||||||
*/
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
void fromCameraToRetina(const Vec3r& p,
|
|
||||||
Vec3r& q,
|
|
||||||
const real projection_matrix[4][4]);
|
|
||||||
|
|
||||||
/*! From retina to image.
|
|
||||||
* Returns the coordinates expressed in Image coorinates system.
|
|
||||||
* p
|
|
||||||
* point's coordinates expressed in retina system
|
|
||||||
* q
|
|
||||||
* vector in which the result will be stored
|
|
||||||
* viewport
|
|
||||||
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
|
|
||||||
*/
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
void fromRetinaToImage(const Vec3r& p,
|
|
||||||
Vec3r& q,
|
|
||||||
const int viewport[4]);
|
|
||||||
|
|
||||||
/*! From image to retina
|
|
||||||
* p
|
|
||||||
* point's coordinates expressed in image system
|
|
||||||
* q
|
|
||||||
* vector in which the result will be stored
|
|
||||||
* viewport
|
|
||||||
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
|
|
||||||
*/
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
void fromImageToRetina(const Vec3r& p,
|
|
||||||
Vec3r& q,
|
|
||||||
const int viewport[4]);
|
|
||||||
|
|
||||||
/*! computes the coordinates of q in the camera coordinates system,
|
|
||||||
* using the known z coordinates of the 3D point.
|
|
||||||
* That means that this method does not inverse any matrices,
|
|
||||||
* it only computes X and Y from x,y and Z)
|
|
||||||
* p
|
|
||||||
* point's coordinates expressed in retina system
|
|
||||||
* q
|
|
||||||
* vector in which the result will be stored
|
|
||||||
* projection_matrix
|
|
||||||
* The projection matrix expressed in line major order (OpenGL
|
|
||||||
* matrices are column major ordered)
|
|
||||||
|
|
||||||
*/
|
|
||||||
LIB_GEOMETRY_EXPORT
|
|
||||||
void fromRetinaToCamera(const Vec3r& p,
|
|
||||||
Vec3r& q,
|
|
||||||
real z,
|
|
||||||
const real projection_matrix[4][4]);
|
|
||||||
|
|
||||||
/*! Projects from camera coordinates to world coordinates
|
/*! Projects from World Coordinates to retina coordinates
|
||||||
* Returns the point's coordinates expressed in the world's
|
* Returns the point's coordinates expressed in Retina system.
|
||||||
* coordinates system.
|
* p
|
||||||
* p
|
* point's coordinates expressed in camera system
|
||||||
* point's coordinates expressed in the camera coordinates system
|
* q
|
||||||
* q
|
* vector in which the result will be stored
|
||||||
* vector in which the result will be stored
|
* projection_matrix
|
||||||
* model_view_matrix
|
* The projection matrix expressed in line major order (OpenGL
|
||||||
* The model view matrix expressed in line major order (OpenGL
|
* matrices are column major ordered)
|
||||||
* matrices are column major ordered)
|
*/
|
||||||
*/
|
LIB_GEOMETRY_EXPORT
|
||||||
LIB_GEOMETRY_EXPORT
|
void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4]);
|
||||||
void fromCameraToWorld(const Vec3r& p,
|
|
||||||
Vec3r& q,
|
/*! From retina to image.
|
||||||
const real model_view_matrix[4][4]);
|
* Returns the coordinates expressed in Image coorinates system.
|
||||||
|
* p
|
||||||
|
* point's coordinates expressed in retina system
|
||||||
|
* q
|
||||||
|
* vector in which the result will be stored
|
||||||
|
* viewport
|
||||||
|
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
|
||||||
|
*/
|
||||||
|
LIB_GEOMETRY_EXPORT
|
||||||
|
void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4]);
|
||||||
|
|
||||||
|
/*! From image to retina
|
||||||
|
* p
|
||||||
|
* point's coordinates expressed in image system
|
||||||
|
* q
|
||||||
|
* vector in which the result will be stored
|
||||||
|
* viewport
|
||||||
|
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
|
||||||
|
*/
|
||||||
|
LIB_GEOMETRY_EXPORT
|
||||||
|
void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4]);
|
||||||
|
|
||||||
|
/*! computes the coordinates of q in the camera coordinates system,
|
||||||
|
* using the known z coordinates of the 3D point.
|
||||||
|
* That means that this method does not inverse any matrices,
|
||||||
|
* it only computes X and Y from x,y and Z)
|
||||||
|
* p
|
||||||
|
* point's coordinates expressed in retina system
|
||||||
|
* q
|
||||||
|
* vector in which the result will be stored
|
||||||
|
* projection_matrix
|
||||||
|
* The projection matrix expressed in line major order (OpenGL
|
||||||
|
* matrices are column major ordered)
|
||||||
|
*/
|
||||||
|
LIB_GEOMETRY_EXPORT
|
||||||
|
void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real z, const real projection_matrix[4][4]);
|
||||||
|
|
||||||
|
/*! Projects from camera coordinates to world coordinates
|
||||||
|
* Returns the point's coordinates expressed in the world's
|
||||||
|
* coordinates system.
|
||||||
|
* p
|
||||||
|
* point's coordinates expressed in the camera coordinates system
|
||||||
|
* q
|
||||||
|
* vector in which the result will be stored
|
||||||
|
* model_view_matrix
|
||||||
|
* The model view matrix expressed in line major order (OpenGL
|
||||||
|
* matrices are column major ordered)
|
||||||
|
*/
|
||||||
|
LIB_GEOMETRY_EXPORT
|
||||||
|
void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
|
||||||
|
|
||||||
} // end of namespace GeomUtils
|
} // end of namespace GeomUtils
|
||||||
|
|
||||||
#endif // GEOMUTILS_H
|
#endif // __GEOMUTILS_H__
|
||||||
|
@ -1,392 +1,390 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Grid.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Base class to define a cell grid surrounding the bounding box of the scene
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "Grid.h"
|
|
||||||
#include "BBox.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "BBox.h"
|
||||||
|
#include "Grid.h"
|
||||||
|
|
||||||
// Grid Visitors
|
// Grid Visitors
|
||||||
/////////////////
|
/////////////////
|
||||||
void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){
|
void allOccludersGridVisitor::examineOccluder(Polygon3r *occ)
|
||||||
occluders_.push_back(occ);
|
{
|
||||||
|
occluders_.push_back(occ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
|
static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max)
|
||||||
if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
|
{
|
||||||
&& ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
|
if (((inter.x() >= box_min.x()) && (inter.x() < box_max.x())) &&
|
||||||
&& ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
|
((inter.y() >= box_min.y()) && (inter.y() < box_max.y())) &&
|
||||||
){
|
((inter.z() >= box_min.z()) && (inter.z() < box_max.z())))
|
||||||
return true;
|
{
|
||||||
}
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
return false;
|
||||||
void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){
|
|
||||||
|
|
||||||
// check whether the edge and the polygon plane are coincident:
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
//first let us compute the plane equation.
|
|
||||||
Vec3r v1(((occ)->getVertices())[0]);
|
|
||||||
Vec3d normal((occ)->getNormal());
|
|
||||||
//soc unused - double d = -(v1 * normal);
|
|
||||||
|
|
||||||
double tmp_u, tmp_v, tmp_t;
|
|
||||||
if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){
|
|
||||||
if (fabs(ray_dir_ * normal) > 0.0001){
|
|
||||||
// Check whether the intersection is in the cell:
|
|
||||||
if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){
|
|
||||||
|
|
||||||
//Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin());
|
|
||||||
//if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){
|
|
||||||
if(tmp_t < t_){
|
|
||||||
occluder_ = occ;
|
|
||||||
u_ = tmp_u;
|
|
||||||
v_ = tmp_v;
|
|
||||||
t_ = tmp_t;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
occ->userdata2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool firstIntersectionGridVisitor::stop(){
|
void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ)
|
||||||
if(occluder_)
|
{
|
||||||
return true;
|
// check whether the edge and the polygon plane are coincident:
|
||||||
return false;
|
//-------------------------------------------------------------
|
||||||
|
//first let us compute the plane equation.
|
||||||
|
Vec3r v1(((occ)->getVertices())[0]);
|
||||||
|
Vec3d normal((occ)->getNormal());
|
||||||
|
//soc unused - double d = -(v1 * normal);
|
||||||
|
|
||||||
|
double tmp_u, tmp_v, tmp_t;
|
||||||
|
if ((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)) {
|
||||||
|
if (fabs(ray_dir_ * normal) > 0.0001) {
|
||||||
|
// Check whether the intersection is in the cell:
|
||||||
|
if (inBox(ray_org_ + tmp_t * ray_dir_ / ray_dir_.norm(), current_cell_->getOrigin(),
|
||||||
|
current_cell_->getOrigin() + cell_size_))
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
Vec3d bboxdiag(_scene3d->bbox().getMax() - _scene3d->bbox().getMin());
|
||||||
|
if ((t > 1.0e-06 * (min(min(bboxdiag.x(), bboxdiag.y()), bboxdiag.z()))) && (t < raylength)) {
|
||||||
|
#else
|
||||||
|
if (tmp_t < t_) {
|
||||||
|
#endif
|
||||||
|
occluder_ = occ;
|
||||||
|
u_ = tmp_u;
|
||||||
|
v_ = tmp_v;
|
||||||
|
t_ = tmp_t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
occ->userdata2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool firstIntersectionGridVisitor::stop()
|
||||||
|
{
|
||||||
|
if (occluder_)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grid
|
// Grid
|
||||||
/////////////////
|
/////////////////
|
||||||
|
void Grid::clear()
|
||||||
void Grid::clear() {
|
{
|
||||||
if (_occluders.size() != 0) {
|
if (_occluders.size() != 0) {
|
||||||
for(OccludersSet::iterator it = _occluders.begin();
|
for (OccludersSet::iterator it = _occluders.begin(); it != _occluders.end(); it++) {
|
||||||
it != _occluders.end();
|
delete (*it);
|
||||||
it++) {
|
}
|
||||||
delete (*it);
|
_occluders.clear();
|
||||||
}
|
|
||||||
_occluders.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
_size = Vec3r(0, 0, 0);
|
|
||||||
_cell_size = Vec3r(0, 0, 0);
|
|
||||||
_orig = Vec3r(0, 0, 0);
|
|
||||||
_cells_nb = Vec3u(0, 0, 0);
|
|
||||||
//_ray_occluders.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grid::configure(const Vec3r& orig,
|
|
||||||
const Vec3r& size,
|
|
||||||
unsigned nb) {
|
|
||||||
|
|
||||||
_orig = orig;
|
|
||||||
Vec3r tmpSize=size;
|
|
||||||
// Compute the volume of the desired grid
|
|
||||||
real grid_vol = size[0] * size[1] * size[2];
|
|
||||||
|
|
||||||
if(grid_vol == 0){
|
|
||||||
double min=DBL_MAX;
|
|
||||||
int index=0;
|
|
||||||
int nzeros=0;
|
|
||||||
for(int i=0;i<3;++i){
|
|
||||||
if(size[i] == 0){
|
|
||||||
++nzeros;
|
|
||||||
index=i;
|
|
||||||
}
|
|
||||||
if((size[i]!=0) && (min>size[i])){
|
|
||||||
min=size[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(nzeros>1){
|
|
||||||
throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
|
|
||||||
}
|
|
||||||
tmpSize[index]=min;
|
|
||||||
_orig[index] = _orig[index]-min/2;
|
|
||||||
}
|
|
||||||
// Compute the desired volume of a single cell
|
|
||||||
real cell_vol = grid_vol / nb;
|
|
||||||
// The edge of such a cubic cell is cubic root of cellVolume
|
|
||||||
real edge = pow(cell_vol, 1.0 / 3.0);
|
|
||||||
|
|
||||||
// We compute the number of cells par edge
|
|
||||||
// such as we cover at least the whole box.
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
_cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
|
|
||||||
|
|
||||||
_size = tmpSize;
|
|
||||||
|
|
||||||
for(i = 0; i < 3; i++)
|
|
||||||
_cell_size[i] = _size[i] / _cells_nb[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grid::insertOccluder(Polygon3r* occluder) {
|
|
||||||
const vector<Vec3r> vertices = occluder->getVertices();
|
|
||||||
if (vertices.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// add this occluder to the grid's occluders list
|
|
||||||
addOccluder(occluder);
|
|
||||||
|
|
||||||
// find the bbox associated to this polygon
|
|
||||||
Vec3r min, max;
|
|
||||||
occluder->getBBox(min, max);
|
|
||||||
|
|
||||||
// Retrieve the cell x, y, z cordinates associated with these min and max
|
|
||||||
Vec3u imax, imin;
|
|
||||||
getCellCoordinates(max, imax);
|
|
||||||
getCellCoordinates(min, imin);
|
|
||||||
|
|
||||||
// We are now going to fill in the cells overlapping with the
|
|
||||||
// polygon bbox.
|
|
||||||
// If the polygon is a triangle (most of cases), we also
|
|
||||||
// check for each of these cells if it is overlapping with
|
|
||||||
// the triangle in order to only fill in the ones really overlapping
|
|
||||||
// the triangle.
|
|
||||||
|
|
||||||
unsigned i, x, y, z;
|
|
||||||
vector<Vec3r>::const_iterator it;
|
|
||||||
Vec3u coord;
|
|
||||||
|
|
||||||
if (vertices.size() == 3) { // Triangle case
|
|
||||||
Vec3r triverts[3];
|
|
||||||
i = 0;
|
|
||||||
for(it = vertices.begin();
|
|
||||||
it != vertices.end();
|
|
||||||
it++) {
|
|
||||||
triverts[i] = Vec3r(*it);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3r boxmin, boxmax;
|
|
||||||
|
|
||||||
for (z = imin[2]; z <= imax[2]; z++)
|
|
||||||
for (y = imin[1]; y <= imax[1]; y++)
|
|
||||||
for (x = imin[0]; x <= imax[0]; x++) {
|
|
||||||
coord[0] = x;
|
|
||||||
coord[1] = y;
|
|
||||||
coord[2] = z;
|
|
||||||
// We retrieve the box coordinates of the current cell
|
|
||||||
getCellBox(coord, boxmin, boxmax);
|
|
||||||
// We check whether the triangle and the box ovewrlap:
|
|
||||||
Vec3r boxcenter((boxmin + boxmax) / 2.0);
|
|
||||||
Vec3r boxhalfsize(_cell_size / 2.0);
|
|
||||||
if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
|
|
||||||
// We must then create the Cell and add it to the cells list
|
|
||||||
// if it does not exist yet.
|
|
||||||
// We must then add the occluder to the occluders list of this cell.
|
|
||||||
Cell* cell = getCell(coord);
|
|
||||||
if (!cell) {
|
|
||||||
cell = new Cell(boxmin);
|
|
||||||
fillCell(coord, *cell);
|
|
||||||
}
|
|
||||||
cell->addOccluder(occluder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
|
_size = Vec3r(0, 0, 0);
|
||||||
for (z = imin[2]; z <= imax[2]; z++)
|
_cell_size = Vec3r(0, 0, 0);
|
||||||
for (y = imin[1]; y <= imax[1]; y++)
|
_orig = Vec3r(0, 0, 0);
|
||||||
for (x = imin[0]; x <= imax[0]; x++) {
|
_cells_nb = Vec3u(0, 0, 0);
|
||||||
coord[0] = x;
|
//_ray_occluders.clear();
|
||||||
coord[1] = y;
|
}
|
||||||
coord[2] = z;
|
|
||||||
Cell* cell = getCell(coord);
|
void Grid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
|
||||||
if (!cell) {
|
{
|
||||||
Vec3r orig;
|
_orig = orig;
|
||||||
getCellOrigin(coord, orig);
|
Vec3r tmpSize = size;
|
||||||
cell = new Cell(orig);
|
// Compute the volume of the desired grid
|
||||||
fillCell(coord, *cell);
|
real grid_vol = size[0] * size[1] * size[2];
|
||||||
}
|
|
||||||
cell->addOccluder(occluder);
|
if (grid_vol == 0) {
|
||||||
|
double min = DBL_MAX;
|
||||||
|
int index = 0;
|
||||||
|
int nzeros = 0;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
if (size[i] == 0) {
|
||||||
|
++nzeros;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
if ((size[i] != 0) && (min > size[i])) {
|
||||||
|
min = size[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nzeros > 1) {
|
||||||
|
throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
|
||||||
|
}
|
||||||
|
tmpSize[index] = min;
|
||||||
|
_orig[index] = _orig[index] - min / 2;
|
||||||
}
|
}
|
||||||
}
|
// Compute the desired volume of a single cell
|
||||||
|
real cell_vol = grid_vol / nb;
|
||||||
|
// The edge of such a cubic cell is cubic root of cellVolume
|
||||||
|
real edge = pow(cell_vol, 1.0 / 3.0);
|
||||||
|
|
||||||
|
// We compute the number of cells par edge such as we cover at least the whole box.
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
_cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
|
||||||
|
|
||||||
|
_size = tmpSize;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
_cell_size[i] = _size[i] / _cells_nb[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) {
|
void Grid::insertOccluder(Polygon3r* occluder)
|
||||||
next_cell = current_cell;
|
{
|
||||||
real t_min, t;
|
const vector<Vec3r> vertices = occluder->getVertices();
|
||||||
unsigned i;
|
if (vertices.size() == 0)
|
||||||
|
return;
|
||||||
t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
|
|
||||||
unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
|
|
||||||
|
|
||||||
|
// add this occluder to the grid's occluders list
|
||||||
|
addOccluder(occluder);
|
||||||
|
|
||||||
// using a parametric equation of
|
// find the bbox associated to this polygon
|
||||||
// a line : B = A + t u, we find
|
Vec3r min, max;
|
||||||
// the tx, ty and tz respectively coresponding
|
occluder->getBBox(min, max);
|
||||||
// to the intersections with the plans:
|
|
||||||
// x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
if (_ray_dir[i] == 0)
|
|
||||||
continue;
|
|
||||||
if (_ray_dir[i] > 0)
|
|
||||||
t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
|
|
||||||
else
|
|
||||||
t = -_pt[i] / _ray_dir[i];
|
|
||||||
if (t < t_min) {
|
|
||||||
t_min = t;
|
|
||||||
coord = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use the parametric line equation and
|
// Retrieve the cell x, y, z cordinates associated with these min and max
|
||||||
// the found t (tamx) to compute the
|
Vec3u imax, imin;
|
||||||
// B coordinates:
|
getCellCoordinates(max, imax);
|
||||||
Vec3r pt_tmp(_pt);
|
getCellCoordinates(min, imin);
|
||||||
_pt = pt_tmp + t_min * _ray_dir;
|
|
||||||
|
|
||||||
// We express B coordinates in the next cell
|
|
||||||
// coordinates system. We just have to
|
|
||||||
// set the coordinate coord of B to 0
|
|
||||||
// of _CellSize[coord] depending on the sign
|
|
||||||
// of _u[coord]
|
|
||||||
if (_ray_dir[coord] > 0) {
|
|
||||||
next_cell[coord]++;
|
|
||||||
_pt[coord] -= _cell_size[coord];
|
|
||||||
// if we are out of the grid, we must stop
|
|
||||||
if (next_cell[coord] >= _cells_nb[coord])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int tmp = next_cell[coord] - 1;
|
|
||||||
_pt[coord] = _cell_size[coord];
|
|
||||||
if (tmp < 0)
|
|
||||||
return false;
|
|
||||||
next_cell[coord]--;
|
|
||||||
}
|
|
||||||
|
|
||||||
_t += t_min;
|
// We are now going to fill in the cells overlapping with the polygon bbox.
|
||||||
if (_t >= _t_end)
|
// If the polygon is a triangle (most of cases), we also check for each of these cells if it is overlapping with
|
||||||
return false;
|
// the triangle in order to only fill in the ones really overlapping the triangle.
|
||||||
|
|
||||||
return true;
|
unsigned i, x, y, z;
|
||||||
|
vector<Vec3r>::const_iterator it;
|
||||||
|
Vec3u coord;
|
||||||
|
|
||||||
|
if (vertices.size() == 3) { // Triangle case
|
||||||
|
Vec3r triverts[3];
|
||||||
|
i = 0;
|
||||||
|
for (it = vertices.begin(); it != vertices.end(); it++) {
|
||||||
|
triverts[i] = Vec3r(*it);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3r boxmin, boxmax;
|
||||||
|
|
||||||
|
for (z = imin[2]; z <= imax[2]; z++) {
|
||||||
|
for (y = imin[1]; y <= imax[1]; y++) {
|
||||||
|
for (x = imin[0]; x <= imax[0]; x++) {
|
||||||
|
coord[0] = x;
|
||||||
|
coord[1] = y;
|
||||||
|
coord[2] = z;
|
||||||
|
// We retrieve the box coordinates of the current cell
|
||||||
|
getCellBox(coord, boxmin, boxmax);
|
||||||
|
// We check whether the triangle and the box ovewrlap:
|
||||||
|
Vec3r boxcenter((boxmin + boxmax) / 2.0);
|
||||||
|
Vec3r boxhalfsize(_cell_size / 2.0);
|
||||||
|
if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
|
||||||
|
// We must then create the Cell and add it to the cells list if it does not exist yet.
|
||||||
|
// We must then add the occluder to the occluders list of this cell.
|
||||||
|
Cell* cell = getCell(coord);
|
||||||
|
if (!cell) {
|
||||||
|
cell = new Cell(boxmin);
|
||||||
|
fillCell(coord, *cell);
|
||||||
|
}
|
||||||
|
cell->addOccluder(occluder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
|
||||||
|
for (z = imin[2]; z <= imax[2]; z++) {
|
||||||
|
for (y = imin[1]; y <= imax[1]; y++) {
|
||||||
|
for (x = imin[0]; x <= imax[0]; x++) {
|
||||||
|
coord[0] = x;
|
||||||
|
coord[1] = y;
|
||||||
|
coord[2] = z;
|
||||||
|
Cell* cell = getCell(coord);
|
||||||
|
if (!cell) {
|
||||||
|
Vec3r orig;
|
||||||
|
getCellOrigin(coord, orig);
|
||||||
|
cell = new Cell(orig);
|
||||||
|
fillCell(coord, *cell);
|
||||||
|
}
|
||||||
|
cell->addOccluder(occluder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grid::castRay(const Vec3r& orig,
|
bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell)
|
||||||
const Vec3r& end,
|
{
|
||||||
OccludersSet& occluders,
|
next_cell = current_cell;
|
||||||
unsigned timestamp) {
|
real t_min, t;
|
||||||
initRay(orig, end, timestamp);
|
unsigned i;
|
||||||
allOccludersGridVisitor visitor(occluders);
|
|
||||||
castRayInternal(visitor);
|
t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
|
||||||
|
unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
|
||||||
|
|
||||||
|
|
||||||
|
// using a parametric equation of a line : B = A + t u, we find the tx, ty and tz respectively coresponding
|
||||||
|
// to the intersections with the plans:
|
||||||
|
// x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (_ray_dir[i] == 0)
|
||||||
|
continue;
|
||||||
|
if (_ray_dir[i] > 0)
|
||||||
|
t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
|
||||||
|
else
|
||||||
|
t = -_pt[i] / _ray_dir[i];
|
||||||
|
if (t < t_min) {
|
||||||
|
t_min = t;
|
||||||
|
coord = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use the parametric line equation and the found t (tamx) to compute the B coordinates:
|
||||||
|
Vec3r pt_tmp(_pt);
|
||||||
|
_pt = pt_tmp + t_min * _ray_dir;
|
||||||
|
|
||||||
|
// We express B coordinates in the next cell coordinates system. We just have to
|
||||||
|
// set the coordinate coord of B to 0 of _CellSize[coord] depending on the sign of _u[coord]
|
||||||
|
if (_ray_dir[coord] > 0) {
|
||||||
|
next_cell[coord]++;
|
||||||
|
_pt[coord] -= _cell_size[coord];
|
||||||
|
// if we are out of the grid, we must stop
|
||||||
|
if (next_cell[coord] >= _cells_nb[coord])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int tmp = next_cell[coord] - 1;
|
||||||
|
_pt[coord] = _cell_size[coord];
|
||||||
|
if (tmp < 0)
|
||||||
|
return false;
|
||||||
|
next_cell[coord]--;
|
||||||
|
}
|
||||||
|
|
||||||
|
_t += t_min;
|
||||||
|
if (_t >= _t_end)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grid::castInfiniteRay(const Vec3r& orig,
|
void Grid::castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp)
|
||||||
const Vec3r& dir,
|
{
|
||||||
OccludersSet& occluders,
|
initRay(orig, end, timestamp);
|
||||||
unsigned timestamp) {
|
allOccludersGridVisitor visitor(occluders);
|
||||||
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
|
castRayInternal(visitor);
|
||||||
bool inter = initInfiniteRay(orig, dir, timestamp);
|
|
||||||
if(!inter)
|
|
||||||
return;
|
|
||||||
allOccludersGridVisitor visitor(occluders);
|
|
||||||
castRayInternal(visitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig,
|
void Grid::castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp)
|
||||||
const Vec3r& dir,
|
{
|
||||||
double& t,
|
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
|
||||||
double& u,
|
bool inter = initInfiniteRay(orig, dir, timestamp);
|
||||||
double& v,
|
if (!inter)
|
||||||
unsigned timestamp){
|
return;
|
||||||
Polygon3r *occluder = 0;
|
allOccludersGridVisitor visitor(occluders);
|
||||||
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
|
castRayInternal(visitor);
|
||||||
bool inter = initInfiniteRay(orig, dir, timestamp);
|
}
|
||||||
if(!inter){
|
|
||||||
return 0;
|
Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
|
||||||
}
|
double& u, double& v, unsigned timestamp)
|
||||||
firstIntersectionGridVisitor visitor(orig,dir,_cell_size);
|
{
|
||||||
castRayInternal(visitor);
|
Polygon3r *occluder = 0;
|
||||||
|
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
|
||||||
|
bool inter = initInfiniteRay(orig, dir, timestamp);
|
||||||
|
if (!inter) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
firstIntersectionGridVisitor visitor(orig, dir, _cell_size);
|
||||||
|
castRayInternal(visitor);
|
||||||
// ARB: This doesn't work, because occluders are unordered within any cell
|
// ARB: This doesn't work, because occluders are unordered within any cell
|
||||||
// visitor.occluder() will be an occluder, but we have no guarantee
|
// visitor.occluder() will be an occluder, but we have no guarantee it will be the *first* occluder.
|
||||||
// it will be the *first* occluder.
|
|
||||||
// I assume that is the reason this code is not actually used for FindOccludee.
|
// I assume that is the reason this code is not actually used for FindOccludee.
|
||||||
occluder = visitor.occluder();
|
occluder = visitor.occluder();
|
||||||
t = visitor.t_;
|
t = visitor.t_;
|
||||||
u = visitor.u_;
|
u = visitor.u_;
|
||||||
v = visitor.v_;
|
v = visitor.v_;
|
||||||
return occluder;
|
return occluder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grid::initRay (const Vec3r &orig,
|
void Grid::initRay (const Vec3r &orig, const Vec3r& end, unsigned timestamp)
|
||||||
const Vec3r& end,
|
{
|
||||||
unsigned timestamp) {
|
_ray_dir = end - orig;
|
||||||
_ray_dir = end - orig;
|
_t_end = _ray_dir.norm();
|
||||||
_t_end = _ray_dir.norm();
|
_t = 0;
|
||||||
_t = 0;
|
_ray_dir.normalize();
|
||||||
_ray_dir.normalize();
|
_timestamp = timestamp;
|
||||||
_timestamp = timestamp;
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < 3; i++) {
|
|
||||||
_current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
|
|
||||||
//soc unused - unsigned u = _current_cell[i];
|
|
||||||
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
|
||||||
}
|
|
||||||
//_ray_occluders.clear();
|
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 3; i++) {
|
||||||
|
_current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
|
||||||
|
//soc unused - unsigned u = _current_cell[i];
|
||||||
|
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
||||||
|
}
|
||||||
|
//_ray_occluders.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Grid::initInfiniteRay (const Vec3r &orig,
|
bool Grid::initInfiniteRay (const Vec3r &orig, const Vec3r& dir, unsigned timestamp) {
|
||||||
const Vec3r& dir,
|
_ray_dir = dir;
|
||||||
unsigned timestamp) {
|
_t_end = FLT_MAX;
|
||||||
_ray_dir = dir;
|
_t = 0;
|
||||||
_t_end = FLT_MAX;
|
_ray_dir.normalize();
|
||||||
_t = 0;
|
_timestamp = timestamp;
|
||||||
_ray_dir.normalize();
|
|
||||||
_timestamp = timestamp;
|
|
||||||
|
|
||||||
// check whether the origin is in or out the box:
|
// check whether the origin is in or out the box:
|
||||||
Vec3r boxMin(_orig);
|
Vec3r boxMin(_orig);
|
||||||
Vec3r boxMax(_orig+_size);
|
Vec3r boxMax(_orig + _size);
|
||||||
BBox<Vec3r> box(boxMin, boxMax);
|
BBox<Vec3r> box(boxMin, boxMax);
|
||||||
if(box.inside(orig)){
|
if (box.inside(orig)) {
|
||||||
for(unsigned i = 0; i < 3; i++) {
|
for (unsigned int i = 0; i < 3; i++) {
|
||||||
_current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
|
_current_cell[i] = (unsigned int)floor((orig[i] - _orig[i]) / _cell_size[i]);
|
||||||
//soc unused - unsigned u = _current_cell[i];
|
//soc unused - unsigned u = _current_cell[i];
|
||||||
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
||||||
}
|
}
|
||||||
}else{
|
}
|
||||||
// is the ray intersecting the box?
|
else {
|
||||||
real tmin(-1.0), tmax(-1.0);
|
// is the ray intersecting the box?
|
||||||
if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){
|
real tmin(-1.0), tmax(-1.0);
|
||||||
assert(tmin != -1.0);
|
if (GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)) {
|
||||||
Vec3r newOrig = orig + tmin*_ray_dir;
|
assert(tmin != -1.0);
|
||||||
for(unsigned i = 0; i < 3; i++) {
|
Vec3r newOrig = orig + tmin * _ray_dir;
|
||||||
_current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
|
for (unsigned int i = 0; i < 3; i++) {
|
||||||
if(_current_cell[i] == _cells_nb[i])
|
_current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
|
||||||
_current_cell[i] = _cells_nb[i] - 1;
|
if (_current_cell[i] == _cells_nb[i])
|
||||||
//soc unused - unsigned u = _current_cell[i];
|
_current_cell[i] = _cells_nb[i] - 1;
|
||||||
_pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
//soc unused - unsigned u = _current_cell[i];
|
||||||
}
|
_pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
|
||||||
|
}
|
||||||
}else{
|
}
|
||||||
return false;
|
else {
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
//_ray_occluders.clear();
|
}
|
||||||
|
//_ray_occluders.clear();
|
||||||
return true;
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,49 +1,54 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Grid.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Base class to define a cell grid surrounding
|
* This program is free software; you can redistribute it and/or
|
||||||
// the bounding box of the scene
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 30/07/2002
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GRID_H__
|
||||||
|
#define __GRID_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Grid.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Base class to define a cell grid surrounding the bounding box of the scene
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GRID_H
|
#include <cstring> // for memset
|
||||||
# define GRID_H
|
#include <float.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
# include <cstring> // for memset
|
#include "Geom.h"
|
||||||
# include <float.h>
|
#include "GeomUtils.h"
|
||||||
# include <vector>
|
#include "Polygon.h"
|
||||||
# include "../system/FreestyleConfig.h"
|
|
||||||
# include "GeomUtils.h"
|
#include "../system/FreestyleConfig.h"
|
||||||
# include "Geom.h"
|
|
||||||
# include "Polygon.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
typedef vector<Polygon3r*> OccludersSet;
|
typedef vector<Polygon3r*> OccludersSet;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class to define cells used by the regular grid
|
// Class to define cells used by the regular grid
|
||||||
@ -52,84 +57,102 @@ typedef vector<Polygon3r*> OccludersSet;
|
|||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT Cell
|
class LIB_GEOMETRY_EXPORT Cell
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Cell(Vec3r& orig) {
|
||||||
Cell(Vec3r& orig) {
|
_orig = orig;
|
||||||
_orig = orig;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Cell() {}
|
virtual ~Cell() {}
|
||||||
|
|
||||||
inline void addOccluder(Polygon3r* o) {
|
inline void addOccluder(Polygon3r* o) {
|
||||||
if (o)
|
if (o)
|
||||||
_occluders.push_back(o);
|
_occluders.push_back(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Vec3r& getOrigin() {
|
inline const Vec3r& getOrigin() {
|
||||||
return _orig;
|
return _orig;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline OccludersSet& getOccluders() {
|
inline OccludersSet& getOccluders() {
|
||||||
return _occluders;
|
return _occluders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Vec3r _orig;
|
private:
|
||||||
OccludersSet _occluders;
|
Vec3r _orig;
|
||||||
|
OccludersSet _occluders;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GridVisitor{
|
class GridVisitor
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~GridVisitor() {}; //soc
|
virtual ~GridVisitor() {}; //soc
|
||||||
virtual void discoverCell(Cell *cell) {}
|
|
||||||
virtual void examineOccluder(Polygon3r *occ) {}
|
virtual void discoverCell(Cell *cell) {}
|
||||||
virtual void finishCell(Cell *cell) {}
|
|
||||||
virtual bool stop() {return false;}
|
virtual void examineOccluder(Polygon3r *occ) {}
|
||||||
|
|
||||||
|
virtual void finishCell(Cell *cell) {}
|
||||||
|
|
||||||
|
virtual bool stop() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Gathers all the occluders belonging to the cells
|
/*! Gathers all the occluders belonging to the cells traversed by the ray */
|
||||||
* traversed by the ray */
|
class allOccludersGridVisitor : public GridVisitor
|
||||||
class allOccludersGridVisitor : public GridVisitor{
|
{
|
||||||
public:
|
public:
|
||||||
allOccludersGridVisitor(OccludersSet& occluders)
|
allOccludersGridVisitor(OccludersSet& occluders) : GridVisitor(), occluders_(occluders) {}
|
||||||
:GridVisitor(), occluders_(occluders){}
|
|
||||||
virtual void examineOccluder(Polygon3r *occ);
|
|
||||||
|
|
||||||
OccludersSet& occluders() {return occluders_;}
|
virtual void examineOccluder(Polygon3r *occ);
|
||||||
void clear() {occluders_.clear();}
|
|
||||||
|
OccludersSet& occluders() {
|
||||||
|
return occluders_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
occluders_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OccludersSet& occluders_;
|
OccludersSet& occluders_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Finds the first intersection and breaks. The occluder and
|
/*! Finds the first intersection and breaks.
|
||||||
* the intersection information are stored and accessible.
|
* The occluder and the intersection information are stored and accessible.
|
||||||
*/
|
*/
|
||||||
class firstIntersectionGridVisitor : public GridVisitor {
|
class firstIntersectionGridVisitor : public GridVisitor
|
||||||
|
{
|
||||||
//soc - changed order to remove warnings
|
//soc - changed order to remove warnings
|
||||||
public:
|
public:
|
||||||
double u_, v_, t_;
|
double u_, v_, t_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Polygon3r *occluder_;
|
Polygon3r *occluder_;
|
||||||
Vec3r ray_org_, ray_dir_, cell_size_;
|
Vec3r ray_org_, ray_dir_, cell_size_;
|
||||||
Cell * current_cell_;
|
Cell *current_cell_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
|
firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
|
||||||
GridVisitor(), u_(0),v_(0),t_(DBL_MAX),
|
GridVisitor(), u_(0),v_(0),t_(DBL_MAX), occluder_(0), ray_org_(ray_org), ray_dir_(ray_dir),
|
||||||
occluder_(0),
|
cell_size_(cell_size), current_cell_(0)
|
||||||
ray_org_(ray_org), ray_dir_(ray_dir), cell_size_(cell_size),
|
{
|
||||||
current_cell_(0) {}
|
}
|
||||||
virtual ~firstIntersectionGridVisitor() {}
|
|
||||||
|
|
||||||
virtual void discoverCell(Cell *cell) {current_cell_=cell;}
|
virtual ~firstIntersectionGridVisitor() {}
|
||||||
virtual void examineOccluder(Polygon3r *occ);
|
|
||||||
virtual bool stop();
|
|
||||||
|
|
||||||
Polygon3r * occluder() {return occluder_;}
|
virtual void discoverCell(Cell *cell) {
|
||||||
|
current_cell_ = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void examineOccluder(Polygon3r *occ);
|
||||||
|
|
||||||
|
virtual bool stop();
|
||||||
|
|
||||||
|
Polygon3r *occluder() {
|
||||||
|
return occluder_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -140,236 +163,197 @@ public:
|
|||||||
class LIB_GEOMETRY_EXPORT Grid
|
class LIB_GEOMETRY_EXPORT Grid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*! Builds a Grid. Must be followed by a call to configure() */
|
||||||
|
Grid() {}
|
||||||
|
|
||||||
/*! Builds a Grid
|
virtual ~Grid() {
|
||||||
* Must be followed by a call to configure()
|
clear();
|
||||||
*/
|
}
|
||||||
Grid() {}
|
|
||||||
|
|
||||||
virtual ~Grid() {
|
/*! clears the grid
|
||||||
clear();
|
* Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
|
||||||
}
|
*/
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
/*! clears the grid
|
/*! Sets the different parameters of the grid
|
||||||
* Deletes all the cells, clears the hashtable,
|
* orig
|
||||||
* resets size, size of cell, number of cells.
|
* The grid origin
|
||||||
*/
|
* size
|
||||||
virtual void clear();
|
* The grid's dimensions
|
||||||
|
* nb
|
||||||
|
* The number of cells of the grid
|
||||||
|
*/
|
||||||
|
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
||||||
|
|
||||||
/*! Sets the different parameters of the grid
|
/*! returns a vector of integer containing the coordinates of the cell containing the point passed as argument
|
||||||
* orig
|
* p
|
||||||
* The grid origin
|
* The point for which we're looking the cell
|
||||||
* size
|
*/
|
||||||
* The grid's dimensions
|
inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
|
||||||
* nb
|
int tmp;
|
||||||
* The number of cells of the grid
|
for (int i = 0; i < 3; i++) {
|
||||||
*/
|
tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
|
||||||
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
if (tmp < 0)
|
||||||
|
res[i] = 0;
|
||||||
/*! returns a vector of integer containing the
|
else if ((unsigned int)tmp >= _cells_nb[i])
|
||||||
* coordinates of the cell containing the point
|
res[i] = _cells_nb[i] - 1;
|
||||||
* passed as argument
|
else
|
||||||
* p
|
res[i] = tmp;
|
||||||
* The point for which we're looking the cell
|
}
|
||||||
*/
|
}
|
||||||
inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
|
|
||||||
int tmp;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
|
|
||||||
if (tmp < 0)
|
|
||||||
res[i] = 0;
|
|
||||||
else if ((unsigned)tmp >= _cells_nb[i])
|
|
||||||
res[i] = _cells_nb[i] - 1;
|
|
||||||
else
|
|
||||||
res[i] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Fills the case corresponding to coord with the cell */
|
/*! Fills the case corresponding to coord with the cell */
|
||||||
virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
|
virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
|
||||||
|
|
||||||
/*! returns the cell whose coordinates
|
/*! returns the cell whose coordinates are pased as argument */
|
||||||
* are pased as argument
|
virtual Cell* getCell(const Vec3u& coord) = 0;
|
||||||
*/
|
|
||||||
virtual Cell* getCell(const Vec3u& coord) = 0;
|
|
||||||
|
|
||||||
/*! returns the cell containing the point
|
/*! returns the cell containing the point passed as argument. If the cell is empty (contains no occluder),
|
||||||
* passed as argument. If the cell is empty
|
* NULL is returned
|
||||||
* (contains no occluder), NULL is returned
|
* p
|
||||||
* p
|
* The point for which we're looking the cell
|
||||||
* The point for which we're looking the cell
|
*/
|
||||||
*/
|
inline Cell* getCell(const Vec3r& p) {
|
||||||
inline Cell* getCell(const Vec3r& p) {
|
Vec3u coord;
|
||||||
Vec3u coord;
|
getCellCoordinates(p, coord);
|
||||||
getCellCoordinates(p, coord);
|
return getCell(coord);
|
||||||
return getCell(coord);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k)
|
/*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k) is passed as argument
|
||||||
* is passed as argument
|
* cell_coord
|
||||||
* cell_coord
|
* i,j,k integer coordinates for the cell
|
||||||
* i,j,k integer coordinates for the cell
|
* orig
|
||||||
* orig
|
* x,y,x vector to be filled in with the cell origin's coordinates
|
||||||
* x,y,x vector to be filled in with the cell origin's coordinates
|
*/
|
||||||
*/
|
inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
|
||||||
inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
|
for (unsigned int i = 0; i < 3; i++)
|
||||||
for (unsigned i = 0; i < 3; i++)
|
orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
|
||||||
orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*! Retrieves the box corresponding to the cell whose coordinates
|
/*! Retrieves the box corresponding to the cell whose coordinates are passed as argument.
|
||||||
* are passed as argument.
|
* cell_coord
|
||||||
* cell_coord
|
* i,j,k integer coordinates for the cell
|
||||||
* i,j,k integer coordinates for the cell
|
* min_out
|
||||||
* min_out
|
* The min x,y,x vector of the box. Filled in by the method.
|
||||||
* The min x,y,x vector of the box. Filled in by the method.
|
* max_out
|
||||||
* max_out
|
* The max x,y,z coordinates of the box. Filled in by the method.
|
||||||
* The max x,y,z coordinates of the box. Filled in by the method.
|
*/
|
||||||
*/
|
inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
|
||||||
inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
|
getCellOrigin(cell_coord, min_out);
|
||||||
getCellOrigin(cell_coord, min_out);
|
max_out = min_out + _cell_size;
|
||||||
max_out = min_out + _cell_size;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*! inserts a convex polygon occluder
|
/*! inserts a convex polygon occluder
|
||||||
* This method is quite coarse insofar as it
|
* This method is quite coarse insofar as it adds all cells intersecting the polygon bounding box
|
||||||
* adds all cells intersecting the polygon bounding box
|
* convex_poly
|
||||||
* convex_poly
|
* The list of 3D points constituing a convex polygon
|
||||||
* The list of 3D points constituing a convex polygon
|
*/
|
||||||
*/
|
void insertOccluder(Polygon3r * convex_poly);
|
||||||
void insertOccluder(Polygon3r * convex_poly);
|
|
||||||
|
|
||||||
/*! Adds an occluder to the list of occluders */
|
/*! Adds an occluder to the list of occluders */
|
||||||
void addOccluder(Polygon3r* occluder) {
|
void addOccluder(Polygon3r* occluder) {
|
||||||
_occluders.push_back(occluder);
|
_occluders.push_back(occluder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Casts a ray between a starting point and an ending point
|
/*! Casts a ray between a starting point and an ending point
|
||||||
* Returns the list of occluders contained
|
* Returns the list of occluders contained in the cells intersected by this ray
|
||||||
* in the cells intersected by this ray
|
* Starts with a call to InitRay.
|
||||||
* Starts with a call to InitRay.
|
*/
|
||||||
*/
|
void castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp);
|
||||||
void castRay(const Vec3r& orig,
|
|
||||||
const Vec3r& end,
|
|
||||||
OccludersSet& occluders,
|
|
||||||
unsigned timestamp);
|
|
||||||
// Prepares to cast ray without generating OccludersSet
|
|
||||||
void initAcceleratedRay(const Vec3r& orig,
|
|
||||||
const Vec3r& end,
|
|
||||||
unsigned timestamp);
|
|
||||||
|
|
||||||
/*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
|
// Prepares to cast ray without generating OccludersSet
|
||||||
* Returns the list of occluders contained
|
void initAcceleratedRay(const Vec3r& orig, const Vec3r& end, unsigned timestamp);
|
||||||
* in the cells intersected by this ray
|
|
||||||
* Starts with a call to InitRay.
|
|
||||||
*/
|
|
||||||
void castInfiniteRay(const Vec3r& orig,
|
|
||||||
const Vec3r& dir,
|
|
||||||
OccludersSet& occluders,
|
|
||||||
unsigned timestamp);
|
|
||||||
// Prepares to cast ray without generating OccludersSet.
|
|
||||||
bool initAcceleratedInfiniteRay(const Vec3r& orig,
|
|
||||||
const Vec3r& dir,
|
|
||||||
unsigned timestamp);
|
|
||||||
|
|
||||||
/*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
|
/*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
|
||||||
* Returns the first intersection (occluder,t,u,v) or null.
|
* Returns the list of occluders contained in the cells intersected by this ray
|
||||||
* Starts with a call to InitRay.
|
* Starts with a call to InitRay.
|
||||||
*/
|
*/
|
||||||
Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig,
|
void castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp);
|
||||||
const Vec3r& dir,
|
|
||||||
double& t,
|
// Prepares to cast ray without generating OccludersSet.
|
||||||
double& u,
|
bool initAcceleratedInfiniteRay(const Vec3r& orig, const Vec3r& dir, unsigned timestamp);
|
||||||
double& v,
|
|
||||||
unsigned timestamp);
|
/*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
|
||||||
|
* Returns the first intersection (occluder,t,u,v) or null.
|
||||||
|
* Starts with a call to InitRay.
|
||||||
|
*/
|
||||||
|
Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
|
||||||
|
double& u, double& v, unsigned timestamp);
|
||||||
|
|
||||||
|
|
||||||
/*! Init all structures and values for computing
|
/*! Init all structures and values for computing the cells intersected by this new ray */
|
||||||
* the cells intersected by this new ray
|
void initRay(const Vec3r &orig, const Vec3r& end, unsigned timestamp);
|
||||||
*/
|
|
||||||
void initRay (const Vec3r &orig,
|
|
||||||
const Vec3r& end,
|
|
||||||
unsigned timestamp);
|
|
||||||
|
|
||||||
/*! Init all structures and values for computing
|
/*! Init all structures and values for computing the cells intersected by this infinite ray.
|
||||||
* the cells intersected by this infinite ray.
|
* Returns false if the ray doesn't intersect the grid.
|
||||||
* Returns false if the ray doesn't intersect the
|
*/
|
||||||
* grid.
|
bool initInfiniteRay(const Vec3r &orig, const Vec3r& dir, unsigned timestamp);
|
||||||
*/
|
|
||||||
bool initInfiniteRay (const Vec3r &orig,
|
|
||||||
const Vec3r& dir,
|
|
||||||
unsigned timestamp);
|
|
||||||
|
|
||||||
|
|
||||||
/*! Accessors */
|
|
||||||
inline const Vec3r& getOrigin() const {
|
|
||||||
return _orig;
|
|
||||||
}
|
|
||||||
inline Vec3r gridSize() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
inline Vec3r getCellSize() const {
|
|
||||||
return _cell_size;
|
|
||||||
}
|
|
||||||
//ARB profiling only:
|
|
||||||
inline OccludersSet* getOccluders() {
|
|
||||||
return &_occluders;
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayDebug() {
|
/*! Accessors */
|
||||||
cerr << "Cells nb : " << _cells_nb << endl;
|
inline const Vec3r& getOrigin() const {
|
||||||
cerr << "Cell size : " << _cell_size << endl;
|
return _orig;
|
||||||
cerr << "Origin : " << _orig << endl;
|
}
|
||||||
cerr << "Occluders nb : " << _occluders.size() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
inline Vec3r gridSize() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Core of castRay and castInfiniteRay, find occluders
|
inline Vec3r getCellSize() const {
|
||||||
* along the given ray
|
return _cell_size;
|
||||||
*/
|
}
|
||||||
inline void castRayInternal(GridVisitor& visitor) {
|
|
||||||
Cell* current_cell = NULL;
|
|
||||||
do {
|
|
||||||
current_cell = getCell(_current_cell);
|
|
||||||
if (current_cell){
|
|
||||||
visitor.discoverCell(current_cell);
|
|
||||||
OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
|
|
||||||
for (OccludersSet::iterator it = occluders.begin();
|
|
||||||
it != occluders.end();
|
|
||||||
it++) {
|
|
||||||
if ((unsigned long)(*it)->userdata2 != _timestamp) {
|
|
||||||
(*it)->userdata2 = (void*)_timestamp;
|
|
||||||
visitor.examineOccluder(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitor.finishCell(current_cell);
|
|
||||||
}
|
|
||||||
} while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//ARB profiling only:
|
||||||
/*! returns the cell next to the cell
|
inline OccludersSet* getOccluders() {
|
||||||
* passed as argument.
|
return &_occluders;
|
||||||
*/
|
}
|
||||||
bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
|
|
||||||
|
|
||||||
unsigned _timestamp;
|
void displayDebug() {
|
||||||
|
cerr << "Cells nb : " << _cells_nb << endl;
|
||||||
|
cerr << "Cell size : " << _cell_size << endl;
|
||||||
|
cerr << "Origin : " << _orig << endl;
|
||||||
|
cerr << "Occluders nb : " << _occluders.size() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
Vec3u _cells_nb; // number of cells for x,y,z axis
|
protected:
|
||||||
Vec3r _cell_size; // cell x,y,z dimensions
|
/*! Core of castRay and castInfiniteRay, find occluders along the given ray */
|
||||||
Vec3r _size; // grid x,y,x dimensions
|
inline void castRayInternal(GridVisitor& visitor) {
|
||||||
Vec3r _orig; // grid origin
|
Cell *current_cell = NULL;
|
||||||
|
do {
|
||||||
|
current_cell = getCell(_current_cell);
|
||||||
|
if (current_cell) {
|
||||||
|
visitor.discoverCell(current_cell);
|
||||||
|
OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
|
||||||
|
for (OccludersSet::iterator it = occluders.begin(); it != occluders.end(); it++) {
|
||||||
|
if ((unsigned long)(*it)->userdata2 != _timestamp) {
|
||||||
|
(*it)->userdata2 = (void*)_timestamp;
|
||||||
|
visitor.examineOccluder(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitor.finishCell(current_cell);
|
||||||
|
}
|
||||||
|
} while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
|
||||||
|
}
|
||||||
|
|
||||||
Vec3r _ray_dir; // direction vector for the ray
|
|
||||||
Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
|
|
||||||
Vec3r _pt; // Points corresponding to the incoming and outgoing intersections
|
|
||||||
// of one cell with the ray
|
|
||||||
real _t_end; // To know when we are at the end of the ray
|
|
||||||
real _t;
|
|
||||||
|
|
||||||
//OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
|
/*! returns the cell next to the cell passed as argument. */
|
||||||
OccludersSet _occluders; // List of all occluders inserted in the grid
|
bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
|
||||||
|
|
||||||
|
unsigned int _timestamp;
|
||||||
|
|
||||||
|
Vec3u _cells_nb; // number of cells for x,y,z axis
|
||||||
|
Vec3r _cell_size; // cell x,y,z dimensions
|
||||||
|
Vec3r _size; // grid x,y,x dimensions
|
||||||
|
Vec3r _orig; // grid origin
|
||||||
|
|
||||||
|
Vec3r _ray_dir; // direction vector for the ray
|
||||||
|
Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
|
||||||
|
Vec3r _pt; // Points corresponding to the incoming and outgoing intersections of one cell with the ray
|
||||||
|
real _t_end; // To know when we are at the end of the ray
|
||||||
|
real _t;
|
||||||
|
|
||||||
|
//OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
|
||||||
|
OccludersSet _occluders; // List of all occluders inserted in the grid
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -378,15 +362,16 @@ public:
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class VirtualOccludersSet {
|
class VirtualOccludersSet {
|
||||||
public:
|
public:
|
||||||
VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
|
VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
|
||||||
Polygon3r* begin();
|
Polygon3r* begin();
|
||||||
Polygon3r* next();
|
Polygon3r* next();
|
||||||
Polygon3r* next(bool stopOnNewCell);
|
Polygon3r* next(bool stopOnNewCell);
|
||||||
private:
|
|
||||||
Polygon3r* firstOccluderFromNextCell();
|
private:
|
||||||
Grid& grid;
|
Polygon3r* firstOccluderFromNextCell();
|
||||||
OccludersSet::iterator it, end;
|
Grid& grid;
|
||||||
|
OccludersSet::iterator it, end;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GRID_H
|
#endif // __GRID_H__
|
||||||
|
@ -1,49 +1,52 @@
|
|||||||
//
|
/*
|
||||||
// Filename : GridHelpers.cpp
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Alexander Beels
|
*
|
||||||
// Purpose : Class to define a cell grid surrounding
|
* This program is free software; you can redistribute it and/or
|
||||||
// the projected image of a scene
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 2010-12-21
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/GridHelpers.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cell grid surrounding the projected image of a scene
|
||||||
//
|
* \author Alexander Beels
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 2010-12-21
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "GridHelpers.h"
|
#include "GridHelpers.h"
|
||||||
|
|
||||||
void GridHelpers::getDefaultViewProscenium(real viewProscenium[4]) {
|
void GridHelpers::getDefaultViewProscenium(real viewProscenium[4])
|
||||||
|
{
|
||||||
// Get proscenium boundary for culling
|
// Get proscenium boundary for culling
|
||||||
// bufferZone determines the amount by which the area processed
|
// bufferZone determines the amount by which the area processed should exceed the actual image area.
|
||||||
// should exceed the actual image area. This is intended to
|
// This is intended to avoid visible artifacts generated along the proscenium edge.
|
||||||
// avoid visible artifacts generated along the proscenium edge.
|
// Perhaps this is no longer needed now that entire view edges are culled at once, since that theoretically
|
||||||
// Perhaps this is no longer needed now that entire view edges
|
// should eliminate visible artifacts.
|
||||||
// are culled at once, since that theoretically should eliminate
|
// To the extent it is still useful, bufferZone should be put into the UI as configurable percentage value
|
||||||
// visible artifacts.
|
|
||||||
// To the extent it is still useful, bufferZone should be put into
|
|
||||||
// the UI as configurable percentage value
|
|
||||||
const real bufferZone = 0.05;
|
const real bufferZone = 0.05;
|
||||||
// borderZone describes a blank border outside the proscenium, but
|
// borderZone describes a blank border outside the proscenium, but still inside the image area.
|
||||||
// still inside the image area. Only intended for exposing possible
|
// Only intended for exposing possible artifacts along or outside the proscenium edge during debugging.
|
||||||
// artifacts along or outside the proscenium edge during debugging.
|
|
||||||
const real borderZone = 0.0;
|
const real borderZone = 0.0;
|
||||||
viewProscenium[0] = freestyle_viewport[2] * (borderZone - bufferZone);
|
viewProscenium[0] = freestyle_viewport[2] * (borderZone - bufferZone);
|
||||||
viewProscenium[1] = freestyle_viewport[2] * (1.0f - borderZone + bufferZone);
|
viewProscenium[1] = freestyle_viewport[2] * (1.0f - borderZone + bufferZone);
|
||||||
@ -51,6 +54,6 @@ void GridHelpers::getDefaultViewProscenium(real viewProscenium[4]) {
|
|||||||
viewProscenium[3] = freestyle_viewport[3] * (1.0f - borderZone + bufferZone);
|
viewProscenium[3] = freestyle_viewport[3] * (1.0f - borderZone + bufferZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
GridHelpers::Transform::~Transform () {}
|
GridHelpers::Transform::~Transform ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -1,47 +1,55 @@
|
|||||||
//
|
/*
|
||||||
// Filename : GridHelpers.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Alexander Beels
|
*
|
||||||
// Purpose : Class to define a cell grid surrounding
|
* This program is free software; you can redistribute it and/or
|
||||||
// the projected image of a scene
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 2010-12-13
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GRIDHELPERS_H__
|
||||||
|
#define __GRIDHELPERS_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/GridHelpers.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cell grid surrounding the projected image of a scene
|
||||||
//
|
* \author Alexander Beels
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 2010-12-13
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GRIDHELPERS_H
|
|
||||||
#define GRIDHELPERS_H
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Polygon.h"
|
|
||||||
#include "../winged_edge/WEdge.h"
|
|
||||||
#include "FRS_freestyle.h"
|
#include "FRS_freestyle.h"
|
||||||
|
|
||||||
#include "GeomUtils.h"
|
#include "GeomUtils.h"
|
||||||
|
#include "Polygon.h"
|
||||||
|
|
||||||
|
#include "../winged_edge/WEdge.h"
|
||||||
|
|
||||||
namespace GridHelpers {
|
namespace GridHelpers {
|
||||||
|
|
||||||
/*! Computes the distance from a point P to a segment AB */
|
/*! Computes the distance from a point P to a segment AB */
|
||||||
template<class T>
|
template<class T>
|
||||||
T closestPointToSegment(const T& P, const T& A , const T& B, real& distance) {
|
T closestPointToSegment(const T& P, const T& A , const T& B, real& distance)
|
||||||
|
{
|
||||||
T AB, AP, BP;
|
T AB, AP, BP;
|
||||||
AB = B - A;
|
AB = B - A;
|
||||||
AP = P - A;
|
AP = P - A;
|
||||||
@ -59,31 +67,32 @@ T closestPointToSegment(const T& P, const T& A , const T& B, real& distance) {
|
|||||||
return B; // B is closest point
|
return B; // B is closest point
|
||||||
}
|
}
|
||||||
|
|
||||||
real b = c1 / c2;
|
real b = c1 / c2;
|
||||||
T Pb, PPb;
|
T Pb, PPb;
|
||||||
Pb = A + b * AB;
|
Pb = A + b * AB;
|
||||||
PPb = P - Pb;
|
PPb = P - Pb;
|
||||||
|
|
||||||
distance = PPb.norm();
|
distance = PPb.norm();
|
||||||
return Pb; // closest point lies on AB
|
return Pb; // closest point lies on AB
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly) {
|
inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly)
|
||||||
|
{
|
||||||
// First cast a ray from the point onto the polygon plane
|
// First cast a ray from the point onto the polygon plane
|
||||||
// If the ray intersects the polygon, then the intersection point
|
// If the ray intersects the polygon, then the intersection point
|
||||||
// is the closest point on the polygon
|
// is the closest point on the polygon
|
||||||
real t, u, v;
|
real t, u, v;
|
||||||
if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
|
if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
|
||||||
return point + poly.getNormal() * t;
|
return point + poly.getNormal() * t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, get the nearest point on each edge, and take the closest
|
// Otherwise, get the nearest point on each edge, and take the closest
|
||||||
real distance;
|
real distance;
|
||||||
Vec3r closest = closestPointToSegment(point, poly.getVertices()[2], poly.getVertices()[0], distance);
|
Vec3r closest = closestPointToSegment(point, poly.getVertices()[2], poly.getVertices()[0], distance);
|
||||||
for ( unsigned i = 0; i < 2; ++i ) {
|
for (unsigned int i = 0; i < 2; ++i) {
|
||||||
real t;
|
real t;
|
||||||
Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
|
Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
|
||||||
if ( t < distance ) {
|
if (t < distance) {
|
||||||
distance = t;
|
distance = t;
|
||||||
closest = p;
|
closest = p;
|
||||||
}
|
}
|
||||||
@ -91,57 +100,63 @@ inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly) {
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly) {
|
inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly)
|
||||||
|
{
|
||||||
// First cast a ray from the point onto the polygon plane
|
// First cast a ray from the point onto the polygon plane
|
||||||
// If the ray intersects the polygon, then the intersection point
|
// If the ray intersects the polygon, then the intersection point
|
||||||
// is the closest point on the polygon
|
// is the closest point on the polygon
|
||||||
real t, u, v;
|
real t, u, v;
|
||||||
if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
|
if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
|
||||||
return t > 0.0 ? t : -t;
|
return (t > 0.0) ? t : -t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, get the nearest point on each edge, and take the closest
|
// Otherwise, get the nearest point on each edge, and take the closest
|
||||||
real distance = GeomUtils::distPointSegment(point, poly.getVertices()[2], poly.getVertices()[0]);
|
real distance = GeomUtils::distPointSegment(point, poly.getVertices()[2], poly.getVertices()[0]);
|
||||||
for ( unsigned i = 0; i < 2; ++i ) {
|
for (unsigned int i = 0; i < 2; ++i) {
|
||||||
real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
|
real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
|
||||||
if ( t < distance ) {
|
if (t < distance) {
|
||||||
distance = t;
|
distance = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Transform {
|
class Transform
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Transform () =0;
|
virtual ~Transform () = 0;
|
||||||
virtual Vec3r operator()(const Vec3r& point) const =0;
|
virtual Vec3r operator()(const Vec3r& point) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon) {
|
inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon)
|
||||||
// N.B. The bounding box check is redundant for inserting occluders into
|
{
|
||||||
// cells, because the cell selection code in insertOccluders has already
|
// N.B. The bounding box check is redundant for inserting occluders into cells, because the cell selection code
|
||||||
// guaranteed that the bounding boxes will overlap.
|
// in insertOccluders has already guaranteed that the bounding boxes will overlap.
|
||||||
// First check the viewport edges, since they are the easiest case
|
// First check the viewport edges, since they are the easiest case
|
||||||
// Check if the bounding box is entirely outside the proscenium
|
// Check if the bounding box is entirely outside the proscenium
|
||||||
Vec3r bbMin, bbMax;
|
Vec3r bbMin, bbMax;
|
||||||
polygon.getBBox(bbMin, bbMax);
|
polygon.getBBox(bbMin, bbMax);
|
||||||
if ( bbMax[0] < proscenium[0]
|
if (bbMax[0] < proscenium[0] || bbMin[0] > proscenium[1] || bbMax[1] < proscenium[2] || bbMin[1] > proscenium[3]) {
|
||||||
|| bbMin[0] > proscenium[1]
|
|
||||||
|| bbMax[1] < proscenium[2]
|
|
||||||
|| bbMin[1] > proscenium[3] ) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0, proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
|
Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0,
|
||||||
Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0, (proscenium[3] - proscenium[2]) / 2.0, 1.0);
|
proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
|
||||||
Vec3r triverts[3] = { Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0), Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0), Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0) };
|
Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0,
|
||||||
|
(proscenium[3] - proscenium[2]) / 2.0, 1.0);
|
||||||
|
Vec3r triverts[3] = {
|
||||||
|
Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0),
|
||||||
|
Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0),
|
||||||
|
Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0)
|
||||||
|
};
|
||||||
return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
|
return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges) {
|
inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges)
|
||||||
|
{
|
||||||
vector<Vec3r> points;
|
vector<Vec3r> points;
|
||||||
// Iterate over vertices, storing projections in points
|
// Iterate over vertices, storing projections in points
|
||||||
for(vector<WOEdge*>::const_iterator woe=fedges.begin(), woend=fedges.end(); woe!=woend; woe++) {
|
for (vector<WOEdge*>::const_iterator woe = fedges.begin(), woend = fedges.end(); woe != woend; woe++) {
|
||||||
points.push_back((*woe)->GetaVertex()->GetVertex());
|
points.push_back((*woe)->GetaVertex()->GetVertex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,50 +165,51 @@ inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges) {
|
|||||||
|
|
||||||
void getDefaultViewProscenium(real viewProscenium[4]);
|
void getDefaultViewProscenium(real viewProscenium[4]);
|
||||||
|
|
||||||
inline void expandProscenium (real proscenium[4], const Polygon3r& polygon) {
|
inline void expandProscenium (real proscenium[4], const Polygon3r& polygon)
|
||||||
|
{
|
||||||
Vec3r bbMin, bbMax;
|
Vec3r bbMin, bbMax;
|
||||||
polygon.getBBox(bbMin, bbMax);
|
polygon.getBBox(bbMin, bbMax);
|
||||||
|
|
||||||
const real epsilon = 1.0e-6;
|
const real epsilon = 1.0e-6;
|
||||||
|
|
||||||
if ( bbMin[0] <= proscenium[0] ) {
|
if (bbMin[0] <= proscenium[0]) {
|
||||||
proscenium[0] = bbMin[0] - epsilon;
|
proscenium[0] = bbMin[0] - epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bbMin[1] <= proscenium[2] ) {
|
if (bbMin[1] <= proscenium[2]) {
|
||||||
proscenium[2] = bbMin[1] - epsilon;
|
proscenium[2] = bbMin[1] - epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bbMax[0] >= proscenium[1] ) {
|
if (bbMax[0] >= proscenium[1]) {
|
||||||
proscenium[1] = bbMax[0] + epsilon;
|
proscenium[1] = bbMax[0] + epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bbMax[1] >= proscenium[3] ) {
|
if (bbMax[1] >= proscenium[3]) {
|
||||||
proscenium[3] = bbMax[1] + epsilon;
|
proscenium[3] = bbMax[1] + epsilon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void expandProscenium (real proscenium[4], const Vec3r& point) {
|
inline void expandProscenium (real proscenium[4], const Vec3r& point)
|
||||||
|
{
|
||||||
const real epsilon = 1.0e-6;
|
const real epsilon = 1.0e-6;
|
||||||
|
|
||||||
if ( point[0] <= proscenium[0] ) {
|
if (point[0] <= proscenium[0]) {
|
||||||
proscenium[0] = point[0] - epsilon;
|
proscenium[0] = point[0] - epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( point[1] <= proscenium[2] ) {
|
if (point[1] <= proscenium[2]) {
|
||||||
proscenium[2] = point[1] - epsilon;
|
proscenium[2] = point[1] - epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( point[0] >= proscenium[1] ) {
|
if (point[0] >= proscenium[1]) {
|
||||||
proscenium[1] = point[0] + epsilon;
|
proscenium[1] = point[0] + epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( point[1] >= proscenium[3] ) {
|
if (point[1] >= proscenium[3]) {
|
||||||
proscenium[3] = point[1] + epsilon;
|
proscenium[3] = point[1] + epsilon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}; // GridHelpers namespace
|
||||||
|
|
||||||
#endif // GRIDHELPERS_H
|
|
||||||
|
|
||||||
|
#endif // __GRIDHELPERS_H__
|
||||||
|
@ -1,41 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/HashGrid.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cell grid surrounding the bounding box of the scene
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "HashGrid.h"
|
#include "HashGrid.h"
|
||||||
|
|
||||||
void HashGrid::clear()
|
void HashGrid::clear()
|
||||||
{
|
{
|
||||||
if(!_cells.empty()) {
|
if (!_cells.empty()) {
|
||||||
for(GridHashTable::iterator it = _cells.begin();
|
for (GridHashTable::iterator it = _cells.begin(); it !=_cells.end(); it++) {
|
||||||
it !=_cells.end();
|
Cell* cell = (*it).second;
|
||||||
it++) {
|
delete cell;
|
||||||
Cell* cell = (*it).second;
|
}
|
||||||
delete cell;
|
_cells.clear();
|
||||||
}
|
}
|
||||||
_cells.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Grid::clear();
|
Grid::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
|
void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
|
||||||
Grid::configure(orig, size, nb);
|
{
|
||||||
|
Grid::configure(orig, size, nb);
|
||||||
}
|
}
|
||||||
|
@ -1,109 +1,116 @@
|
|||||||
//
|
/*
|
||||||
// Filename : HashGrid.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a cell grid surrounding the
|
* This program is free software; you can redistribute it and/or
|
||||||
// bounding box of the scene
|
* modify it under the terms of the GNU General Public License
|
||||||
// Date of creation : 30/07/2002
|
* as published by the Free Software Foundation; either version 2
|
||||||
//
|
* of the License, or (at your option) any later version.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HASHGRID_H__
|
||||||
|
#define __HASHGRID_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/HashGrid.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a cell grid surrounding the bounding box of the scene
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef HASHGRID_H
|
#if 0
|
||||||
# define HASHGRID_H
|
# if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
|
|
||||||
//# if defined(__GNUC__) && (__GNUC__ >= 3)
|
|
||||||
// hash_map is not part of the C++ standard anymore;
|
// hash_map is not part of the C++ standard anymore;
|
||||||
// hash_map.h has been kept though for backward compatibility
|
// hash_map.h has been kept though for backward compatibility
|
||||||
//# include <hash_map.h>
|
# include <hash_map.h>
|
||||||
//# else
|
# else
|
||||||
//# include <hash_map>
|
# include <hash_map>
|
||||||
//# endif
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Grid.h"
|
||||||
|
|
||||||
# include "Grid.h"
|
|
||||||
# include <map>
|
|
||||||
/*! Defines a hash table used for searching the Cells */
|
/*! Defines a hash table used for searching the Cells */
|
||||||
struct GridHasher{
|
struct GridHasher
|
||||||
|
{
|
||||||
#define _MUL 950706376UL
|
#define _MUL 950706376UL
|
||||||
#define _MOD 2147483647UL
|
#define _MOD 2147483647UL
|
||||||
inline size_t operator() (const Vec3u& p) const
|
inline size_t operator() (const Vec3u& p) const
|
||||||
{
|
{
|
||||||
size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
|
size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
|
||||||
res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
|
res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
|
||||||
return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
|
return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
|
||||||
}
|
}
|
||||||
|
#undef _MUL
|
||||||
|
#undef _MOD
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Class to define a regular grid used for ray
|
/*! Class to define a regular grid used for ray casting computations */
|
||||||
casting computations */
|
|
||||||
|
|
||||||
class LIB_GEOMETRY_EXPORT HashGrid : public Grid
|
class LIB_GEOMETRY_EXPORT HashGrid : public Grid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef map<Vec3u, Cell*> GridHashTable;
|
||||||
|
|
||||||
typedef map<Vec3u, Cell*> GridHashTable;
|
HashGrid() : Grid() {}
|
||||||
|
|
||||||
HashGrid() : Grid() {}
|
|
||||||
|
|
||||||
virtual ~HashGrid() {
|
virtual ~HashGrid()
|
||||||
clear();
|
{
|
||||||
}
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
/*! clears the grid
|
/*! clears the grid
|
||||||
* Deletes all the cells, clears the hashtable,
|
* Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
|
||||||
* resets size, size of cell, number of cells.
|
*/
|
||||||
*/
|
virtual void clear();
|
||||||
virtual void clear();
|
|
||||||
|
|
||||||
/*! Sets the different parameters of the grid
|
/*! Sets the different parameters of the grid
|
||||||
* orig
|
* orig
|
||||||
* The grid origin
|
* The grid origin
|
||||||
* size
|
* size
|
||||||
* The grid's dimensions
|
* The grid's dimensions
|
||||||
* nb
|
* nb
|
||||||
* The number of cells of the grid
|
* The number of cells of the grid
|
||||||
*/
|
*/
|
||||||
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
|
||||||
|
|
||||||
/*! returns the cell whose coordinates
|
/*! returns the cell whose coordinates are pased as argument */
|
||||||
* are pased as argument
|
virtual Cell* getCell(const Vec3u& p)
|
||||||
*/
|
{
|
||||||
virtual Cell* getCell(const Vec3u& p) {
|
Cell* found_cell = NULL;
|
||||||
Cell* found_cell = NULL;
|
|
||||||
|
GridHashTable::const_iterator found = _cells.find(p);
|
||||||
GridHashTable::const_iterator found = _cells.find(p);
|
if (found != _cells.end())
|
||||||
if (found != _cells.end())
|
found_cell = (*found).second;
|
||||||
found_cell = (*found).second;
|
return found_cell;
|
||||||
return found_cell;
|
}
|
||||||
}
|
|
||||||
|
/*! Fills the case p with the cell iCell */
|
||||||
/*! Fills the case p with the cell iCell */
|
virtual void fillCell(const Vec3u& p, Cell& cell)
|
||||||
virtual void fillCell(const Vec3u& p, Cell& cell) {
|
{
|
||||||
_cells[p] = &cell;
|
_cells[p] = &cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
GridHashTable _cells;
|
||||||
GridHashTable _cells;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HASHGRID_H
|
#endif // __HASHGRID_H__
|
||||||
|
@ -1,264 +1,285 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Noise.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define Perlin noise
|
||||||
//
|
* \author Emmanuel Turquin
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 12/01/2004
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "Noise.h"
|
#include <math.h>
|
||||||
# include <stdlib.h>
|
#include <stdio.h>
|
||||||
# include <stdio.h>
|
#include <stdlib.h>
|
||||||
# include <math.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define MINX -1000000
|
#include "Noise.h"
|
||||||
#define MINY MINX
|
|
||||||
#define MINZ MINX
|
#define MINX -1000000
|
||||||
#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
|
#define MINY MINX
|
||||||
#define REALSCALE ( 2.0 / 65536.0 )
|
#define MINZ MINX
|
||||||
#define NREALSCALE ( 2.0 / 4096.0 )
|
|
||||||
#define HASH3D(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
|
#define SCURVE(a) ((a) * (a) * (3.0 - 2.0 * (a)))
|
||||||
#define HASH(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
|
|
||||||
#define INCRSUM(m,s,x,y,z) ((s)*(RTable[m]*0.5 \
|
#define REALSCALE (2.0 / 65536.0)
|
||||||
+ RTable[m+1]*(x) \
|
#define NREALSCALE (2.0 / 4096.0)
|
||||||
+ RTable[m+2]*(y) \
|
|
||||||
+ RTable[m+3]*(z)))
|
#define HASH3D(a, b, c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
|
||||||
#define MAXSIZE 500
|
#define HASH(a, b, c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
|
||||||
#define nrand() ((float)rand()/(float)RAND_MAX)
|
|
||||||
#define seednrand(x) srand(x*RAND_MAX)
|
#define INCRSUM(m, s, x, y, z) \
|
||||||
|
((s) * (RTable[m] * 0.5 + RTable[m + 1] * (x) + RTable[m + 2] * (y) + RTable[m + 3] * (z)))
|
||||||
|
|
||||||
|
#define MAXSIZE 500
|
||||||
|
|
||||||
|
#if 0 // XXX Unused
|
||||||
|
#define NRAND() ((float)rand() / (float)RAND_MAX)
|
||||||
|
#endif
|
||||||
|
#define SEEDNRAND(x) (srand(x * RAND_MAX))
|
||||||
|
|
||||||
#define BM 0xff
|
#define BM 0xff
|
||||||
|
#define N 0x1000
|
||||||
#define N 0x1000
|
#define NP 12 /* 2^N */
|
||||||
#define NP 12 /* 2^N */
|
|
||||||
#define NM 0xfff
|
#define NM 0xfff
|
||||||
|
|
||||||
#define s_curve(t) ( t * t * (3. - 2. * t) )
|
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
|
||||||
|
|
||||||
#define lerp(t, a, b) ( a + t * (b - a) )
|
#define SETUP(i, b0, b1, r0, r1) \
|
||||||
|
{ \
|
||||||
#define setup(i,b0,b1,r0,r1)\
|
(t) = (i) + (N); \
|
||||||
t = i + N;\
|
(b0) = ((int)(t)) & BM; \
|
||||||
b0 = ((int)t) & BM;\
|
(b1) = ((b0) + 1) & BM; \
|
||||||
b1 = (b0+1) & BM;\
|
(r0) = (t) - (int)(t); \
|
||||||
r0 = t - (int)t;\
|
(r1) = (r0) - 1.0; \
|
||||||
r1 = r0 - 1.;
|
} (void)0
|
||||||
|
|
||||||
static void normalize2(float v[2])
|
static void normalize2(float v[2])
|
||||||
{
|
{
|
||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
v[0] = v[0] / s;
|
v[0] = v[0] / s;
|
||||||
v[1] = v[1] / s;
|
v[1] = v[1] / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void normalize3(float v[3])
|
static void normalize3(float v[3])
|
||||||
{
|
{
|
||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
v[0] = v[0] / s;
|
v[0] = v[0] / s;
|
||||||
v[1] = v[1] / s;
|
v[1] = v[1] / s;
|
||||||
v[2] = v[2] / s;
|
v[2] = v[2] / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
|
float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
|
||||||
{
|
{
|
||||||
float t;
|
float t;
|
||||||
float vec;
|
float vec;
|
||||||
|
|
||||||
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
|
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
|
||||||
{
|
vec = freq * arg;
|
||||||
vec = freq * arg;
|
t += smoothNoise1(vec) * amp;
|
||||||
t += smoothNoise1(vec) * amp;
|
}
|
||||||
}
|
return t;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
|
float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
|
||||||
{
|
{
|
||||||
float t;
|
float t;
|
||||||
Vec2f vec;
|
Vec2f vec;
|
||||||
|
|
||||||
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
|
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
|
||||||
{
|
vec.x() = freq * v.x();
|
||||||
vec.x() = freq * v.x();
|
vec.y() = freq * v.y();
|
||||||
vec.y() = freq * v.y();
|
t += smoothNoise2(vec) * amp;
|
||||||
t += smoothNoise2(vec) * amp;
|
}
|
||||||
}
|
return t;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
|
float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
|
||||||
{
|
{
|
||||||
float t;
|
float t;
|
||||||
Vec3f vec;
|
Vec3f vec;
|
||||||
|
|
||||||
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
|
for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
|
||||||
{
|
vec.x() = freq * v.x();
|
||||||
vec.x() = freq * v.x();
|
vec.y() = freq * v.y();
|
||||||
vec.y() = freq * v.y();
|
vec.z() = freq * v.z();
|
||||||
vec.z() = freq * v.z();
|
t += smoothNoise3(vec) * amp;
|
||||||
t += smoothNoise3(vec) * amp;
|
}
|
||||||
}
|
return t;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Noise functions over 1, 2, and 3 dimensions
|
// Noise functions over 1, 2, and 3 dimensions
|
||||||
|
|
||||||
float Noise::smoothNoise1(float arg)
|
float Noise::smoothNoise1(float arg)
|
||||||
{
|
{
|
||||||
int bx0, bx1;
|
int bx0, bx1;
|
||||||
float rx0, rx1, sx, t, u, v, vec;
|
float rx0, rx1, sx, t, u, v, vec;
|
||||||
|
|
||||||
vec = arg;
|
vec = arg;
|
||||||
setup(vec, bx0,bx1, rx0,rx1);
|
SETUP(vec, bx0, bx1, rx0, rx1);
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = SCURVE(rx0);
|
||||||
|
|
||||||
u = rx0 * g1[ p[ bx0 ] ];
|
u = rx0 * g1[p[bx0]];
|
||||||
v = rx1 * g1[ p[ bx1 ] ];
|
v = rx1 * g1[p[bx1]];
|
||||||
|
|
||||||
return lerp(sx, u, v);
|
return LERP(sx, u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Noise::smoothNoise2(Vec2f& vec)
|
float Noise::smoothNoise2(Vec2f& vec)
|
||||||
{
|
{
|
||||||
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
||||||
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
||||||
register int i, j;
|
register int i, j;
|
||||||
|
|
||||||
setup(vec.x(), bx0,bx1, rx0,rx1);
|
SETUP(vec.x(), bx0, bx1, rx0, rx1);
|
||||||
setup(vec.y(), by0,by1, ry0,ry1);
|
SETUP(vec.y(), by0, by1, ry0, ry1);
|
||||||
|
|
||||||
i = p[ bx0 ];
|
i = p[bx0];
|
||||||
j = p[ bx1 ];
|
j = p[bx1];
|
||||||
|
|
||||||
b00 = p[ i + by0 ];
|
b00 = p[i + by0];
|
||||||
b10 = p[ j + by0 ];
|
b10 = p[j + by0];
|
||||||
b01 = p[ i + by1 ];
|
b01 = p[i + by1];
|
||||||
b11 = p[ j + by1 ];
|
b11 = p[j + by1];
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = SCURVE(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = SCURVE(ry0);
|
||||||
|
|
||||||
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
#define AT2(rx, ry) ((rx) * q[0] + (ry) * q[1])
|
||||||
|
|
||||||
q = g2[ b00 ] ; u = at2(rx0,ry0);
|
q = g2[b00];
|
||||||
q = g2[ b10 ] ; v = at2(rx1,ry0);
|
u = AT2(rx0, ry0);
|
||||||
a = lerp(sx, u, v);
|
q = g2[b10];
|
||||||
|
v = AT2(rx1, ry0);
|
||||||
|
a = LERP(sx, u, v);
|
||||||
|
|
||||||
q = g2[ b01 ] ; u = at2(rx0,ry1);
|
q = g2[b01];
|
||||||
q = g2[ b11 ] ; v = at2(rx1,ry1);
|
u = AT2(rx0, ry1);
|
||||||
b = lerp(sx, u, v);
|
q = g2[b11];
|
||||||
|
v = AT2(rx1, ry1);
|
||||||
|
b = LERP(sx, u, v);
|
||||||
|
|
||||||
return lerp(sy, a, b);
|
#undef AT2
|
||||||
|
|
||||||
|
return LERP(sy, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Noise::smoothNoise3(Vec3f& vec)
|
float Noise::smoothNoise3(Vec3f& vec)
|
||||||
{
|
{
|
||||||
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
||||||
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
||||||
register int i, j;
|
register int i, j;
|
||||||
|
|
||||||
setup(vec.x(), bx0,bx1, rx0,rx1);
|
SETUP(vec.x(), bx0, bx1, rx0, rx1);
|
||||||
setup(vec.y(), by0,by1, ry0,ry1);
|
SETUP(vec.y(), by0, by1, ry0, ry1);
|
||||||
setup(vec.z(), bz0,bz1, rz0,rz1);
|
SETUP(vec.z(), bz0, bz1, rz0, rz1);
|
||||||
|
|
||||||
i = p[ bx0 ];
|
i = p[bx0];
|
||||||
j = p[ bx1 ];
|
j = p[bx1];
|
||||||
|
|
||||||
b00 = p[ i + by0 ];
|
b00 = p[i + by0];
|
||||||
b10 = p[ j + by0 ];
|
b10 = p[j + by0];
|
||||||
b01 = p[ i + by1 ];
|
b01 = p[i + by1];
|
||||||
b11 = p[ j + by1 ];
|
b11 = p[j + by1];
|
||||||
|
|
||||||
t = s_curve(rx0);
|
t = SCURVE(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = SCURVE(ry0);
|
||||||
sz = s_curve(rz0);
|
sz = SCURVE(rz0);
|
||||||
|
|
||||||
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
#define AT3(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2])
|
||||||
|
|
||||||
q = g3[ b00 + bz0 ] ;
|
q = g3[b00 + bz0];
|
||||||
u = at3(rx0,ry0,rz0);
|
u = AT3(rx0, ry0, rz0);
|
||||||
q = g3[ b10 + bz0 ] ;
|
q = g3[b10 + bz0];
|
||||||
v = at3(rx1,ry0,rz0);
|
v = AT3(rx1, ry0, rz0);
|
||||||
a = lerp(t, u, v);
|
a = LERP(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz0 ] ;
|
q = g3[b01 + bz0];
|
||||||
u = at3(rx0,ry1,rz0);
|
u = AT3(rx0, ry1, rz0);
|
||||||
q = g3[ b11 + bz0 ] ;
|
q = g3[b11 + bz0];
|
||||||
v = at3(rx1,ry1,rz0);
|
v = AT3(rx1, ry1, rz0);
|
||||||
b = lerp(t, u, v);
|
b = LERP(t, u, v);
|
||||||
|
|
||||||
c = lerp(sy, a, b);
|
c = LERP(sy, a, b);
|
||||||
|
|
||||||
q = g3[ b00 + bz1 ] ;
|
q = g3[b00 + bz1];
|
||||||
u = at3(rx0,ry0,rz1);
|
u = AT3(rx0, ry0, rz1);
|
||||||
q = g3[ b10 + bz1 ] ;
|
q = g3[b10 + bz1];
|
||||||
v = at3(rx1,ry0,rz1);
|
v = AT3(rx1, ry0, rz1);
|
||||||
a = lerp(t, u, v);
|
a = LERP(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz1 ] ;
|
q = g3[b01 + bz1];
|
||||||
u = at3(rx0,ry1,rz1);
|
u = AT3(rx0, ry1, rz1);
|
||||||
q = g3[ b11 + bz1 ] ;
|
q = g3[b11 + bz1];
|
||||||
v = at3(rx1,ry1,rz1);
|
v = AT3(rx1, ry1, rz1);
|
||||||
b = lerp(t, u, v);
|
b = LERP(t, u, v);
|
||||||
|
|
||||||
d = lerp(sy, a, b);
|
d = LERP(sy, a, b);
|
||||||
|
|
||||||
return lerp(sz, c, d);
|
#undef AT3
|
||||||
|
|
||||||
|
return LERP(sz, c, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
Noise::Noise(long seed)
|
Noise::Noise(long seed)
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
seednrand((seed < 0) ? time(NULL) : seed);
|
|
||||||
for (i = 0 ; i < _Noise_B_ ; i++)
|
|
||||||
{
|
|
||||||
p[i] = i;
|
|
||||||
|
|
||||||
g1[i] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
|
SEEDNRAND((seed < 0) ? time(NULL) : seed);
|
||||||
|
for (i = 0 ; i < _NOISE_B ; i++) {
|
||||||
|
p[i] = i;
|
||||||
|
g1[i] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
|
||||||
|
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
|
g2[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
|
||||||
normalize2(g2[i]);
|
normalize2(g2[i]);
|
||||||
|
|
||||||
for (j = 0 ; j < 3 ; j++)
|
for (j = 0 ; j < 3 ; j++)
|
||||||
g3[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
|
g3[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
|
||||||
normalize3(g3[i]);
|
normalize3(g3[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (--i)
|
while (--i) {
|
||||||
{
|
k = p[i];
|
||||||
k = p[i];
|
p[i] = p[j = rand() % _NOISE_B];
|
||||||
p[i] = p[j = rand() % _Noise_B_];
|
p[j] = k;
|
||||||
p[j] = k;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0 ; i < _Noise_B_ + 2 ; i++)
|
for (i = 0 ; i < _NOISE_B + 2 ; i++) {
|
||||||
{
|
p[_NOISE_B + i] = p[i];
|
||||||
p[_Noise_B_ + i] = p[i];
|
g1[_NOISE_B + i] = g1[i];
|
||||||
g1[_Noise_B_ + i] = g1[i];
|
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[_Noise_B_ + i][j] = g2[i][j];
|
g2[_NOISE_B + i][j] = g2[i][j];
|
||||||
for (j = 0 ; j < 3 ; j++)
|
|
||||||
g3[_Noise_B_ + i][j] = g3[i][j];
|
for (j = 0 ; j < 3 ; j++)
|
||||||
}
|
g3[_NOISE_B + i][j] = g3[i][j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,45 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Noise.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Emmanuel Turquin
|
*
|
||||||
// Purpose : Class to define Perlin noise
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 12/01/2004
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NOISE_H__
|
||||||
|
#define __NOISE_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Noise.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define Perlin noise
|
||||||
//
|
* \author Emmanuel Turquin
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 12/01/2004
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef NOISE_H
|
#include "Geom.h"
|
||||||
# define NOISE_H
|
|
||||||
|
|
||||||
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
# include "../system/FreestyleConfig.h"
|
#define _NOISE_B 0x100
|
||||||
# include "Geom.h"
|
|
||||||
|
|
||||||
#define _Noise_B_ 0x100
|
|
||||||
|
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -42,36 +47,37 @@ using namespace std;
|
|||||||
/*! Class to provide Perlin Noise functionalities */
|
/*! Class to provide Perlin Noise functionalities */
|
||||||
class LIB_GEOMETRY_EXPORT Noise
|
class LIB_GEOMETRY_EXPORT Noise
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*! Builds a Noise object */
|
||||||
|
Noise(long seed = -1);
|
||||||
|
|
||||||
/*! Builds a Noise object */
|
/*! Destructor */
|
||||||
Noise(long seed = -1);
|
~Noise() {}
|
||||||
/*! Destructor */
|
|
||||||
~Noise() {}
|
|
||||||
|
|
||||||
/*! Returns a noise value for a 1D element */
|
/*! Returns a noise value for a 1D element */
|
||||||
float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
|
float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
|
||||||
|
|
||||||
/*! Returns a noise value for a 2D element */
|
/*! Returns a noise value for a 2D element */
|
||||||
float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
|
float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
|
||||||
|
|
||||||
/*! Returns a noise value for a 3D element */
|
/*! Returns a noise value for a 3D element */
|
||||||
float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
|
float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
|
||||||
|
|
||||||
/*! Returns a smooth noise value for a 1D element */
|
/*! Returns a smooth noise value for a 1D element */
|
||||||
float smoothNoise1(float arg);
|
float smoothNoise1(float arg);
|
||||||
/*! Returns a smooth noise value for a 2D element */
|
|
||||||
float smoothNoise2(Vec2f& vec);
|
|
||||||
/*! Returns a smooth noise value for a 3D element */
|
|
||||||
float smoothNoise3(Vec3f& vec);
|
|
||||||
|
|
||||||
private:
|
/*! Returns a smooth noise value for a 2D element */
|
||||||
|
float smoothNoise2(Vec2f& vec);
|
||||||
|
|
||||||
int p[ _Noise_B_ + _Noise_B_ + 2];
|
/*! Returns a smooth noise value for a 3D element */
|
||||||
float g3[ _Noise_B_ + _Noise_B_ + 2][3];
|
float smoothNoise3(Vec3f& vec);
|
||||||
float g2[ _Noise_B_ + _Noise_B_ + 2][2];
|
|
||||||
float g1[ _Noise_B_ + _Noise_B_ + 2];
|
private:
|
||||||
int start;
|
int p[_NOISE_B + _NOISE_B + 2];
|
||||||
|
float g3[_NOISE_B + _NOISE_B + 2][3];
|
||||||
|
float g2[_NOISE_B + _NOISE_B + 2][2];
|
||||||
|
float g1[_NOISE_B + _NOISE_B + 2];
|
||||||
|
int start;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NOISE_H
|
#endif // __NOISE_H__
|
||||||
|
@ -1,38 +1,44 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Polygon.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a polygon
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 30/07/2002
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __POLYGON_H__
|
||||||
|
#define __POLYGON_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/Polygon.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a polygon
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 30/07/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef POLYGON_H
|
#include <vector>
|
||||||
# define POLYGON_H
|
|
||||||
|
|
||||||
# include <vector>
|
#include "Geom.h"
|
||||||
# include "Geom.h"
|
#include "GeomUtils.h"
|
||||||
# include "GeomUtils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -41,129 +47,129 @@ namespace Geometry {
|
|||||||
template <class Point>
|
template <class Point>
|
||||||
class Polygon
|
class Polygon
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
inline Polygon()
|
||||||
|
{
|
||||||
|
_id = 0;
|
||||||
|
userdata = 0;
|
||||||
|
userdata2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline Polygon() {
|
inline Polygon(const vector<Point>& vertices)
|
||||||
_id = 0;
|
{
|
||||||
userdata = 0;
|
_vertices = vertices;
|
||||||
userdata2 = 0;
|
computeBBox();
|
||||||
}
|
_id = 0;
|
||||||
|
userdata = 0;
|
||||||
|
userdata2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline Polygon(const vector<Point>& vertices) {
|
inline Polygon(const Polygon<Point>& poly)
|
||||||
_vertices = vertices;
|
{
|
||||||
computeBBox();
|
Point p;
|
||||||
_id = 0;
|
for (typename vector<Point>::const_iterator it = poly.getVertices().begin();
|
||||||
userdata = 0;
|
it != poly.getVertices().end();
|
||||||
userdata2 = 0;
|
it++)
|
||||||
}
|
{
|
||||||
|
p = *it;
|
||||||
|
_vertices.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
inline Polygon(const Polygon<Point>& poly) {
|
_id = poly.getId();
|
||||||
Point p;
|
poly.getBBox(_min, _max);
|
||||||
for(typename vector<Point>::const_iterator it = poly.getVertices().begin();
|
userdata = 0;
|
||||||
it != poly.getVertices().end();
|
userdata2 = 0;
|
||||||
it++) {
|
}
|
||||||
p = *it;
|
|
||||||
_vertices.push_back(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
_id = poly.getId();
|
virtual ~Polygon() {}
|
||||||
poly.getBBox(_min, _max);
|
|
||||||
userdata = 0;
|
|
||||||
userdata2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Polygon() {}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Accessors
|
// Accessors
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
inline const vector<Point>& getVertices() const
|
||||||
|
{
|
||||||
|
return _vertices;
|
||||||
|
}
|
||||||
|
|
||||||
inline const vector<Point>& getVertices() const {
|
inline void getBBox(Point& min, Point& max) const
|
||||||
return _vertices;
|
{
|
||||||
}
|
min = _min;
|
||||||
|
max = _max;
|
||||||
|
}
|
||||||
|
|
||||||
inline void getBBox(Point& min, Point& max) const {
|
inline Point& getBBoxCenter()
|
||||||
min = _min;
|
{
|
||||||
max = _max;
|
Point result;
|
||||||
}
|
result = (_min + _max) / 2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline Point& getBBoxCenter()
|
inline Point& getCenter()
|
||||||
{
|
{
|
||||||
Point result;
|
Point result;
|
||||||
result = (_min + _max) / 2;
|
for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++)
|
||||||
return result;
|
result += *it;
|
||||||
}
|
result /= _vertices.size();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline Point& getCenter() {
|
inline unsigned getId() const
|
||||||
Point result;
|
{
|
||||||
for (typename vector<Point>::iterator it = _vertices.begin();
|
return _id;
|
||||||
it != _vertices.end();
|
}
|
||||||
it++)
|
|
||||||
result += *it;
|
|
||||||
result /= _vertices.size();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned getId() const {
|
//
|
||||||
return _id;
|
// Modifiers
|
||||||
}
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
inline void setVertices(const vector<Point>& vertices)
|
||||||
|
{
|
||||||
|
_vertices.clear();
|
||||||
|
Point p;
|
||||||
|
for (typename vector<Point>::const_iterator it = vertices.begin(); it != vertices.end(); it++) {
|
||||||
|
p = *it;
|
||||||
|
_vertices.push_back(p);
|
||||||
|
}
|
||||||
|
computeBBox();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
inline void setId(unsigned id)
|
||||||
// Modifiers
|
{
|
||||||
//
|
_id = id;
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
}
|
||||||
|
|
||||||
inline void setVertices(const vector<Point>& vertices) {
|
//
|
||||||
_vertices.clear();
|
// Other methods
|
||||||
Point p;
|
//
|
||||||
for (typename vector<Point>::const_iterator it = vertices.begin();
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
it != vertices.end();
|
inline void computeBBox()
|
||||||
it++) {
|
{
|
||||||
p = *it;
|
if (_vertices.empty())
|
||||||
_vertices.push_back(p);
|
return;
|
||||||
}
|
|
||||||
computeBBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setId(unsigned id) {
|
_max = _vertices[0];
|
||||||
_id = id;
|
_min = _vertices[0];
|
||||||
}
|
|
||||||
|
|
||||||
//
|
for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++) {
|
||||||
// Other methods
|
for (unsigned int i = 0; i < Point::dim(); i++) {
|
||||||
//
|
if ((*it)[i] > _max[i])
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
_max[i] = (*it)[i];
|
||||||
|
if ((*it)[i] < _min[i])
|
||||||
|
_min[i] = (*it)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void computeBBox() {
|
// FIXME Is it possible to get rid of userdatas ?
|
||||||
if(_vertices.empty())
|
void* userdata;
|
||||||
return;
|
void* userdata2; // Used during ray casting
|
||||||
|
|
||||||
_max = _vertices[0];
|
|
||||||
_min = _vertices[0];
|
|
||||||
|
|
||||||
for(typename vector<Point>::iterator it = _vertices.begin();
|
protected:
|
||||||
it != _vertices.end();
|
vector<Point> _vertices;
|
||||||
it++) {
|
Point _min;
|
||||||
for(unsigned i = 0; i < Point::dim(); i++) {
|
Point _max;
|
||||||
if((*it)[i] > _max[i])
|
unsigned _id;
|
||||||
_max[i] = (*it)[i];
|
|
||||||
if((*it)[i] < _min[i])
|
|
||||||
_min[i] = (*it)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME Is it possible to get rid of userdatas ?
|
|
||||||
void* userdata;
|
|
||||||
void* userdata2; // Used during ray casting
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
vector<Point> _vertices;
|
|
||||||
Point _min;
|
|
||||||
Point _max;
|
|
||||||
unsigned _id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -171,44 +177,45 @@ class Polygon
|
|||||||
// Polygon3r class
|
// Polygon3r class
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class Polygon3r : public Polygon<Vec3r>
|
class Polygon3r : public Polygon<Vec3r>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Polygon3r() : Polygon<Vec3r>() {}
|
inline Polygon3r() : Polygon<Vec3r>() {}
|
||||||
|
|
||||||
inline Polygon3r(const vector<Vec3r>& vertices,
|
inline Polygon3r(const vector<Vec3r>& vertices, const Vec3r& normal) : Polygon<Vec3r>(vertices)
|
||||||
const Vec3r& normal) : Polygon<Vec3r>(vertices) {
|
{
|
||||||
setNormal(normal);
|
setNormal(normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
|
inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
|
||||||
|
|
||||||
virtual ~Polygon3r() {}
|
|
||||||
|
|
||||||
void setNormal(const Vec3r& normal) {
|
virtual ~Polygon3r() {}
|
||||||
_normal = normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Vec3r getNormal() const {
|
void setNormal(const Vec3r& normal)
|
||||||
return _normal;
|
{
|
||||||
}
|
_normal = normal;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Check whether the Polygon intersects with the ray or not */
|
inline Vec3r getNormal() const
|
||||||
inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir,
|
{
|
||||||
real& t, real& u, real& v, real epsilon = M_EPSILON) const {
|
return _normal;
|
||||||
// if (_vertices.size() < 3)
|
}
|
||||||
// return false;
|
|
||||||
return GeomUtils::intersectRayTriangle(orig, dir,
|
|
||||||
_vertices[0], _vertices[1], _vertices[2],
|
|
||||||
t, u, v, epsilon);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
/*! Check whether the Polygon intersects with the ray or not */
|
||||||
|
inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir, real& t, real& u, real& v,
|
||||||
|
real epsilon = M_EPSILON) const
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (_vertices.size() < 3)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
return GeomUtils::intersectRayTriangle(orig, dir, _vertices[0], _vertices[1], _vertices[2], t, u, v, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
Vec3r _normal;
|
private:
|
||||||
|
Vec3r _normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Geometry
|
} // end of namespace Geometry
|
||||||
|
|
||||||
#endif // POLYGON_H
|
#endif // __POLYGON_H__
|
||||||
|
@ -1,198 +1,202 @@
|
|||||||
//
|
/*
|
||||||
// Filename : SweepLine.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to define a Sweep Line
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 29/08/2002
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SWEEPLINE_H__
|
||||||
|
#define __SWEEPLINE_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/geometry/SweepLine.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to define a Sweep Line
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 29/08/2002
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef SWEEPLINE_H
|
#include <list>
|
||||||
# define SWEEPLINE_H
|
#include <vector>
|
||||||
|
|
||||||
# include <list>
|
|
||||||
# include <vector>
|
|
||||||
|
|
||||||
/*! Class to define the intersection berween two segments*/
|
/*! Class to define the intersection berween two segments*/
|
||||||
template<class Edge>
|
template<class Edge>
|
||||||
class Intersection
|
class Intersection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
template<class EdgeClass>
|
||||||
|
Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
|
||||||
|
{
|
||||||
|
EdgeA = eA;
|
||||||
|
EdgeB = eB;
|
||||||
|
tA = ta;
|
||||||
|
tB = tb;
|
||||||
|
userdata = 0;
|
||||||
|
}
|
||||||
|
|
||||||
template<class EdgeClass>
|
Intersection(const Intersection& iBrother)
|
||||||
Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
|
{
|
||||||
{
|
EdgeA = iBrother.EdgeA;
|
||||||
EdgeA = eA;
|
EdgeB = iBrother.EdgeB;
|
||||||
EdgeB = eB;
|
tA = iBrother.tA;
|
||||||
tA = ta;
|
tB = iBrother.tB;
|
||||||
tB = tb;
|
userdata = 0;
|
||||||
userdata = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Intersection(const Intersection& iBrother)
|
/*! returns the parameter giving the intersection, for the edge iEdge */
|
||||||
{
|
real getParameter(Edge *iEdge)
|
||||||
EdgeA = iBrother.EdgeA;
|
{
|
||||||
EdgeB = iBrother.EdgeB;
|
if (iEdge == EdgeA)
|
||||||
tA = iBrother.tA;
|
return tA;
|
||||||
tB = iBrother.tB;
|
if (iEdge == EdgeB)
|
||||||
userdata = 0;
|
return tB;
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
/*! returns the parameter giving the
|
|
||||||
* intersection, for the edge iEdge
|
|
||||||
*/
|
|
||||||
real getParameter(Edge *iEdge)
|
|
||||||
{
|
|
||||||
if(iEdge == EdgeA)
|
|
||||||
return tA;
|
|
||||||
if(iEdge == EdgeB)
|
|
||||||
return tB;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void * userdata; // FIXME
|
void * userdata; // FIXME
|
||||||
|
|
||||||
Edge *EdgeA; // first segment
|
Edge *EdgeA; // first segment
|
||||||
Edge *EdgeB; // second segment
|
Edge *EdgeB; // second segment
|
||||||
real tA; // parameter defining the intersection point with respect to the segment EdgeA.
|
real tA; // parameter defining the intersection point with respect to the segment EdgeA.
|
||||||
real tB; // parameter defining the intersection point with respect to the segment EdgeB.
|
real tB; // parameter defining the intersection point with respect to the segment EdgeB.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Point>
|
template<class T, class Point>
|
||||||
class Segment
|
class Segment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Segment()
|
Segment()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Segment(T& s, const Point& iA, const Point& iB)
|
|
||||||
{
|
|
||||||
_edge = s;
|
|
||||||
if(iA < iB)
|
|
||||||
{
|
|
||||||
A = iA;
|
|
||||||
B = iB;
|
|
||||||
_order = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
A = iB;
|
|
||||||
B = iA;
|
|
||||||
_order = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Segment(Segment<T,Point>& iBrother)
|
Segment(T& s, const Point& iA, const Point& iB)
|
||||||
{
|
{
|
||||||
_edge = iBrother.edge();
|
_edge = s;
|
||||||
A = iBrother.A;
|
if (iA < iB) {
|
||||||
B = iBrother.B;
|
A = iA;
|
||||||
_Intersections = iBrother._Intersections;
|
B = iB;
|
||||||
_order = iBrother._order;
|
_order = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
A = iB;
|
||||||
|
B = iA;
|
||||||
|
_order = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Segment(const Segment<T,Point>& iBrother)
|
Segment(Segment<T,Point>& iBrother)
|
||||||
{
|
{
|
||||||
_edge = iBrother._edge;
|
_edge = iBrother.edge();
|
||||||
A = iBrother.A;
|
A = iBrother.A;
|
||||||
B = iBrother.B;
|
B = iBrother.B;
|
||||||
_Intersections = iBrother._Intersections;
|
_Intersections = iBrother._Intersections;
|
||||||
_order = iBrother._order;
|
_order = iBrother._order;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Segment() {
|
Segment(const Segment<T,Point>& iBrother)
|
||||||
_Intersections.clear();
|
{
|
||||||
}
|
_edge = iBrother._edge;
|
||||||
|
A = iBrother.A;
|
||||||
|
B = iBrother.B;
|
||||||
|
_Intersections = iBrother._Intersections;
|
||||||
|
_order = iBrother._order;
|
||||||
|
}
|
||||||
|
|
||||||
inline Point operator[](const unsigned short int& i) const
|
~Segment()
|
||||||
{
|
{
|
||||||
return i%2==0 ? A : B;
|
_Intersections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const Segment<T,Point>& iBrother)
|
inline Point operator[](const unsigned short int& i) const
|
||||||
{
|
{
|
||||||
if(_edge == iBrother._edge)
|
return (i % 2 == 0) ? A : B;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
return false;
|
inline bool operator==(const Segment<T,Point>& iBrother)
|
||||||
}
|
{
|
||||||
|
if (_edge == iBrother._edge)
|
||||||
/* Adds an intersection for this segment */
|
return true;
|
||||||
inline void AddIntersection(Intersection<Segment<T,Point> > *i) {_Intersections.push_back(i);}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Checks for a common vertex with another edge */
|
/* Adds an intersection for this segment */
|
||||||
inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
|
inline void AddIntersection(Intersection<Segment<T,Point> > *i)
|
||||||
{
|
{
|
||||||
if((A == S[0]) || (A == S[1]))
|
_Intersections.push_back(i);
|
||||||
{
|
}
|
||||||
CP = A;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if((B == S[0]) || (B == S[1]))
|
|
||||||
{
|
|
||||||
CP = B;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
/*! Checks for a common vertex with another edge */
|
||||||
}
|
inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
|
||||||
|
{
|
||||||
|
if ((A == S[0]) || (A == S[1])) {
|
||||||
|
CP = A;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((B == S[0]) || (B == S[1])) {
|
||||||
|
CP = B;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
inline vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
|
inline vector<Intersection<Segment<T,Point> >*>& intersections()
|
||||||
inline bool order() {return _order;}
|
{
|
||||||
inline T& edge() {return _edge;}
|
return _Intersections;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
inline bool order()
|
||||||
T _edge;
|
{
|
||||||
Point A;
|
return _order;
|
||||||
Point B;
|
}
|
||||||
std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
|
|
||||||
bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
|
inline T& edge()
|
||||||
|
{
|
||||||
|
return _edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _edge;
|
||||||
|
Point A;
|
||||||
|
Point B;
|
||||||
|
std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
|
||||||
|
bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! defines a binary function that can be overload
|
/*! defines a binary function that can be overload by the user to specify at each condition the intersection
|
||||||
* by the user to specify at each condition
|
* between 2 edges must be computed
|
||||||
* the intersection between 2 edges must be computed
|
|
||||||
*/
|
*/
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
struct binary_rule
|
struct binary_rule
|
||||||
{
|
{
|
||||||
binary_rule() {}
|
binary_rule() {}
|
||||||
template<class T3,class T4>
|
template<class T3,class T4> binary_rule(const binary_rule<T3,T4>& brother) {}
|
||||||
binary_rule(const binary_rule<T3,T4>& brother) {}
|
virtual ~binary_rule() {}
|
||||||
virtual ~binary_rule() {}
|
|
||||||
|
|
||||||
virtual bool operator()(T1&, T2&)
|
virtual bool operator()(T1&, T2&)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -200,126 +204,121 @@ template<class T,class Point>
|
|||||||
class SweepLine
|
class SweepLine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
SweepLine() {}
|
||||||
|
~SweepLine()
|
||||||
|
{
|
||||||
|
for (typename vector<Intersection<Segment<T,Point> >*>::iterator i = _Intersections.begin(),
|
||||||
|
iend = _Intersections.end();
|
||||||
|
i != iend;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
delete (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SweepLine() {}
|
inline void process(Point& p, vector<Segment<T,Point>*>& segments,
|
||||||
~SweepLine()
|
#if 0
|
||||||
{
|
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = \
|
||||||
for(typename vector<Intersection<Segment<T,Point> >*>::iterator i=_Intersections.begin(),iend=_Intersections.end();
|
binary_rule<Segment<T,Point>,Segment<T,Point> >(),
|
||||||
i!=iend;
|
#else
|
||||||
i++)
|
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
|
||||||
{
|
#endif
|
||||||
delete (*i);
|
real epsilon = M_EPSILON)
|
||||||
}
|
{
|
||||||
}
|
// first we remove the segments that need to be removed and then we add the segments to add
|
||||||
|
vector<Segment<T,Point>*> toadd;
|
||||||
|
typename vector<Segment<T,Point>*>::iterator s, send;
|
||||||
|
for (s = segments.begin(), send = segments.end(); s != send; s++) {
|
||||||
|
if (p == (*(*s))[0])
|
||||||
|
toadd.push_back((*s));
|
||||||
|
else
|
||||||
|
remove((*s));
|
||||||
|
}
|
||||||
|
for (s = toadd.begin(), send = toadd.end(); s != send; s++) {
|
||||||
|
add((*s), binrule, epsilon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void add(Segment<T,Point>* S,
|
||||||
inline void process(Point& p,
|
#if 0
|
||||||
vector<Segment<T,Point>*>& segments,
|
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = \
|
||||||
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
|
binary_rule<Segment<T,Point>, Segment<T,Point> >(),
|
||||||
//binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>,Segment<T,Point> >(),
|
#else
|
||||||
real epsilon = M_EPSILON
|
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
|
||||||
)
|
#endif
|
||||||
{
|
real epsilon)
|
||||||
// first we remove the segments that need to be removed and then
|
{
|
||||||
// we add the segments to add
|
real t,u;
|
||||||
vector<Segment<T,Point>*> toadd;
|
Point CP;
|
||||||
typename vector<Segment<T,Point>*>::iterator s, send;
|
Vec2r v0, v1, v2, v3;
|
||||||
for(s=segments.begin(), send=segments.end();
|
if (true == S->order()) {
|
||||||
s!=send;
|
v0[0] = ((*S)[0])[0];
|
||||||
s++)
|
v0[1] = ((*S)[0])[1];
|
||||||
{
|
v1[0] = ((*S)[1])[0];
|
||||||
if(p == (*(*s))[0])
|
v1[1] = ((*S)[1])[1];
|
||||||
toadd.push_back((*s));
|
}
|
||||||
else
|
else {
|
||||||
remove((*s));
|
v1[0] = ((*S)[0])[0];
|
||||||
}
|
v1[1] = ((*S)[0])[1];
|
||||||
for(s=toadd.begin(), send=toadd.end();
|
v0[0] = ((*S)[1])[0];
|
||||||
s!=send;
|
v0[1] = ((*S)[1])[1];
|
||||||
s++)
|
}
|
||||||
{
|
for (typename std::list<Segment<T,Point>* >::iterator s = _set.begin(), send = _set.end(); s != send; s++) {
|
||||||
add((*s), binrule, epsilon);
|
Segment<T,Point>* currentS = (*s);
|
||||||
}
|
if (true != binrule(*S, *currentS))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
inline void add(Segment<T,Point>* S,
|
|
||||||
binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
|
|
||||||
//binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>, Segment<T,Point> >(),
|
|
||||||
real epsilon
|
|
||||||
)
|
|
||||||
{
|
|
||||||
real t,u;
|
|
||||||
Point CP;
|
|
||||||
Vec2r v0, v1, v2, v3;
|
|
||||||
if(true == S->order())
|
|
||||||
{
|
|
||||||
v0[0] = ((*S)[0])[0];
|
|
||||||
v0[1] = ((*S)[0])[1];
|
|
||||||
v1[0] = ((*S)[1])[0];
|
|
||||||
v1[1] = ((*S)[1])[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v1[0] = ((*S)[0])[0];
|
|
||||||
v1[1] = ((*S)[0])[1];
|
|
||||||
v0[0] = ((*S)[1])[0];
|
|
||||||
v0[1] = ((*S)[1])[1];
|
|
||||||
}
|
|
||||||
for(typename std::list<Segment<T,Point>* >::iterator s=_set.begin(), send=_set.end();
|
|
||||||
s!=send;
|
|
||||||
s++)
|
|
||||||
{
|
|
||||||
Segment<T,Point>* currentS = (*s);
|
|
||||||
if(true != binrule(*S, *currentS))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(true == currentS->order())
|
if (true == currentS->order()) {
|
||||||
{
|
v2[0] = ((*currentS)[0])[0];
|
||||||
v2[0] = ((*currentS)[0])[0];
|
v2[1] = ((*currentS)[0])[1];
|
||||||
v2[1] = ((*currentS)[0])[1];
|
v3[0] = ((*currentS)[1])[0];
|
||||||
v3[0] = ((*currentS)[1])[0];
|
v3[1] = ((*currentS)[1])[1];
|
||||||
v3[1] = ((*currentS)[1])[1];
|
}
|
||||||
}
|
else {
|
||||||
else
|
v3[0] = ((*currentS)[0])[0];
|
||||||
{
|
v3[1] = ((*currentS)[0])[1];
|
||||||
v3[0] = ((*currentS)[0])[0];
|
v2[0] = ((*currentS)[1])[0];
|
||||||
v3[1] = ((*currentS)[0])[1];
|
v2[1] = ((*currentS)[1])[1];
|
||||||
v2[0] = ((*currentS)[1])[0];
|
}
|
||||||
v2[1] = ((*currentS)[1])[1];
|
if (S->CommonVertex(*currentS, CP))
|
||||||
}
|
continue; // the two edges have a common vertex->no need to check
|
||||||
if(S->CommonVertex(*currentS, CP))
|
|
||||||
continue; // the two edges have a common vertex->no need to check
|
|
||||||
|
|
||||||
if(GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT)
|
|
||||||
{
|
|
||||||
// create the intersection
|
|
||||||
Intersection<Segment<T,Point> > * inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
|
|
||||||
// add it to the intersections list
|
|
||||||
_Intersections.push_back(inter);
|
|
||||||
// add this intersection to the first edge intersections list
|
|
||||||
S->AddIntersection(inter);
|
|
||||||
// add this intersection to the second edge intersections list
|
|
||||||
currentS->AddIntersection(inter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// add the added segment to the list of active segments
|
|
||||||
_set.push_back(S);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void remove(Segment<T,Point>* s)
|
|
||||||
{
|
|
||||||
if(s->intersections().size() > 0)
|
|
||||||
_IntersectedEdges.push_back(s);
|
|
||||||
_set.remove(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<Segment<T,Point>* >& intersectedEdges() {return _IntersectedEdges;}
|
if (GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT) {
|
||||||
vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
|
// create the intersection
|
||||||
|
Intersection<Segment<T,Point> > *inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
|
||||||
|
// add it to the intersections list
|
||||||
|
_Intersections.push_back(inter);
|
||||||
|
// add this intersection to the first edge intersections list
|
||||||
|
S->AddIntersection(inter);
|
||||||
|
// add this intersection to the second edge intersections list
|
||||||
|
currentS->AddIntersection(inter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add the added segment to the list of active segments
|
||||||
|
_set.push_back(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void remove(Segment<T,Point>* s)
|
||||||
|
{
|
||||||
|
if (s->intersections().size() > 0)
|
||||||
|
_IntersectedEdges.push_back(s);
|
||||||
|
_set.remove(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Segment<T,Point>* >& intersectedEdges()
|
||||||
|
{
|
||||||
|
return _IntersectedEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Intersection<Segment<T,Point> >*>& intersections()
|
||||||
|
{
|
||||||
|
return _Intersections;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
|
std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
|
||||||
std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
|
std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
|
||||||
std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
|
std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SWEEPLINE_H
|
#endif // __SWEEPLINE_H__
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,265 +1,266 @@
|
|||||||
/*
|
/*
|
||||||
* GXML/Graphite: Geometry and Graphics Programming Library + Utilities
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
* Copyright (C) 2000 Bruno Levy
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or
|
||||||
* it under the terms of the GNU General Public License as published by
|
* modify it under the terms of the GNU General Public License
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* as published by the Free Software Foundation; either version 2
|
||||||
* (at your option) any later version.
|
* of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
* If you modify this software, you should include a notice giving the
|
* This Code is Copyright (C) 2010 Blender Foundation.
|
||||||
* name of the person performing the modification, the date of modification,
|
* All rights reserved.
|
||||||
* and the reason for such modification.
|
|
||||||
*
|
*
|
||||||
* Contact: Bruno Levy
|
* The Original Code is:
|
||||||
|
* GXML/Graphite: Geometry and Graphics Programming Library + Utilities
|
||||||
|
* Copyright (C) 2000 Bruno Levy
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
* levy@loria.fr
|
||||||
|
* ISA Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
*
|
*
|
||||||
* levy@loria.fr
|
* Contributor(s): none yet.
|
||||||
*
|
*
|
||||||
* ISA Project
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
* LORIA, INRIA Lorraine,
|
|
||||||
* Campus Scientifique, BP 239
|
|
||||||
* 54506 VANDOEUVRE LES NANCY CEDEX
|
|
||||||
* FRANCE
|
|
||||||
*
|
|
||||||
* Note that the GNU General Public License does not permit incorporating
|
|
||||||
* the Software into proprietary programs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** \file blender/freestyle/intern/geometry/matrix_util.cpp
|
||||||
|
* \ingroup freestyle
|
||||||
|
* \author Bruno Levy
|
||||||
|
*/
|
||||||
|
|
||||||
#include "matrix_util.h"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "matrix_util.h"
|
||||||
|
|
||||||
namespace OGF {
|
namespace OGF {
|
||||||
|
|
||||||
namespace MatrixUtil {
|
|
||||||
|
|
||||||
static const double EPS = 0.00001 ;
|
namespace MatrixUtil {
|
||||||
static int MAX_ITER = 100 ;
|
|
||||||
|
|
||||||
void semi_definite_symmetric_eigen(
|
|
||||||
const double *mat, int n, double *eigen_vec, double *eigen_val
|
|
||||||
) {
|
|
||||||
double *a,*v;
|
|
||||||
double a_norm,a_normEPS,thr,thr_nn;
|
|
||||||
int nb_iter = 0;
|
|
||||||
int jj;
|
|
||||||
int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn;
|
|
||||||
int *index;
|
|
||||||
double a_ij,a_lm,a_ll,a_mm,a_im,a_il;
|
|
||||||
double a_lm_2;
|
|
||||||
double v_ilv,v_imv;
|
|
||||||
double x;
|
|
||||||
double sinx,sinx_2,cosx,cosx_2,sincos;
|
|
||||||
double delta;
|
|
||||||
|
|
||||||
// Number of entries in mat
|
|
||||||
|
|
||||||
nn = (n*(n+1))/2;
|
|
||||||
|
|
||||||
// Step 1: Copy mat to a
|
|
||||||
|
|
||||||
a = new double[nn];
|
|
||||||
|
|
||||||
for( ij=0; ij<nn; ij++ ) {
|
|
||||||
a[ij] = mat[ij];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ugly Fortran-porting trick: indices for a are between 1 and n
|
|
||||||
a--;
|
|
||||||
|
|
||||||
// Step 2 : Init diagonalization matrix as the unit matrix
|
|
||||||
v = new double[n*n];
|
|
||||||
|
|
||||||
ij = 0;
|
|
||||||
for( i=0; i<n; i++ ) {
|
|
||||||
for( j=0; j<n; j++ ) {
|
|
||||||
if( i==j ) {
|
|
||||||
v[ij++] = 1.0;
|
|
||||||
} else {
|
|
||||||
v[ij++] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ugly Fortran-porting trick: indices for v are between 1 and n
|
|
||||||
v--;
|
|
||||||
|
|
||||||
// Step 3 : compute the weight of the non diagonal terms
|
|
||||||
ij = 1 ;
|
|
||||||
a_norm = 0.0;
|
|
||||||
for( i=1; i<=n; i++ ) {
|
|
||||||
for( j=1; j<=i; j++ ) {
|
|
||||||
if( i!=j ) {
|
|
||||||
a_ij = a[ij];
|
|
||||||
a_norm += a_ij*a_ij;
|
|
||||||
}
|
|
||||||
ij++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( a_norm != 0.0 ) {
|
|
||||||
|
|
||||||
a_normEPS = a_norm*EPS;
|
|
||||||
thr = a_norm ;
|
|
||||||
|
|
||||||
// Step 4 : rotations
|
|
||||||
while( thr > a_normEPS && nb_iter < MAX_ITER ) {
|
|
||||||
|
|
||||||
nb_iter++;
|
|
||||||
thr_nn = thr / nn;
|
|
||||||
|
|
||||||
for( l=1 ; l< n; l++ ) {
|
|
||||||
for( m=l+1; m<=n; m++ ) {
|
|
||||||
|
|
||||||
// compute sinx and cosx
|
|
||||||
|
|
||||||
lq = (l*l-l)/2;
|
|
||||||
mq = (m*m-m)/2;
|
|
||||||
|
|
||||||
lm = l+mq;
|
|
||||||
a_lm = a[lm];
|
|
||||||
a_lm_2 = a_lm*a_lm;
|
|
||||||
|
|
||||||
if( a_lm_2 < thr_nn ) {
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
|
|
||||||
ll = l+lq;
|
|
||||||
mm = m+mq;
|
|
||||||
a_ll = a[ll];
|
|
||||||
a_mm = a[mm];
|
|
||||||
|
|
||||||
delta = a_ll - a_mm;
|
|
||||||
|
|
||||||
if( delta == 0.0 ) {
|
|
||||||
x = - M_PI/4 ;
|
|
||||||
} else {
|
|
||||||
x = - atan( (a_lm+a_lm) / delta ) / 2.0 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
sinx = sin(x) ;
|
static const double EPS = 0.00001;
|
||||||
cosx = cos(x) ;
|
static int MAX_ITER = 100;
|
||||||
sinx_2 = sinx*sinx;
|
|
||||||
cosx_2 = cosx*cosx;
|
|
||||||
sincos = sinx*cosx;
|
|
||||||
|
|
||||||
// rotate L and M columns
|
|
||||||
|
|
||||||
ilv = n*(l-1);
|
|
||||||
imv = n*(m-1);
|
|
||||||
|
|
||||||
for( i=1; i<=n;i++ ) {
|
|
||||||
if( (i!=l) && (i!=m) ) {
|
|
||||||
iq = (i*i-i)/2;
|
|
||||||
|
|
||||||
if( i<m ) {
|
|
||||||
im = i + mq;
|
|
||||||
} else {
|
|
||||||
im = m + iq;
|
|
||||||
}
|
|
||||||
a_im = a[im];
|
|
||||||
|
|
||||||
if( i<l ) {
|
|
||||||
il = i + lq;
|
|
||||||
} else {
|
|
||||||
il = l + iq;
|
|
||||||
}
|
|
||||||
a_il = a[il];
|
|
||||||
|
|
||||||
a[il] = a_il*cosx - a_im*sinx;
|
|
||||||
a[im] = a_il*sinx + a_im*cosx;
|
|
||||||
}
|
|
||||||
|
|
||||||
ilv++;
|
|
||||||
imv++;
|
|
||||||
|
|
||||||
v_ilv = v[ilv];
|
|
||||||
v_imv = v[imv];
|
|
||||||
|
|
||||||
v[ilv] = cosx*v_ilv - sinx*v_imv;
|
|
||||||
v[imv] = sinx*v_ilv + cosx*v_imv;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = a_lm*sincos; x+=x;
|
|
||||||
|
|
||||||
a[ll] = a_ll*cosx_2 + a_mm*sinx_2 - x;
|
|
||||||
a[mm] = a_ll*sinx_2 + a_mm*cosx_2 + x;
|
|
||||||
a[lm] = 0.0;
|
|
||||||
|
|
||||||
thr = fabs( thr - a_lm_2 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5: index conversion and copy eigen values
|
|
||||||
|
|
||||||
// back from Fortran to C++
|
|
||||||
a++;
|
|
||||||
|
|
||||||
for( i=0; i<n; i++ ) {
|
|
||||||
k = i + (i*(i+1))/2;
|
|
||||||
eigen_val[i] = a[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] a;
|
|
||||||
|
|
||||||
// Step 6: sort the eigen values and eigen vectors
|
|
||||||
|
|
||||||
index = new int[n];
|
|
||||||
for( i=0; i<n; i++ ) {
|
|
||||||
index[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i=0; i<(n-1); i++ ) {
|
|
||||||
x = eigen_val[i];
|
|
||||||
k = i;
|
|
||||||
|
|
||||||
for( j=i+1; j<n; j++ ) {
|
|
||||||
if( x < eigen_val[j] ) {
|
|
||||||
k = j;
|
|
||||||
x = eigen_val[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eigen_val[k] = eigen_val[i];
|
|
||||||
eigen_val[i] = x;
|
|
||||||
|
|
||||||
jj = index[k];
|
|
||||||
index[k] = index[i];
|
|
||||||
index[i] = jj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val)
|
||||||
|
{
|
||||||
|
double *a, *v;
|
||||||
|
double a_norm, a_normEPS, thr, thr_nn;
|
||||||
|
int nb_iter = 0;
|
||||||
|
int jj;
|
||||||
|
int i, j, k, ij, ik, l, m, lm, mq, lq, ll, mm, imv, im, iq, ilv, il, nn;
|
||||||
|
int *index;
|
||||||
|
double a_ij, a_lm, a_ll, a_mm, a_im, a_il;
|
||||||
|
double a_lm_2;
|
||||||
|
double v_ilv, v_imv;
|
||||||
|
double x;
|
||||||
|
double sinx, sinx_2, cosx, cosx_2, sincos;
|
||||||
|
double delta;
|
||||||
|
|
||||||
|
// Number of entries in mat
|
||||||
|
nn = (n * (n + 1)) / 2;
|
||||||
|
|
||||||
|
// Step 1: Copy mat to a
|
||||||
|
a = new double[nn];
|
||||||
|
|
||||||
|
for (ij = 0; ij < nn; ij++) {
|
||||||
|
a[ij] = mat[ij];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ugly Fortran-porting trick: indices for a are between 1 and n
|
||||||
|
a--;
|
||||||
|
|
||||||
|
// Step 2 : Init diagonalization matrix as the unit matrix
|
||||||
|
v = new double[n * n];
|
||||||
|
|
||||||
|
ij = 0;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
for (j = 0; j < n; j++) {
|
||||||
|
if (i == j) {
|
||||||
|
v[ij++] = 1.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v[ij++] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ugly Fortran-porting trick: indices for v are between 1 and n
|
||||||
|
v--;
|
||||||
|
|
||||||
|
// Step 3 : compute the weight of the non diagonal terms
|
||||||
|
ij = 1;
|
||||||
|
a_norm = 0.0;
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
for (j = 1; j <= i; j++) {
|
||||||
|
if (i != j) {
|
||||||
|
a_ij = a[ij];
|
||||||
|
a_norm += a_ij * a_ij;
|
||||||
|
}
|
||||||
|
ij++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_norm != 0.0) {
|
||||||
|
a_normEPS = a_norm * EPS;
|
||||||
|
thr = a_norm;
|
||||||
|
|
||||||
|
// Step 4 : rotations
|
||||||
|
while (thr > a_normEPS && nb_iter < MAX_ITER) {
|
||||||
|
nb_iter++;
|
||||||
|
thr_nn = thr / nn;
|
||||||
|
|
||||||
|
for (l = 1; l < n; l++) {
|
||||||
|
for (m = l + 1; m <= n; m++) {
|
||||||
|
// compute sinx and cosx
|
||||||
|
lq = (l * l - l) / 2;
|
||||||
|
mq = (m * m - m) / 2;
|
||||||
|
|
||||||
|
lm = l + mq;
|
||||||
|
a_lm = a[lm];
|
||||||
|
a_lm_2 = a_lm * a_lm;
|
||||||
|
|
||||||
|
if (a_lm_2 < thr_nn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ll = l + lq;
|
||||||
|
mm = m + mq;
|
||||||
|
a_ll = a[ll];
|
||||||
|
a_mm = a[mm];
|
||||||
|
|
||||||
|
delta = a_ll - a_mm;
|
||||||
|
|
||||||
|
if (delta == 0.0) {
|
||||||
|
x = -M_PI / 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = -atan((a_lm + a_lm) / delta) / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sinx = sin(x);
|
||||||
|
cosx = cos(x);
|
||||||
|
sinx_2 = sinx * sinx;
|
||||||
|
cosx_2 = cosx * cosx;
|
||||||
|
sincos = sinx * cosx;
|
||||||
|
|
||||||
|
// rotate L and M columns
|
||||||
|
ilv = n * (l - 1);
|
||||||
|
imv = n * (m - 1);
|
||||||
|
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
if ((i != l) && (i != m)) {
|
||||||
|
iq = (i * i - i) / 2;
|
||||||
|
|
||||||
|
if (i < m) {
|
||||||
|
im = i + mq;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
im = m + iq;
|
||||||
|
}
|
||||||
|
a_im = a[im];
|
||||||
|
|
||||||
|
if (i < l) {
|
||||||
|
il = i + lq;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
il = l + iq;
|
||||||
|
}
|
||||||
|
a_il = a[il];
|
||||||
|
|
||||||
|
a[il] = a_il * cosx - a_im * sinx;
|
||||||
|
a[im] = a_il * sinx + a_im * cosx;
|
||||||
|
}
|
||||||
|
|
||||||
|
ilv++;
|
||||||
|
imv++;
|
||||||
|
|
||||||
|
v_ilv = v[ilv];
|
||||||
|
v_imv = v[imv];
|
||||||
|
|
||||||
|
v[ilv] = cosx * v_ilv - sinx * v_imv;
|
||||||
|
v[imv] = sinx * v_ilv + cosx * v_imv;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = a_lm * sincos;
|
||||||
|
x += x;
|
||||||
|
|
||||||
|
a[ll] = a_ll * cosx_2 + a_mm * sinx_2 - x;
|
||||||
|
a[mm] = a_ll * sinx_2 + a_mm * cosx_2 + x;
|
||||||
|
a[lm] = 0.0;
|
||||||
|
|
||||||
|
thr = fabs(thr - a_lm_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5: index conversion and copy eigen values
|
||||||
|
|
||||||
|
// back from Fortran to C++
|
||||||
|
a++;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
k = i + (i * (i + 1)) / 2;
|
||||||
|
eigen_val[i] = a[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] a;
|
||||||
|
|
||||||
|
// Step 6: sort the eigen values and eigen vectors
|
||||||
|
|
||||||
|
index = new int[n];
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
index[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (n - 1); i++) {
|
||||||
|
x = eigen_val[i];
|
||||||
|
k = i;
|
||||||
|
|
||||||
|
for (j = i + 1; j < n; j++) {
|
||||||
|
if (x < eigen_val[j]) {
|
||||||
|
k = j;
|
||||||
|
x = eigen_val[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eigen_val[k] = eigen_val[i];
|
||||||
|
eigen_val[i] = x;
|
||||||
|
|
||||||
|
jj = index[k];
|
||||||
|
index[k] = index[i];
|
||||||
|
index[i] = jj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 7: save the eigen vectors
|
||||||
|
|
||||||
|
// back from Fortran to to C++
|
||||||
|
v++;
|
||||||
|
|
||||||
|
ij = 0;
|
||||||
|
for (k = 0; k < n; k++) {
|
||||||
|
ik = index[k] * n;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
eigen_vec[ij++] = v[ik++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] v;
|
||||||
|
delete[] index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 7: save the eigen vectors
|
|
||||||
|
|
||||||
v++; // back from Fortran to to C++
|
|
||||||
|
|
||||||
ij = 0;
|
|
||||||
for( k=0; k<n; k++ ) {
|
|
||||||
ik = index[k]*n;
|
|
||||||
for( i=0; i<n; i++ ) {
|
|
||||||
eigen_vec[ij++] = v[ik++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] v ;
|
|
||||||
delete[] index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//_________________________________________________________
|
//_________________________________________________________
|
||||||
|
|
||||||
}
|
} // MatrixUtil namespace
|
||||||
}
|
|
||||||
|
} // OGF namespace
|
||||||
|
@ -1,69 +1,72 @@
|
|||||||
/*
|
/*
|
||||||
* GXML/Graphite: Geometry and Graphics Programming Library + Utilities
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
* Copyright (C) 2000 Bruno Levy
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or
|
||||||
* it under the terms of the GNU General Public License as published by
|
* modify it under the terms of the GNU General Public License
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* as published by the Free Software Foundation; either version 2
|
||||||
* (at your option) any later version.
|
* of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
* If you modify this software, you should include a notice giving the
|
* This Code is Copyright (C) 2010 Blender Foundation.
|
||||||
* name of the person performing the modification, the date of modification,
|
* All rights reserved.
|
||||||
* and the reason for such modification.
|
|
||||||
*
|
*
|
||||||
* Contact: Bruno Levy
|
* The Original Code is:
|
||||||
|
* GXML/Graphite: Geometry and Graphics Programming Library + Utilities
|
||||||
|
* Copyright (C) 2000 Bruno Levy
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
* levy@loria.fr
|
||||||
|
* ISA Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
*
|
*
|
||||||
* levy@loria.fr
|
* Contributor(s): none yet.
|
||||||
*
|
*
|
||||||
* ISA Project
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
* LORIA, INRIA Lorraine,
|
|
||||||
* Campus Scientifique, BP 239
|
|
||||||
* 54506 VANDOEUVRE LES NANCY CEDEX
|
|
||||||
* FRANCE
|
|
||||||
*
|
|
||||||
* Note that the GNU General Public License does not permit incorporating
|
|
||||||
* the Software into proprietary programs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MATRIX_UTIL__
|
#ifndef __MATRIX_UTIL__
|
||||||
#define __MATRIX_UTIL__
|
#define __MATRIX_UTIL__
|
||||||
|
|
||||||
# include "../system/FreestyleConfig.h"
|
/** \file blender/freestyle/intern/geometry/matrix_util.h
|
||||||
|
* \ingroup freestyle
|
||||||
|
* \author Bruno Levy
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
namespace OGF {
|
namespace OGF {
|
||||||
|
|
||||||
namespace MatrixUtil {
|
namespace MatrixUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* computes the eigen values and eigen vectors
|
* computes the eigen values and eigen vectors of a semi definite symmetric matrix
|
||||||
* of a semi definite symmetric matrix
|
*
|
||||||
*
|
* @param matrix is stored in column symmetric storage, i.e.
|
||||||
* @param matrix is stored in column symmetric storage, i.e.
|
* matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
|
||||||
* matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
|
* size = n(n+1)/2
|
||||||
* size = n(n+1)/2
|
*
|
||||||
*
|
* @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
|
||||||
* @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
|
* where vk = vk0, vk1, ..., vkn
|
||||||
* where vk = vk0, vk1, ..., vkn
|
* size = n^2, must be allocated by caller
|
||||||
* size = n^2, must be allocated by caller
|
*
|
||||||
*
|
* @param eigen_values (return) are in decreasing order
|
||||||
* @param eigen_values (return) are in decreasing order
|
* size = n, must be allocated by caller
|
||||||
* size = n, must be allocated by caller
|
*/
|
||||||
*/
|
LIB_GEOMETRY_EXPORT
|
||||||
LIB_GEOMETRY_EXPORT
|
void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
|
||||||
void semi_definite_symmetric_eigen(
|
|
||||||
const double *mat, int n, double *eigen_vec, double *eigen_val
|
|
||||||
) ;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
} // MatrixUtil namespace
|
||||||
|
|
||||||
|
} // OGF namespace
|
||||||
|
|
||||||
|
#endif // __MATRIX_UTIL__
|
||||||
|
@ -1,87 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* This Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is:
|
||||||
|
* OGF/Graphite: Geometry and Graphics Programming Library + Utilities
|
||||||
|
* Copyright (C) 2000 Bruno Levy
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
* levy@loria.fr
|
||||||
|
* ISA Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/freestyle/intern/geometry/normal_cycle.cpp
|
||||||
|
* \ingroup freestyle
|
||||||
|
* \author Bruno Levy
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
|
||||||
// with this source distribution.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "normal_cycle.h"
|
|
||||||
#include "matrix_util.h"
|
#include "matrix_util.h"
|
||||||
|
#include "normal_cycle.h"
|
||||||
|
|
||||||
namespace OGF {
|
namespace OGF {
|
||||||
|
|
||||||
//_________________________________________________________
|
//_________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
NormalCycle::NormalCycle() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void NormalCycle::begin() {
|
NormalCycle::NormalCycle()
|
||||||
M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0 ;
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void NormalCycle::end() {
|
|
||||||
|
|
||||||
double eigen_vectors[9] ;
|
|
||||||
MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_) ;
|
|
||||||
|
|
||||||
axis_[0] = Vec3r(
|
|
||||||
eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]
|
|
||||||
) ;
|
|
||||||
|
|
||||||
axis_[1] = Vec3r(
|
|
||||||
eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]
|
|
||||||
) ;
|
|
||||||
|
|
||||||
axis_[2] = Vec3r(
|
|
||||||
eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]
|
|
||||||
) ;
|
|
||||||
|
|
||||||
// Normalize the eigen vectors
|
|
||||||
|
|
||||||
for(int i=0; i<3; i++) {
|
|
||||||
axis_[i].normalize() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the eigen vectors
|
void NormalCycle::begin()
|
||||||
|
{
|
||||||
|
M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
i_[0] = 0 ;
|
void NormalCycle::end()
|
||||||
i_[1] = 1 ;
|
{
|
||||||
i_[2] = 2 ;
|
double eigen_vectors[9];
|
||||||
|
MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_);
|
||||||
|
|
||||||
double l0 = ::fabs(eigen_value_[0]) ;
|
axis_[0] = Vec3r(eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]);
|
||||||
double l1 = ::fabs(eigen_value_[1]) ;
|
|
||||||
double l2 = ::fabs(eigen_value_[2]) ;
|
|
||||||
|
|
||||||
if(l1 > l0) {
|
|
||||||
ogf_swap(l0 , l1 ) ;
|
|
||||||
ogf_swap(i_[0], i_[1]) ;
|
|
||||||
}
|
|
||||||
if(l2 > l1) {
|
|
||||||
ogf_swap(l1 , l2 ) ;
|
|
||||||
ogf_swap(i_[1], i_[2]) ;
|
|
||||||
}
|
|
||||||
if(l1 > l0) {
|
|
||||||
ogf_swap(l0 , l1 ) ;
|
|
||||||
ogf_swap(i_[0],i_[1]) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
axis_[1] = Vec3r(eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]);
|
||||||
|
|
||||||
|
axis_[2] = Vec3r(eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]);
|
||||||
|
|
||||||
|
// Normalize the eigen vectors
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
axis_[i].normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the eigen vectors
|
||||||
|
i_[0] = 0;
|
||||||
|
i_[1] = 1;
|
||||||
|
i_[2] = 2;
|
||||||
|
|
||||||
|
double l0 = ::fabs(eigen_value_[0]);
|
||||||
|
double l1 = ::fabs(eigen_value_[1]);
|
||||||
|
double l2 = ::fabs(eigen_value_[2]);
|
||||||
|
|
||||||
|
if (l1 > l0) {
|
||||||
|
ogf_swap(l0 , l1 );
|
||||||
|
ogf_swap(i_[0], i_[1]);
|
||||||
|
}
|
||||||
|
if (l2 > l1) {
|
||||||
|
ogf_swap(l1 , l2 );
|
||||||
|
ogf_swap(i_[1], i_[2]);
|
||||||
|
}
|
||||||
|
if (l1 > l0) {
|
||||||
|
ogf_swap(l0 , l1 );
|
||||||
|
ogf_swap(i_[0], i_[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//_________________________________________________________
|
//_________________________________________________________
|
||||||
|
|
||||||
}
|
} // OGF namespace
|
||||||
|
@ -1,110 +1,144 @@
|
|||||||
/*
|
/*
|
||||||
* OGF/Graphite: Geometry and Graphics Programming Library + Utilities
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
* Copyright (C) 2000 Bruno Levy
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or
|
||||||
* it under the terms of the GNU General Public License as published by
|
* modify it under the terms of the GNU General Public License
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* as published by the Free Software Foundation; either version 2
|
||||||
* (at your option) any later version.
|
* of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
* If you modify this software, you should include a notice giving the
|
* This Code is Copyright (C) 2010 Blender Foundation.
|
||||||
* name of the person performing the modification, the date of modification,
|
* All rights reserved.
|
||||||
* and the reason for such modification.
|
|
||||||
*
|
*
|
||||||
* Contact: Bruno Levy
|
* The Original Code is:
|
||||||
|
* OGF/Graphite: Geometry and Graphics Programming Library + Utilities
|
||||||
|
* Copyright (C) 2000 Bruno Levy
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
* levy@loria.fr
|
||||||
|
* ISA Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
*
|
*
|
||||||
* levy@loria.fr
|
* Contributor(s): none yet.
|
||||||
*
|
*
|
||||||
* ISA Project
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
* LORIA, INRIA Lorraine,
|
|
||||||
* Campus Scientifique, BP 239
|
|
||||||
* 54506 VANDOEUVRE LES NANCY CEDEX
|
|
||||||
* FRANCE
|
|
||||||
*
|
|
||||||
* Note that the GNU General Public License does not permit incorporating
|
|
||||||
* the Software into proprietary programs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
|
#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
|
||||||
#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
|
#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
|
||||||
|
|
||||||
# include "../system/FreestyleConfig.h"
|
/** \file blender/freestyle/intern/geometry/normal_cycle.h
|
||||||
# include "Geom.h"
|
* \ingroup freestyle
|
||||||
|
* \author Bruno Levy
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Geom.h"
|
||||||
|
|
||||||
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
using namespace Geometry;
|
using namespace Geometry;
|
||||||
|
|
||||||
namespace OGF {
|
namespace OGF {
|
||||||
|
|
||||||
template <class T> inline void ogf_swap(T& x, T& y) {
|
template <class T> inline void ogf_swap(T& x, T& y)
|
||||||
T z = x ;
|
{
|
||||||
x = y ;
|
T z = x ;
|
||||||
y = z ;
|
x = y ;
|
||||||
}
|
y = z ;
|
||||||
|
|
||||||
//_________________________________________________________
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NormalCycle evaluates the curvature tensor in function
|
|
||||||
* of a set of dihedral angles and associated vectors.
|
|
||||||
* Reference:
|
|
||||||
* Restricted Delaunay Triangulation and Normal Cycle,
|
|
||||||
* D. Cohen-Steiner and J.M. Morvan,
|
|
||||||
* SOCG 2003
|
|
||||||
*/
|
|
||||||
class LIB_GEOMETRY_EXPORT NormalCycle {
|
|
||||||
public:
|
|
||||||
NormalCycle() ;
|
|
||||||
void begin() ;
|
|
||||||
void end() ;
|
|
||||||
/**
|
|
||||||
* Note: the specified edge vector needs to be pre-clipped
|
|
||||||
* by the neighborhood.
|
|
||||||
*/
|
|
||||||
void accumulate_dihedral_angle(
|
|
||||||
const Vec3r& edge, real angle, real neigh_area = 1.0
|
|
||||||
) ;
|
|
||||||
const Vec3r& eigen_vector(int i) const { return axis_[i_[i]] ; }
|
|
||||||
real eigen_value(int i) const { return eigen_value_[i_[i]] ; }
|
|
||||||
|
|
||||||
const Vec3r& N() const { return eigen_vector(2) ; }
|
|
||||||
const Vec3r& Kmax() const { return eigen_vector(1) ; }
|
|
||||||
const Vec3r& Kmin() const { return eigen_vector(0) ; }
|
|
||||||
|
|
||||||
real n() const { return eigen_value(2) ; }
|
|
||||||
real kmax() const { return eigen_value(1) ; }
|
|
||||||
real kmin() const { return eigen_value(0) ; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
real center_[3] ;
|
|
||||||
Vec3r axis_[3] ;
|
|
||||||
real eigen_value_[3] ;
|
|
||||||
real M_[6] ;
|
|
||||||
int i_[3] ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
inline void NormalCycle::accumulate_dihedral_angle(
|
|
||||||
const Vec3r& edge, const double beta, double neigh_area
|
|
||||||
) {
|
|
||||||
double s = beta * neigh_area / edge.norm();
|
|
||||||
|
|
||||||
M_[0] += s * edge.x() * edge.x() ;
|
|
||||||
M_[1] += s * edge.x() * edge.y() ;
|
|
||||||
M_[2] += s * edge.y() * edge.y() ;
|
|
||||||
M_[3] += s * edge.x() * edge.z() ;
|
|
||||||
M_[4] += s * edge.y() * edge.z() ;
|
|
||||||
M_[5] += s * edge.z() * edge.z() ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//_________________________________________________________
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
//_________________________________________________________
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NormalCycle evaluates the curvature tensor in function
|
||||||
|
* of a set of dihedral angles and associated vectors.
|
||||||
|
* Reference:
|
||||||
|
* Restricted Delaunay Triangulation and Normal Cycle,
|
||||||
|
* D. Cohen-Steiner and J.M. Morvan,
|
||||||
|
* SOCG 2003
|
||||||
|
*/
|
||||||
|
class LIB_GEOMETRY_EXPORT NormalCycle {
|
||||||
|
public:
|
||||||
|
NormalCycle();
|
||||||
|
void begin();
|
||||||
|
void end();
|
||||||
|
/**
|
||||||
|
* Note: the specified edge vector needs to be pre-clipped by the neighborhood.
|
||||||
|
*/
|
||||||
|
void accumulate_dihedral_angle(const Vec3r& edge, real angle, real neigh_area = 1.0);
|
||||||
|
|
||||||
|
const Vec3r& eigen_vector(int i) const
|
||||||
|
{
|
||||||
|
return axis_[i_[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
real eigen_value(int i) const
|
||||||
|
{
|
||||||
|
return eigen_value_[i_[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3r& N() const
|
||||||
|
{
|
||||||
|
return eigen_vector(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3r& Kmax() const
|
||||||
|
{
|
||||||
|
return eigen_vector(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3r& Kmin() const
|
||||||
|
{
|
||||||
|
return eigen_vector(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
real n() const
|
||||||
|
{
|
||||||
|
return eigen_value(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
real kmax() const
|
||||||
|
{
|
||||||
|
return eigen_value(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
real kmin() const
|
||||||
|
{
|
||||||
|
return eigen_value(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
real center_[3];
|
||||||
|
Vec3r axis_[3];
|
||||||
|
real eigen_value_[3];
|
||||||
|
real M_[6];
|
||||||
|
int i_[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void NormalCycle::accumulate_dihedral_angle(const Vec3r& edge, const double beta, double neigh_area)
|
||||||
|
{
|
||||||
|
double s = beta * neigh_area / edge.norm();
|
||||||
|
|
||||||
|
M_[0] += s * edge.x() * edge.x();
|
||||||
|
M_[1] += s * edge.x() * edge.y();
|
||||||
|
M_[2] += s * edge.y() * edge.y();
|
||||||
|
M_[3] += s * edge.x() * edge.z();
|
||||||
|
M_[4] += s * edge.y() * edge.z();
|
||||||
|
M_[5] += s * edge.z() * edge.z();
|
||||||
|
}
|
||||||
|
|
||||||
|
//_________________________________________________________
|
||||||
|
|
||||||
|
} // OGF namespace
|
||||||
|
|
||||||
|
#endif // __MESH_TOOLS_MATH_NORMAL_CYCLE__
|
||||||
|
@ -1,96 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/image/GaussianFilter.cpp
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to perform gaussian filtering operations on an image
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 20/05/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "GaussianFilter.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
GaussianFilter::GaussianFilter(float iSigma )
|
#include "GaussianFilter.h"
|
||||||
|
|
||||||
|
GaussianFilter::GaussianFilter(float iSigma)
|
||||||
{
|
{
|
||||||
_sigma = iSigma;
|
_sigma = iSigma;
|
||||||
_mask = 0;
|
_mask = 0;
|
||||||
computeMask();
|
computeMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
GaussianFilter::GaussianFilter(const GaussianFilter& iBrother)
|
GaussianFilter::GaussianFilter(const GaussianFilter& iBrother)
|
||||||
{
|
{
|
||||||
_sigma = iBrother._sigma;
|
_sigma = iBrother._sigma;
|
||||||
_maskSize = iBrother._maskSize;
|
_maskSize = iBrother._maskSize;
|
||||||
_bound = iBrother._bound;
|
_bound = iBrother._bound;
|
||||||
_storedMaskSize = iBrother._storedMaskSize;
|
_storedMaskSize = iBrother._storedMaskSize;
|
||||||
_mask = new float[_maskSize*_maskSize];
|
_mask = new float[_maskSize * _maskSize];
|
||||||
memcpy(_mask, iBrother._mask, _maskSize*_maskSize*sizeof(float));
|
memcpy(_mask, iBrother._mask, _maskSize * _maskSize * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GaussianFilter& GaussianFilter::operator=(const GaussianFilter& iBrother)
|
||||||
GaussianFilter& GaussianFilter::operator= (const GaussianFilter& iBrother)
|
|
||||||
{
|
{
|
||||||
_sigma = iBrother._sigma;
|
_sigma = iBrother._sigma;
|
||||||
_maskSize = iBrother._maskSize;
|
_maskSize = iBrother._maskSize;
|
||||||
_bound = iBrother._bound;
|
_bound = iBrother._bound;
|
||||||
_storedMaskSize = iBrother._storedMaskSize;
|
_storedMaskSize = iBrother._storedMaskSize;
|
||||||
_mask = new float[_storedMaskSize*_storedMaskSize];
|
_mask = new float[_storedMaskSize * _storedMaskSize];
|
||||||
memcpy(_mask, iBrother._mask, _storedMaskSize*_storedMaskSize*sizeof(float));
|
memcpy(_mask, iBrother._mask, _storedMaskSize * _storedMaskSize * sizeof(float));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GaussianFilter::~GaussianFilter()
|
GaussianFilter::~GaussianFilter()
|
||||||
{
|
{
|
||||||
if(0!=_mask)
|
if (0 != _mask) {
|
||||||
{
|
delete[] _mask;
|
||||||
delete [] _mask;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GaussianFilter::computeMaskSize(float sigma)
|
int GaussianFilter::computeMaskSize(float sigma)
|
||||||
{
|
{
|
||||||
int maskSize = (int)floor(4*sigma)+1;
|
int maskSize = (int)floor(4 * sigma) + 1;
|
||||||
if(0 == maskSize%2)
|
if (0 == (maskSize % 2))
|
||||||
++maskSize;
|
++maskSize;
|
||||||
|
|
||||||
return maskSize;
|
return maskSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GaussianFilter::setSigma(float sigma)
|
void GaussianFilter::setSigma(float sigma)
|
||||||
{
|
{
|
||||||
_sigma = sigma;
|
_sigma = sigma;
|
||||||
computeMask();
|
computeMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GaussianFilter::computeMask()
|
void GaussianFilter::computeMask()
|
||||||
{
|
{
|
||||||
if(0 != _mask){
|
if (0 != _mask) {
|
||||||
delete [] _mask;
|
delete[] _mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
_maskSize = computeMaskSize(_sigma);
|
_maskSize = computeMaskSize(_sigma);
|
||||||
_storedMaskSize = (_maskSize+1)>>1;
|
_storedMaskSize = (_maskSize + 1) >> 1;
|
||||||
_bound = _storedMaskSize-1;
|
_bound = _storedMaskSize - 1;
|
||||||
|
|
||||||
float norm = _sigma*_sigma*2.f*M_PI;
|
float norm = _sigma * _sigma * 2.0f * M_PI;
|
||||||
float invNorm = 1.0/norm;
|
float invNorm = 1.0f / norm;
|
||||||
_mask = new float[_storedMaskSize*_storedMaskSize*sizeof(float)];
|
_mask = new float[_storedMaskSize * _storedMaskSize * sizeof(float)];
|
||||||
for(int i=0; i<_storedMaskSize; ++i)
|
for (int i = 0; i < _storedMaskSize; ++i) {
|
||||||
for(int j=0; j<_storedMaskSize; ++j)
|
for (int j = 0; j < _storedMaskSize; ++j) {
|
||||||
_mask[i*_storedMaskSize+j] = invNorm*exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
|
#if 0
|
||||||
//_mask[i*_storedMaskSize+j] = exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
|
_mask[i * _storedMaskSize + j] = exp(-(i * i + j * j) / (2.0 * _sigma * _sigma));
|
||||||
|
#else
|
||||||
|
_mask[i * _storedMaskSize + j] = invNorm * exp(-(i * i + j * j) / (2.0 * _sigma * _sigma));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,95 +1,114 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Image.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to perform gaussian filtering operations on an image
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 20/05/2003
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GAUSSIANFILTER_H__
|
||||||
|
#define __GAUSSIANFILTER_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/image/GaussianFilter.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to perform gaussian filtering operations on an image
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 20/05/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef GAUSSIANFILTER_H
|
|
||||||
# define GAUSSIANFILTER_H
|
|
||||||
|
|
||||||
#include <string.h> // for memcpy
|
|
||||||
#include <cstdlib> // for abs
|
#include <cstdlib> // for abs
|
||||||
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
#include "../system/FreestyleConfig.h"
|
#include "../system/FreestyleConfig.h"
|
||||||
|
|
||||||
class LIB_IMAGE_EXPORT GaussianFilter{
|
class LIB_IMAGE_EXPORT GaussianFilter
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
/* the mask is a symetrical 2d array (with respect
|
/* The mask is a symetrical 2d array (with respect to the middle point).
|
||||||
to the middle point).
|
* Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j).
|
||||||
Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j).
|
* For this reason, to represent a NxN array (N odd), we only store a ((N+1)/2)x((N+1)/2) array.
|
||||||
For this reason, to represent a NxN array (N odd), we only store
|
*/
|
||||||
a ((N+1)/2)x((N+1)/2) array.
|
float _sigma;
|
||||||
*/
|
float *_mask;
|
||||||
float _sigma;
|
int _bound;
|
||||||
float *_mask;
|
int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2))
|
||||||
int _bound;
|
int _storedMaskSize; // (_maskSize+1)/2)
|
||||||
int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2))
|
|
||||||
int _storedMaskSize; //(_maskSize+1)/2)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GaussianFilter(float iSigma = 1.f) ;
|
GaussianFilter(float iSigma = 1.0f);
|
||||||
GaussianFilter(const GaussianFilter&) ;
|
GaussianFilter(const GaussianFilter&);
|
||||||
GaussianFilter& operator= (const GaussianFilter&) ;
|
GaussianFilter& operator=(const GaussianFilter&);
|
||||||
virtual ~GaussianFilter() ;
|
virtual ~GaussianFilter();
|
||||||
|
|
||||||
/*! Returns the value for pixel x,y of image "map" after a gaussian blur,
|
/*! Returns the value for pixel x,y of image "map" after a gaussian blur, made using the sigma value.
|
||||||
* made using the sigma value.
|
* The sigma value determines the mask size (~ 2 x sigma).
|
||||||
* The sigma value determines the mask size (~ 2 x sigma).
|
* \param map
|
||||||
* \param map
|
* The image we wish to work on. The Map template must implement the following methods:
|
||||||
* The image we wish to work on. The Map template must implement the
|
* - float pixel(unsigned int x,unsigned int y) const;
|
||||||
* foloowing methods:
|
* - unsigned width() const;
|
||||||
* - float pixel(unsigned int x,unsigned int y) const;
|
* - unsigned height() const;
|
||||||
* - unsigned width() const;
|
* \param x
|
||||||
* - unsigned height() const;
|
* The abscissa of the pixel where we want to evaluate the gaussian blur.
|
||||||
* \param x
|
* \param y
|
||||||
* The abscissa of the pixel where we want to evaluate the gaussian blur.
|
* The ordinate of the pixel where we want to evaluate the gaussian blur.
|
||||||
* \param y
|
* \param sigma
|
||||||
* The ordinate of the pixel where we want to evaluate the gaussian blur.
|
* The sigma value of the gaussian function.
|
||||||
* \param sigma
|
*/
|
||||||
* The sigma value of the gaussian function.
|
template<class Map>
|
||||||
*/
|
float getSmoothedPixel(Map *map, int x, int y);
|
||||||
template<class Map>
|
|
||||||
float getSmoothedPixel(Map * map, int x, int y) ;
|
|
||||||
|
|
||||||
/*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1)
|
|
||||||
* This method is provided for convenience.
|
|
||||||
*/
|
|
||||||
static int computeMaskSize(float sigma) ;
|
|
||||||
|
|
||||||
/*! accessors */
|
/*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1)
|
||||||
inline float sigma() const {return _sigma;}
|
* This method is provided for convenience.
|
||||||
inline int maskSize() const {return _maskSize;}
|
*/
|
||||||
inline int getBound() {return _bound;}
|
static int computeMaskSize(float sigma);
|
||||||
|
|
||||||
|
/*! accessors */
|
||||||
|
inline float sigma() const
|
||||||
|
{
|
||||||
|
return _sigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int maskSize() const
|
||||||
|
{
|
||||||
|
return _maskSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getBound()
|
||||||
|
{
|
||||||
|
return _bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! modifiers */
|
||||||
|
void setSigma(float sigma);
|
||||||
|
#if 0
|
||||||
|
void SetMaskSize(int size)
|
||||||
|
{
|
||||||
|
_maskSize = size;
|
||||||
|
_storedMaskSize = (_maskSize + 1) >> 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! modifiers */
|
|
||||||
void setSigma(float sigma) ;
|
|
||||||
// void SetMaskSize(int size) {_maskSize = size;_storedMaskSize=(_maskSize+1)>>1;}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void computeMask();
|
void computeMask();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -106,41 +125,37 @@ protected:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef __MACH__
|
#ifdef __MACH__
|
||||||
#define sqrtf(x) (sqrt(x))
|
# define sqrtf(x) (sqrt(x))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<class Map>
|
template<class Map>
|
||||||
float GaussianFilter::getSmoothedPixel(Map * map, int x, int y)
|
float GaussianFilter::getSmoothedPixel(Map *map, int x, int y)
|
||||||
{
|
{
|
||||||
float sum = 0.f;
|
float sum = 0.0f;
|
||||||
float L=0.f;
|
float L = 0.0f;
|
||||||
int w = (int)map->width(); //soc
|
int w = (int)map->width(); //soc
|
||||||
int h = (int)map->height(); //soc
|
int h = (int)map->height(); //soc
|
||||||
|
|
||||||
// Current pixel is x,y
|
// Current pixel is x,y
|
||||||
// Sum surrounding pixels L value:
|
// Sum surrounding pixels L value:
|
||||||
for(int i=-_bound; i<=_bound; ++i)
|
for (int i = -_bound; i <= _bound; ++i) {
|
||||||
{
|
if ((y + i < 0) || (y + i >= h))
|
||||||
if((y+i < 0) || (y+i >= h))
|
continue;
|
||||||
continue;
|
for (int j = -_bound; j <= _bound; ++j) {
|
||||||
for(int j=-_bound; j<=_bound; ++j)
|
if ((x + j < 0) || (x + j >= w))
|
||||||
{
|
continue;
|
||||||
if((x+j < 0) || (x+j >= w))
|
|
||||||
continue;
|
float tmpL = map->pixel(x + j, y + i);
|
||||||
|
float m = _mask[abs(i) * _storedMaskSize + abs(j)];
|
||||||
float tmpL = map->pixel(x+j,y+i);
|
L += m * tmpL;
|
||||||
float m = _mask[abs(i)*_storedMaskSize+abs(j)];
|
sum += m;
|
||||||
L += m*tmpL;
|
}
|
||||||
sum += m;
|
}
|
||||||
}
|
//L /= sum;
|
||||||
}
|
return L;
|
||||||
//L /= sum;
|
|
||||||
return L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __GAUSSIANFILTER_H__
|
||||||
#endif // GAUSSIANFILTER
|
|
||||||
|
@ -1,178 +1,177 @@
|
|||||||
//
|
/*
|
||||||
// Filename : Image.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to encapsulate an array of RGB or Gray level values
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 20/05/2003
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __IMAGE_H__
|
||||||
|
#define __IMAGE_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/image/Image.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to encapsulate an array of RGB or Gray level values
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 20/05/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef IMAGE_H
|
#include <string.h> // for memcpy
|
||||||
# define IMAGE_H
|
|
||||||
|
|
||||||
# include <string.h> // for memcpy
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Image base class, for all types of images
|
// Image base class, for all types of images
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*! This class allows the storing of part of an image,
|
/*! This class allows the storing of part of an image, while allowing a normal access to its pixel values.
|
||||||
* while allowing a normal access to its pixel values.
|
* You can for example only a rectangle of sw*sh, whose lower-left corner is at (ox, oy), of an image of
|
||||||
* You can for example only a rectangle of sw*sh, whose
|
* size w*h, and access these pixels using x,y coordinates specified in the whole image coordinate system.
|
||||||
* lower-left corner is at (ox, oy), of an image of
|
|
||||||
* size w*h, and access these pixels using x,y coordinates
|
|
||||||
* specified in the whole image coordinate system.
|
|
||||||
*/
|
*/
|
||||||
class FrsImage
|
class FrsImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*! Default constructor */
|
||||||
|
FrsImage()
|
||||||
|
{
|
||||||
|
_storedWidth = 0;
|
||||||
|
_storedHeight = 0;
|
||||||
|
_width = 0;
|
||||||
|
_height = 0;
|
||||||
|
_Ox = 0;
|
||||||
|
_Oy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Default constructor */
|
/*! Copy constructor */
|
||||||
FrsImage() {
|
FrsImage(const FrsImage& brother)
|
||||||
_storedWidth = 0;
|
{
|
||||||
_storedHeight = 0;
|
_storedWidth = brother._storedWidth;
|
||||||
_width = 0;
|
_storedHeight = brother._storedHeight;
|
||||||
_height = 0;
|
_width = brother._width;
|
||||||
_Ox = 0;
|
_height = brother._height;
|
||||||
_Oy = 0;
|
_Ox = brother._Ox;
|
||||||
}
|
_Oy = brother._Oy;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Copy constructor */
|
/*! Builds an FrsImage from its width and height.
|
||||||
FrsImage(const FrsImage& brother) {
|
* The memory is allocated consequently.
|
||||||
_storedWidth = brother._storedWidth;
|
*/
|
||||||
_storedHeight = brother._storedHeight;
|
FrsImage(unsigned w, unsigned h)
|
||||||
_width = brother._width;
|
{
|
||||||
_height = brother._height;
|
_width = w;
|
||||||
_Ox = brother._Ox;
|
_height = h;
|
||||||
_Oy = brother._Oy;
|
_storedWidth = w;
|
||||||
}
|
_storedHeight = h;
|
||||||
|
_Ox = 0;
|
||||||
|
_Oy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Builds an FrsImage from its width and height.
|
/*! Builds a partial-storing image.
|
||||||
* The memory is allocated consequently.
|
* \param w
|
||||||
*/
|
* The width of the complete image
|
||||||
FrsImage(unsigned w, unsigned h) {
|
* \param h
|
||||||
_width = w;
|
* The height of the complete image
|
||||||
_height = h;
|
* \param sw
|
||||||
_storedWidth = w;
|
* The width of the rectangle that will actually be stored.
|
||||||
_storedHeight = h;
|
* \param sh
|
||||||
_Ox = 0;
|
* The height of the rectangle that will actually be stored.
|
||||||
_Oy = 0;
|
* \param ox
|
||||||
}
|
* The x-abscissa of the origin of the rectangle that will actually be stored.
|
||||||
|
* \param oy
|
||||||
|
* The x-abscissa of the origin of the rectangle that will actually be stored.
|
||||||
|
*/
|
||||||
|
FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
|
||||||
|
{
|
||||||
|
_width = w;
|
||||||
|
_height = h;
|
||||||
|
_storedWidth = sw;
|
||||||
|
_storedHeight = sh;
|
||||||
|
_Ox = ox;
|
||||||
|
_Oy = oy;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Builds a partial-storing image.
|
/*! Operator= */
|
||||||
* \param w
|
FrsImage& operator=(const FrsImage& brother)
|
||||||
* The width of the complete image
|
{
|
||||||
* \param h
|
_width = brother._width;
|
||||||
* The height of the complete image
|
_height = brother._height;
|
||||||
* \param sw
|
_storedWidth = brother._storedWidth;
|
||||||
* The width of the rectangle that will actually
|
_storedHeight = brother._storedHeight;
|
||||||
* be stored.
|
_Ox = brother._Ox;
|
||||||
* \param sh
|
_Oy = brother._Oy;
|
||||||
* The height of the rectangle that will actually
|
return *this;
|
||||||
* be stored.
|
}
|
||||||
* \param ox
|
|
||||||
* The x-abscissa of the origin of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
* \param oy
|
|
||||||
* The x-abscissa of the origin of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
*/
|
|
||||||
FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) {
|
|
||||||
_width = w;
|
|
||||||
_height = h;
|
|
||||||
_storedWidth = sw;
|
|
||||||
_storedHeight = sh;
|
|
||||||
_Ox = ox;
|
|
||||||
_Oy = oy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Operator= */
|
/*! Destructor */
|
||||||
FrsImage& operator=(const FrsImage& brother) {
|
virtual ~FrsImage() {}
|
||||||
_width = brother._width;
|
|
||||||
_height = brother._height;
|
|
||||||
_storedWidth = brother._storedWidth;
|
|
||||||
_storedHeight = brother._storedHeight;
|
|
||||||
_Ox = brother._Ox;
|
|
||||||
_Oy = brother._Oy;
|
|
||||||
return* this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Destructor */
|
/*! Returns the width of the complete image */
|
||||||
virtual ~FrsImage() {}
|
inline unsigned width() const
|
||||||
|
{
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the width of the complete image */
|
/*! Returns the height of the complete image */
|
||||||
inline unsigned width() const {
|
inline unsigned height() const
|
||||||
return _width;
|
{
|
||||||
}
|
return _height;
|
||||||
/*! Returns the height of the complete image */
|
}
|
||||||
inline unsigned height() const {
|
|
||||||
return _height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Returns the grey value for pixel x,y */
|
|
||||||
virtual float pixel(unsigned x, unsigned y) const = 0;
|
|
||||||
|
|
||||||
/*! Sets the array.
|
/*! Returns the grey value for pixel x,y */
|
||||||
* \param array
|
virtual float pixel(unsigned x, unsigned y) const = 0;
|
||||||
* The array containing the values we wish to store.
|
|
||||||
* Its size is sw*sh.
|
|
||||||
* \param width
|
|
||||||
* The width of the complete image
|
|
||||||
* \param height
|
|
||||||
* The height of the complete image
|
|
||||||
* \param sw
|
|
||||||
* The width of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
* \param sh
|
|
||||||
* The height of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
* \param ox
|
|
||||||
* The x-abscissa of the origin of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
* \param oy
|
|
||||||
* The x-abscissa of the origin of the rectangle that will actually
|
|
||||||
* be stored.
|
|
||||||
* \param copy
|
|
||||||
* If true, the array is copied, otherwise the pointer is
|
|
||||||
* copied
|
|
||||||
*/
|
|
||||||
virtual void setArray(float* array, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) = 0;
|
|
||||||
|
|
||||||
/*! Returns the array containing the pixels values.
|
|
||||||
* Its size is sw*sh, i.e. potentially a smaller
|
|
||||||
* rectangular part of the complete image.
|
|
||||||
*/
|
|
||||||
virtual float * getArray() = 0;
|
|
||||||
|
|
||||||
protected:
|
/*! Sets the array.
|
||||||
|
* \param array
|
||||||
|
* The array containing the values we wish to store.
|
||||||
|
* Its size is sw*sh.
|
||||||
|
* \param width
|
||||||
|
* The width of the complete image
|
||||||
|
* \param height
|
||||||
|
* The height of the complete image
|
||||||
|
* \param sw
|
||||||
|
* The width of the rectangle that will actually be stored.
|
||||||
|
* \param sh
|
||||||
|
* The height of the rectangle that will actually be stored.
|
||||||
|
* \param ox
|
||||||
|
* The x-abscissa of the origin of the rectangle that will actually be stored.
|
||||||
|
* \param oy
|
||||||
|
* The x-abscissa of the origin of the rectangle that will actually be stored.
|
||||||
|
* \param copy
|
||||||
|
* If true, the array is copied, otherwise the pointer is copied
|
||||||
|
*/
|
||||||
|
virtual void setArray(float *array, unsigned width, unsigned height, unsigned sw, unsigned sh,
|
||||||
|
unsigned x, unsigned y, bool copy = true) = 0;
|
||||||
|
|
||||||
unsigned _width;
|
/*! Returns the array containing the pixels values.
|
||||||
unsigned _height;
|
* Its size is sw*sh, i.e. potentially a smaller rectangular part of the complete image.
|
||||||
unsigned _storedWidth;
|
*/
|
||||||
unsigned _storedHeight;
|
virtual float *getArray() = 0;
|
||||||
unsigned _Ox; // origin of the stored part
|
|
||||||
unsigned _Oy; // origin of the stored part
|
protected:
|
||||||
|
unsigned _width;
|
||||||
|
unsigned _height;
|
||||||
|
unsigned _storedWidth;
|
||||||
|
unsigned _storedHeight;
|
||||||
|
unsigned _Ox; // origin of the stored part
|
||||||
|
unsigned _Oy; // origin of the stored part
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -180,114 +179,130 @@ class FrsImage
|
|||||||
// RGBImage
|
// RGBImage
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class RGBImage : public FrsImage
|
class RGBImage : public FrsImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
RGBImage() : FrsImage()
|
||||||
|
{
|
||||||
|
_rgb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
RGBImage() : FrsImage() {
|
RGBImage(const RGBImage& brother) : FrsImage(brother)
|
||||||
_rgb = 0;
|
{
|
||||||
}
|
_rgb = new float[3 * _storedWidth * _storedHeight];
|
||||||
|
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
RGBImage(const RGBImage& brother) : FrsImage(brother) {
|
RGBImage(unsigned w, unsigned h) : FrsImage(w, h)
|
||||||
_rgb = new float[3 * _storedWidth * _storedHeight];
|
{
|
||||||
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
_rgb = new float[3 * _width * _height];
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBImage(unsigned w, unsigned h) : FrsImage(w, h) {
|
RGBImage(float *rgb, unsigned w, unsigned h) : FrsImage(w, h)
|
||||||
_rgb = new float[3 * _width * _height];
|
{
|
||||||
}
|
_rgb = new float[3 * _width * _height];
|
||||||
|
memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
RGBImage(float* rgb, unsigned w, unsigned h) : FrsImage(w, h) {
|
/*! Builds an RGB partial image from the useful part buffer.
|
||||||
_rgb = new float[3 * _width * _height];
|
* \param rgb
|
||||||
memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
|
* The array of size 3*sw*sh containing the RGB values of the sw*sh pixels we need to stored.
|
||||||
}
|
* These sw*sh pixels constitute a rectangular part of a bigger RGB image containing w*h pixels.
|
||||||
|
* \param w
|
||||||
/*! Builds an RGB partial image from the useful part buffer.
|
* The width of the complete image
|
||||||
* \param rgb
|
* \param h
|
||||||
* The array of size 3*sw*sh containing the RGB values
|
* The height of the complete image
|
||||||
* of the sw*sh pixels we need to stored.
|
* \param sw
|
||||||
* These sw*sh pixels constitute a rectangular part of
|
* The width of the part of the image we want to store and work on
|
||||||
* a bigger RGB image containing w*h pixels.
|
* \param sh
|
||||||
* \param w
|
* The height of the part of the image we want to store and work on
|
||||||
* The width of the complete image
|
*/
|
||||||
* \param h
|
RGBImage(float *rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
|
||||||
* The height of the complete image
|
: FrsImage(w, h, sw, sh, ox, oy)
|
||||||
* \param sw
|
{
|
||||||
* The width of the part of the image we want to store and work on
|
_rgb = new float[3 * _storedWidth * _storedHeight];
|
||||||
* \param sh
|
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
||||||
* The height of the part of the image we want to store and work on
|
}
|
||||||
*/
|
|
||||||
RGBImage(float* rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
|
|
||||||
_rgb = new float[3 * _storedWidth * _storedHeight];
|
|
||||||
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
|
||||||
}
|
|
||||||
|
|
||||||
RGBImage& operator=(const RGBImage& brother) {
|
RGBImage& operator=(const RGBImage& brother)
|
||||||
dynamic_cast<FrsImage&>(*this) = brother;
|
{
|
||||||
_rgb = new float[3 * _storedWidth * _storedHeight];
|
dynamic_cast<FrsImage&>(*this) = brother;
|
||||||
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
_rgb = new float[3 * _storedWidth * _storedHeight];
|
||||||
return* this;
|
memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
||||||
}
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~RGBImage() {
|
virtual ~RGBImage()
|
||||||
if(_rgb)
|
{
|
||||||
delete[] _rgb;
|
if(_rgb)
|
||||||
}
|
delete[] _rgb;
|
||||||
|
}
|
||||||
|
|
||||||
inline float getR(unsigned x, unsigned y) const {
|
inline float getR(unsigned x, unsigned y) const
|
||||||
return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3];
|
{
|
||||||
}
|
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3];
|
||||||
|
}
|
||||||
|
|
||||||
inline float getG(unsigned x, unsigned y) const {
|
inline float getG(unsigned x, unsigned y) const
|
||||||
return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 1];
|
{
|
||||||
}
|
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
inline float getB(unsigned x, unsigned y) const {
|
inline float getB(unsigned x, unsigned y) const
|
||||||
return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 2];
|
{
|
||||||
}
|
return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 2];
|
||||||
|
}
|
||||||
|
|
||||||
virtual void setPixel(unsigned x, unsigned y, float r, float g, float b){
|
virtual void setPixel(unsigned x, unsigned y, float r, float g, float b)
|
||||||
float * tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
|
{
|
||||||
*tmp = r;++tmp;
|
float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
|
||||||
*tmp = g;++tmp;
|
*tmp = r;
|
||||||
*tmp = b;
|
tmp++;
|
||||||
}
|
*tmp = g;
|
||||||
|
tmp++;
|
||||||
|
*tmp = b;
|
||||||
|
}
|
||||||
|
|
||||||
virtual float pixel(unsigned x, unsigned y) const {
|
virtual float pixel(unsigned x, unsigned y) const
|
||||||
float res = 0;
|
{
|
||||||
float* tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
|
float res = 0.0f;
|
||||||
res += 11 * (*tmp++);
|
float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
|
||||||
res += 16 * (*tmp++);
|
res += 11.0f * (*tmp);
|
||||||
res += 5 * (*tmp);
|
tmp++;
|
||||||
return res / 32;
|
res += 16.0f * (*tmp);
|
||||||
}
|
tmp++;
|
||||||
|
res += 5.0f * (*tmp);
|
||||||
|
return res / 32.0f;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Sets the RGB array.
|
/*! Sets the RGB array.
|
||||||
* copy
|
* copy
|
||||||
* If true, the array is copied, otherwise the pointer is
|
* If true, the array is copied, otherwise the pointer is copied
|
||||||
* copied
|
*/
|
||||||
*/
|
virtual void setArray(float *rgb, unsigned width, unsigned height, unsigned sw, unsigned sh,
|
||||||
virtual void setArray(float* rgb, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
|
unsigned x, unsigned y, bool copy = true)
|
||||||
_width = width;
|
{
|
||||||
_height = height;
|
_width = width;
|
||||||
_storedWidth = sw;
|
_height = height;
|
||||||
_storedHeight = sh;
|
_storedWidth = sw;
|
||||||
_Ox = x;
|
_storedHeight = sh;
|
||||||
_Oy = y;
|
_Ox = x;
|
||||||
if(!copy) {
|
_Oy = y;
|
||||||
_rgb = rgb;
|
if (!copy) {
|
||||||
return;
|
_rgb = rgb;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight* sizeof(float));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual float * getArray() {return _rgb;}
|
memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
virtual float *getArray()
|
||||||
|
{
|
||||||
|
return _rgb;
|
||||||
|
}
|
||||||
|
|
||||||
float* _rgb;
|
protected:
|
||||||
|
float *_rgb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -298,92 +313,103 @@ class RGBImage : public FrsImage
|
|||||||
|
|
||||||
class GrayImage : public FrsImage
|
class GrayImage : public FrsImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
GrayImage() : FrsImage()
|
||||||
|
{
|
||||||
|
_lvl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
GrayImage() : FrsImage() {
|
GrayImage(const GrayImage& brother) : FrsImage(brother)
|
||||||
_lvl = 0;
|
{
|
||||||
}
|
_lvl = new float[_storedWidth * _storedHeight];
|
||||||
|
memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(*_lvl));
|
||||||
|
}
|
||||||
|
|
||||||
GrayImage(const GrayImage& brother) : FrsImage(brother) {
|
/*! Builds an empty gray image */
|
||||||
_lvl = new float[_storedWidth*_storedHeight];
|
GrayImage(unsigned w, unsigned h) : FrsImage(w, h)
|
||||||
memcpy(_lvl, brother._lvl, _storedWidth*_storedHeight*sizeof(*_lvl));
|
{
|
||||||
}
|
_lvl = new float[_width * _height];
|
||||||
|
}
|
||||||
|
|
||||||
/*! Builds an empty gray image */
|
GrayImage(float *lvl, unsigned w, unsigned h) : FrsImage(w, h)
|
||||||
GrayImage(unsigned w, unsigned h) : FrsImage(w, h) {
|
{
|
||||||
_lvl = new float[_width*_height];
|
_lvl = new float[_width * _height];
|
||||||
}
|
memcpy(_lvl, lvl, _width * _height * sizeof(*_lvl));
|
||||||
|
}
|
||||||
|
|
||||||
GrayImage(float* lvl, unsigned w, unsigned h) : FrsImage(w, h) {
|
/*! Builds a partial image from the useful part buffer.
|
||||||
_lvl = new float[_width*_height];
|
* \param lvl
|
||||||
memcpy(_lvl, lvl, _width*_height*sizeof(*_lvl));
|
* The array of size sw*sh containing the gray values of the sw*sh pixels we need to stored.
|
||||||
}
|
* These sw*sh pixels constitute a rectangular part of a bigger gray image containing w*h pixels.
|
||||||
|
* \param w
|
||||||
/*! Builds a partial image from the useful part buffer.
|
* The width of the complete image
|
||||||
* \param lvl
|
* \param h
|
||||||
* The array of size sw*sh containing the gray values
|
* The height of the complete image
|
||||||
* of the sw*sh pixels we need to stored.
|
* \param sw
|
||||||
* These sw*sh pixels constitute a rectangular part of
|
* The width of the part of the image we want to store and work on
|
||||||
* a bigger gray image containing w*h pixels.
|
* \param sh
|
||||||
* \param w
|
* The height of the part of the image we want to store and work on
|
||||||
* The width of the complete image
|
*/
|
||||||
* \param h
|
GrayImage(float *lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
|
||||||
* The height of the complete image
|
: FrsImage(w, h, sw, sh, ox, oy)
|
||||||
* \param sw
|
{
|
||||||
* The width of the part of the image we want to store and work on
|
_lvl = new float[_storedWidth * _storedHeight];
|
||||||
* \param sh
|
memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
|
||||||
* The height of the part of the image we want to store and work on
|
}
|
||||||
*/
|
|
||||||
GrayImage(float* lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
|
|
||||||
_lvl = new float[_storedWidth*_storedHeight];
|
|
||||||
memcpy(_lvl, lvl, _storedWidth*_storedHeight*sizeof(float));
|
|
||||||
}
|
|
||||||
|
|
||||||
GrayImage& operator=(const GrayImage& brother) {
|
GrayImage& operator=(const GrayImage& brother)
|
||||||
dynamic_cast<FrsImage&>(*this) = brother;
|
{
|
||||||
_lvl = new float[_storedWidth * _storedHeight];
|
dynamic_cast<FrsImage&>(*this) = brother;
|
||||||
memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
|
_lvl = new float[_storedWidth * _storedHeight];
|
||||||
return *this;
|
memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
|
||||||
}
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~GrayImage() {
|
virtual ~GrayImage()
|
||||||
if(_lvl)
|
{
|
||||||
delete[] _lvl;
|
if (_lvl)
|
||||||
}
|
delete[] _lvl;
|
||||||
|
}
|
||||||
|
|
||||||
inline void setPixel(unsigned x, unsigned y, float v){
|
inline void setPixel(unsigned x, unsigned y, float v)
|
||||||
_lvl[(y-_Oy) * _storedWidth+ (x-_Ox)] = v;
|
{
|
||||||
}
|
_lvl[(y - _Oy) * _storedWidth + (x - _Ox)] = v;
|
||||||
|
}
|
||||||
|
|
||||||
inline float pixel(unsigned x, unsigned y) const {
|
inline float pixel(unsigned x, unsigned y) const
|
||||||
return _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)];
|
{
|
||||||
}
|
return _lvl[(y - _Oy) * _storedWidth + (x - _Ox)];
|
||||||
|
}
|
||||||
|
|
||||||
/*! Sets the array.
|
/*! Sets the array.
|
||||||
* copy
|
* copy
|
||||||
* If true, the array is copie, otherwise the pounsigneder is
|
* If true, the array is copie, otherwise the pounsigneder is copied
|
||||||
* copied
|
*/
|
||||||
*/
|
void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh,
|
||||||
void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
|
unsigned x, unsigned y, bool copy = true)
|
||||||
_width = width;
|
{
|
||||||
_height = height;
|
_width = width;
|
||||||
_storedWidth = sw;
|
_height = height;
|
||||||
_storedHeight = sh;
|
_storedWidth = sw;
|
||||||
_Ox = x;
|
_storedHeight = sh;
|
||||||
_Oy = y;
|
_Ox = x;
|
||||||
if(!copy) {
|
_Oy = y;
|
||||||
_lvl = lvl;
|
if (!copy) {
|
||||||
return;
|
_lvl = lvl;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
|
|
||||||
}
|
|
||||||
/*! Returns the array containing the gray values. */
|
|
||||||
virtual float * getArray() {return _lvl;}
|
|
||||||
|
|
||||||
protected:
|
memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
float *_lvl;
|
/*! Returns the array containing the gray values. */
|
||||||
|
virtual float *getArray()
|
||||||
|
{
|
||||||
|
return _lvl;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float *_lvl;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMAGE_H
|
#endif // __IMAGE_H__
|
||||||
|
@ -1,166 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/freestyle/intern/image/ImagePyramid.cpp
|
||||||
|
* \ingroup freestyle
|
||||||
|
* \brief Class to represent a pyramid of images
|
||||||
|
* \author Stephane Grabli
|
||||||
|
* \date 25/12/2003
|
||||||
|
*/
|
||||||
|
|
||||||
//
|
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
|
||||||
// with this source distribution.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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 "ImagePyramid.h"
|
|
||||||
#include "Image.h"
|
|
||||||
#include "GaussianFilter.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "GaussianFilter.h"
|
||||||
|
#include "Image.h"
|
||||||
|
#include "ImagePyramid.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels){
|
#if 0
|
||||||
// //BuildPyramid(level0,nbLevels);
|
ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels)
|
||||||
//}
|
|
||||||
|
|
||||||
ImagePyramid::ImagePyramid(const ImagePyramid& iBrother){
|
|
||||||
if(!_levels.empty()){
|
|
||||||
for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
|
|
||||||
im!=imend;
|
|
||||||
++im){
|
|
||||||
_levels.push_back(new GrayImage(**im));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImagePyramid::~ImagePyramid(){
|
|
||||||
if(!_levels.empty()){
|
|
||||||
for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
|
|
||||||
im!=imend;
|
|
||||||
++im){
|
|
||||||
delete (*im);
|
|
||||||
}
|
|
||||||
_levels.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GrayImage * ImagePyramid::getLevel(int l){
|
|
||||||
return _levels[l];
|
|
||||||
}
|
|
||||||
|
|
||||||
float ImagePyramid::pixel(int x, int y, int level){
|
|
||||||
GrayImage *img = _levels[level];
|
|
||||||
if(0 == level){
|
|
||||||
return img->pixel(x,y);
|
|
||||||
}
|
|
||||||
unsigned int i = 1<<level;
|
|
||||||
unsigned int sx = x>>level;
|
|
||||||
unsigned int sy = y>>level;
|
|
||||||
if(sx >= img->width())
|
|
||||||
sx = img->width()-1;
|
|
||||||
if(sy >= img->height())
|
|
||||||
sy = img->height()-1;
|
|
||||||
|
|
||||||
// bilinear interpolation
|
|
||||||
float A = i*(sx+1)-x;
|
|
||||||
float B = x-i*sx;
|
|
||||||
float C = i*(sy+1)-y;
|
|
||||||
float D = y-i*sy;
|
|
||||||
|
|
||||||
float P1(0), P2(0);
|
|
||||||
P1 = A*img->pixel(sx,sy);
|
|
||||||
if(sx < img->width()-1){
|
|
||||||
if(x%i != 0)
|
|
||||||
P1 += B*img->pixel(sx+1,sy);
|
|
||||||
}else{
|
|
||||||
P1 += B*img->pixel(sx,sy);
|
|
||||||
}
|
|
||||||
if(sy<img->height()-1){
|
|
||||||
if(y%i != 0){
|
|
||||||
P2 = A*img->pixel(sx,sy+1);
|
|
||||||
if(sx < img->width()-1){
|
|
||||||
if(x%i != 0)
|
|
||||||
P2 += B*img->pixel(sx+1,sy+1);
|
|
||||||
}else{
|
|
||||||
P2 += B*img->pixel(sx,sy+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
P2 = P1;
|
|
||||||
}
|
|
||||||
return (1.f/(float)(1<<2*level))*(C*P1 + D*P2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ImagePyramid::width(int level){
|
|
||||||
return _levels[level]->width();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ImagePyramid::height(int level){
|
|
||||||
return _levels[level]->height();
|
|
||||||
}
|
|
||||||
|
|
||||||
GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma)
|
|
||||||
: ImagePyramid()
|
|
||||||
{
|
{
|
||||||
_sigma = iSigma;
|
BuildPyramid(level0,nbLevels);
|
||||||
BuildPyramid(level0,nbLevels);
|
}
|
||||||
}
|
#endif
|
||||||
GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma)
|
|
||||||
: ImagePyramid()
|
ImagePyramid::ImagePyramid(const ImagePyramid& iBrother)
|
||||||
{
|
{
|
||||||
_sigma = iSigma;
|
if (!_levels.empty()) {
|
||||||
BuildPyramid(level0,nbLevels);
|
for (vector<GrayImage*>::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) {
|
||||||
|
_levels.push_back(new GrayImage(**im));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother)
|
ImagePyramid::~ImagePyramid()
|
||||||
: ImagePyramid(iBrother){
|
{
|
||||||
_sigma = iBrother._sigma;
|
if (!_levels.empty()) {
|
||||||
}
|
for (vector<GrayImage*>::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) {
|
||||||
void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels){
|
delete (*im);
|
||||||
GrayImage *pLevel = new GrayImage(level0);
|
}
|
||||||
BuildPyramid(pLevel, nbLevels);
|
_levels.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels){
|
GrayImage * ImagePyramid::getLevel(int l)
|
||||||
GrayImage *pLevel = level0;
|
{
|
||||||
_levels.push_back(pLevel);
|
return _levels[l];
|
||||||
GaussianFilter gf(_sigma);
|
}
|
||||||
// build the nbLevels:
|
|
||||||
unsigned w = pLevel->width();
|
float ImagePyramid::pixel(int x, int y, int level)
|
||||||
unsigned h = pLevel->height();
|
{
|
||||||
if(nbLevels!=0)
|
GrayImage *img = _levels[level];
|
||||||
{
|
if (0 == level) {
|
||||||
for(unsigned i=0; i<nbLevels; ++i){ //soc
|
return img->pixel(x, y);
|
||||||
w = pLevel->width()>>1;
|
}
|
||||||
h = pLevel->height()>>1;
|
unsigned int i = 1 << level;
|
||||||
GrayImage *img = new GrayImage(w,h);
|
unsigned int sx = x >> level;
|
||||||
for(unsigned y=0; y<h; ++y){
|
unsigned int sy = y >> level;
|
||||||
for(unsigned x=0; x<w; ++x){
|
if (sx >= img->width())
|
||||||
float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
|
sx = img->width() - 1;
|
||||||
img->setPixel(x,y,v);
|
if (sy >= img->height())
|
||||||
}
|
sy = img->height() - 1;
|
||||||
}
|
|
||||||
_levels.push_back(img);
|
// bilinear interpolation
|
||||||
pLevel = img;
|
float A = i * (sx + 1) - x;
|
||||||
}
|
float B = x - i * sx;
|
||||||
}else{
|
float C = i * (sy + 1) - y;
|
||||||
while((w>1) && (h>1)){
|
float D = y - i * sy;
|
||||||
w = pLevel->width()>>1;
|
|
||||||
h = pLevel->height()>>1;
|
float P1(0), P2(0);
|
||||||
GrayImage *img = new GrayImage(w,h);
|
P1 = A * img->pixel(sx, sy);
|
||||||
for(unsigned y=0; y<h; ++y){
|
if (sx < img->width() - 1) {
|
||||||
for(unsigned x=0; x<w; ++x){
|
if (x % i != 0)
|
||||||
float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
|
P1 += B * img->pixel(sx + 1, sy);
|
||||||
img->setPixel(x,y,v);
|
}
|
||||||
}
|
else {
|
||||||
}
|
P1 += B * img->pixel(sx, sy);
|
||||||
_levels.push_back(img);
|
}
|
||||||
pLevel = img;
|
if (sy < img->height() - 1) {
|
||||||
}
|
if (y % i != 0) {
|
||||||
}
|
P2 = A * img->pixel(sx, sy + 1);
|
||||||
|
if (sx < img->width() - 1) {
|
||||||
|
if (x % i != 0)
|
||||||
|
P2 += B * img->pixel(sx + 1, sy + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
P2 += B * img->pixel(sx, sy + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
P2 = P1;
|
||||||
|
}
|
||||||
|
return (1.0f / (float)(1 << (2 * level))) * (C * P1 + D * P2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImagePyramid::width(int level)
|
||||||
|
{
|
||||||
|
return _levels[level]->width();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImagePyramid::height(int level)
|
||||||
|
{
|
||||||
|
return _levels[level]->height();
|
||||||
|
}
|
||||||
|
|
||||||
|
GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma) : ImagePyramid()
|
||||||
|
{
|
||||||
|
_sigma = iSigma;
|
||||||
|
BuildPyramid(level0, nbLevels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma) : ImagePyramid()
|
||||||
|
{
|
||||||
|
_sigma = iSigma;
|
||||||
|
BuildPyramid(level0, nbLevels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother) : ImagePyramid(iBrother)
|
||||||
|
{
|
||||||
|
_sigma = iBrother._sigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels)
|
||||||
|
{
|
||||||
|
GrayImage *pLevel = new GrayImage(level0);
|
||||||
|
BuildPyramid(pLevel, nbLevels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels)
|
||||||
|
{
|
||||||
|
GrayImage *pLevel = level0;
|
||||||
|
_levels.push_back(pLevel);
|
||||||
|
GaussianFilter gf(_sigma);
|
||||||
|
// build the nbLevels:
|
||||||
|
unsigned w = pLevel->width();
|
||||||
|
unsigned h = pLevel->height();
|
||||||
|
if (nbLevels != 0) {
|
||||||
|
for (unsigned int i = 0; i < nbLevels; ++i) { //soc
|
||||||
|
w = pLevel->width() >> 1;
|
||||||
|
h = pLevel->height() >> 1;
|
||||||
|
GrayImage *img = new GrayImage(w, h);
|
||||||
|
for (unsigned int y = 0; y < h; ++y) {
|
||||||
|
for (unsigned int x = 0; x < w; ++x) {
|
||||||
|
float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2 * x, 2 * y);
|
||||||
|
img->setPixel(x, y, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_levels.push_back(img);
|
||||||
|
pLevel = img;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while ((w > 1) && (h > 1)) {
|
||||||
|
w = pLevel->width() >> 1;
|
||||||
|
h = pLevel->height() >> 1;
|
||||||
|
GrayImage *img = new GrayImage(w, h);
|
||||||
|
for (unsigned int y = 0; y < h; ++y) {
|
||||||
|
for (unsigned int x = 0; x < w; ++x) {
|
||||||
|
float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2 * x, 2 * y);
|
||||||
|
img->setPixel(x, y, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_levels.push_back(img);
|
||||||
|
pLevel = img;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,92 +1,116 @@
|
|||||||
//
|
/*
|
||||||
// Filename : ImagePyramid.h
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
// Author(s) : Stephane Grabli
|
*
|
||||||
// Purpose : Class to represent a pyramid of images
|
* This program is free software; you can redistribute it and/or
|
||||||
// Date of creation : 25/12/2003
|
* 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.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __IMAGEPYRAMID_H__
|
||||||
|
#define __IMAGEPYRAMID_H__
|
||||||
|
|
||||||
//
|
/** \file blender/freestyle/intern/image/ImagePyramid.h
|
||||||
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
* \ingroup freestyle
|
||||||
// with this source distribution.
|
* \brief Class to represent a pyramid of images
|
||||||
//
|
* \author Stephane Grabli
|
||||||
// This program is free software; you can redistribute it and/or
|
* \date 25/12/2003
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef IMAGEPYRAMID_H
|
|
||||||
# define IMAGEPYRAMID_H
|
|
||||||
|
|
||||||
#include "../system/FreestyleConfig.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class GrayImage;
|
#include "../system/FreestyleConfig.h"
|
||||||
class LIB_IMAGE_EXPORT ImagePyramid{
|
|
||||||
protected:
|
|
||||||
std::vector<GrayImage*> _levels;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ImagePyramid(){}
|
|
||||||
ImagePyramid(const ImagePyramid& iBrother);
|
|
||||||
//ImagePyramid(const GrayImage& level0, unsigned nbLevels);
|
|
||||||
virtual ~ImagePyramid();
|
|
||||||
|
|
||||||
/*! Builds the pyramid.
|
class GrayImage;
|
||||||
* must be overloaded by inherited classes.
|
|
||||||
* if nbLevels==0, the complete pyramid is built
|
class LIB_IMAGE_EXPORT ImagePyramid
|
||||||
*/
|
{
|
||||||
virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0;
|
protected:
|
||||||
|
std::vector<GrayImage*> _levels;
|
||||||
/*! Builds a pyramid without copying the base level */
|
|
||||||
virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0;
|
public:
|
||||||
|
ImagePyramid(){}
|
||||||
virtual GrayImage * getLevel(int l);
|
ImagePyramid(const ImagePyramid& iBrother);
|
||||||
/*! Returns the pixel x,y using bilinear interpolation.
|
//ImagePyramid(const GrayImage& level0, unsigned nbLevels);
|
||||||
* \param x
|
virtual ~ImagePyramid();
|
||||||
* the abscissa specified in the finest level coordinate system
|
|
||||||
* \param y
|
/*! Builds the pyramid.
|
||||||
* the ordinate specified in the finest level coordinate system
|
* must be overloaded by inherited classes.
|
||||||
* \param level
|
* if nbLevels==0, the complete pyramid is built
|
||||||
* the level from which we want the pixel to be evaluated
|
*/
|
||||||
*/
|
virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0;
|
||||||
virtual float pixel(int x, int y, int level=0);
|
|
||||||
/*! Returns the width of the level-th level image */
|
/*! Builds a pyramid without copying the base level */
|
||||||
virtual int width(int level=0);
|
virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0;
|
||||||
/*! Returns the height of the level-th level image */
|
|
||||||
virtual int height(int level=0);
|
virtual GrayImage * getLevel(int l);
|
||||||
/*! Returns the number of levels in the pyramid */
|
/*! Returns the pixel x,y using bilinear interpolation.
|
||||||
inline int getNumberOfLevels() const { return _levels.size();}
|
* \param x
|
||||||
};
|
* the abscissa specified in the finest level coordinate system
|
||||||
|
* \param y
|
||||||
|
* the ordinate specified in the finest level coordinate system
|
||||||
|
* \param level
|
||||||
|
* the level from which we want the pixel to be evaluated
|
||||||
|
*/
|
||||||
|
virtual float pixel(int x, int y, int level=0);
|
||||||
|
|
||||||
|
/*! Returns the width of the level-th level image */
|
||||||
|
virtual int width(int level=0);
|
||||||
|
|
||||||
|
/*! Returns the height of the level-th level image */
|
||||||
|
virtual int height(int level=0);
|
||||||
|
|
||||||
|
/*! Returns the number of levels in the pyramid */
|
||||||
|
inline int getNumberOfLevels() const
|
||||||
|
{
|
||||||
|
return _levels.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid
|
class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
float _sigma;
|
float _sigma;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GaussianPyramid(float iSigma=1.f) : ImagePyramid() {_sigma=iSigma;}
|
GaussianPyramid(float iSigma=1.f) : ImagePyramid()
|
||||||
GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.f);
|
{
|
||||||
GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.f);
|
_sigma = iSigma;
|
||||||
GaussianPyramid(const GaussianPyramid& iBrother);
|
}
|
||||||
virtual ~GaussianPyramid(){}
|
|
||||||
|
|
||||||
virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels);
|
GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.0f);
|
||||||
virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels);
|
GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.0f);
|
||||||
/* accessors */
|
GaussianPyramid(const GaussianPyramid& iBrother);
|
||||||
inline float getSigma() const {return _sigma;}
|
virtual ~GaussianPyramid() {}
|
||||||
/* modifiers */
|
|
||||||
|
|
||||||
|
virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels);
|
||||||
|
virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels);
|
||||||
|
|
||||||
|
/* accessors */
|
||||||
|
inline float getSigma() const
|
||||||
|
{
|
||||||
|
return _sigma;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modifiers */
|
||||||
};
|
};
|
||||||
#endif // IMAGEPYRAMID_H
|
|
||||||
|
#endif // __IMAGEPYRAMID_H__
|
||||||
|
Loading…
Reference in New Issue
Block a user