KiCad PCB EDA Suite
lib_circle.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 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2004-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <fctsys.h>
26 #include <gr_basic.h>
27 #include <macros.h>
28 #include <sch_draw_panel.h>
29 #include <plotter.h>
30 #include <trigo.h>
31 #include <base_units.h>
32 #include <msgpanel.h>
33 #include <bitmaps.h>
34 #include <math/util.h> // for KiROUND
35 #include <eda_draw_frame.h>
36 #include <general.h>
37 #include <lib_circle.h>
39 #include <transform.h>
40 
41 
43  LIB_ITEM( LIB_CIRCLE_T, aParent )
44 {
45  m_Width = 0;
46  m_Fill = NO_FILL;
47  m_isFillable = true;
48 }
49 
50 
51 bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef, int aAccuracy ) const
52 {
53  int mindist = std::max( aAccuracy + GetPenWidth() / 2,
54  Mils2iu( MINIMUM_SELECTION_DISTANCE ) );
55  int dist = KiROUND( GetLineLength( aPosRef, DefaultTransform.TransformCoordinate( m_Pos ) ) );
56 
57  if( abs( dist - GetRadius() ) <= mindist )
58  return true;
59 
60  return false;
61 }
62 
63 
64 bool LIB_CIRCLE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
65 {
66  if( m_Flags & ( STRUCT_DELETED | SKIP_STRUCT ) )
67  return false;
68 
70  int radius = GetRadius();
71  int lineWidth = GetWidth();
72  EDA_RECT sel = aRect ;
73 
74  if ( aAccuracy )
75  sel.Inflate( aAccuracy );
76 
77  if( aContained )
78  return sel.Contains( GetBoundingBox() );
79 
80  // If the rectangle does not intersect the bounding box, this is a much quicker test
81  if( !sel.Intersects( GetBoundingBox() ) )
82  return false;
83  else
84  return sel.IntersectsCircleEdge( center, radius, lineWidth );
85 }
86 
87 
89 {
90  return new LIB_CIRCLE( *this );
91 }
92 
93 
94 int LIB_CIRCLE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
95 {
96  wxASSERT( aOther.Type() == LIB_CIRCLE_T );
97 
98  int retv = LIB_ITEM::compare( aOther, aCompareFlags );
99 
100  if( retv )
101  return retv;
102 
103  const LIB_CIRCLE* tmp = ( LIB_CIRCLE* ) &aOther;
104 
105  if( m_Pos.x != tmp->m_Pos.x )
106  return m_Pos.x - tmp->m_Pos.x;
107 
108  if( m_Pos.y != tmp->m_Pos.y )
109  return m_Pos.y - tmp->m_Pos.y;
110 
111  if( m_EndPos.x != tmp->m_EndPos.x )
112  return m_EndPos.x - tmp->m_EndPos.x;
113 
114  if( m_EndPos.y != tmp->m_EndPos.y )
115  return m_EndPos.y - tmp->m_EndPos.y;
116 
117  return 0;
118 }
119 
120 
121 void LIB_CIRCLE::Offset( const wxPoint& aOffset )
122 {
123  m_Pos += aOffset;
124  m_EndPos += aOffset;
125 }
126 
127 
128 void LIB_CIRCLE::MoveTo( const wxPoint& aPosition )
129 {
130  Offset( aPosition - m_Pos );
131 }
132 
133 
134 void LIB_CIRCLE::MirrorHorizontal( const wxPoint& aCenter )
135 {
136  m_Pos.x -= aCenter.x;
137  m_Pos.x *= -1;
138  m_Pos.x += aCenter.x;
139  m_EndPos.x -= aCenter.x;
140  m_EndPos.x *= -1;
141  m_EndPos.x += aCenter.x;
142 }
143 
144 
145 void LIB_CIRCLE::MirrorVertical( const wxPoint& aCenter )
146 {
147  m_Pos.y -= aCenter.y;
148  m_Pos.y *= -1;
149  m_Pos.y += aCenter.y;
150  m_EndPos.y -= aCenter.y;
151  m_EndPos.y *= -1;
152  m_EndPos.y += aCenter.y;
153 }
154 
155 
156 void LIB_CIRCLE::Rotate( const wxPoint& aCenter, bool aRotateCCW )
157 {
158  int rot_angle = aRotateCCW ? -900 : 900;
159 
160  RotatePoint( &m_Pos, aCenter, rot_angle );
161  RotatePoint( &m_EndPos, aCenter, rot_angle );
162 }
163 
164 
165 void LIB_CIRCLE::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
166  const TRANSFORM& aTransform )
167 {
168  wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
169 
170  if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR )
171  {
172  aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE_BACKGROUND ) );
173  aPlotter->Circle( pos, GetRadius() * 2, FILLED_WITH_BG_BODYCOLOR, 0 );
174  }
175 
176  bool already_filled = m_Fill == FILLED_WITH_BG_BODYCOLOR;
177  int pen_size = GetPenWidth();
178 
179  if( !already_filled || pen_size > 0 )
180  {
181  pen_size = std::max( pen_size, aPlotter->RenderSettings()->GetMinPenWidth() );
182 
183  aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_DEVICE ) );
184  aPlotter->Circle( pos, GetRadius() * 2, already_filled ? NO_FILL : m_Fill, pen_size );
185  }
186 }
187 
188 
190 {
191  // Historically 0 meant "default width" and negative numbers meant "don't stroke".
192  if( m_Width < 0 && GetFillMode() != NO_FILL )
193  return 0;
194  else
195  return std::max( m_Width, 1 );
196 }
197 
198 
199 void LIB_CIRCLE::print( RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
200  const TRANSFORM& aTransform )
201 {
202  bool forceNoFill = static_cast<bool>( aData );
203  int penWidth = GetPenWidth();
204 
205  if( forceNoFill && m_Fill != NO_FILL && penWidth == 0 )
206  return;
207 
208  wxDC* DC = aSettings->GetPrintDC();
209  wxPoint pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
210  COLOR4D color = aSettings->GetLayerColor( LAYER_DEVICE );
211 
212  if( forceNoFill || m_Fill == NO_FILL )
213  {
214  penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
215 
216  GRCircle( nullptr, DC, pos1.x, pos1.y, GetRadius(), penWidth, color );
217  }
218  else
219  {
222 
223  GRFilledCircle( nullptr, DC, pos1.x, pos1.y, GetRadius(), 0, color, color );
224  }
225 }
226 
227 
229 {
230  EDA_RECT rect;
231  int radius = GetRadius();
232 
233  rect.SetOrigin( m_Pos.x - radius, m_Pos.y - radius );
234  rect.SetEnd( m_Pos.x + radius, m_Pos.y + radius );
235  rect.Inflate( ( GetPenWidth() / 2 ) + 1 );
236 
237  rect.RevertYAxis();
238 
239  return rect;
240 }
241 
242 
244 {
245  wxString msg;
246  EDA_RECT bBox = GetBoundingBox();
247 
248  LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
249 
250  msg = MessageTextFromValue( aFrame->GetUserUnits(), m_Width, true );
251 
252  aList.push_back( MSG_PANEL_ITEM( _( "Line Width" ), msg, BLUE ) );
253 
254  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetRadius(), true );
255  aList.push_back( MSG_PANEL_ITEM( _( "Radius" ), msg, RED ) );
256 
257  msg.Printf( wxT( "(%d, %d, %d, %d)" ),
258  bBox.GetOrigin().x,
259  bBox.GetOrigin().y,
260  bBox.GetEnd().x,
261  bBox.GetEnd().y );
262 
263  aList.push_back( MSG_PANEL_ITEM( _( "Bounding Box" ), msg, BROWN ) );
264 }
265 
266 
267 wxString LIB_CIRCLE::GetSelectMenuText( EDA_UNITS aUnits ) const
268 {
269  return wxString::Format( _( "Circle, radius %s" ),
270  MessageTextFromValue( aUnits, GetRadius() ) );
271 }
272 
273 
275 {
276  return add_circle_xpm;
277 }
278 
279 
280 void LIB_CIRCLE::BeginEdit( const wxPoint aPosition )
281 {
282  m_Pos = aPosition;
283 }
284 
285 
286 void LIB_CIRCLE::CalcEdit( const wxPoint& aPosition )
287 {
288  SetEnd( aPosition );
289 }
EDA_UNITS
Definition: common.h:198
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:211
PNG memory record (file in memory).
Definition: bitmap_def.h:29
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
Implementation of conversion functions that require both schematic and board internal units.
virtual void SetColor(COLOR4D color)=0
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: lib_circle.cpp:51
#define SKIP_STRUCT
flag indicating that the structure should be ignored
Definition: base_struct.h:128
int color
Definition: DXF_plotter.cpp:61
void BeginEdit(const wxPoint aStartPoint) override
Begin drawing a component library draw item at aPosition.
Definition: lib_circle.cpp:280
FILL_T GetFillMode() const
Definition: lib_item.h:301
Definition: color4d.h:61
const COLOR4D & GetLayerColor(int aLayer) const
Function GetLayerColor Returns the color used to draw a layer.
wxPoint GetPosition() const override
Definition: lib_circle.h:72
TRANSFORM DefaultTransform
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
bool IntersectsCircleEdge(const wxPoint &aCenter, const int aRadius, const int aWidth) const
IntersectsCircleEdge Tests for intersection between this rect and the edge (radius) of a circle.
void Rotate(const wxPoint &aCenter, bool aRotateCCW=true) override
Rotate the object about aCenter point.
Definition: lib_circle.cpp:156
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
wxPoint m_Pos
Definition: lib_circle.h:35
The base class for create windows for drawing purpose.
int GetWidth() const override
Definition: lib_circle.h:84
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:621
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: lib_circle.cpp:88
void RevertYAxis()
Function RevertYAxis Mirror the rectangle from the X axis (negate Y pos and size)
Definition: eda_rect.h:209
bool Contains(const wxPoint &aPoint) const
Function Contains.
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
The base class for drawable items used by schematic library components.
Definition: lib_item.h:61
This file contains miscellaneous commonly used macros and functions.
const wxPoint GetEnd() const
Definition: eda_rect.h:116
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
COMPARE_FLAGS
The list of flags used by the compare function.
Definition: lib_item.h:116
void MirrorVertical(const wxPoint &aCenter) override
Mirror the draw object along the MirrorVertical (Y) axis about aCenter point.
Definition: lib_circle.cpp:145
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
void SetEnd(int x, int y)
Definition: eda_rect.h:192
#define MINIMUM_SELECTION_DISTANCE
Definition: lib_item.h:47
bool m_isFillable
Definition: lib_item.h:94
Define a library symbol object.
int GetPenWidth() const override
Definition: lib_circle.cpp:189
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Definition: lib_circle.cpp:274
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:126
int GetRadius() const
Definition: lib_circle.h:88
Definition: color4d.h:59
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: lib_circle.cpp:267
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Display basic info (type, part and convert) about the current item in message panel.
Definition: lib_item.cpp:52
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:124
Base plotter engine class.
Definition: plotter.h:114
Definition: color4d.h:56
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:147
LIB_CIRCLE(LIB_PART *aParent)
Definition: lib_circle.cpp:42
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
int compare(const LIB_ITEM &aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags=LIB_ITEM::COMPARE_FLAGS::NORMAL) const override
Provide the draw object specific comparison called by the == and < operators.
Definition: lib_circle.cpp:94
#define _(s)
Definition: 3d_actions.cpp:33
void MirrorHorizontal(const wxPoint &aCenter) override
Mirror the draw object along the horizontal (X) axis about aCenter point.
Definition: lib_circle.cpp:134
FILL_T m_Fill
The body fill type.
Definition: lib_item.h:93
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:598
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: lib_circle.cpp:243
STATUS_FLAGS m_Flags
Definition: base_struct.h:176
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void print(RENDER_SETTINGS *aSettings, const wxPoint &aOffset, void *aData, const TRANSFORM &aTransform) override
Print the item to aDC.
Definition: lib_circle.cpp:199
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:68
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
void Offset(const wxPoint &aOffset) override
Set the drawing object by aOffset from the current position.
Definition: lib_circle.cpp:121
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
int GetDefaultPenWidth() const
int m_Width
Definition: lib_circle.h:37
wxPoint m_EndPos
Definition: lib_circle.h:36
void MoveTo(const wxPoint &aPosition) override
Move a draw object to aPosition.
Definition: lib_circle.cpp:128
void CalcEdit(const wxPoint &aPosition) override
Calculates the attributes of an item at aPosition when it is being edited.
Definition: lib_circle.cpp:286
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
Message panel definition file.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: lib_circle.cpp:228
virtual int compare(const LIB_ITEM &aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags=LIB_ITEM::COMPARE_FLAGS::NORMAL) const
Provide the draw object specific comparison called by the == and < operators.
Definition: lib_item.cpp:76
const BITMAP_OPAQUE add_circle_xpm[1]
Definition: add_circle.cpp:55
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void SetEnd(const wxPoint &aPosition)
Definition: lib_circle.h:74
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void Plot(PLOTTER *aPlotter, const wxPoint &aOffset, bool aFill, const TRANSFORM &aTransform) override
Plot the draw item using the plot object.
Definition: lib_circle.cpp:165
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99