KiCad PCB EDA Suite
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 <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
45 : EDA_ITEM( NOT_USED ), m_parent( aParent ), m_allowPoints( true )
46{
47}
48
49
50EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ) // fixme: ugly
51{
52 unsigned size = std::abs( KiROUND( aView->ToWorld( EDIT_POINT::POINT_SIZE ) ) );
53
54 if( m_allowPoints )
55 {
56 for( EDIT_POINT& point : m_points )
57 {
58 if( point.WithinPoint( aLocation, size ) )
59 return &point;
60 }
61 }
62
63 for( EDIT_LINE& line : m_lines )
64 {
65 if( line.WithinPoint( aLocation, size ) )
66 return &line;
67 }
68
69 return nullptr;
70}
71
72
73int EDIT_POINTS::GetContourStartIdx( int aPointIdx ) const
74{
75 int lastIdx = 0;
76
77 for( int idx : m_contours )
78 {
79 if( idx >= aPointIdx )
80 return lastIdx;
81
82 lastIdx = idx + 1;
83 }
84
85 return lastIdx;
86}
87
88
89int EDIT_POINTS::GetContourEndIdx( int aPointIdx ) const
90{
91 for( int idx : m_contours )
92 {
93 if( idx >= aPointIdx )
94 return idx;
95 }
96
97 return m_points.size() - 1;
98}
99
100
101bool EDIT_POINTS::IsContourStart( int aPointIdx ) const
102{
103 for( int idx : m_contours )
104 {
105 if( idx + 1 == aPointIdx )
106 return true;
107
108 // the list is sorted, so we cannot expect it any further
109 if( idx > aPointIdx )
110 break;
111 }
112
113 return ( aPointIdx == 0 );
114}
115
116
117bool EDIT_POINTS::IsContourEnd( int aPointIdx ) const
118{
119 for( int idx : m_contours )
120 {
121 if( idx == aPointIdx )
122 return true;
123
124 // the list is sorted, so we cannot expect it any further
125 if( idx > aPointIdx )
126 break;
127 }
128
129 // the end of the list surely is the end of a contour
130 return ( aPointIdx == (int) m_points.size() - 1 );
131}
132
133
134EDIT_POINT* EDIT_POINTS::Previous( const EDIT_POINT& aPoint, bool aTraverseContours )
135{
136 for( unsigned int i = 0; i < m_points.size(); ++i )
137 {
138 if( m_points[i] == aPoint )
139 {
140 if( !aTraverseContours && IsContourStart( i ) )
141 return &m_points[GetContourEndIdx( i )];
142
143 if( i == 0 )
144 return &m_points[m_points.size() - 1];
145 else
146 return &m_points[i - 1];
147 }
148 }
149
150 return nullptr;
151}
152
153
155{
156 for( unsigned int i = 0; i < m_lines.size(); ++i )
157 {
158 if( m_lines[i] == aLine )
159 {
160 if( i == 0 )
161 return &m_lines[m_lines.size() - 1];
162 else
163 return &m_lines[i - 1];
164 }
165 }
166
167 return nullptr;
168}
169
170
171EDIT_POINT* EDIT_POINTS::Next( const EDIT_POINT& aPoint, bool aTraverseContours )
172{
173 for( unsigned int i = 0; i < m_points.size(); ++i )
174 {
175 if( m_points[i] == aPoint )
176 {
177 if( !aTraverseContours && IsContourEnd( i ) )
178 return &m_points[GetContourStartIdx( i )];
179
180 if( i == m_points.size() - 1 )
181 return &m_points[0];
182 else
183 return &m_points[i + 1];
184 }
185 }
186
187 return nullptr;
188}
189
190
192{
193 for( unsigned int i = 0; i < m_lines.size(); ++i )
194 {
195 if( m_lines[i] == aLine )
196 {
197 if( i == m_lines.size() - 1 )
198 return &m_lines[0];
199 else
200 return &m_lines[i + 1];
201 }
202 }
203
204 return nullptr;
205}
206
207
209{
210 BOX2I box;
211 bool empty = true;
212
213 for( const auto& point : m_points )
214 {
215 if( empty )
216 {
217 box.SetOrigin( point.GetPosition() );
218 empty = false;
219 }
220 else
221 {
222 box.Merge( point.GetPosition() );
223 }
224 }
225
226 for( const auto& line : m_lines )
227 {
228 if( empty )
229 {
230 box.SetOrigin( line.GetOrigin().GetPosition() );
231 box.SetEnd( line.GetEnd().GetPosition() );
232 empty = false;
233 }
234 else
235 {
236 box.Merge( line.GetOrigin().GetPosition() );
237 box.Merge( line.GetEnd().GetPosition() );
238 }
239 }
240
241 return box;
242}
243
244
245void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
246{
247 KIGFX::GAL* gal = aView->GetGAL();
248 KIGFX::RENDER_SETTINGS* settings = aView->GetPainter()->GetSettings();
249 KIGFX::COLOR4D drawColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
250
251 // Don't assume LAYER_AUX_ITEMS is always a good choice. Compare with background.
252 if( aView->GetGAL()->GetClearColor().Distance( drawColor ) < 0.5 )
253 drawColor.Invert();
254
255 // Linear darkening doesn't fit well with human color perception, and there's no guarantee
256 // that there's enough room for contrast either.
257 KIGFX::COLOR4D borderColor;
258 KIGFX::COLOR4D highlightColor;
259 double brightness = drawColor.GetBrightness();
260
261 if( brightness > 0.5 )
262 {
263 borderColor = drawColor.Darkened( 0.3 ).WithAlpha( 0.8 );
264 highlightColor = drawColor.Brightened( 0.6 ).WithAlpha( 0.8 );
265 }
266 else if( brightness > 0.2 )
267 {
268 borderColor = drawColor.Darkened( 0.6 ).WithAlpha( 0.8 );
269 highlightColor = drawColor.Brightened( 0.3 ).WithAlpha( 0.8 );
270 }
271 else
272 {
273 borderColor = drawColor.Brightened( 0.3 ).WithAlpha( 0.8 );
274 highlightColor = drawColor.Brightened( 0.6 ).WithAlpha( 0.8 );
275 }
276
277 gal->SetFillColor( drawColor );
278 gal->SetStrokeColor( borderColor );
279 gal->SetIsFill( true );
280 gal->SetIsStroke( true );
281 gal->PushDepth();
282 gal->SetLayerDepth( gal->GetMinDepth() );
283
284 double size = aView->ToWorld( EDIT_POINT::POINT_SIZE ) / 2.0;
285 double borderSize = aView->ToWorld( EDIT_POINT::BORDER_SIZE );
286 double hoverSize = aView->ToWorld( EDIT_POINT::HOVER_SIZE );
287
288 auto drawPoint =
289 [&]( const EDIT_POINT& aPoint, bool aDrawCircle = false )
290 {
291 if( aPoint.IsHover() || aPoint.IsActive() )
292 {
293 gal->SetStrokeColor( highlightColor );
294 gal->SetLineWidth( hoverSize );
295 }
296 else
297 {
298 gal->SetStrokeColor( borderColor );
299 gal->SetLineWidth( borderSize );
300 }
301
302 gal->SetFillColor( drawColor );
303
304 if( aDrawCircle )
305 gal->DrawCircle( aPoint.GetPosition(), size );
306 else
307 gal->DrawRectangle( aPoint.GetPosition() - size, aPoint.GetPosition() + size );
308 };
309
310 for( const EDIT_POINT& point : m_points )
311 drawPoint( point );
312
313 for( const EDIT_LINE& line : m_lines )
314 drawPoint( line, true );
315
316 gal->PopDepth();
317}
void SetOrigin(const Vec &pos)
Definition: box2.h:202
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:255
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
Represent a line connecting two EDIT_POINTs.
Definition: edit_points.h:221
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:530
int GetContourEndIdx(int aPointIdx) const
Return index of the contour finish for a point with given index.
Definition: edit_points.cpp:89
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:528
std::list< int > m_contours
Indices of end contour points.
Definition: edit_points.h:529
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:527
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:50
int GetContourStartIdx(int aPointIdx) const
Return index of the contour origin for a point with given index.
Definition: edit_points.cpp:73
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
Definition: edit_points.h:196
bool IsActive() const
Definition: edit_points.h:172
static const int POINT_SIZE
Border size when not hovering.
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 hovering.
Definition: edit_points.h:193
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:321
COLOR4D & Invert()
Makes the color inverted, alpha remains the same.
Definition: color4d.h:258
COLOR4D Darkened(double aFactor) const
Return a color that is darker by a given factor, without modifying object.
Definition: color4d.h:292
double GetBrightness() const
Returns the brightness value of the color ranged from 0.0 to 1.0.
Definition: color4d.h:343
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:278
double Distance(const COLOR4D &other) const
Returns the distance (in RGB space) between two colors.
Definition: color4d.cpp:536
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.
void PushDepth()
Store current drawing depth on the depth stack.
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.
const COLOR4D & GetClearColor() const
double GetMinDepth() const
void PopDepth()
Restore previously stored drawing depth for the depth stack.
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:69
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
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:445
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
static bool empty(const wxTextEntryBase *aCtrl)
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:222
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
@ NOT_USED
the 3d code uses this value
Definition: typeinfo.h:79
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