aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/CubicBounds.cpp
blob: 7fd9feff6fa557490ba0868dc368ffc038874985 (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
/*
 * 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 "CurveIntersection.h"
#include "CurveUtilities.h"
#include "Extrema.h"

static int isBoundedByEndPoints(double a, double b, double c, double d)
{
    return between(a, b, d) && between(a, c, d);
}

double leftMostT(const Cubic& cubic, double startT, double endT) {
    double leftTs[2];
    _Point pt[2];
    int results = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, leftTs);
    int best = -1;
    for (int index = 0; index < results; ++index) {
        if (startT > leftTs[index] || leftTs[index] > endT) {
            continue;
        }
        if (best < 0) {
            best = index;
            continue;
        }
        xy_at_t(cubic, leftTs[0], pt[0].x, pt[0].y);
        xy_at_t(cubic, leftTs[1], pt[1].x, pt[1].y);
        if (pt[0].x > pt[1].x) {
            best = 1;
        }
    }
    if (best >= 0) {
        return leftTs[best];
    }
    xy_at_t(cubic, startT, pt[0].x, pt[0].y);
    xy_at_t(cubic, endT, pt[1].x, pt[1].y);
    return pt[0].x <= pt[1].x ? startT : endT;
}

void _Rect::setBounds(const Cubic& cubic) {
    set(cubic[0]);
    add(cubic[3]);
    double tValues[4];
    int roots = 0;
    if (!isBoundedByEndPoints(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x)) {
        roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
    }
    if (!isBoundedByEndPoints(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y)) {
        roots += findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, &tValues[roots]);
    }
    for (int x = 0; x < roots; ++x) {
        _Point result;
        xy_at_t(cubic, tValues[x], result.x, result.y);
        add(result);
    }
}

void _Rect::setRawBounds(const Cubic& cubic) {
    set(cubic[0]);
    for (int x = 1; x < 4; ++x) {
        add(cubic[x]);
    }
}