simplifiedvoronoi.h revision 3b711c89939d4f10cb1b81da2726a49aa45a2ab7
/* This file is part of the libdepixelize project
Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
GNU Lesser General Public License Usage
under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version.
You should have received a copy of the GNU Lesser General Public License
along with this library. If not, see <http://www.gnu.org/licenses/>.
GNU General Public License Usage
Alternatively, this library may be used 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.
You should have received a copy of the GNU General Public License along with
this library. If not, see <http://www.gnu.org/licenses/>.
This library 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
Lesser General Public License for more details.
*/
#include "pixelgraph.h"
#include "colorspace.h"
#include "point.h"
#include "branchless.h"
{
/**
* The "smooth" attribute of each vertex is only accurate if edge is
* visible. This decision was made because invisible edges will disappear
* during polygon-union, the next phase of Kopf-Lischinski.
*/
struct Cell
{
// There may not exist more than 8 vertices per cell and a
// "small vector optimization" could improve the performance
// by avoiding memory fragmentation. Serious testing is needed.
// The vertices are filled in clockwise order
};
/*
It will work correctly if no crossing-edges are present.
*/
// Iterators
{
}
const_iterator begin() const
{
}
{
}
const_iterator end() const
{
}
{
}
const_reverse_iterator rbegin() const
{
}
{
}
const_reverse_iterator rend() const
{
}
{
}
int width() const
{
return _width;
}
int height() const
{
return _height;
}
#ifdef LIBDEPIXELIZE_VERY_TYPE_SAFE
#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
/**
* Output is translated by -.5 in each axis. This function fixes this error.
*/
{
}
/**
* Output is translated by -.5 in each axis. This function fixes this error.
*/
{
}
/*
* The memory layout assumed goes like this (with a_it being the current
* iterated element):
*
* (a_it) | (b_it)
* -------+-------
* (c_it) | (d_it)
*
* If you want to use it with another directions (topleft, topright, ...)
* **DO NOT** invert x or y axis, because the insertion order will go mad.
*
* The idea behind this abstraction is to rotate the iterators, then the
* insertion order will be preserved.
*
* The initial value of all nodes that will be inserted is {x, y}. All
* changes to this node **MUST** occur through \p transform or _adjust.
*
* Some maintainers may like this function because they will handle a
* code base 4 times smaller and bugs will be MUCH MUCH difficult to hide.
*
* Some maintainers may go mad because the level extra level of
* abstraction.
*
* "All problems in computer science can be solved by another level of
* indirection, except for the problem of too many layers of indirection."
* -- David J. Wheeler
*/
#ifndef LIBDEPIXELIZE_VERY_TYPE_SAFE
#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
int _width;
int _height;
};
{
return;
/*
* The insertion order of cells is not a big deal. Here I just follow
* the order of PixelGraph arrangement.
*/
// ...the "center" cells first...
for ( int k = 0 ; k != 4 ; ++k )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
// After the previous loop, 'it' is pointing to the last cell from
// the row.
// Go south, then first node in the row (increment 'it' by 1)
// Go to the second node in the line (increment 'it' by 1)
graph_it += 2;
cells_it += 2;
}
}
// ...then the "top" cells...
if ( _width > 2 ) {
for ( int j = 0 ; j != 4 ; ++j )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
}
// ...then the "bottom" cells...
// Node *it = &((*this)[1][_height - 1]);
for ( int j = 0 ; j != 4 ; ++j )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
}
// ...then the "left" cells...
if ( _height > 2 ) {
for ( int j = 0 ; j != 4 ; ++j )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
}
// ...then the "right" cells...
for ( int j = 0 ; j != 4 ; ++j )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
}
// ...and the 4 corner nodes
// top-left
{
for ( int i = 0 ; i != 4 ; ++i )
// Top-left
// Top-right
// Bottom-right
else
// Bottom-left
}
// top-right
if ( _width > 1 ) {
for ( int i = 0 ; i != 4 ; ++i )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
if ( _height > 1 )
else
}
// bottom-left
if ( _height > 1 ) {
for ( int i = 0 ; i != 4 ; ++i )
// Top-left
// Top-right
if ( _width > 1)
else
// Bottom-right
// Bottom-left
}
// bottom-right
for ( int i = 0 ; i != 4 ; ++i )
// Top-left
// Top-right
// Bottom-right
// Bottom-left
}
}
int x, int y)
{
cells_it, x, y,
}
int x, int y)
{
cells_it, x, y,
}
int x, int y)
{
cells_it, x, y,
}
int x, int y)
{
cells_it, x, y,
}
{
p.x -= dx;
p.y -= dy;
}
{
p.x += dy;
p.y -= dx;
}
{
p.x += dx;
p.y += dy;
}
{
p.x -= dy;
p.y += dx;
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
bool SimplifiedVoronoi<T, adjust_splines>
{
}
#ifndef LIBDEPIXELIZE_VERY_TYPE_SAFE
#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
void
{
/*
* The insertion order of points within the cell is very important. You must
* follow current practice: Clockwise order.
*/
if ( bottomright(a_it) ) {
// this and bottom-right are connected
bool smooth[2] = {
};
{
}
{
}
if ( !smooth[0] && adjust_splines ) {
{
- ( 0.1875
// y
- ( 0.5625
}
{
- ( 0.0625
// y
- ( 0.1875
}
{
0.1875
// y
0.0625
}
{
0.0625
// y
- ( 0.0625
* 0.03125 ));
}
}
{
- ( 0.0625
* 0.03125 ),
// y
0.0625
}
{
0.0625
// y
0.1875
}
{
- ( 0.1875
* 0.0625 ),
// y
- ( 0.0625
* 0.0625 ));
}
{
- ( 0.5625
* 0.1875 ),
// y
- ( 0.1875
* 0.1875 ));
}
}
} else if ( bottomleft(b_it) ) {
// right and bottom are connected
} else {
// Connections don't affect the shape of this squared-like
// pixel
// compute smoothness
// this and right are connected
// bottom and bottom-right are disconnected
+ foreign_is_contour == 2 ) {
if ( another_is_contour ) {
{
T amount = 0.125
* 0.03125 );
}
{
}
{
- amount);
}
{
- amount);
}
} else if ( twin_is_contour ) {
T amount = 0.125
* 0.03125 );
}
// This is the same code of the if ( special )
// I REALLY NEED lambdas to improve this code without
// creating yet another interface that takes a million
// of function parameters and keep code locality
{
T amount = 0.03125;
// y
- amount
}
{
T amount = 0.0625;
0.25 - amount
// y
- amount
}
{
T amount = 0.0625;
- ( 0.25 - amount
// y
- amount
}
{
T amount = 0.1875;
- ( 0.75 - amount
// y
- amount
}
}
} else {
// {this, right} is the pair with the angle
// closest to 180 degrees
}
} else {
// there might be 2-color, then vertex.smooth = true
// or it might be 1-color and doesn't matter,
// because the current node will disappear
}
// this and bottom are connected
// right and bottom-right are disconnected
+ foreign_is_contour == 2 ) {
if ( another_is_contour ) {
{
- ( 0.75 - amount ));
}
{
- ( 0.25 - amount ));
}
{
}
{
T amount = 0.125
* 0.03125;
}
} else if ( twin_is_contour ) {
T amount = 0.125
* 0.03125 );
}
// This is the same code of the if ( special )
// I REALLY NEED lambdas to improve this code without
// creating yet another interface that takes a million
// of function parameters and keep code locality
{
T amount = 0.1875;
// y
- ( 0.75
* amount ));
}
{
T amount = 0.0625;
// y
- ( 0.25
* amount ));
}
{
T amount = 0.0625;
// y
0.25 - amount
}
{
* 0.03125,
// y
* 0.03125);
}
}
} else {
// {this, bottom} is the pair with the angle
// closest to 180 degrees
}
} else {
// there might be 2-color, then vertex.smooth = true
// or it might be 1-color and doesn't matter,
// because the current node will disappear
}
// right and bottom-right are connected
bool special = false;
// the neighbor similar in 90° feature
+ foreign_is_contour == 2 ) {
if ( similar_neighbor_is_contour ) {
{
T amount = 0.125
* 0.03125;
}
{
}
{
}
{
}
} else {
special = true;
}
}
} else {
// {right, bottom-right} is the pair with the
// angle closest to 180 degrees
special = true;
}
if ( special ) {
{
T amount = 0.1875;
// y
- ( 0.75
* amount ));
}
{
T amount = 0.0625;
// y
- ( 0.25
* amount ));
}
{
T amount = 0.0625;
// y
0.25 - amount
}
{
* 0.03125,
// y
* 0.03125);
}
}
// bottom and bottom-right are connected
bool special = false;
// the neighbor similar in 90° feature
+ foreign_is_contour == 2 ) {
if ( similar_neighbor_is_contour ) {
{
}
{
}
{
}
{
T amount = 0.125
}
} else {
special = true;
}
}
} else {
// {bottom, bottom-right} is the pair with the
// angle closest to 180 degrees
special = true;
}
if ( special ) {
{
T amount = 0.03125;
// y
- amount
}
{
T amount = 0.0625;
0.25 - amount
// y
- amount
}
{
T amount = 0.0625;
- ( 0.25 - amount
// y
- amount
}
{
T amount = 0.1875;
- ( 0.75 - amount
// y
- amount
}
}
} else {
// there is a 4-color pattern, where the current node
// won't be smooth
}
}
}
} // namespace Tracer
#endif // LIBDEPIXELIZE_TRACER_SIMPLIFIEDVORONOI_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :