summaryrefslogtreecommitdiffstats
path: root/src/2geom/interval.h
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2007-08-14 20:54:48 +0000
committerjohanengelen <johanengelen@users.sourceforge.net>2007-08-14 20:54:48 +0000
commit55d43e4e27e0ba58a47fad70957dfa989aa173ad (patch)
tree2ccfbac1c50023d08ae32975c876fa2478c1ad2a /src/2geom/interval.h
parentFix for bug #1752113; added set_preview_widget_active(false) to FileSaveDialo... (diff)
downloadinkscape-55d43e4e27e0ba58a47fad70957dfa989aa173ad.tar.gz
inkscape-55d43e4e27e0ba58a47fad70957dfa989aa173ad.zip
Commit LivePathEffect branch to trunk!
(disabled extension/internal/bitmap/*.* in build.xml to fix compilation) (bzr r3472)
Diffstat (limited to 'src/2geom/interval.h')
-rw-r--r--src/2geom/interval.h219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/2geom/interval.h b/src/2geom/interval.h
new file mode 100644
index 000000000..459f2cd49
--- /dev/null
+++ b/src/2geom/interval.h
@@ -0,0 +1,219 @@
+/*
+ * interval.h - Simple closed interval class
+ *
+ * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ *
+ * Original Rect/Range code by:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * MenTaLguY <mental@rydia.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+#ifndef SEEN_INTERVAL_H
+#define SEEN_INTERVAL_H
+
+#include <assert.h>
+#include "coord.h"
+
+#include <boost/optional/optional.hpp>
+
+namespace Geom {
+
+//
+class Interval {
+private:
+ Coord _b[2];
+
+public:
+ //TODO: I just know this'll pop up somewhere, starting off someone's interval at 0... I can't see how to avoid this.
+ explicit Interval() { _b[0] = _b[1] = 0; }
+ explicit Interval(Coord u) { _b[0] = _b[1] = u; }
+ Interval(Coord u, Coord v) {
+ if(u < v) {
+ _b[0] = u; _b[1] = v;
+ } else {
+ _b[0] = v; _b[1] = u;
+ }
+ }
+
+ double operator[](unsigned i) const {
+ assert(i < 2);
+ return _b[i];
+ }
+ double& operator[](unsigned i) { return _b[i]; } //Trust the user...
+
+ Coord min() const { return _b[0]; }
+ Coord max() const { return _b[1]; }
+ Coord extent() const { return _b[1] - _b[0]; }
+ Coord middle() const { return (_b[1] + _b[0]) * 0.5; }
+
+ bool isEmpty() const { return _b[0] == _b[1]; }
+ bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; }
+ bool contains(const Interval & val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; }
+ bool intersects(const Interval & val) const {
+ return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this);
+ }
+
+ static Interval fromArray(const Coord* c, int n) {
+ assert(n > 0);
+ Interval result(c[0]);
+ for(int i = 1; i < n; i++) result.extendTo(c[i]);
+ return result;
+ }
+
+ bool operator==(Interval other) { return _b[0] == other._b[0] && _b[1] == other._b[1]; }
+ bool operator!=(Interval other) { return _b[0] != other._b[0] || _b[1] != other._b[1]; }
+
+ //IMPL: OffsetableConcept
+ //TODO: rename output_type to something else in the concept
+ typedef Coord output_type;
+ Interval operator+(Coord amnt) {
+ return Interval(_b[0] + amnt, _b[1] + amnt);
+ }
+ Interval operator-(Coord amnt) {
+ return Interval(_b[0] - amnt, _b[1] - amnt);
+ }
+ Interval operator+=(Coord amnt) {
+ _b[0] += amnt; _b[1] += amnt;
+ return *this;
+ }
+ Interval operator-=(Coord amnt) {
+ _b[0] -= amnt; _b[1] -= amnt;
+ return *this;
+ }
+
+ //IMPL: ScalableConcept
+ Interval operator-() const { return Interval(*this); }
+ Interval operator*(Coord s) const { return Interval(_b[0]*s, _b[1]*s); }
+ Interval operator/(Coord s) const { return Interval(_b[0]/s, _b[1]/s); }
+ Interval operator*=(Coord s) {
+ if(s < 0) {
+ Coord temp = _b[0];
+ _b[0] = _b[1]*s;
+ _b[1] = temp*s;
+ } else {
+ _b[0] *= s;
+ _b[1] *= s;
+ }
+ return *this;
+ }
+ Interval operator/=(Coord s) {
+ //TODO: what about s=0?
+ if(s < 0) {
+ Coord temp = _b[0];
+ _b[0] = _b[1]/s;
+ _b[1] = temp/s;
+ } else {
+ _b[0] /= s;
+ _b[1] /= s;
+ }
+ return *this;
+ }
+
+ //TODO: NaN handleage for the next two?
+ //TODO: Evaluate if wrap behaviour is proper.
+ //If val > max, then rather than becoming a min==max range, it 'wraps' over
+ void setMin(Coord val) {
+ if(val > _b[1]) {
+ _b[0] = _b[1];
+ _b[1] = val;
+ } else {
+ _b[0] = val;
+ }
+ }
+ //If val < min, then rather than becoming a min==max range, it 'wraps' over
+ void setMax(Coord val) {
+ if(val < _b[0]) {
+ _b[1] = _b[0];
+ _b[0] = val;
+ } else {
+ _b[1] = val;
+ }
+ }
+
+ void extendTo(Coord val) {
+ if(val < _b[0]) _b[0] = val;
+ if(val > _b[1]) _b[1] = val; //no else, as we want to handle NaN
+ }
+
+ void expandBy(double amnt) {
+ _b[0] -= amnt;
+ _b[1] += amnt;
+ }
+
+ void unionWith(const Interval & a) {
+ if(a._b[0] < _b[0]) _b[0] = a._b[0];
+ if(a._b[1] > _b[1]) _b[1] = a._b[1];
+ }
+};
+
+//IMPL: AddableConcept
+inline Interval operator+(const Interval & a, const Interval & b) {
+ return Interval(a.min() + b.min(), a.max() + b.max());
+}
+inline Interval operator-(const Interval & a, const Interval & b) {
+ return Interval(a.min() - b.max(), a.max() - b.min());
+}
+inline Interval operator+=(Interval & a, const Interval & b) { a = a + b; return a; }
+inline Interval operator-=(Interval & a, const Interval & b) { a = a - b; return a; }
+
+//There might be impls of this based off sign checks
+inline Interval operator*(const Interval & a, const Interval & b) {
+ Interval res(a.min() * b.min());
+ res.extendTo(a.min() * b.max());
+ res.extendTo(a.max() * b.min());
+ res.extendTo(a.max() * b.max());
+ return res;
+}
+inline Interval operator*=(Interval & a, const Interval & b) { a = a * b; return a; }
+
+/* reinstate if useful (doesn't do the proper thing for 0 inclusion)
+inline Interval operator/(const Interval & a, const Interval & b) {
+ Interval res(a.min() / b.min());
+ res.extendTo(a.min() / b.max());
+ res.extendTo(a.max() / b.min());
+ res.extendTo(a.max() / b.max());
+ return res;
+}
+inline Interval operator/=(Interval & a, const Interval & b) { a = a / b; return a; }
+*/
+
+// 'union' conflicts with C keyword
+inline Interval unify(const Interval & a, const Interval & b) {
+ return Interval(std::min(a.min(), b.min()),
+ std::max(a.max(), b.max()));
+}
+inline boost::optional<Interval> intersect(const Interval & a, const Interval & b) {
+ Coord u = std::max(a.min(), b.min()),
+ v = std::min(a.max(), b.max());
+ //technically >= might be incorrect, but singulars suck
+ return u >= v ? boost::optional<Interval>()
+ : boost::optional<Interval>(Interval(u, v));
+}
+
+}
+#endif //SEEN_INTERVAL_H