KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <math/util.h> // for KiROUND
23#include <geometry/eda_angle.h>
24#include <trigo.h>
25
26using namespace KIGFX::PREVIEW;
27
28
30static EDA_ANGLE snapAngle( const EDA_ANGLE& aAngle )
31{
32 return ANGLE_45 * KiROUND( aAngle / ANGLE_45 );
33}
34
35
37{
38 switch( getStep() )
39 {
40 case SET_ORIGIN: return setOrigin( aPt );
41 case SET_START: return setStart( aPt );
42 case SET_ANGLE: return setEnd( aPt );
43 case COMPLETE: return false;
44 }
45
46 return false;
47}
48
49
51{
53
54 // The manager is reused for every arc in a chain, so the next arc must not inherit the
55 // previous arc's direction, its locked-in direction choice, or its geometry
56 m_clockwise = true;
57 m_directionLocked = false;
58 m_angleSnap = false;
60 m_radius = 0.0;
63}
64
65
67{
68 m_clockwise = aCw;
69 m_directionLocked = true;
71}
72
73
80
81
86
87
89{
90 VECTOR2I vec( static_cast<int>( m_radius ), 0 );
92 return m_origin +vec;
93}
94
95
97{
98 VECTOR2I vec( static_cast<int>( m_radius ), 0 );
99 RotatePoint( vec, -m_endAngle );
100 return m_origin + vec;
101}
102
103
105{
106 return m_radius;
107}
108
109
111{
112 EDA_ANGLE angle = m_startAngle;
113
114 if( m_clockwise )
115 angle -= ANGLE_360;
116
117 return -angle;
118}
119
120
122{
124
125 if( m_endAngle <= m_startAngle )
126 angle += ANGLE_360;
127
128 if( m_clockwise )
129 angle -= ANGLE_360;
130
131 return -angle;
132}
133
134
136{
137 m_origin = aOrigin;
140
141 return true;
142}
143
144
146{
147 const VECTOR2I radVec = aEnd - m_origin;
148
149 m_radius = radVec.EuclideanNorm();
150 m_startAngle = EDA_ANGLE( radVec );
151
152 if( m_angleSnap )
154
155 // normalise to 0..360
156 while( m_startAngle < ANGLE_0 )
158
160
161 return m_radius != 0.0;
162}
163
164
165bool ARC_GEOM_MANAGER::setEnd( const VECTOR2I& aCursor )
166{
167 const VECTOR2I radVec = aCursor - m_origin;
168
169 m_endAngle = EDA_ANGLE( radVec );
170
171 if( m_angleSnap )
173
174 // normalise to 0..360
175 while( m_endAngle < ANGLE_0 )
177
178 if( !m_directionLocked )
179 {
180 EDA_ANGLE ccwAngle = m_endAngle - m_startAngle;
181
182 if( m_endAngle <= m_startAngle )
183 ccwAngle += ANGLE_360;
184
185 EDA_ANGLE cwAngle = std::abs( ccwAngle - ANGLE_360 );
186
187 if( std::min( ccwAngle, cwAngle ) >= ANGLE_90 )
188 m_directionLocked = true;
189 else
190 m_clockwise = cwAngle < ccwAngle;
191 }
192 else if( std::abs( GetSubtended() ) < ANGLE_90 )
193 {
194 m_directionLocked = false;
195 }
196
197 // if the end is the same as the start, this is a bad point
198 return m_endAngle != m_startAngle;
199}
static EDA_ANGLE snapAngle(const EDA_ANGLE &aAngle)
< Snap an angle to the nearest 45 degrees
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
VECTOR2I GetOrigin() const
< Get the center point of the arc (valid when state > SET_ORIGIN)
void Reset() override
The arc to be clockwise from start.
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.
bool acceptPoint(const VECTOR2I &aPt) override
< Function that accepts a point for a stage, or rejects it to return to the previous stage
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
virtual void Reset()
Reset the manager to the initial state.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:279
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:423
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:428
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683