Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
point.cpp
Go to the documentation of this file.
1/*
5 * Authors:
6 * Michael G. Sloan <mgsloan@gmail.com>
7 * Nathan Hurst <njh@njhurst.com>
8 * Krzysztof KosiƄski <tweenk.pl@gmail.com>
9 *
10 * Copyright (C) 2006-2009 Authors
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, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
36#include <assert.h>
37#include <math.h>
38#include <2geom/angle.h>
39#include <2geom/coord.h>
40#include <2geom/point.h>
41#include <2geom/transforms.h>
42
43namespace Geom {
44
69Point Point::polar(Coord angle) {
70 Point ret;
71 Coord remainder = Angle(angle).radians0();
72 if (are_near(remainder, 0) || are_near(remainder, 2*M_PI)) {
73 ret[X] = 1;
74 ret[Y] = 0;
75 } else if (are_near(remainder, M_PI/2)) {
76 ret[X] = 0;
77 ret[Y] = 1;
78 } else if (are_near(remainder, M_PI)) {
79 ret[X] = -1;
80 ret[Y] = 0;
81 } else if (are_near(remainder, 3*M_PI/2)) {
82 ret[X] = 0;
83 ret[Y] = -1;
84 } else {
85 sincos(angle, ret[Y], ret[X]);
86 }
87 return ret;
88}
89
96void Point::normalize() {
97 double len = hypot(_pt[0], _pt[1]);
98 if(len == 0) return;
99 if(std::isnan(len)) return;
100 static double const inf = HUGE_VAL;
101 if(len != inf) {
102 *this /= len;
103 } else {
104 unsigned n_inf_coords = 0;
105 /* Delay updating pt in case neither coord is infinite. */
106 Point tmp;
107 for ( unsigned i = 0 ; i < 2 ; ++i ) {
108 if ( _pt[i] == inf ) {
109 ++n_inf_coords;
110 tmp[i] = 1.0;
111 } else if ( _pt[i] == -inf ) {
112 ++n_inf_coords;
113 tmp[i] = -1.0;
114 } else {
115 tmp[i] = 0.0;
116 }
117 }
118 switch (n_inf_coords) {
119 case 0: {
120 /* Can happen if both coords are near +/-DBL_MAX. */
121 *this /= 4.0;
122 len = hypot(_pt[0], _pt[1]);
123 assert(len != inf);
124 *this /= len;
125 break;
126 }
127 case 1: {
128 *this = tmp;
129 break;
130 }
131 case 2: {
132 *this = tmp * sqrt(0.5);
133 break;
134 }
135 }
136 }
137}
138
143Coord L1(Point const &p) {
144 Coord d = 0;
145 for ( int i = 0 ; i < 2 ; i++ ) {
146 d += fabs(p[i]);
147 }
148 return d;
149}
150
154Coord LInfty(Point const &p) {
155 Coord const a(fabs(p[0]));
156 Coord const b(fabs(p[1]));
157 return ( a < b || std::isnan(b)
158 ? b
159 : a );
160}
161
165bool is_zero(Point const &p) {
166 return ( p[0] == 0 &&
167 p[1] == 0 );
168}
169
172bool is_unit_vector(Point const &p, Coord eps) {
173 return are_near(L2(p), 1.0, eps);
174}
178Coord atan2(Point const &p) {
179 return std::atan2(p[Y], p[X]);
180}
181
186Coord angle_between(Point const &a, Point const &b) {
187 return std::atan2(cross(a,b), dot(a,b));
188}
189
199{
200 Point ret(a);
201 ret.normalize();
202 return ret;
203}
215Point abs(Point const &b)
216{
217 Point ret;
218 if (b[Y] < 0.0) {
219 ret = -b;
220 } else if (b[Y] == 0.0) {
221 ret = b[X] < 0.0 ? -b : b;
222 } else {
223 ret = b;
224 }
225 return ret;
226}
227
229Point &Point::operator*=(Affine const &m) {
230 double x = _pt[X], y = _pt[Y];
231 for(int i = 0; i < 2; i++) {
232 _pt[i] = x * m[i] + y * m[i + 2] + m[i + 4];
233 }
234 return *this;
235}
236
244Point constrain_angle(Point const &A, Point const &B, unsigned int n, Point const &dir)
245{
246 // for special cases we could perhaps use explicit testing (which might be faster)
247 if (n == 0.0) {
248 return B;
249 }
250 Point diff(B - A);
251 double angle = -angle_between(diff, dir);
252 double k = round(angle * (double)n / (2.0*M_PI));
253 return A + dir * Rotate(k * 2.0 * M_PI / (double)n) * L2(diff);
254}
255
256std::ostream &operator<<(std::ostream &out, Geom::Point const &p)
257{
258 return out << "(" << format_coord_nice(p[X]) << ", "
259 << format_coord_nice(p[Y]) << ")";
260}
261
262} // namespace Geom
263
264/*
265 Local Variables:
266 mode:c++
267 c-file-style:"stroustrup"
268 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
269 indent-tabs-mode:nil
270 fill-column:99
271 End:
272*/
273// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Cartesian point / 2D vector and related operations.
Various trigoniometric helper functions.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Wrapper for angular values.
Definition angle.h:73
Coord radians0() const
Get the angle as positive radians.
Definition angle.h:112
Two-dimensional point that doubles as a vector.
Definition point.h:66
bool is_zero(Point const &p)
True if the point has both coordinates zero.
Definition point.cpp:165
Coord L1(Point const &p)
Compute the first norm (Manhattan distance) of p.
Definition point.cpp:143
Point abs(Point const &b)
Return the "absolute value" of the point's vector.
Definition point.cpp:215
bool are_near(Point const &a, Point const &b, double eps=EPSILON)
Test whether two points are no further apart than some threshold.
Definition point.h:402
bool is_unit_vector(Point const &p, Coord eps)
True if the point has a length near 1.
Definition point.cpp:172
Coord angle_between(Point const &a, Point const &b)
Compute the angle between a and b relative to the origin.
Definition point.cpp:186
Coord _pt[2]
Definition point.h:67
void normalize()
Normalize the vector representing the point.
Definition point.cpp:96
constexpr Coord y() const noexcept
Definition point.h:106
constexpr Coord x() const noexcept
Definition point.h:104
Coord atan2(Point const &p)
Return the angle between the point and the +X axis.
Definition point.cpp:178
Point unit_vector(Point const &a)
Create a normalized version of a point.
Definition point.cpp:198
Coord LInfty(Point const &p)
Compute the infinity norm (maximum norm) of p.
Definition point.cpp:154
Point constrain_angle(Point const &A, Point const &B, unsigned int n, Point const &dir)
Snap the angle B - A - dir to multiples of .
Definition point.cpp:244
Rotation around the origin.
Definition transforms.h:187
Integral and real coordinate types and some basic utilities.
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Various utility functions.
Definition affine.h:22
void sincos(double angle, double &sin_, double &cos_)
Simultaneously compute a sine and a cosine of the same angle.
Definition math-utils.h:89
std::ostream & operator<<(std::ostream &os, const Bezier &b)
Definition bezier.h:372
SBasisN< n > sqrt(SBasisN< n > const &a, int k)
double angle_between(Line const &l1, Line const &l2)
Definition line.h:456
std::string format_coord_nice(Coord x)
Definition coord.cpp:89
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
SBasis L2(D2< SBasis > const &a, unsigned k)
Definition d2-sbasis.cpp:42
T dot(D2< T > const &a, D2< T > const &b)
Definition d2.h:355
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
auto len
Definition safe-printf.h:21
Affine transformation classes.