KiCad PCB EDA Suite
arc_geom_manager.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017-2021 Kicad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <math/util.h> // for KiROUND
27#include <geometry/eda_angle.h>
28#include <trigo.h>
29
30using namespace KIGFX::PREVIEW;
31
32
34static EDA_ANGLE snapAngle( const EDA_ANGLE& aAngle )
35{
36 return ANGLE_45 * KiROUND( aAngle / ANGLE_45 );
37}
38
39
40bool ARC_GEOM_MANAGER::acceptPoint( const VECTOR2I& aPt )
41{
42 switch( getStep() )
43 {
44 case SET_ORIGIN: return setOrigin( aPt );
45 case SET_START: return setStart( aPt );
46 case SET_ANGLE: return setEnd( aPt );
47 case COMPLETE: return false;
48 }
49
50 return false;
51}
52
53
55{
56 m_clockwise = aCw;
57 m_directionLocked = true;
59}
60
61
63{
65 m_directionLocked = true;
67}
68
69
71{
72 return m_origin;
73}
74
75
77{
78 VECTOR2I vec( m_radius, 0 );
80 return m_origin +vec;
81}
82
83
85{
86 VECTOR2I vec( m_radius, 0 );
87 RotatePoint( vec, -m_endAngle );
88 return m_origin + vec;
89}
90
91
93{
94 return m_radius;
95}
96
97
99{
101
102 if( m_clockwise )
103 angle -= ANGLE_360;
104
105 return -angle;
106}
107
108
110{
112
113 if( m_endAngle <= m_startAngle )
114 angle += ANGLE_360;
115
116 if( m_clockwise )
117 angle -= ANGLE_360;
118
119 return -angle;
120}
121
122
124{
125 m_origin = aOrigin;
128
129 return true;
130}
131
132
134{
135 const VECTOR2I radVec = aEnd - m_origin;
136
137 m_radius = radVec.EuclideanNorm();
138 m_startAngle = EDA_ANGLE( radVec );
139
140 if( m_angleSnap )
142
143 // normalise to 0..360
144 while( m_startAngle < ANGLE_0 )
146
148
149 return m_radius != 0.0;
150}
151
152
153bool ARC_GEOM_MANAGER::setEnd( const VECTOR2I& aCursor )
154{
155 const VECTOR2I radVec = aCursor - m_origin;
156
157 m_endAngle = EDA_ANGLE( radVec );
158
159 if( m_angleSnap )
161
162 // normalise to 0..360
163 while( m_endAngle < ANGLE_0 )
165
166 if( !m_directionLocked )
167 {
168 EDA_ANGLE ccwAngle = m_endAngle - m_startAngle;
169
170 if( m_endAngle <= m_startAngle )
171 ccwAngle += ANGLE_360;
172
173 EDA_ANGLE cwAngle = std::abs( ccwAngle - ANGLE_360 );
174
175 if( std::min( ccwAngle, cwAngle ) >= ANGLE_90 )
176 m_directionLocked = true;
177 else
178 m_clockwise = cwAngle < ccwAngle;
179 }
180 else if( std::abs( GetSubtended() ) < ANGLE_90 )
181 {
182 m_directionLocked = false;
183 }
184
185 // if the end is the same as the start, this is a bad point
186 return m_endAngle != m_startAngle;
187}
static EDA_ANGLE snapAngle(const EDA_ANGLE &aAngle)
< Snap an angle to the nearest 45 degrees
VECTOR2I GetOrigin() const
< Get the center point of the arc (valid when state > SET_ORIGIN)
void SetClockwise(bool aCw)
Reverse the current are direction.
void ToggleClockwise()
Set angle snapping (for the next point)
EDA_ANGLE GetStartAngle() const
Get the angle of the vector leading to the end point (valid if step >= SET_ANGLE)
bool setStart(const VECTOR2I &aEnd)
Set a point of the second radius line (collinear with arc end)
VECTOR2I GetStartRadiusEnd() const
Get the coordinates of the arc end point.
VECTOR2I GetEndRadiusEnd() const
Get the radius of the arc (valid if step >= SET_START)
bool setEnd(const VECTOR2I &aCursor)
double GetRadius() const
Get the angle of the vector leading to the start point (valid if step >= SET_START)
bool setOrigin(const VECTOR2I &aOrigin)
< Set the center point of the arc
@ SET_ORIGIN
Waiting to lock in origin point.
@ SET_ANGLE
Waiting to lock in the arc end point.
@ SET_START
Waiting to lock in the arc start point.
void setGeometryChanged()
< Mark the geometry as changed for clients to notice
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:435
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:430
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:431
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85