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 
28 using namespace KIGFX::PREVIEW;
29 
30 
32 static double snapAngle( double aAngle )
33 {
34  return KiROUND( aAngle / M_PI_4 ) * M_PI_4;
35 }
36 
37 
39 {
40  switch( getStep() )
41  {
42  case SET_ORIGIN: return setOrigin( aPt );
43  case SET_START: return setStart( aPt );
44  case SET_ANGLE: return setEnd( aPt );
45  case COMPLETE: return false;
46  }
47 
48  return false;
49 }
50 
51 
53 {
54  m_clockwise = aCw;
55  m_directionLocked = true;
57 }
58 
59 
61 {
63  m_directionLocked = true;
65 }
66 
67 
69 {
70  return m_origin;
71 }
72 
73 
75 {
76  return m_origin + VECTOR2I( m_radius, 0 ).Rotate( m_startAngle );
77 }
78 
79 
81 {
82  return m_origin + VECTOR2I( m_radius, 0 ).Rotate( m_endAngle );
83 }
84 
85 
87 {
88  return m_radius;
89 }
90 
91 
93 {
94  double angle = m_startAngle;
95 
96  if( m_clockwise )
97  angle -= 2 * M_PI;
98 
99  return -angle;
100 }
101 
102 
104 {
105  double angle = m_endAngle - m_startAngle;
106 
107  if( m_endAngle <= m_startAngle )
108  angle += 2 * M_PI;
109 
110  if( m_clockwise )
111  angle -= 2 * M_PI;
112 
113  return -angle;
114 }
115 
116 
117 bool ARC_GEOM_MANAGER::setOrigin( const VECTOR2I& aOrigin )
118 {
119  m_origin = aOrigin;
120  m_startAngle = 0.0;
121  m_endAngle = 0.0;
122 
123  return true;
124 }
125 
126 
128 {
129  const VECTOR2I radVec = aEnd - m_origin;
130 
131  m_radius = radVec.EuclideanNorm();
132  m_startAngle = radVec.Angle();
133 
134  if( m_angleSnap )
136 
137  // normalise into 0-2Pi
138  while( m_startAngle < 0 )
139  m_startAngle += M_PI * 2;
140 
142 
143  return m_radius != 0.0;
144 }
145 
146 
147 bool ARC_GEOM_MANAGER::setEnd( const VECTOR2I& aCursor )
148 {
149  const VECTOR2I radVec = aCursor - m_origin;
150 
151  m_endAngle = radVec.Angle();
152 
153  if( m_angleSnap )
155 
156  // normalise into 0-2Pi
157  while( m_endAngle < 0 )
158  m_endAngle += M_PI * 2;
159 
160  if( !m_directionLocked )
161  {
162  double ccwAngle = m_endAngle - m_startAngle;
163 
164  if( m_endAngle <= m_startAngle )
165  ccwAngle += 2 * M_PI;
166 
167  double cwAngle = std::abs( ccwAngle - 2 * M_PI );
168 
169  if( std::min( ccwAngle, cwAngle ) >= M_PI_2 )
170  m_directionLocked = true;
171  else
172  m_clockwise = cwAngle < ccwAngle;
173  }
174  else if( std::abs( GetSubtended() ) < M_PI_2 )
175  {
176  m_directionLocked = false;
177  }
178 
179  // if the end is the same as the start, this is a bad point
180  return m_endAngle != m_startAngle;
181 }
VECTOR2I GetEndRadiusEnd() const
Get the radius of the arc (valid if step >= SET_START)
bool setEnd(const VECTOR2I &aCursor)
#define M_PI_2
Definition: transline.cpp:40
VECTOR2I GetStartRadiusEnd() const
Get the coordinates of the arc end point.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
double GetStartAngle() const
Get the angle of the vector leading to the end point (valid if step >= SET_ANGLE)
void setGeometryChanged()
< Mark the geometry as changed for clients to notice
Waiting to lock in the arc start point.
VECTOR2I GetOrigin() const
< Get the center point of the arc (valid when state > SET_ORIGIN)
Waiting to lock in origin point.
double GetRadius() const
Get the angle of the vector leading to the start point (valid if step >= SET_START)
double Angle() const
Compute the angle of the vector.
Definition: vector2d.h:307
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
bool setStart(const VECTOR2I &aEnd)
Set a point of the second radius line (collinear with arc end)
Waiting to lock in the arc end point.
bool acceptPoint(const VECTOR2I &aPt) override
The arc to be clockwise from start.
void ToggleClockwise()
Set angle snapping (for the next point)
void SetClockwise(bool aCw)
Reverse the current are direction.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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:73
bool setOrigin(const VECTOR2I &aOrigin)
< Set the center point of the arc
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
static double snapAngle(double aAngle)
< Snap an angle to the nearest 45 degrees