aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/Intersections.cpp
blob: d1e0f9bdb24f5f7ca68ef95520ee72743ec52485 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "DataTypes.h"
#include "Intersections.h"

void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
    assert((fCoincidentUsed & 1) != 1);
    for (int index = 0; index < fCoincidentUsed; index += 2) {
        double cs1 = fCoincidentT[fSwap][index];
        double ce1 = fCoincidentT[fSwap][index + 1];
        bool s1in = approximately_between(cs1, s1, ce1);
        bool e1in = approximately_between(cs1, e1, ce1);
        double cs2 = fCoincidentT[fSwap ^ 1][index];
        double ce2 = fCoincidentT[fSwap ^ 1][index + 1];
        bool s2in = approximately_between(cs2, s2, ce2);
        bool e2in = approximately_between(cs2, e2, ce2);
        if ((s1in | e1in) & (s2in | e2in)) {
            double lesser1 = std::min(cs1, ce1);
            index += cs1 > ce1;
            if (s1in < lesser1) {
                fCoincidentT[fSwap][index] = s1in;
            } else if (e1in < lesser1) {
                fCoincidentT[fSwap][index] = e1in;
            }
            index ^= 1;
            double greater1 = fCoincidentT[fSwap][index];
            if (s1in > greater1) {
                fCoincidentT[fSwap][index] = s1in;
            } else if (e1in > greater1) {
                fCoincidentT[fSwap][index] = e1in;
            }
            index &= ~1;
            double lesser2 = std::min(cs2, ce2);
            index += cs2 > ce2;
            if (s2in < lesser2) {
                fCoincidentT[fSwap ^ 1][index] = s2in;
            } else if (e2in < lesser2) {
                fCoincidentT[fSwap ^ 1][index] = e2in;
            }
            index ^= 1;
            double greater2 = fCoincidentT[fSwap ^ 1][index];
            if (s2in > greater2) {
                fCoincidentT[fSwap ^ 1][index] = s2in;
            } else if (e2in > greater2) {
                fCoincidentT[fSwap ^ 1][index] = e2in;
            }
            return;
        }
    }
    assert(fCoincidentUsed < 9);
    fCoincidentT[fSwap][fCoincidentUsed] = s1;
    fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
    ++fCoincidentUsed;
    fCoincidentT[fSwap][fCoincidentUsed] = e1;
    fCoincidentT[fSwap ^ 1][fCoincidentUsed] = e2;
    ++fCoincidentUsed;
}

void Intersections::cleanUp() {
    assert(fCoincidentUsed);
    assert(fUsed);
    // find any entries in fT that could be part of the coincident range

}

void Intersections::insert(double one, double two) {
    assert(fUsed <= 1 || fT[0][0] < fT[0][1]);
    int index;
    for (index = 0; index < fUsed; ++index) {
        if (approximately_equal(fT[0][index], one)
                && approximately_equal(fT[1][index], two)) {
            return;
        }
        if (fT[0][index] > one) {
            break;
        }
    }
    assert(fUsed < 9);
    int remaining = fUsed - index;
    if (remaining > 0) {
        memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
        memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
    }
    fT[0][index] = one;
    fT[1][index] = two;
    ++fUsed;
}

// FIXME: all callers should be moved to regular insert. Failures are likely
// if two separate callers differ on whether ts are equal or not
void Intersections::insertOne(double t, int side) {
    int used = side ? fUsed2 : fUsed;
    assert(used <= 1 || fT[side][0] < fT[side][1]);
    int index;
    for (index = 0; index < used; ++index) {
        if (approximately_equal(fT[side][index], t)) {
            return;
        }
        if (fT[side][index] > t) {
            break;
        }
    }
    assert(used < 9);
    int remaining = used - index;
    if (remaining > 0) {
        memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);
    }
    fT[side][index] = t;
    side ? ++fUsed2 : ++fUsed;
}