KiCad PCB EDA Suite
Loading...
Searching...
No Matches
roundrect.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 CERN
5 * Copyright (C) 2019-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[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
26#include "geometry/roundrect.h"
27
28#include <stdexcept>
29
32
33
34namespace
35{
36
37SHAPE_ARC MakeCornerArcCw90( const SHAPE_RECT& aRect, int aRadius, DIRECTION_45::Directions aDir )
38{
39 const VECTOR2I center = KIGEOM::GetPoint( aRect, aDir );
40 return KIGEOM::MakeArcCw90( center, aRadius, aDir );
41}
42
43
44SHAPE_ARC MakeSideArcCw180( const SHAPE_RECT& aRect, int aRadius, DIRECTION_45::Directions aDir )
45{
46 const VECTOR2I center = KIGEOM::GetPoint( aRect, aDir );
47 return KIGEOM::MakeArcCw180( center, aRadius, aDir );
48}
49
50} // namespace
51
52
53ROUNDRECT::ROUNDRECT( SHAPE_RECT aRect, int aRadius ) :
54 m_rect( std::move( aRect ) ), m_radius( aRadius )
55{
57 {
58 throw std::invalid_argument(
59 "Roundrect radius is larger than the rectangle's major dimension" );
60 }
61
62 if( m_radius < 0 )
63 {
64 throw std::invalid_argument( "Roundrect radius must be non-negative" );
65 }
66}
67
68
69ROUNDRECT ROUNDRECT::OutsetFrom( const SHAPE_RECT& aRect, int aOutset )
70{
71 return ROUNDRECT( aRect.GetInflated( aOutset ), aOutset );
72}
73
74
76{
77 return ROUNDRECT( m_rect.GetInflated( aOutset ), m_radius + aOutset );
78}
79
80
81void ROUNDRECT::TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError, ERROR_LOC aErrorLoc ) const
82{
83 const int idx = aBuffer.NewOutline();
84 SHAPE_LINE_CHAIN& outline = aBuffer.Outline( idx );
85
86 const int w = m_rect.GetWidth();
87 const int h = m_rect.GetHeight();
88 const int x_edge = m_rect.GetWidth() - 2 * m_radius;
89 const int y_edge = m_rect.GetHeight() - 2 * m_radius;
90
91 // This is a class invariant
92 wxASSERT( x_edge >= 0 );
93 wxASSERT( y_edge >= 0 );
94 wxASSERT( m_radius >= 0 );
95
96 const VECTOR2I& m_p0 = m_rect.GetPosition();
97
98 if( m_radius == 0 )
99 {
100 // It's just a rectangle
101 outline.Append( m_p0 );
102 outline.Append( m_p0 + VECTOR2I( w, 0 ) );
103 outline.Append( m_p0 + VECTOR2I( w, h ) );
104 outline.Append( m_p0 + VECTOR2I( 0, h ) );
105 }
106 else if( x_edge == 0 && y_edge == 0 )
107 {
108 // It's a circle
109 outline.Append( SHAPE_ARC( m_p0 + VECTOR2I( m_radius, m_radius ),
110 m_p0 + VECTOR2I( -m_radius, 0 ), ANGLE_360 ) );
111 }
112 else
113 {
114 const SHAPE_RECT inner_rect{ m_p0 + VECTOR2I( m_radius, m_radius ), x_edge, y_edge };
115
116 if( x_edge > 0 )
117 {
118 // Either a normal roundrect or an oval with x_edge > 0
119
120 // Start to the right of the top left radius
121 outline.Append( m_p0 + VECTOR2I( m_radius, 0 ) );
122
123 // Top side
124 outline.Append( m_p0 + VECTOR2I( m_radius + x_edge, 0 ) );
125
126 if( y_edge > 0 )
127 {
128 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::NE ) );
129 outline.Append( m_p0 + VECTOR2I( w, m_radius + y_edge ) );
130 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::SE ) );
131 }
132 else
133 {
134 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::E ) );
135 }
136
137 // Bottom side
138 outline.Append( m_p0 + VECTOR2I( m_radius, h ) );
139
140 if( y_edge > 0 )
141 {
142 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::SW ) );
143 outline.Append( m_p0 + VECTOR2I( 0, m_radius ) );
144 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::NW ) );
145 }
146 else
147 {
148 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::W ) );
149 }
150 }
151 else
152 {
153 // x_edge is 0 but y_edge is not, so it's an oval the other way up
154 outline.Append( m_p0 + VECTOR2I( 0, m_radius ) );
155 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::N ) );
156 outline.Append( m_p0 + VECTOR2I( w, m_radius + y_edge ) );
157 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::S ) );
158 }
159 }
160
161 outline.SetClosed( true );
162}
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
Definition: approximation.h:32
Directions
Available directions, there are 8 of them, as on a rectilinear map (north = up) + an extra undefined ...
Definition: direction45.h:49
A round rectangle shape, based on a rectangle and a radius.
Definition: roundrect.h:36
int m_radius
Definition: roundrect.h:83
SHAPE_RECT m_rect
Definition: roundrect.h:82
static ROUNDRECT OutsetFrom(const SHAPE_RECT &aRect, int aOutset)
Definition: roundrect.cpp:69
ROUNDRECT GetInflated(int aOutset) const
Get the roundrect with the size increased by aOutset in all directions.
Definition: roundrect.cpp:75
ROUNDRECT()
Definition: roundrect.h:38
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const
Get the polygonal representation of the roundrect.
Definition: roundrect.cpp:81
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
SHAPE_RECT GetInflated(int aOffset) const
Return a rectangle that is larger by aOffset in all directions, but still centered on the original re...
Definition: shape_rect.h:113
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:160
int GetWidth() const
Definition: shape_rect.h:176
int GetHeight() const
Definition: shape_rect.h:184
int MajorDimension() const
Definition: shape_rect.h:132
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
VECTOR2I GetPoint(const SHAPE_RECT &aRect, DIRECTION_45::Directions aDir, int aOutset=0)
Get the point on a rectangle that corresponds to a given direction.
SHAPE_ARC MakeArcCw180(const VECTOR2I &aCenter, int aRadius, DIRECTION_45::Directions aDir)
Get a SHAPE_ARC representing a 180-degree arc in the clockwise direction with the midpoint in the giv...
SHAPE_ARC MakeArcCw90(const VECTOR2I &aCenter, int aRadius, DIRECTION_45::Directions aDir)
Get a SHAPE_ARC representing a 90-degree arc in the clockwise direction with the midpoint in the give...
STL namespace.
Utility functions for working with shapes.
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691