KiCad PCB EDA Suite
Loading...
Searching...
No Matches
arc_assistant.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
24
26#include <view/view.h>
27
28#include <algorithm>
29
30#include <base_units.h>
31#include <math/util.h>
32#include <trigo.h>
33
34using namespace KIGFX::PREVIEW;
35
37 EDA_UNITS aUnits ) :
39 m_constructMan( aManager ),
40 m_iuScale( aIuScale ),
41 m_units( aUnits ),
42 m_drawArc( false )
43{
44}
45
46
48{
49 BOX2I tmp;
50
51 // no bounding box when no graphic shown
52 if( !m_constructMan.HasPreview() )
53 return tmp;
54
55 // this is an edit-time artifact; no reason to try and be smart with the bounding box
56 // (besides, we can't tell the text extents without a view to know what the scale is)
57 tmp.SetMaximum();
58 return tmp;
59}
60
61
62void ARC_ASSISTANT::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
63{
64 // not in a position to draw anything
65 if( !m_constructMan.HasPreview() )
66 return;
67
68 aView->GetGAL()->ResetTextAttributes();
69
71 drawCenterGuides( aLayer, aView );
72 else
73 drawEndpointGuides( aLayer, aView );
74}
75
76
77void ARC_ASSISTANT::drawCenterGuides( int aLayer, KIGFX::VIEW* aView ) const
78{
79 const VECTOR2I origin = m_constructMan.GetOrigin();
80
81 KIGFX::PREVIEW::DRAW_CONTEXT preview_ctx( *aView );
82
83 // draw first radius line
84 bool dimFirstLine = m_constructMan.GetStep() > ARC_GEOM_MANAGER::SECOND_POINT;
85
86 preview_ctx.DrawLineWithAngleHighlight( origin, m_constructMan.GetStartRadiusEnd(),
87 dimFirstLine );
88
89 wxArrayString cursorStrings;
90
92 {
93 // haven't started the angle selection phase yet
94
95 EDA_ANGLE initAngle = m_constructMan.GetStartAngle();
96
97 // Draw the radius guide circle if wanted
98 if( m_drawArc )
99 {
100 preview_ctx.DrawCircle( origin, m_constructMan.GetRadius(), true );
101 }
102
103 initAngle.Normalize720();
104
105 cursorStrings.push_back(
106 DimensionLabel( "r", m_constructMan.GetRadius(), m_iuScale, m_units ) );
107 cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "θ" ),
108 initAngle.AsDegrees(), m_iuScale,
110 }
111 else
112 {
113 preview_ctx.DrawLineWithAngleHighlight( origin, m_constructMan.GetEndRadiusEnd(), false );
114
115 EDA_ANGLE start = m_constructMan.GetStartAngle();
116 EDA_ANGLE subtended = m_constructMan.GetSubtended();
117 EDA_ANGLE normalizedEnd = ( start + subtended ).Normalize180();
118
119 // draw dimmed extender line to cursor
120 preview_ctx.DrawLineWithAngleHighlight( origin, m_constructMan.GetLastPoint(), true );
121
122 cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "Δθ" ), subtended.AsDegrees(),
124 cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "θ" ),
125 normalizedEnd.AsDegrees(), m_iuScale,
127 }
128
129 // place the text next to cursor, on opposite side from radius
130 DrawTextNextToCursor( aView, m_constructMan.GetLastPoint(),
131 origin - m_constructMan.GetLastPoint(), cursorStrings,
132 aLayer == LAYER_SELECT_OVERLAY );
133}
134
135
136void ARC_ASSISTANT::drawEndpointGuides( int aLayer, KIGFX::VIEW* aView ) const
137{
138 const int index = m_constructMan.GetPointIndex();
139
140 // The first point is only being placed
141 if( index == 0 )
142 return;
143
144 const ARC_DRAW_MODE mode = m_constructMan.GetMode();
145 const KIGEOM::ARC_SOLUTION& sol = m_constructMan.GetSolution();
146 const VECTOR2I start = m_constructMan.GetStartRadiusEnd();
147 const VECTOR2I cursor = m_constructMan.GetLastPoint();
148 const bool chordModes = mode == ARC_DRAW_MODE::START_END_MID || mode == ARC_DRAW_MODE::START_END_CENTER;
149 const double pixel = aView->ToWorld( 1.0 );
150 const int dashSize = KiROUND( 12 * pixel );
151
152 KIGFX::PREVIEW::DRAW_CONTEXT preview_ctx( *aView );
153
154 // Long guides, such as the line to a far away center, are cut so the dashes stay bounded
155 auto dashedGuide =
156 [&]( const VECTOR2I& aFrom, const VECTOR2D& aTo )
157 {
158 const VECTOR2D delta = aTo - VECTOR2D( aFrom );
159 const double length = delta.EuclideanNorm();
160 const double limit = 400 * pixel;
161 const VECTOR2D end = length > limit ? VECTOR2D( aFrom ) + delta * ( limit / length ) : aTo;
162
163 preview_ctx.DrawLineDashed( aFrom, KiROUND( end ), dashSize,
164 dashSize / 2, false );
165 };
166
167 wxArrayString cursorStrings;
168 VECTOR2D labelAnchor( start );
169
170 if( chordModes )
171 {
172 // The chord is what the first two clicks fixed, and the cursor chases its end until then
173 const VECTOR2I chordEnd = index == 1 ? cursor : m_constructMan.GetPoint( 1 );
174 const VECTOR2D chordMid = ( VECTOR2D( start ) + VECTOR2D( chordEnd ) ) / 2.0;
175
176 preview_ctx.DrawLineWithAngleHighlight( start, chordEnd, index > 1 );
177 labelAnchor = chordMid;
178
179 if( index > 1 && sol.valid )
180 {
181 const VECTOR2D marked = mode == ARC_DRAW_MODE::START_END_MID ? VECTOR2D( sol.mid ) : sol.center;
182
183 // Bisector guide and a marker on the point derived from the cursor
184 dashedGuide( KiROUND( chordMid ), marked );
185 preview_ctx.DrawCircle( KiROUND( marked ), 4 * pixel, false );
186
188 {
189 preview_ctx.DrawLine( KiROUND( marked ), sol.start, true );
190 preview_ctx.DrawLine( KiROUND( marked ), sol.end, true );
191 }
192
193 cursorStrings.push_back( DimensionLabel( "r", sol.radius, m_iuScale, m_units ) );
194 cursorStrings.push_back( DimensionLabel( "s", ( VECTOR2D( sol.mid ) - chordMid ).EuclideanNorm(),
195 m_iuScale, m_units ) );
196 }
197 }
198 else
199 {
200 // The tangent ray is at least as long as the distance to the cursor so it reads as a direction
201 const VECTOR2D dir = m_constructMan.GetTangentDirection();
202 const double length = dir.EuclideanNorm();
203
204 if( length > 0.0 )
205 dashedGuide( start, VECTOR2D( start ) + dir * ( std::max( length, 100 * pixel ) / length ) );
206
207 if( index == 1 )
208 {
209 preview_ctx.DrawLineWithAngleHighlight( start, cursor, true );
210
211 EDA_ANGLE heading( dir );
212
213 cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "θ" ), heading.AsDegrees(), m_iuScale,
215 }
216 else if( sol.valid )
217 {
218 preview_ctx.DrawLine( start, sol.end, true );
219 cursorStrings.push_back( DimensionLabel( "r", sol.radius, m_iuScale, m_units ) );
220 }
221 }
222
223 if( sol.valid )
224 {
225 cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "Δθ" ), m_constructMan.GetSubtended().AsDegrees(),
227 }
228
229 if( cursorStrings.empty() )
230 return;
231
232 // place the text next to cursor, on opposite side from the guides
233 DrawTextNextToCursor( aView, cursor, labelAnchor - VECTOR2D( cursor ), cursorStrings,
234 aLayer == LAYER_SELECT_OVERLAY );
235}
int index
ARC_DRAW_MODE
Construction sequence used when interactively drawing a circular arc.
@ START_END_MID
Start, end, then the arc midpoint dragged along the chord bisector.
@ START_END_CENTER
Start, end, then the center dragged along the chord bisector.
@ CENTER_START_END
Center, then start (sets radius), then sweep to the end.
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
constexpr void SetMaximum()
Definition box2.h:77
double AsDegrees() const
Definition eda_angle.h:115
EDA_ANGLE Normalize720()
Definition eda_angle.h:286
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
void ResetTextAttributes()
Reset text attributes to default styling.
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override final
Draw the assistance (with reference to the construction manager.
void drawCenterGuides(int aLayer, KIGFX::VIEW *aView) const
Guides for center, start and end construction.
bool m_drawArc
Draw the arc segment (or just the radius lines).
void drawEndpointGuides(int aLayer, KIGFX::VIEW *aView) const
Guides for the modes that keep the clicked endpoints.
const ARC_GEOM_MANAGER & m_constructMan
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
ARC_ASSISTANT(const ARC_GEOM_MANAGER &aManager, const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
const EDA_IU_SCALE & m_iuScale
Manage the construction of a circular arc though sequential setting of critical points.
@ SECOND_POINT
Waiting to lock in the second point.
A KIGFX::PREVIEW::DRAW_CONTEXT is a wrapper around a GAL and some other settings that makes it easy t...
void DrawLineDashed(const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDashStep, int aDashFill, bool aDeEmphasised)
Draw a dashed line on the current layer.
void DrawLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, bool aDeEmphasised)
Draw a simple line on the current layer.
void DrawLineWithAngleHighlight(const VECTOR2I &aStart, const VECTOR2I &aEnd, bool aDeEmphasised)
Draw a straight line on the current layer, with a special highlight when the line angle is a multiple...
void DrawCircle(const VECTOR2I &aOrigin, double aRad, bool aDeEmphasised)
Draw a preview circle on the current layer.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:209
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition view.cpp:548
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:281
EDA_UNITS
Definition eda_units.h:44
@ LAYER_SELECT_OVERLAY
Selected items overlay.
Definition layer_ids.h:276
void DrawTextNextToCursor(KIGFX::VIEW *aView, const VECTOR2D &aCursorPos, const VECTOR2D &aTextQuadrant, const wxArrayString &aStrings, bool aDrawingDropShadows)
Draw strings next to the cursor.
wxString DimensionLabel(const wxString &prefix, double aVal, const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, bool aIncludeUnits=true)
Get a formatted string showing a dimension to a sane precision with an optional prefix and unit suffi...
bool valid
False for degenerate input (collinear points, zero chord, etc)
VECTOR2I mid
The point on the arc halfway along the sweep.
VECTOR2I end
int delta
@ NOT_USED
the 3d code uses this value
Definition typeinfo.h:71
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707