Subversion Repositories Scribus

Rev

Rev 15347 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15347 fschmid 1
/*
2
 * interval.h - Simple closed interval class
3
 *
12065 fschmid 4
 * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
5
 *
6
 * Original Rect/Range code by:
7
 *   Lauris Kaplinski <lauris@kaplinski.com>
8
 *   Nathan Hurst <njh@mail.csse.monash.edu.au>
9
 *   bulia byak <buliabyak@users.sf.net>
10
 *   MenTaLguY <mental@rydia.net>
11
 *
12
 * This library is free software; you can redistribute it and/or
13
 * modify it either under the terms of the GNU Lesser General Public
14
 * License version 2.1 as published by the Free Software Foundation
15
 * (the "LGPL") or, at your option, under the terms of the Mozilla
16
 * Public License Version 1.1 (the "MPL"). If you do not alter this
17
 * notice, a recipient may use your version of this file under either
18
 * the MPL or the LGPL.
19
 *
20
 * You should have received a copy of the LGPL along with this library
21
 * in the file COPYING-LGPL-2.1; if not, output to the Free Software
18122 mrdocs 22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12065 fschmid 23
 * You should have received a copy of the MPL along with this library
24
 * in the file COPYING-MPL-1.1
25
 *
26
 * The contents of this file are subject to the Mozilla Public License
27
 * Version 1.1 (the "License"); you may not use this file except in
28
 * compliance with the License. You may obtain a copy of the License at
29
 * http://www.mozilla.org/MPL/
30
 *
31
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
32
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
33
 * the specific language governing rights and limitations.
34
 *
35
 */
15347 fschmid 36
#ifndef SEEN_INTERVAL_H
37
#define SEEN_INTERVAL_H
12065 fschmid 38
 
39
#include <assert.h>
40
#include "coord.h"
41
 
15347 fschmid 42
#include <boost/optional/optional.hpp>
43
 
44
//error in miesh_distortion
45
#ifdef min
46
# undef min
47
#endif
48
 
49
#ifdef max
50
# undef max
51
#endif
52
 
15344 fschmid 53
namespace Geom {
12065 fschmid 54
 
15347 fschmid 55
//
56
class Interval {
12065 fschmid 57
private:
58
    Coord _b[2];
59
 
60
public:
15347 fschmid 61
    //TODO: I just know this'll pop up somewhere, starting off someone's interval at 0...  I can't see how to avoid this.
62
    explicit Interval() { _b[0] = _b[1] = 0; }    
12065 fschmid 63
    explicit Interval(Coord u) { _b[0] = _b[1] = u; }
64
    Interval(Coord u, Coord v) {
15347 fschmid 65
        if(u < v) {
12065 fschmid 66
            _b[0] = u; _b[1] = v;
67
        } else {
68
            _b[0] = v; _b[1] = u;
69
        }
70
    }
15347 fschmid 71
 
72
    double operator[](unsigned i) const {
73
        assert(i < 2);
74
        return _b[i];
12065 fschmid 75
    }
15347 fschmid 76
    inline double& operator[](unsigned i) { return _b[i]; }  //Trust the user...
77
 
78
    inline Coord min() const { return _b[0]; }
79
    inline Coord max() const { return _b[1]; }
80
    inline Coord extent() const { return _b[1] - _b[0]; }
81
    inline Coord middle() const { return (_b[1] + _b[0]) * 0.5; }
82
 
83
    inline bool isEmpty() const { return _b[0] == _b[1]; }
84
    inline bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; }
12065 fschmid 85
    bool contains(const Interval & val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; }
86
    bool intersects(const Interval & val) const {
87
        return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this);
88
    }
89
 
15347 fschmid 90
    inline bool operator==(Interval other) { return _b[0] == other._b[0] && _b[1] == other._b[1]; }
91
    inline bool operator!=(Interval other) { return _b[0] != other._b[0] || _b[1] != other._b[1]; }
92
 
12065 fschmid 93
    //IMPL: OffsetableConcept
94
    //TODO: rename output_type to something else in the concept
95
    typedef Coord output_type;
15347 fschmid 96
    inline Interval operator+(Coord amnt) {
97
        return Interval(_b[0] + amnt, _b[1] + amnt);
98
    }
99
    inline Interval operator-(Coord amnt) {
100
        return Interval(_b[0] - amnt, _b[1] - amnt);
101
    }
102
    inline Interval operator+=(Coord amnt) {
12065 fschmid 103
        _b[0] += amnt; _b[1] += amnt;
104
        return *this;
105
    }
15347 fschmid 106
    inline Interval operator-=(Coord amnt) {
12065 fschmid 107
        _b[0] -= amnt; _b[1] -= amnt;
108
        return *this;
109
    }
110
 
15347 fschmid 111
    //IMPL: ScalableConcept
112
    inline Interval operator-() const { return Interval(*this); }
113
    inline Interval operator*(Coord s) const { return Interval(_b[0]*s, _b[1]*s); }
114
    inline Interval operator/(Coord s) const { return Interval(_b[0]/s, _b[1]/s); }
115
    Interval operator*=(Coord s) {
116
        if(s < 0) {
117
            Coord temp = _b[0];
118
            _b[0] = _b[1]*s;
119
            _b[1] = temp*s;
120
        } else {
121
            _b[0] *= s;
122
            _b[1] *= s;
123
        }
12065 fschmid 124
        return *this;
125
    }
15347 fschmid 126
    Interval operator/=(Coord s) {
127
        //TODO: what about s=0?
128
        if(s < 0) {
129
            Coord temp = _b[0];
130
            _b[0] = _b[1]/s;
131
            _b[1] = temp/s;
132
        } else {
133
            _b[0] /= s;
134
            _b[1] /= s;
135
        }
12065 fschmid 136
        return *this;
137
    }
15347 fschmid 138
 
139
    //TODO: NaN handleage for the next two?
140
    //TODO: Evaluate if wrap behaviour is proper.
141
    //If val > max, then rather than becoming a min==max range, it 'wraps' over
142
    void setMin(Coord val) {
143
        if(val > _b[1]) {
144
            _b[0] = _b[1];
145
            _b[1] = val;
146
        } else {
147
            _b[0] = val;
12065 fschmid 148
        }
149
    }
15347 fschmid 150
    //If val < min, then rather than becoming a min==max range, it 'wraps' over
151
    void setMax(Coord val) {
152
        if(val < _b[0]) {
153
            _b[1] = _b[0];
154
            _b[0] = val;
155
        } else {
156
            _b[1] = val;
12065 fschmid 157
        }
158
    }
15347 fschmid 159
 
160
    inline void extendTo(Coord val) {
161
       if(val < _b[0]) _b[0] = val;
162
       if(val > _b[1]) _b[1] = val;  //no else, as we want to handle NaN
12065 fschmid 163
    }
15347 fschmid 164
 
165
    static Interval fromArray(const Coord* c, int n) {
166
        assert(n > 0);
167
        Interval result(c[0]);
168
        for(int i = 1; i < n; i++) result.extendTo(c[i]);
169
        return result;
12065 fschmid 170
    }
15347 fschmid 171
 
172
    inline void expandBy(double amnt) {
173
        _b[0] -= amnt;
174
        _b[1] += amnt;
12065 fschmid 175
    }
15347 fschmid 176
 
177
    inline void unionWith(const Interval & a) {
178
        if(a._b[0] < _b[0]) _b[0] = a._b[0];
179
        if(a._b[1] > _b[1]) _b[1] = a._b[1];
180
    }
12065 fschmid 181
};
182
 
15347 fschmid 183
//IMPL: AddableConcept
184
inline Interval operator+(const Interval & a, const Interval & b) {
185
    return Interval(a.min() + b.min(), a.max() + b.max());
12065 fschmid 186
}
15347 fschmid 187
inline Interval operator-(const Interval & a, const Interval & b) {
188
    return Interval(a.min() - b.max(), a.max() - b.min());
12065 fschmid 189
}
15347 fschmid 190
inline Interval operator+=(Interval & a, const Interval & b) { a = a + b; return a; }
191
inline Interval operator-=(Interval & a, const Interval & b) { a = a - b; return a; }
12065 fschmid 192
 
15347 fschmid 193
//There might be impls of this based off sign checks
194
inline Interval operator*(const Interval & a, const Interval & b) {
195
    Interval res(a.min() * b.min());
196
    res.extendTo(a.min() * b.max());
197
    res.extendTo(a.max() * b.min());
198
    res.extendTo(a.max() * b.max());
199
    return res;
12065 fschmid 200
}
15347 fschmid 201
inline Interval operator*=(Interval & a, const Interval & b) { a = a * b; return a; }
12065 fschmid 202
 
15347 fschmid 203
/* reinstate if useful (doesn't do the proper thing for 0 inclusion)
204
inline Interval operator/(const Interval & a, const Interval & b) {
205
    Interval res(a.min() / b.min());
206
    res.extendTo(a.min() / b.max());
207
    res.extendTo(a.max() / b.min());
208
    res.extendTo(a.max() / b.max());
209
    return res;
12065 fschmid 210
}
15347 fschmid 211
inline Interval operator/=(Interval & a, const Interval & b) { a = a / b; return a; }
212
*/
12065 fschmid 213
 
15347 fschmid 214
// 'union' conflicts with C keyword
215
inline Interval unify(const Interval & a, const Interval & b) {
216
    return Interval(std::min(a.min(), b.min()),
217
                    std::max(a.max(), b.max()));
12065 fschmid 218
}
15347 fschmid 219
inline boost::optional<Interval> intersect(const Interval & a, const Interval & b) {
220
    Coord u = std::max(a.min(), b.min()),
221
          v = std::min(a.max(), b.max());
222
    //technically >= might be incorrect, but singulars suck
223
    return u >= v ? boost::optional<Interval>()
224
                  : boost::optional<Interval>(Interval(u, v));
225
}
226
 
227
}
15344 fschmid 228
#endif //SEEN_INTERVAL_H