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 The 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 <ki_exception.h>
29
32#include <wx/intl.h>
33
34
35namespace
36{
37
38SHAPE_ARC MakeCornerArcCw90( const SHAPE_RECT& aRect, int aRadius, DIRECTION_45::Directions aDir )
39{
40 const VECTOR2I center = KIGEOM::GetPoint( aRect, aDir );
41 return KIGEOM::MakeArcCw90( center, aRadius, aDir );
42}
43
44
45SHAPE_ARC MakeSideArcCw180( const SHAPE_RECT& aRect, int aRadius, DIRECTION_45::Directions aDir )
46{
47 const VECTOR2I center = KIGEOM::GetPoint( aRect, aDir );
48 return KIGEOM::MakeArcCw180( center, aRadius, aDir );
49}
50
51} // namespace
52
53
54ROUNDRECT::ROUNDRECT( SHAPE_RECT aRect, int aRadius ) :
55 m_rect( std::move( aRect ) ), m_radius( aRadius )
56{
58 {
59 throw KI_PARAM_ERROR(
60 _( "Roundrect radius is larger than the rectangle's major dimension" ) );
61 }
62
63 if( m_radius < 0 )
64 {
65 throw KI_PARAM_ERROR( _( "Roundrect radius must be non-negative" ) );
66 }
67}
68
69
70ROUNDRECT ROUNDRECT::OutsetFrom( const SHAPE_RECT& aRect, int aOutset )
71{
72 return ROUNDRECT( aRect.GetInflated( aOutset ), aOutset );
73}
74
75
77{
78 return ROUNDRECT( m_rect.GetInflated( aOutset ), m_radius + aOutset );
79}
80
81
82void ROUNDRECT::TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError, ERROR_LOC aErrorLoc ) const
83{
84 const int idx = aBuffer.NewOutline();
85 SHAPE_LINE_CHAIN& outline = aBuffer.Outline( idx );
86
87 const int w = m_rect.GetWidth();
88 const int h = m_rect.GetHeight();
89 const int x_edge = m_rect.GetWidth() - 2 * m_radius;
90 const int y_edge = m_rect.GetHeight() - 2 * m_radius;
91
92 // This is a class invariant
93 wxASSERT( x_edge >= 0 );
94 wxASSERT( y_edge >= 0 );
95 wxASSERT( m_radius >= 0 );
96
97 const VECTOR2I& m_p0 = m_rect.GetPosition();
98
99 if( m_radius == 0 )
100 {
101 // It's just a rectangle
102 outline.Append( m_p0 );
103 outline.Append( m_p0 + VECTOR2I( w, 0 ) );
104 outline.Append( m_p0 + VECTOR2I( w, h ) );
105 outline.Append( m_p0 + VECTOR2I( 0, h ) );
106 }
107 else if( x_edge == 0 && y_edge == 0 )
108 {
109 // It's a circle
110 outline.Append( SHAPE_ARC( m_p0 + VECTOR2I( m_radius, m_radius ),
111 m_p0 + VECTOR2I( -m_radius, 0 ), ANGLE_360 ) );
112 }
113 else
114 {
115 const SHAPE_RECT inner_rect{ m_p0 + VECTOR2I( m_radius, m_radius ), x_edge, y_edge };
116
117 if( x_edge > 0 )
118 {
119 // Either a normal roundrect or an oval with x_edge > 0
120
121 // Start to the right of the top left radius
122 outline.Append( m_p0 + VECTOR2I( m_radius, 0 ) );
123
124 // Top side
125 outline.Append( m_p0 + VECTOR2I( m_radius + x_edge, 0 ) );
126
127 if( y_edge > 0 )
128 {
129 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::NE ) );
130 outline.Append( m_p0 + VECTOR2I( w, m_radius + y_edge ) );
131 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::SE ) );
132 }
133 else
134 {
135 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::E ) );
136 }
137
138 // Bottom side
139 outline.Append( m_p0 + VECTOR2I( m_radius, h ) );
140
141 if( y_edge > 0 )
142 {
143 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::SW ) );
144 outline.Append( m_p0 + VECTOR2I( 0, m_radius ) );
145 outline.Append( MakeCornerArcCw90( inner_rect, m_radius, DIRECTION_45::NW ) );
146 }
147 else
148 {
149 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::W ) );
150 }
151 }
152 else
153 {
154 // x_edge is 0 but y_edge is not, so it's an oval the other way up
155 outline.Append( m_p0 + VECTOR2I( 0, m_radius ) );
156 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::N ) );
157 outline.Append( m_p0 + VECTOR2I( w, m_radius + y_edge ) );
158 outline.Append( MakeSideArcCw180( inner_rect, m_radius, DIRECTION_45::S ) );
159 }
160 }
161
162 outline.SetClosed( true );
163}
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
Hold a translatable error message and may be used when throwing exceptions containing a translated er...
Definition: ki_exception.h:46
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:70
ROUNDRECT GetInflated(int aOutset) const
Get the roundrect with the size increased by aOutset in all directions.
Definition: roundrect.cpp:76
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:82
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
#define _(s)
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.
VECTOR2I center
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695