KiCad PCB EDA Suite
Loading...
Searching...
No Matches
edit_points.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) 2014-2019 CERN
5 * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27#include <gal/color4d.h>
28#include <gal/painter.h>
29#include <math/util.h> // for KiROUND
30#include "tool/edit_points.h"
31
32
33bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const
34{
35 // Corners of the EDIT_POINT square
36 VECTOR2I topLeft = GetPosition() - aSize;
37 VECTOR2I bottomRight = GetPosition() + aSize;
38
39 return ( aPoint.x > topLeft.x && aPoint.y > topLeft.y &&
40 aPoint.x < bottomRight.x && aPoint.y < bottomRight.y );
41}
42
43
46 m_parent( aParent ),
47 m_swapX( false ),
48 m_swapY( false ),
49 m_allowPoints( true )
50{
51}
52
53
54EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ) // fixme: ugly
55{
56 unsigned size = std::abs( KiROUND( aView->ToWorld( EDIT_POINT::POINT_SIZE ) ) );
57
58 if( m_allowPoints )
59 {
60 for( EDIT_POINT& point : m_points )
61 {
62 if( point.WithinPoint( aLocation, size ) )
63 return &point;
64 }
65 }
66
67 for( EDIT_LINE& line : m_lines )
68 {
69 if( line.WithinPoint( aLocation, size ) )
70 return &line;
71 }
72
73 return nullptr;
74}
75
76
77int EDIT_POINTS::GetContourStartIdx( int aPointIdx ) const
78{
79 int lastIdx = 0;
80
81 for( int idx : m_contours )
82 {
83 if( idx >= aPointIdx )
84 return lastIdx;
85
86 lastIdx = idx + 1;
87 }
88
89 return lastIdx;
90}
91
92
93int EDIT_POINTS::GetContourEndIdx( int aPointIdx ) const
94{
95 for( int idx : m_contours )
96 {
97 if( idx >= aPointIdx )
98 return idx;
99 }
100
101 return m_points.size() - 1;
102}
103
104
105bool EDIT_POINTS::IsContourStart( int aPointIdx ) const
106{
107 for( int idx : m_contours )
108 {
109 if( idx + 1 == aPointIdx )
110 return true;
111
112 // the list is sorted, so we cannot expect it any further
113 if( idx > aPointIdx )
114 break;
115 }
116
117 return ( aPointIdx == 0 );
118}
119
120
121bool EDIT_POINTS::IsContourEnd( int aPointIdx ) const
122{
123 for( int idx : m_contours )
124 {
125 if( idx == aPointIdx )
126 return true;
127
128 // the list is sorted, so we cannot expect it any further
129 if( idx > aPointIdx )
130 break;
131 }
132
133 // the end of the list surely is the end of a contour
134 return ( aPointIdx == (int) m_points.size() - 1 );
135}
136
137
138EDIT_POINT* EDIT_POINTS::Previous( const EDIT_POINT& aPoint, bool aTraverseContours )
139{
140 for( unsigned int i = 0; i < m_points.size(); ++i )
141 {
142 if( m_points[i] == aPoint )
143 {
144 if( !aTraverseContours && IsContourStart( i ) )
145 return &m_points[GetContourEndIdx( i )];
146
147 if( i == 0 )
148 return &m_points[m_points.size() - 1];
149 else
150 return &m_points[i - 1];
151 }
152 }
153
154 return nullptr;
155}
156
157
159{
160 for( unsigned int i = 0; i < m_lines.size(); ++i )
161 {
162 if( m_lines[i] == aLine )
163 {
164 if( i == 0 )
165 return &m_lines[m_lines.size() - 1];
166 else
167 return &m_lines[i - 1];
168 }
169 }
170
171 return nullptr;
172}
173
174
175EDIT_POINT* EDIT_POINTS::Next( const EDIT_POINT& aPoint, bool aTraverseContours )
176{
177 for( unsigned int i = 0; i < m_points.size(); ++i )
178 {
179 if( m_points[i] == aPoint )
180 {
181 if( !aTraverseContours && IsContourEnd( i ) )
182 return &m_points[GetContourStartIdx( i )];
183
184 if( i == m_points.size() - 1 )
185 return &m_points[0];
186 else
187 return &m_points[i + 1];
188 }
189 }
190
191 return nullptr;
192}
193
194
196{
197 for( unsigned int i = 0; i < m_lines.size(); ++i )
198 {
199 if( m_lines[i] == aLine )
200 {
201 if( i == m_lines.size() - 1 )
202 return &m_lines[0];
203 else
204 return &m_lines[i + 1];
205 }
206 }
207
208 return nullptr;
209}
210
211
213{
214 BOX2I box;
215 bool empty = true;
216
217 for( const auto& point : m_points )
218 {
219 if( empty )
220 {
221 box.SetOrigin( point.GetPosition() );
222 empty = false;
223 }
224 else
225 {
226 box.Merge( point.GetPosition() );
227 }
228 }
229
230 for( const auto& line : m_lines )
231 {
232 if( empty )
233 {
234 box.SetOrigin( line.GetOrigin().GetPosition() );
235 box.SetEnd( line.GetEnd().GetPosition() );
236 empty = false;
237 }
238 else
239 {
240 box.Merge( line.GetOrigin().GetPosition() );
241 box.Merge( line.GetEnd().GetPosition() );
242 }
243 }
244
245 return box;
246}
247
248
249void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
250{
251 KIGFX::GAL* gal = aView->GetGAL();
252 KIGFX::RENDER_SETTINGS* settings = aView->GetPainter()->GetSettings();
253 KIGFX::COLOR4D drawColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
254
255 // Don't assume LAYER_AUX_ITEMS is always a good choice. Compare with background.
256 if( aView->GetGAL()->GetClearColor().Distance( drawColor ) < 0.5 )
257 drawColor.Invert();
258
259 // Linear darkening doesn't fit well with human color perception, and there's no guarantee
260 // that there's enough room for contrast either.
261 KIGFX::COLOR4D borderColor;
262 KIGFX::COLOR4D highlightColor;
263 double brightness = drawColor.GetBrightness();
264
265 if( brightness > 0.5 )
266 {
267 borderColor = drawColor.Darkened( 0.7 ).WithAlpha( 0.8 );
268 highlightColor = drawColor.Darkened( 0.5 ).WithAlpha( 0.8 );
269 }
270 else if( brightness > 0.2 )
271 {
272 borderColor = drawColor.Brightened( 0.4 ).WithAlpha( 0.8 );
273 highlightColor = drawColor.Brightened( 0.3 ).WithAlpha( 0.8 );
274 }
275 else
276 {
277 borderColor = drawColor.Brightened( 0.7 ).WithAlpha( 0.8 );
278 highlightColor = drawColor.Brightened( 0.5 ).WithAlpha( 0.8 );
279 }
280
282 gal->SetFillColor( drawColor );
283 gal->SetStrokeColor( borderColor );
284 gal->SetIsFill( true );
285 gal->SetIsStroke( true );
286 gal->SetLayerDepth( gal->GetMinDepth() );
287
288 double size = aView->ToWorld( EDIT_POINT::POINT_SIZE ) / 2.0;
289 double borderSize = aView->ToWorld( EDIT_POINT::BORDER_SIZE );
290 double hoverSize = aView->ToWorld( EDIT_POINT::HOVER_SIZE );
291
292 auto drawPoint =
293 [&]( const EDIT_POINT& aPoint, bool aDrawCircle = false )
294 {
295 if( aPoint.IsHover() || aPoint.IsActive() )
296 {
297 gal->SetStrokeColor( highlightColor );
298 gal->SetLineWidth( hoverSize );
299 }
300 else
301 {
302 gal->SetStrokeColor( borderColor );
303 gal->SetLineWidth( borderSize );
304 }
305
306 gal->SetFillColor( drawColor );
307
308 if( aDrawCircle )
309 gal->DrawCircle( aPoint.GetPosition(), size );
310 else
311 gal->DrawRectangle( aPoint.GetPosition() - size, aPoint.GetPosition() + size );
312 };
313
314 for( const EDIT_POINT& point : m_points )
315 drawPoint( point );
316
317 for( const EDIT_LINE& line : m_lines )
318 {
319 if( line.HasCenterPoint() )
320 {
321 drawPoint( line.GetPosition(), true );
322 }
323
324 if( line.DrawLine() )
325 {
326 gal->SetLineWidth( borderSize );
327 gal->SetStrokeColor( borderColor );
328 gal->DrawLine( line.GetOrigin().GetPosition(), line.GetEnd().GetPosition() );
329 }
330 }
331}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
constexpr void SetOrigin(const Vec &pos)
Definition: box2.h:237
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
constexpr void SetEnd(coord_type x, coord_type y)
Definition: box2.h:297
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
Represent a line connecting two EDIT_POINTs.
Definition: edit_points.h:223
bool IsContourStart(int aPointIdx) const
Check if a point with given index is a contour origin.
bool m_allowPoints
If false, only allow editing of EDIT_LINES.
Definition: edit_points.h:589
int GetContourEndIdx(int aPointIdx) const
Return index of the contour finish for a point with given index.
Definition: edit_points.cpp:93
virtual const BOX2I ViewBBox() const override
EDIT_POINT * Previous(const EDIT_POINT &aPoint, bool aTraverseContours=true)
Return the point that is after the given point in the list.
EDIT_POINT * Next(const EDIT_POINT &aPoint, bool aTraverseContours=true)
Return the point that is before the given point in the list.
std::deque< EDIT_LINE > m_lines
EDIT_LINEs for modifying m_parent.
Definition: edit_points.h:587
std::list< int > m_contours
Indices of end contour points.
Definition: edit_points.h:588
EDIT_POINTS(EDA_ITEM *aParent)
Definition: edit_points.cpp:44
bool IsContourEnd(int aPointIdx) const
Check is a point with given index is a contour finish.
std::deque< EDIT_POINT > m_points
EDIT_POINTs for modifying m_parent.
Definition: edit_points.h:586
EDIT_POINT * FindPoint(const VECTOR2I &aLocation, KIGFX::VIEW *aView)
Return a point that is at given coordinates or NULL if there is no such point.
Definition: edit_points.cpp:54
int GetContourStartIdx(int aPointIdx) const
Return index of the contour origin for a point with given index.
Definition: edit_points.cpp:77
virtual void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override
Represent a single point that can be used for modifying items.
Definition: edit_points.h:48
static const int HOVER_SIZE
Border size when hovering.
Definition: edit_points.h:197
bool IsActive() const
Definition: edit_points.h:172
static const int POINT_SIZE
Definition: edit_points.h:190
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition: edit_points.h:71
bool WithinPoint(const VECTOR2I &aPoint, unsigned int aSize) const
Check if given point is within a square centered in the EDIT_POINT position.
Definition: edit_points.cpp:33
bool IsHover() const
Definition: edit_points.h:175
static const int BORDER_SIZE
Border size when not hovering.
Definition: edit_points.h:196
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
COLOR4D & Invert()
Makes the color inverted, alpha remains the same.
Definition: color4d.h:242
COLOR4D Darkened(double aFactor) const
Return a color that is darker by a given factor, without modifying object.
Definition: color4d.h:282
double GetBrightness() const
Returns the brightness value of the color ranged from 0.0 to 1.0.
Definition: color4d.h:333
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:268
double Distance(const COLOR4D &other) const
Returns the distance (in RGB space) between two colors.
Definition: color4d.cpp:532
Attribute save/restore for GAL attributes.
Abstract interface for drawing on a 2D-surface.
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a rectangle.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius)
Draw a circle using world coordinates.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
const COLOR4D & GetClearColor() const
double GetMinDepth() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:203
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:484
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
static bool empty(const wxTextEntryBase *aCtrl)
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:223
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
@ NOT_USED
the 3d code uses this value
Definition: typeinfo.h:79