summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5675f17)
raw | patch | inline | side by side (parent: 5675f17)
author | johanengelen <johanengelen@users.sourceforge.net> | |
Mon, 12 Nov 2007 19:47:07 +0000 (19:47 +0000) | ||
committer | johanengelen <johanengelen@users.sourceforge.net> | |
Mon, 12 Nov 2007 19:47:07 +0000 (19:47 +0000) |
19 files changed:
index 694760d5abcdc9b000f96c8a1fa4954d7434bc1f..0d84ee7f33ed3ce8a5ca8124bba015b3d5264ba5 100644 (file)
#include "basic-intersection.h"
+unsigned intersect_steps = 0;
+
using std::vector;
namespace Geom {
OldBezier b, double u0, double u1, int depthb,
std::vector<std::pair<double, double> > ¶meters)
{
+ intersect_steps ++;
if( deptha > 0 )
{
OldBezier A[2];
diff --git a/src/2geom/bezier.h b/src/2geom/bezier.h
index e0d274e3bec628698423376cacd055a3c627dcb4..16b4d7446d1b942e1df3e827d9b406d2a580b6a7 100644 (file)
--- a/src/2geom/bezier.h
+++ b/src/2geom/bezier.h
- /*
+/*
* bezier.h
*
* Copyright 2007 MenTaLguY <mental@rydia.net>
diff --git a/src/2geom/concepts.h b/src/2geom/concepts.h
index bd020ab6625d9fab3ae7bcc7fe83cc4a120dc47e..92ec66c7f52d7f16d8de826214edc537cc845dd3 100644 (file)
--- a/src/2geom/concepts.h
+++ b/src/2geom/concepts.h
double tol;
bool res;
void constraints() {
- res = near(a, b, tol);
+ res = are_near(a, b, tol);
}
};
diff --git a/src/2geom/coord.h b/src/2geom/coord.h
index 34a585bf9fe43ac44a799b59b32ce7c974777c66..e9abfc927d84a8d8c5ab06865b8dec14a96cfd31 100644 (file)
--- a/src/2geom/coord.h
+++ b/src/2geom/coord.h
const Coord EPSILON = 1e-5; //1e-18;
-
-#ifdef near
-#define lib2geom_near_save near
-#undef near
-#endif
-
//IMPL: NearConcept
-inline bool near(Coord a, Coord b, double eps=EPSILON) { return fabs(a-b) <= eps; }
-
-#ifdef lib2geom_near_save
-#define near lib2geom_near_save
-#undef lib2geom_near_save
-#endif
+inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return fabs(a-b) <= eps; }
} /* namespace Geom */
diff --git a/src/2geom/crossing.cpp b/src/2geom/crossing.cpp
index 8f29635e82c5095b3fc4230d596752ed2b357eef..a8add187766247c227b775ee87a98a5c2c33f95c 100644 (file)
--- a/src/2geom/crossing.cpp
+++ b/src/2geom/crossing.cpp
#include "crossing.h"
+#include "path.h"
namespace Geom {
+//bool edge_involved_in(Edge const &e, Crossing const &c) {
+// if(e.path == c.a) {
+// if(e.time == c.ta) return true;
+// } else if(e.path == c.b) {
+// if(e.time == c.tb) return true;
+// }
+// return false;
+//}
+
+double wrap_dist(double from, double to, double size, bool rev) {
+ if(rev) {
+ if(to > from) {
+ return from + (size - to);
+ } else {
+ return from - to;
+ }
+ } else {
+ if(to < from) {
+ return to + (size - from);
+ } else {
+ return to - from;
+ }
+ }
+}
+
+CrossingGraph create_crossing_graph(std::vector<Path> const &p, Crossings const &crs) {
+ std::vector<Point> locs;
+ CrossingGraph ret;
+ for(unsigned i = 0; i < crs.size(); i++) {
+ Point pnt = p[crs[i].a].pointAt(crs[i].ta);
+ unsigned j = 0;
+ for(; j < locs.size(); j++) {
+ if(are_near(pnt, locs[j])) break;
+ }
+ if(j == locs.size()) {
+ ret.push_back(CrossingNode());
+ locs.push_back(pnt);
+ }
+ ret[j].add_edge(Edge(crs[i].a, crs[i].ta, false));
+ ret[j].add_edge(Edge(crs[i].a, crs[i].ta, true));
+ ret[j].add_edge(Edge(crs[i].b, crs[i].tb, false));
+ ret[j].add_edge(Edge(crs[i].b, crs[i].tb, true));
+ }
+
+ for(unsigned i = 0; i < ret.size(); i++) {
+ for(unsigned j = 0; j < ret[i].edges.size(); j++) {
+ unsigned pth = ret[i].edges[j].path;
+ double t = ret[i].edges[j].time;
+ bool rev = ret[i].edges[j].reverse;
+ double size = p[pth].size()+1;
+ double best = size;
+ unsigned bix = ret.size();
+ for(unsigned k = 0; k < ret.size(); k++) {
+ for(unsigned l = 0; l < ret[k].edges.size(); l++) {
+ if(ret[i].edges[j].path == ret[k].edges[l].path && (k != i || l != j)) {
+ double d = wrap_dist(t, ret[i].edges[j].time, size, rev);
+ if(d < best) {
+ best = d;
+ bix = k;
+ }
+ }
+ }
+ }
+ if(bix == ret.size()) {
+ std::cout << "couldn't find an adequate next-crossing node";
+ bix = i;
+ }
+ ret[i].edges[j].node = bix;
+ }
+ }
+
+ return ret;
+
+ /* Various incoherent code bits
+ // list of sets of edges, each set corresponding to those emanating from the path
+ CrossingGraph ret;
+ std::vector<Edge> edges(crs.size());
+
+ std::vector<std::vector<bool> > used;
+ unsigned i, j;
+ do {
+ first_false(used, i, j);
+ CrossingNode cn;
+ do {
+ unsigned di = i, dj = j;
+ crossing_dual(di, dj);
+ if(!used[di,dj]) {
+
+ }
+ }
+
+ } while(!used[i,j])
+
+
+ for(unsigned j = 0; j < crs[i].size(); j++) {
+
+ edges.push_back(Edge(i, crs[i][j].getOtherTime(i), false));
+ edges.push_back(Edge(i, crs[i][j].getOtherTime(i), true));
+ }
+ std::sort(edges.begin(), edges.end(), TimeOrder());
+ for(unsigned j = 0; j < edges.size(); ) {
+ CrossingNode cn;
+ double t = edges[j].time;
+ while(j < edges.size() && are_near(edges[j].time, t)) {
+ cn.edges.push_back(edges[j]);
+ }
+ }
+*/
+}
+
void merge_crossings(Crossings &a, Crossings &b, unsigned i) {
Crossings n;
sort_crossings(b, i);
const Crossing cur = *i;
Eraser<Crossings> next(i);
next++;
- if(near(cur, *next)) {
+ if(are_near(cur, *next)) {
cr_b.erase(std::find(cr_b.begin(), cr_b.end(), cur));
for(i = next; near(*i, cur); i++) {
cr_b.erase(std::find(cr_b.begin(), cr_b.end(), *i));
diff --git a/src/2geom/crossing.h b/src/2geom/crossing.h
index 79912f024dd558b2b376e6316d7d9ad351abd315..8e3a45142b9b86054c4dd06b6606f5985bf02b47 100644 (file)
--- a/src/2geom/crossing.h
+++ b/src/2geom/crossing.h
#define __GEOM_CROSSING_H
#include <vector>
-#include <set>
#include "rect.h"
#include "sweep.h"
+
namespace Geom {
+//Crossing between one or two paths
struct Crossing {
bool dir; //True: along a, a becomes outside.
double ta, tb; //time on a and b of crossing
Crossing(double t_a, double t_b, unsigned ai, unsigned bi, bool direction) : dir(direction), ta(t_a), tb(t_b), a(ai), b(bi) {}
bool operator==(const Crossing & other) const { return a == other.a && b == other.b && dir == other.dir && ta == other.ta && tb == other.tb; }
bool operator!=(const Crossing & other) const { return !(*this == other); }
+
unsigned getOther(unsigned cur) const { return a == cur ? b : a; }
double getTime(unsigned cur) const { return a == cur ? ta : tb; }
double getOtherTime(unsigned cur) const { return a == cur ? tb : ta; }
};
-/*inline bool near(Crossing a, Crossing b) {
- return near(a.ta, b.ta) && near(a.tb, b.tb);
+struct Edge {
+ unsigned node, path;
+ double time;
+ bool reverse;
+ Edge(unsigned p, double t, bool r) : path(p), time(t), reverse(r) {}
+ bool operator==(Edge const &other) const { return other.path == path && other.time == time && other.reverse == reverse; }
+};
+
+struct CrossingNode {
+ std::vector<Edge> edges;
+ CrossingNode() : edges(std::vector<Edge>()) {}
+ explicit CrossingNode(std::vector<Edge> es) : edges(es) {}
+ void add_edge(Edge const &e) {
+ if(std::find(edges.begin(), edges.end(), e) == edges.end())
+ edges.push_back(e);
+ }
+ double time_on(unsigned p) {
+ for(unsigned i = 0; i < edges.size(); i++)
+ if(edges[i].path == p) return edges[i].time;
+ std::cout << "CrossingNode time_on failed\n";
+ return 0;
+ }
+};
+
+typedef std::vector<Crossing> Crossings;
+
+typedef std::vector<CrossingNode> CrossingGraph;
+
+struct TimeOrder {
+ bool operator()(Edge a, Edge b) {
+ return a.time < b.time;
+ }
+};
+
+class Path;
+CrossingGraph create_crossing_graph(std::vector<Path> const &p, Crossings const &crs);
+
+/*inline bool are_near(Crossing a, Crossing b) {
+ return are_near(a.ta, b.ta) && are_near(a.tb, b.tb);
}
-struct NearF { bool operator()(Crossing a, Crossing b) { return near(a, b); } };
+struct NearF { bool operator()(Crossing a, Crossing b) { return are_near(a, b); } };
*/
struct CrossingOrder {
}
};
-typedef std::vector<Crossing> Crossings;
+
typedef std::vector<Crossings> CrossingSet;
template<typename C>
diff --git a/src/2geom/d2.h b/src/2geom/d2.h
index 3a9e14bda8739cd614658123f672051534a6c55a..47355eb6028625904bd181a19df8f0e9bb1f59ba 100644 (file)
--- a/src/2geom/d2.h
+++ b/src/2geom/d2.h
//IMPL: NearConcept
template <typename T>
inline bool
-near(D2<T> const &a, D2<T> const &b, double tol) {
+are_near(D2<T> const &a, D2<T> const &b, double tol) {
boost::function_requires<NearConcept<T> >();
- return near(a[0], b[0]) && near(a[1], b[1]);
+ return are_near(a[0], b[0]) && are_near(a[1], b[1]);
}
//IMPL: AddableConcept
diff --git a/src/2geom/geom.cpp b/src/2geom/geom.cpp
index e93247899f1b6e3ba071e721b1a60f30b1f1a32b..8845cefa89fe443ae321fe022a7ee4be8c22c574 100644 (file)
--- a/src/2geom/geom.cpp
+++ b/src/2geom/geom.cpp
#include "point.h"
namespace Geom {
+
/**
* Finds the intersection of the two (infinite) lines
* defined by the points p such that dot(n0, p) == d0 and dot(n1, p) == d1.
diff --git a/src/2geom/geom.h b/src/2geom/geom.h
index c24acea63ccb678464f248248364000e78c1d7fe..f25e43c4922e3cec0aee7b13e846db66ec71066c 100644 (file)
--- a/src/2geom/geom.h
+++ b/src/2geom/geom.h
* the specific language governing rights and limitations.
*
*/
-#ifndef SEEN_2Geom_GEOM_H
-#define SEEN_2Geom_GEOM_H
+#ifndef LIB2GEOM_SEEN_GEOM_H
+#define LIB2GEOM_SEEN_GEOM_H
//TODO: move somewhere else
diff --git a/src/2geom/matrix.cpp b/src/2geom/matrix.cpp
index c0e64ad33a0525f31b923faa6ef216f4252b8886..a6e3025d9ce2f0be6219f0da974e259de3c9cef7 100644 (file)
--- a/src/2geom/matrix.cpp
+++ b/src/2geom/matrix.cpp
void Matrix::setExpansionX(double val) {
double exp_x = expansionX();
- if(!near(exp_x, 0.0)) { //TODO: best way to deal with it is to skip op?
+ if(!are_near(exp_x, 0.0)) { //TODO: best way to deal with it is to skip op?
double coef = val / expansionX();
for(unsigned i=0;i<2;i++) _c[i] *= coef;
}
void Matrix::setExpansionY(double val) {
double exp_y = expansionY();
- if(!near(exp_y, 0.0)) { //TODO: best way to deal with it is to skip op?
+ if(!are_near(exp_y, 0.0)) { //TODO: best way to deal with it is to skip op?
double coef = val / expansionY();
for(unsigned i=2; i<4; i++) _c[i] *= coef;
}
//TODO: use eps
bool Matrix::isIdentity(Coord const eps) const {
- return near(_c[0], 1.0) && near(_c[1], 0.0) &&
- near(_c[2], 0.0) && near(_c[3], 1.0) &&
- near(_c[4], 0.0) && near(_c[5], 0.0);
+ return are_near(_c[0], 1.0) && are_near(_c[1], 0.0) &&
+ are_near(_c[2], 0.0) && are_near(_c[3], 1.0) &&
+ are_near(_c[4], 0.0) && are_near(_c[5], 0.0);
}
/** Answers the question "Does this matrix perform a translation, and \em{only} a translation?"
\return A bool representing yes/no.
*/
bool Matrix::isTranslation(Coord const eps) const {
- return near(_c[0], 1.0) && near(_c[1], 0.0) &&
- near(_c[2], 0.0) && near(_c[3], 1.0) &&
- !near(_c[4], 0.0) && !near(_c[5], 0.0);
+ return are_near(_c[0], 1.0) && are_near(_c[1], 0.0) &&
+ are_near(_c[2], 0.0) && are_near(_c[3], 1.0) &&
+ !are_near(_c[4], 0.0) && !are_near(_c[5], 0.0);
}
/** Answers the question "Does this matrix perform a scale, and \em{only} a Scale?"
\return A bool representing yes/no.
*/
bool Matrix::isScale(Coord const eps) const {
- return !near(_c[0], 1.0) || !near(_c[3], 1.0) && //NOTE: these are the diags, and the next line opposite diags
- near(_c[1], 0.0) && near(_c[2], 0.0) &&
- near(_c[4], 0.0) && near(_c[5], 0.0);
+ return !are_near(_c[0], 1.0) || !are_near(_c[3], 1.0) && //NOTE: these are the diags, and the next line opposite diags
+ are_near(_c[1], 0.0) && are_near(_c[2], 0.0) &&
+ are_near(_c[4], 0.0) && are_near(_c[5], 0.0);
}
/** Answers the question "Does this matrix perform a uniform scale, and \em{only} a uniform scale?"
\return A bool representing yes/no.
*/
bool Matrix::isUniformScale(Coord const eps) const {
- return !near(_c[0], 1.0) && near(_c[0], _c[3]) &&
- near(_c[1], 0.0) && near(_c[2], 0.0) &&
- near(_c[4], 0.0) && near(_c[5], 0.0);
+ return !are_near(_c[0], 1.0) && are_near(_c[0], _c[3]) &&
+ are_near(_c[1], 0.0) && are_near(_c[2], 0.0) &&
+ are_near(_c[4], 0.0) && are_near(_c[5], 0.0);
}
/** Answers the question "Does this matrix perform a rotation, and \em{only} a rotation?"
\return A bool representing yes/no.
*/
bool Matrix::isRotation(Coord const eps) const {
- return !near(_c[0], _c[3]) && near(_c[1], -_c[2]) &&
- near(_c[4], 0.0) && near(_c[5], 0.0) &&
- near(_c[0]*_c[0] + _c[1]*_c[1], 1.0);
+ return !are_near(_c[0], _c[3]) && are_near(_c[1], -_c[2]) &&
+ are_near(_c[4], 0.0) && are_near(_c[5], 0.0) &&
+ are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0);
}
bool Matrix::onlyScaleAndTranslation(Coord const eps) const {
- return near(_c[0], _c[3]) && near(_c[1], 0) && near(_c[2], 0);
+ return are_near(_c[0], _c[3]) && are_near(_c[1], 0) && are_near(_c[2], 0);
}
bool Matrix::flips() const {
Matrix d;
Geom::Coord const determ = det();
- if (!near(determ, 0.0)) {
+ if (!are_near(determ, 0.0)) {
Geom::Coord const ideterm = 1.0 / determ;
d._c[0] = _c[3] * ideterm;
index 2ad78e42f87a39465fb4719e27acd517ee725a6e..9a4d65f72ada2b67cb91a107ac806239b6dd5a5f 100644 (file)
if(iter->boundsFast().height()!=0.){ start = iter; break; }
}
int wind = 0;
- int cnt = 0;
+ unsigned cnt = 0;
bool starting = true;
for (Path::const_iterator iter = start; iter != start || starting
; ++iter, iter = (iter == path.end_closed()) ? path.begin() : iter )
diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp
index 79dc0a5f4765faa4d25038ada4f0746b87a94fae..98fec6e24555c3cd9f2fc632c7a9b13984ba7a54 100644 (file)
--- a/src/2geom/path.cpp
+++ b/src/2geom/path.cpp
const double eps = .1;
void Path::append(Curve const &curve) {
- if ( curves_.front() != final_ && !near(curve.initialPoint(), (*final_)[0], eps) ) {
+ if ( curves_.front() != final_ && !are_near(curve.initialPoint(), (*final_)[0], eps) ) {
throw ContinuityError();
}
do_append(curve.duplicate());
void Path::append(D2<SBasis> const &curve) {
if ( curves_.front() != final_ ) {
for ( int i = 0 ; i < 2 ; ++i ) {
- if ( !near(curve[i][0][0], (*final_)[0][i], eps) ) {
+ if ( !are_near(curve[i][0][0], (*final_)[0][i], eps) ) {
throw ContinuityError();
}
}
{
if ( first != last ) {
if ( first_replaced != curves_.begin() ) {
- if ( !near( (*first_replaced)->initialPoint(), (*first)->initialPoint(), eps ) ) {
+ if ( !are_near( (*first_replaced)->initialPoint(), (*first)->initialPoint(), eps ) ) {
throw ContinuityError();
}
}
if ( last_replaced != (curves_.end()-1) ) {
- if ( !near( (*(last_replaced-1))->finalPoint(), (*(last-1))->finalPoint(), eps ) ) {
+ if ( !are_near( (*(last_replaced-1))->finalPoint(), (*(last-1))->finalPoint(), eps ) ) {
throw ContinuityError();
}
}
} else if ( first_replaced != last_replaced && first_replaced != curves_.begin() && last_replaced != curves_.end()-1) {
- if ( !near((*first_replaced)->initialPoint(), (*(last_replaced-1))->finalPoint(), eps ) ) {
+ if ( !are_near((*first_replaced)->initialPoint(), (*(last_replaced-1))->finalPoint(), eps ) ) {
throw ContinuityError();
}
}
diff --git a/src/2geom/point.h b/src/2geom/point.h
index bf7dc444f3b80355b8b454b2e10cff0d01c9b103..91df159cad90f5364b3cdda88e8cbdaac5c5ee95 100644 (file)
--- a/src/2geom/point.h
+++ b/src/2geom/point.h
/** compute the angle turning from a to b (signed). */
extern double angle_between(Point const a, Point const b);
-
-#ifdef near
-#define lib2geom_near_save near
-#undef near
-#endif
-
//IMPL: NearConcept
-inline bool near(Point const &a, Point const &b, double const eps=EPSILON) {
- return ( near(a[X],b[X],eps) && near(a[Y],b[Y],eps) );
+inline bool are_near(Point const &a, Point const &b, double const eps=EPSILON) {
+ return ( are_near(a[X],b[X],eps) && are_near(a[Y],b[Y],eps) );
}
-#ifdef lib2geom_near_save
-#define near lib2geom_near_save
-#undef lib2geom_near_save
-#endif
-
/** Returns p * Geom::rotate_degrees(90), but more efficient.
*
* Angle direction in Inkscape code: If you use the traditional mathematics convention that y
index 2484af18d94e6026ab42e0b37b9165a0d0934230..7283dd87d3ee02638aad0aba7db46db99fd562e2 100644 (file)
return result;
}
+double mopi(int i) {
+ return (i&1)?-1:1;
+}
+
+// this produces a degree k sbasis from a degree 2q bezier
+SBasis
+bezier_to_sbasis(Bezier const &B) {
+ unsigned n = B.size();
+ unsigned q = (n+1)/2;
+ SBasis result;
+ result.resize(q+1);
+ for(unsigned k = 0; k < q; k++) {
+ result[k][0] = result[k][1] = 0;
+ for(unsigned j = 0; j <= n-k; j++) {
+ result[k][0] += mopi(int(j)-int(k))*W(n, j, k)*B[j];
+ result[k][1] += mopi(int(j)-int(k))*W(n, j, k)*B[j];
+ //W(n, n-j, k)*B[k][1]);
+ }
+ }
+ return result;
+}
+
// this produces a 2q point bezier from a degree q sbasis
std::vector<Geom::Point>
sbasis_to_bezier(D2<SBasis> const &B, unsigned qq) {
@@ -188,9 +210,9 @@ path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double to
Geom::Point start = B[0].at0();
pb.moveTo(start);
for(unsigned i = 0; ; i++) {
- if(i+1 == B.size() || !near(B[i+1].at0(), B[i].at1(), tol)) {
+ if(i+1 == B.size() || !are_near(B[i+1].at0(), B[i].at1(), tol)) {
//start of a new path
- if(near(start, B[i].at1())) {
+ if(are_near(start, B[i].at1())) {
//it's closed
pb.closePath();
if(sbasis_size(B[i]) <= 1) {
index e566d71561a37b8f5529af98b21c145a2737006b..2c49464f60325b9c342445591c18585bf31ac0cf 100644 (file)
Bezier
sbasis_to_bezier(SBasis const &B, unsigned q = 0);
+// inverse
+SBasis bezier_to_sbasis(Bezier const &B);
+
+
std::vector<Geom::Point>
sbasis_to_bezier(D2<SBasis> const &B, unsigned q = 0);
diff --git a/src/2geom/sbasis.h b/src/2geom/sbasis.h
index 118cf2c561731ca3c4f485649c7b916c8256002a..9fc16f1c6caa639da53cebeda6fd750ec245beb9 100644 (file)
--- a/src/2geom/sbasis.h
+++ b/src/2geom/sbasis.h
}
return (1-t)*p0 + t*p1;
}
+ double valueAndDerivative(double t, double &der) const {
+ double s = t*(1-t);
+ double p0 = 0, p1 = 0;
+ double sk = 1;
+//TODO: rewrite as horner
+ for(unsigned k = 0; k < size(); k++) {
+ p0 += sk*(*this)[k][0];
+ p1 += sk*(*this)[k][1];
+ sk *= s;
+ }
+ // p0 and p1 at this point form a linear approximation at t
+ der = p1 - p0;
+ return (1-t)*p0 + t*p1;
+ }
double operator()(double t) const {
return valueAt(t);
}
diff --git a/src/2geom/shape.cpp b/src/2geom/shape.cpp
index 54218d4d99171e3ebe704681bb177feeec5e5bba..3cf6d0bc0ddab00c1e03737bcd886b2bbb7d4462 100644 (file)
--- a/src/2geom/shape.cpp
+++ b/src/2geom/shape.cpp
for(unsigned k = jx; k < crs[ix].size(); k++) {
unsigned koix = crs[ix][k].getOther(ix);
if(koix == oix) {
- if(!near(otime, crs[ix][k].getTime(oix))) break;
+ if(!are_near(otime, crs[ix][k].getTime(oix))) break;
for(unsigned dir = 0; dir < 2; dir++) {
Point val = ps[ix].pointAt(fudgerize(crs[ix][k].getTime(ix), dir)) - cross_point;
Cmp to_prev = cmp(cross(val, prev), 0);
@@ -470,7 +470,7 @@ unsigned pick_coincident(unsigned ix, unsigned jx, bool pref, bool &rev, std::ve
for(unsigned k = jx; k < crs[ix].size(); k++) {
unsigned koix = crs[ix][k].getOther(ix);
if(koix == oix) {
- if(!near(otime, crs[ix][k].getTime(oix))) break;
+ if(!are_near(otime, crs[ix][k].getTime(oix))) break;
for(unsigned dir = 0; dir < 2; dir++) {
Point val = ps[ix].pointAt(crs[ix][k].getTime(ix) + (dir ? -0.01 : 0.01)) - cross_point;
Cmp to_prev = cmp(cross(val, prev), 0);
diff --git a/src/2geom/sturm.h b/src/2geom/sturm.h
index 4a9fcc6e2d4a292512bf168351fab93d5a616b6c..9937a6f1517ece1bbfead5d1d58037e50327b36b 100644 (file)
--- a/src/2geom/sturm.h
+++ b/src/2geom/sturm.h
+#ifndef LIB2GEOM_STURM_HEADER
+#define LIB2GEOM_STURM_HEADER
+
#include "poly.h"
#include "utils.h"
+namespace Geom {
+
class sturm : public std::vector<Poly>{
public:
sturm(Poly const &X) {
}
};
+} //namespace Geom
+
+#endif
/*
Local Variables:
mode:c++
diff --git a/src/2geom/utils.h b/src/2geom/utils.h
index a96a34dff30de2724eaa0d463174662b40fe56fd..50dfa82fe5ac68c0c5a54ca6b16d4eeb24588028 100644 (file)
--- a/src/2geom/utils.h
+++ b/src/2geom/utils.h
-#ifndef UTILS_HEADER
-#define UTILS_HEADER
+#ifndef LIB2GEOM_UTILS_HEADER
+#define LIB2GEOM_UTILS_HEADER
/** Various utility functions.
*
NotImplemented() : std::logic_error("method not implemented") {}
};
+class NotInvertible : public std::range_error {
+ public:
+ NotInvertible() : std::range_error("function does not have a unique inverse") {}
+};
+
// proper logical xor
inline bool logical_xor (bool a, bool b) { return (a || b) && !(a && b); }