KiCad PCB EDA Suite
Loading...
Searching...
No Matches
angle_item.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) 2024 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, 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#include <tool/edit_points.h>
27#include <gal/painter.h>
28#include <view/view.h>
29#include <geometry/seg.h>
31#include <font/font.h>
32#include <wx/string.h>
33#include <algorithm>
34#include <map>
35
36using namespace KIGFX::PREVIEW;
37
40 m_points( aPoints )
41{
42}
43
45{
46 if( m_points )
47 return m_points->ViewBBox();
48 else
49 return BOX2I();
50}
51
53{
54 if( !m_points )
55 return;
56
57 KIGFX::GAL* gal = aView->GetGAL();
58 KIGFX::RENDER_SETTINGS* settings = aView->GetPainter()->GetSettings();
59 KIGFX::COLOR4D drawColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
60
61 double size = aView->ToWorld( EDIT_POINT::POINT_SIZE ) / 2.0;
62 double borderSize = aView->ToWorld( EDIT_POINT::BORDER_SIZE );
63 double radius = size * 10.0;
64
65 gal->SetStrokeColor( drawColor );
66 gal->SetFillColor( drawColor );
67 gal->SetIsFill( false );
68 gal->SetLineWidth( borderSize * 2.0 );
69 gal->SetGlyphSize( VECTOR2I( radius / 2, radius / 2 ) );
70
71 std::vector<const EDIT_POINT*> anglePoints;
72
73 for( unsigned i = 0; i < m_points->PointsSize(); ++i )
74 {
75 const EDIT_POINT& point = m_points->Point( i );
76
77 if( point.IsActive() || point.IsHover() )
78 {
79 anglePoints.push_back( &point );
80
81 EDIT_POINT* prev = m_points->Previous( point );
82 EDIT_POINT* next = m_points->Next( point );
83
84 if( prev )
85 anglePoints.push_back( prev );
86
87 if( next )
88 anglePoints.push_back( next );
89 }
90 }
91
92 std::sort( anglePoints.begin(), anglePoints.end() );
93 anglePoints.erase( std::unique( anglePoints.begin(), anglePoints.end() ), anglePoints.end() );
94
95 // First pass: collect all angles and identify congruent ones
96 struct AngleInfo
97 {
98 const EDIT_POINT* point;
99 EDA_ANGLE angle;
101 VECTOR2D v1, v2;
102 EDA_ANGLE start;
103 EDA_ANGLE sweep;
104 EDA_ANGLE mid;
105 bool isRightAngle;
106 };
107
108 std::vector<AngleInfo> angles;
109 std::map<int, int> angleCount; // Map angle (in tenths of degree) to count
110
111 for( const EDIT_POINT* pt : anglePoints )
112 {
113 EDIT_POINT* prev = m_points->Previous( *pt );
114 EDIT_POINT* next = m_points->Next( *pt );
115
116 if( !( prev && next ) )
117 continue;
118
119 SEG seg1( pt->GetPosition(), prev->GetPosition() );
120 SEG seg2( pt->GetPosition(), next->GetPosition() );
121
122 // Calculate the interior angle (0-180 degrees) instead of the smallest angle
123 VECTOR2I c = pt->GetPosition();
124 VECTOR2I v1 = prev->GetPosition() - c;
125 VECTOR2I v2 = next->GetPosition() - c;
126 EDA_ANGLE angle = seg2.Angle( seg1 );
127
128 EDA_ANGLE start = EDA_ANGLE( VECTOR2D( v1 ) );
129 EDA_ANGLE sweep = ( EDA_ANGLE( VECTOR2D( v2 ) ) - start ).Normalize180();
130 EDA_ANGLE mid = start + sweep / 2.0;
131 VECTOR2D center( c );
132
133 AngleInfo info;
134 info.point = pt;
135 info.angle = angle;
136 info.center = center;
137 info.v1 = v1;
138 info.v2 = v2;
139 info.start = start;
140 info.sweep = sweep;
141 info.mid = mid;
142 info.isRightAngle = ( angle.AsTenthsOfADegree() == 900 );
143
144 angles.push_back( info );
145 angleCount[angle.AsTenthsOfADegree()]++;
146 }
147
148 // Second pass: draw the angles with congruence markings
149 for( const AngleInfo& angleInfo : angles )
150 {
151 bool isCongruent = angleCount[angleInfo.angle.AsTenthsOfADegree()] > 1;
152
153 if( angleInfo.isRightAngle )
154 {
155 VECTOR2D u1 = VECTOR2D( angleInfo.v1 ).Resize( radius );
156 VECTOR2D u2 = VECTOR2D( angleInfo.v2 ).Resize( radius );
157 VECTOR2D p1 = angleInfo.center + u1;
158 VECTOR2D p2 = angleInfo.center + u2;
159 VECTOR2D corner = angleInfo.center + u1 + u2;
160
161 // Draw the primary right angle marker
162 gal->DrawLine( p1, corner );
163 gal->DrawLine( p2, corner );
164
165 // Draw congruence marking for right angles
166 if( isCongruent )
167 {
168 double innerRadius = radius * 0.6;
169 VECTOR2D u1_inner = VECTOR2D( angleInfo.v1 ).Resize( innerRadius );
170 VECTOR2D u2_inner = VECTOR2D( angleInfo.v2 ).Resize( innerRadius );
171 VECTOR2D p1_inner = angleInfo.center + u1_inner;
172 VECTOR2D p2_inner = angleInfo.center + u2_inner;
173 VECTOR2D corner_inner = angleInfo.center + u1_inner + u2_inner;
174
175 gal->DrawLine( p1_inner, corner_inner );
176 gal->DrawLine( p2_inner, corner_inner );
177 }
178 }
179 else
180 {
181 // Draw the primary arc
182 gal->DrawArc( angleInfo.center, radius, angleInfo.start, angleInfo.sweep );
183
184 // Draw congruence marking for non-right angles
185 if( isCongruent )
186 {
187 double innerRadius = radius * 0.7;
188 gal->DrawArc( angleInfo.center, innerRadius, angleInfo.start, angleInfo.sweep );
189 }
190 }
191
192 VECTOR2D textDir( angleInfo.mid.Cos(), angleInfo.mid.Sin() );
193 wxString label = wxString::Format( wxT( "%.1f°" ), angleInfo.angle.AsDegrees() );
194
195 // Calculate actual text dimensions to ensure proper clearance
197 VECTOR2I textSize = font->StringBoundaryLimits( label, gal->GetGlyphSize(), 0, false, false,
199
200 // Calculate offset based on text direction - use width for horizontal, height for vertical
201 double absX = std::abs( textDir.x );
202 double absY = std::abs( textDir.y );
203 double textClearance = ( absX * textSize.x + absY * textSize.y ) / 2.0;
204 double textOffset = radius + borderSize + textClearance;
205 VECTOR2I textPos = angleInfo.center + VECTOR2I( textDir * textOffset );
206 gal->BitmapText( label, textPos, ANGLE_HORIZONTAL );
207 }
208}
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
int AsTenthsOfADegree() const
Definition eda_angle.h:118
EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
Represent a single point that can be used for modifying items.
Definition edit_points.h:48
bool IsActive() const
static const int POINT_SIZE
Single point size in pixels.
virtual VECTOR2I GetPosition() const
Return coordinates of an EDIT_POINT.
Definition edit_points.h:72
bool IsHover() const
static const int BORDER_SIZE
Border size when not hovering.
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:131
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:147
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic, const METRICS &aFontMetrics) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition font.cpp:427
static const METRICS & Default()
Definition font.cpp:52
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
Abstract interface for drawing on a 2D-surface.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
const VECTOR2I & GetGlyphSize() const
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
void SetGlyphSize(const VECTOR2I aSize)
virtual void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle)
Draw an arc.
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
ANGLE_ITEM(EDIT_POINTS *aPoints)
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
void drawPreviewShape(KIGFX::VIEW *aView) const override
Draw the preview onto the given GAL.
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:66
GAL * GetGAL() const
Return the GAL this view is using to draw graphical primitives.
Definition view.h:202
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:467
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:220
Definition seg.h:42
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
Definition seg.cpp:102
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:385
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc).
Definition layer_ids.h:282
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
CITER next(CITER it)
Definition ptree.cpp:124
VECTOR3I v1(5, 5, 5)
VECTOR2I center
int radius
VECTOR2I v2(1, 0)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694