diff options
| author | Johan B. C. Engelen <jbc.engelen@swissonline.ch> | 2007-08-14 20:54:48 +0000 |
|---|---|---|
| committer | johanengelen <johanengelen@users.sourceforge.net> | 2007-08-14 20:54:48 +0000 |
| commit | 55d43e4e27e0ba58a47fad70957dfa989aa173ad (patch) | |
| tree | 2ccfbac1c50023d08ae32975c876fa2478c1ad2a /src/2geom/interval.h | |
| parent | Fix for bug #1752113; added set_preview_widget_active(false) to FileSaveDialo... (diff) | |
| download | inkscape-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.h | 219 |
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 |
