ShapeMisc.cpp revision e3d8c95258fb754412be519fbccceee487bccff9
/*
* nlivarot
*
* Created by fred on Sun Jul 20 2003.
*
*/
#include <libnr/nr-point-fns.h>
#include "livarot/path-description.h"
#include <glib.h>
/*
* polygon offset and polyline to path reassembling (when using back data)
*/
// until i find something better
#define MiscNormalize(v) {\
if ( _l < 0.0000001 ) { \
v[0]=v[1]=0; \
} else { \
v/=_l; \
}\
}
// extracting the contour of an uncrossed polygon: a mere depth first search
// more precisely that's extracting an eulerian path from a graph, but here we want to split
// the polygon into contours and avoid holes. so we take a "next counter-clockwise edge first" approach
// (make a checkboard and extract its contours to see the difference)
void
{
return;
// prepare
MakePointData (true);
MakeEdgeData (true);
MakeSweepDestData (true);
for (int i = 0; i < numberOfPoints(); i++)
{
}
for (int i = 0; i < numberOfEdges(); i++)
{
}
// sort edge clockwise, with the closest after midnight being first in the doubly-linked list
// that's vital to the algorithm...
SortEdges ();
// depth-first search implies: we make a stack of edges traversed.
// precParc: previous in the stack
// suivParc: next in the stack
for (int i = 0; i < numberOfEdges(); i++)
{
}
int searchInd = 0;
int lastPtUsed = 0;
do
{
// first get a starting point, and a starting edge
// -> take the upper left point, and take its first edge
// points traversed have swdData[].misc != 0, so it's easy
int startBord = -1;
{
int fi = 0;
{
break;
}
if (fi < numberOfPoints())
{
if (bestB >= 0)
{
}
}
}
// and walk the graph, doing contours when needed
if (startBord >= 0)
{
// parcours en profondeur pour mettre les leF et riF a leurs valeurs
// printf("part de %d\n",startBord);
bool back = false;
do
{
// printf("de curBord= %d au point %i -> ",curBord,cPt);
// get next edge
do
{
{
// cul-de-sac
nb = -1;
break;
}
break;
}
{
// no next edge: end of this contour, we get back
if (back == false)
back = true;
// retour en arriere
// printf("retour vers %d\n",curBord);
if (curBord < 0)
break;
}
else
{
// new edge, maybe for a new contour
if (back)
{
// we were backtracking, so if we have a new edge, that means we're creating a new contour
back = false;
}
// printf("suite %d\n",curBord);
{
// add that edge
}
}
}
while (1 /*swdData[curBord].precParc >= 0 */ );
// fin du cas non-oriente
}
}
while (lastPtUsed < numberOfPoints());
MakePointData (false);
MakeEdgeData (false);
MakeSweepDestData (false);
}
// same as before, but each time we have a contour, try to reassemble the segments on it to make chunks of
// the original(s) path(s)
// originals are in the orig array, whose size is nbP
void
{
return;
// if (Eulerian (true) == false)
// return;
if (_has_back_data == false)
{
return;
}
MakePointData (true);
MakeEdgeData (true);
MakeSweepDestData (true);
for (int i = 0; i < numberOfPoints(); i++)
{
}
for (int i = 0; i < numberOfEdges(); i++)
{
}
SortEdges ();
for (int i = 0; i < numberOfEdges(); i++)
{
}
int searchInd = 0;
int lastPtUsed = 0;
do
{
int startBord = -1;
{
int fi = 0;
{
break;
}
if (fi < numberOfPoints())
{
if (bestB >= 0)
{
}
}
}
if (startBord >= 0)
{
// parcours en profondeur pour mettre les leF et riF a leurs valeurs
//printf("part de %d\n",startBord);
bool back = false;
do
{
//printf("de curBord= %d au point %i -> ",curBord,cPt);
do
{
{
// cul-de-sac
nb = -1;
break;
}
break;
}
{
if (back == false)
{
{
// probleme -> on vire le moveto
// dest->descr_nb--;
}
else
{
}
// dest->Close();
}
back = true;
// retour en arriere
//printf("retour vers %d\n",curBord);
if (curBord < 0)
break;
}
else
{
if (back)
{
back = false;
} else {
//printf("contour %i ",curStartPt);
}
}
//printf("suite %d\n",curBord);
}
}
while (1 /*swdData[curBord].precParc >= 0 */ );
// fin du cas non-oriente
}
}
while (lastPtUsed < numberOfPoints());
MakePointData (false);
MakeEdgeData (false);
MakeSweepDestData (false);
}
void
Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,int &nbNest,int *&nesting,int *&contStart,bool splitWhenForced)
{
nbNest=0;
return;
// if (Eulerian (true) == false)
// return;
if (_has_back_data == false)
{
return;
}
// MakePointData (true);
MakeEdgeData (true);
MakeSweepDestData (true);
for (int i = 0; i < numberOfPoints(); i++)
{
}
for (int i = 0; i < numberOfEdges(); i++)
{
}
SortEdges ();
for (int i = 0; i < numberOfEdges(); i++)
{
}
int searchInd = 0;
int lastPtUsed = 0;
do
{
int dadContour=-1;
int startBord = -1;
{
int fi = 0;
{
break;
}
{
dadContour=-1;
} else {
}
}
if (fi < numberOfPoints())
{
if (bestB >= 0)
{
}
}
}
if (startBord >= 0)
{
// parcours en profondeur pour mettre les leF et riF a leurs valeurs
//printf("part de %d\n",startBord);
bool back = false;
do
{
//printf("de curBord= %d au point %i -> ",curBord,cPt);
do
{
{
// cul-de-sac
nb = -1;
break;
}
break;
}
{
if (back == false)
{
{
// probleme -> on vire le moveto
// dest->descr_nb--;
}
else
{
bool escapePath=false;
escapePath=true;
break;
}
}
if ( escapePath ) {
} else {
}
}
// dest->Close();
}
back = true;
// retour en arriere
//printf("retour vers %d\n",curBord);
if (curBord < 0)
break;
}
else
{
if (back)
{
back = false;
} else {
//printf("contour %i ",curStartPt);
bool escapePath=false;
escapePath=true;
break;
}
}
if ( escapePath ) {
} else {
}
}
}
//printf("suite %d\n",curBord);
}
}
while (1 /*swdData[curBord].precParc >= 0 */ );
// fin du cas non-oriente
}
}
while (lastPtUsed < numberOfPoints());
MakePointData (false);
MakeEdgeData (false);
MakeSweepDestData (false);
}
int
Shape::MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc)
{
Reset (0, 0);
bool done_something = false;
double power;
if (mode == tweak_mode_push) {
} else {
}
if (power == 0)
{
if (numberOfPoints() > maxPt)
{
maxPt = numberOfPoints();
if (_has_points_data) {
_point_data_initialised = false;
_bbox_up_to_date = false;
}
}
if (numberOfEdges() > maxAr)
{
maxAr = numberOfEdges();
if (_has_edges_data)
if (_has_sweep_src_data)
if (_has_sweep_dest_data)
if (_has_raster_data)
if (_has_back_data)
}
return 0;
}
return shape_input_err;
a->SortEdges ();
a->MakeSweepDestData (true);
a->MakeSweepSrcData (true);
for (int i = 0; i < a->numberOfEdges(); i++)
{
if (power <= 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) {
} else {
}
MiscNormalize (stD);
MiscNormalize (enD);
MiscNormalize (seD);
if (mode == tweak_mode_push) {
power = 1;
}
double this_power;
if (do_profile && i2doc) {
double alpha = 1;
double x;
if (mode == tweak_mode_repel) {
} else {
}
if (x > 1) {
this_power = 0;
} else if (x <= 0) {
if (mode == tweak_mode_repel) {
this_power = 0;
} else {
this_power = power;
}
} else {
}
} else {
if (mode == tweak_mode_repel) {
this_power = 0;
} else {
this_power = power;
}
}
if (this_power != 0)
done_something = true;
if (mode == tweak_mode_push) {
} else if (mode == tweak_mode_repel) {
} else if (mode == tweak_mode_roughen) {
}
int usePathID=-1;
int usePieceID=0;
double useT=0.0;
if ( a->_has_back_data ) {
if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID
} else {
usePieceID=0;
useT=0;
}
}
} else {
if (power > 0) {
} else {
}
}
}
{
for (int i = 0; i < numberOfEdges(); i++)
Inverse (i);
}
if ( _has_back_data ) {
for (int i = 0; i < a->numberOfEdges(); i++)
{
}
} else {
for (int i = 0; i < a->numberOfEdges(); i++)
{
}
}
a->MakeSweepSrcData (false);
a->MakeSweepDestData (false);
return (done_something? 0 : shape_nothing_to_do);
}
// offsets
// take each edge, offset it, and make joins with previous at edge start and next at edge end (previous and
// next being with respect to the clockwise order)
// you gotta be very careful with the join, as anything but the right one will fuck everything up
// see PathStroke.cpp for the "right" joins
int
Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, NR::Matrix *i2doc)
{
Reset (0, 0);
bool done_something = false;
if (dec == 0)
{
if (numberOfPoints() > maxPt)
{
maxPt = numberOfPoints();
if (_has_points_data) {
_point_data_initialised = false;
_bbox_up_to_date = false;
}
}
if (numberOfEdges() > maxAr)
{
maxAr = numberOfEdges();
if (_has_edges_data)
if (_has_sweep_src_data)
if (_has_sweep_dest_data)
if (_has_raster_data)
if (_has_back_data)
}
return 0;
}
return shape_input_err;
a->SortEdges ();
a->MakeSweepDestData (true);
a->MakeSweepSrcData (true);
for (int i = 0; i < a->numberOfEdges(); i++)
{
// int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/;
if (dec > 0)
{
}
else
{
}
MiscNormalize (stD);
MiscNormalize (enD);
MiscNormalize (seD);
double this_dec;
if (do_profile && i2doc) {
double alpha = 1;
if (x > 1) {
this_dec = 0;
} else if (x <= 0) {
} else {
}
} else {
}
if (this_dec != 0)
done_something = true;
int usePathID=-1;
int usePieceID=0;
double useT=0.0;
if ( a->_has_back_data ) {
if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID
} else {
usePieceID=0;
useT=0;
}
}
if (dec > 0)
{
}
else
{
}
}
if (dec < 0)
{
for (int i = 0; i < numberOfEdges(); i++)
Inverse (i);
}
if ( _has_back_data ) {
for (int i = 0; i < a->numberOfEdges(); i++)
{
}
} else {
for (int i = 0; i < a->numberOfEdges(); i++)
{
}
}
a->MakeSweepSrcData (false);
a->MakeSweepDestData (false);
return (done_something? 0 : shape_nothing_to_do);
}
// we found a contour, now reassemble the edges on it, instead of dumping them in the Path "dest" as a
// polyline. since it was a DFS, the precParc and suivParc make a nice doubly-linked list of the edges in
// the contour. the first and last edges of the contour are startBord and curBord
void
Shape::AddContour (Path * dest, int nbP, Path * *orig, int startBord, int curBord, bool splitWhenForced)
{
{
}
while (bord >= 0)
{
{
// segment batard
}
else
{
{
// segment batard
}
else
{
|| nType == descr_forced)
{
// devrait pas arriver
}
else if (nType == descr_lineto)
{
}
else if (nType == descr_arcto)
{
}
else if (nType == descr_cubicto)
{
}
else if (nType == descr_bezierto)
{
{
}
else
{
}
}
else if (nType == descr_interm_bezier)
{
}
else
{
// devrait pas arriver non plus
}
dest->ForcePoint ();
} else if ( bord >= 0 && getPoint(getEdge(bord).st).oldDegree > 2 && getPoint(getEdge(bord).st).totalDegree() == 2) {
if ( splitWhenForced ) {
// pour les coupures
dest->ForcePoint ();
} else {
if ( _has_back_data ) {
}
if ( ebData[prevEdge].pieceID == ebData[nextEdge].pieceID && ebData[prevEdge].pathID == ebData[nextEdge].pathID ) {
} else {
dest->ForcePoint ();
}
} else {
dest->ForcePoint ();
}
} else {
dest->ForcePoint ();
}
}
}
}
}
}
}
int
{
while (bord >= 0)
{
{
break;
}
{
break;
}
else
{
break;
}
}
{
}
return bord;
}
int
{
// double px=pts[getEdge(bord).st].x,py=pts[getEdge(bord).st].y;
while (bord >= 0)
{
{
break;
}
{
{
break;
}
}
else
{
break;
}
}
Path::ArcAngles (from->PrevPoint (nPiece - 1), nData->p,nData->rx,nData->ry,nData->angle, nLarge, nClockwise, sang, eang);
if (nClockwise)
{
}
else
{
}
nClockwise = !nClockwise;
if (ndelta < 0)
nLarge = true;
else
nLarge = false;
/* if ( delta < 0 ) delta=-delta;
if ( ndelta < 0 ) ndelta=-ndelta;
if ( ( delta < M_PI && ndelta < M_PI ) || ( delta >= M_PI && ndelta >= M_PI ) ) {
if ( ts < te ) {
} else {
nClockwise=!(nClockwise);
}
} else {
// nLarge=!(nLarge);
nLarge=false; // c'est un sous-segment -> l'arc ne peut que etre plus petit
if ( ts < te ) {
} else {
nClockwise=!(nClockwise);
}
}*/
{
}
return bord;
}
int
{
while (bord >= 0)
{
{
break;
}
{
{
break;
}
}
else
{
break;
}
}
{
}
{
}
return bord;
}
int
{
int typ;
if (typ == descr_bezierto)
{
}
else
{
int n = nPiece - 1;
while (n > 0)
{
if (typ == descr_bezierto)
{
inBezier = n;
break;
}
n--;
}
if (inBezier < 0)
{
return bord;
}
}
while (bord >= 0)
{
{
break;
}
{
break;
break;
break;
break;
}
else
{
break;
}
}
{
}
{
if (ts < 0.0001)
{
if (te > 0.9999)
{
{
}
dest->EndBezierTo ();
}
else
{
{
}
{
}
dest->EndBezierTo ();
}
}
else
{
if (te > 0.9999)
{
{
}
{
}
dest->EndBezierTo ();
}
else
{
{
}
{
}
{
}
dest->EndBezierTo ();
}
}
}
else
{
if (ts > 0.9999)
{
if (te < 0.0001)
{
{
}
dest->EndBezierTo ();
}
else
{
{
}
{
}
dest->EndBezierTo ();
}
}
else
{
if (te < 0.0001)
{
{
}
{
}
dest->EndBezierTo ();
}
else
{
{
}
{
}
{
}
dest->EndBezierTo ();
}
}
}
return bord;
}
void
{
if (p == inBezier)
{
// premier bout
if (nbInterm <= 1)
{
// seul bout de la spline
PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[inBezier+1]);
}
else
{
// premier bout d'une spline qui en contient plusieurs
PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[inBezier+1]);
}
}
{
// dernier bout
// si nbInterm == 1, le cas a deja ete traite
// donc dernier bout d'une spline qui en contient plusieurs
PathDescrIntermBezierTo* nData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[inBezier+nbInterm]);
}
else
{
// la spline contient forcément plusieurs bouts, et ce n'est ni le premier ni le dernier
}
{
}
{
dest->EndBezierTo ();
}
}