summaryrefslogtreecommitdiffstats
path: root/src/helper/geom.h
blob: 50e434da7809aac750fede83f324511c012e4f6b (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef INKSCAPE_HELPER_GEOM_H
#define INKSCAPE_HELPER_GEOM_H

/**
 * @file
 * Specific geometry functions for Inkscape, not provided my lib2geom.
 */
/*
 * Author:
 *   Johan Engelen <goejendaagh@zonnet.nl>
 *
 * Copyright (C) 2008 Johan Engelen
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#include <vector>
#include <2geom/forward.h>
#include <2geom/rect.h>
#include <2geom/affine.h>
#include "mathfns.h"

Geom::OptRect bounds_fast_transformed(Geom::PathVector const & pv, Geom::Affine const & t);
Geom::OptRect bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t);

void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geom::Affine const &m, Geom::Point const &pt,
                                             Geom::Rect *bbox, int *wind, Geom::Coord *dist,
                                             Geom::Coord tolerance, Geom::Rect const *viewbox);

bool pathvs_have_nonempty_overlap(Geom::PathVector const &a, Geom::PathVector const &b);

size_t count_pathvector_nodes(Geom::PathVector const &pathv );
size_t count_path_nodes(Geom::Path const &path);
size_t count_pathvector_degenerations(Geom::PathVector const &pathv );
size_t count_path_degenerations(Geom::Path const &path);
bool pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3);
Geom::PathVector pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv );
Geom::PathVector pathv_to_linear( Geom::PathVector const &pathv, double maxdisp );
Geom::PathVector pathv_to_cubicbezier( Geom::PathVector const &pathv, bool nolines);
size_t pathv_real_size(Geom::Path path); 
bool pathv_similar(Geom::PathVector const &apv, Geom::PathVector const &bpv, double precission = 0.001);
void recursive_bezier4(const double x1, const double y1, const double x2, const double y2, 
                       const double x3, const double y3, const double x4, const double y4,
                       std::vector<Geom::Point> &pointlist,
                       int level);
bool approx_dihedral(Geom::Affine const &affine, double eps = 0.0001);
std::pair<Geom::Affine, Geom::Rect> min_bounding_box(std::vector<Geom::Point> const &pts);

/// Returns signed area of triangle given by points; may be negative.
inline Geom::Coord triangle_area(Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3)
{
    using Geom::X;
    using Geom::Y;
    return p1[X] * p2[Y] + p1[Y] * p3[X] + p2[X] * p3[Y] - p2[Y] * p3[X] - p1[Y] * p2[X] - p1[X] * p3[Y];
}

inline auto rounddown(Geom::IntPoint const &a, Geom::IntPoint const &b)
{
    using namespace Inkscape::Util;
    return Geom::IntPoint(rounddown(a.x(), b.x()), rounddown(a.y(), b.y()));
}

inline auto expandedBy(Geom::IntRect rect, int amount)
{
    rect.expandBy(amount);
    return rect;
}

inline auto expandedBy(Geom::Rect rect, double amount)
{
    rect.expandBy(amount);
    return rect;
}

inline Geom::OptRect expandedBy(Geom::OptRect const &rect, double amount)
{
    if (!rect) {
        return {};
    } else {
        return expandedBy(*rect, amount);
    }
}

inline auto operator/(double a, Geom::Point const &b)
{
    return Geom::Point(a / b.x(), a / b.y());
}

inline auto absolute(Geom::Point const &a)
{
    return Geom::Point(std::abs(a.x()), std::abs(a.y()));
}

inline auto min(Geom::IntPoint const &a)
{
    return std::min(a.x(), a.y());
}

inline auto min(Geom::Point const &a)
{
    return std::min(a.x(), a.y());
}

inline auto max(Geom::IntPoint const &a)
{
    return std::max(a.x(), a.y());
}

inline auto max(Geom::Point const &a)
{
    return std::max(a.x(), a.y());
}

/// Get the bounding box of a collection of points.
template <typename... Args>
auto bounds_of(Geom::Point const &pt, Args const &... args)
{
    if constexpr (sizeof...(args) == 0) {
        return Geom::Rect(pt, pt);
    } else {
        auto rect = bounds_of(args...);
        rect.expandTo(pt);
        return rect;
    }
}

inline auto floor(Geom::Rect const &rect)
{
    return Geom::Rect(rect.min().floor(), rect.max().floor());
}

inline auto roundedOutwards(Geom::OptRect const &rect)
{
    return rect ? rect->roundOutwards() : Geom::OptIntRect();
}

/**
 * Compute the maximum factor by which @a affine can increase a vector's length.
 */
inline double max_expansion(Geom::Affine const &affine)
{
    auto const t = (Geom::sqr(affine[0]) + Geom::sqr(affine[1]) + Geom::sqr(affine[2]) + Geom::sqr(affine[3])) / 2;
    auto const d = std::abs(affine.det());
    return std::sqrt(t + std::sqrt(std::max(t - d, 0.0) * (t + d)));
}

#endif // INKSCAPE_HELPER_GEOM_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :