KiCad PCB EDA Suite
Loading...
Searching...
No Matches
oval.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 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "geometry/oval.h"
23
24#include <trigo.h> // for RotatePoint
25#include <geometry/shape_arc.h>
27
28using namespace KIGEOM;
29
30
32{
33 const SEG& seg = aOval.GetSeg();
34 const VECTOR2I perp = GetRotated( seg.B - seg.A, ANGLE_90 ).Resize( aOval.GetWidth() / 2 );
35
37 chain.Append( seg.A - perp );
38 chain.Append( SHAPE_ARC( seg.A, seg.A - perp, ANGLE_180 ) );
39 chain.Append( seg.B + perp );
40 chain.Append( SHAPE_ARC( seg.B, seg.B + perp, ANGLE_180 ) );
41 chain.SetClosed( true );
42 return chain;
43}
44
45
46std::vector<TYPED_POINT2I> KIGEOM::GetOvalKeyPoints( const SHAPE_SEGMENT& aOval, OVAL_KEY_POINT_FLAGS aFlags )
47{
48 const int half_width = aOval.GetWidth() / 2;
49 const int half_len = aOval.GetTotalLength() / 2;
50 const EDA_ANGLE rotation = aOval.GetAngle() - ANGLE_90;
51
52 // Points on a non-rotated pad at the origin, long-axis is y
53 // (so for now, width is left/right, len is up/down)
54 std::vector<TYPED_POINT2I> pts;
55
56 if( aFlags & OVAL_CENTER )
57 {
58 // Centre is easy
59 pts.emplace_back( VECTOR2I{ 0, 0 }, POINT_TYPE::PT_CENTER );
60 };
61
62 if( aFlags & OVAL_SIDE_MIDPOINTS )
63 {
64 // Side midpoints
65 pts.emplace_back( VECTOR2I{ half_width, 0 }, POINT_TYPE::PT_MID );
66 pts.emplace_back( VECTOR2I{ -half_width, 0 }, POINT_TYPE::PT_MID );
67 }
68
69 if( aFlags & OVAL_CAP_TIPS )
70 {
71 // If the oval is square-on, the tips are quadrants
72 const POINT_TYPE pt_type = rotation.IsCardinal() ? PT_QUADRANT : PT_END;
73
74 // Cap ends
75 pts.emplace_back( VECTOR2I{ 0, half_len }, pt_type );
76 pts.emplace_back( VECTOR2I{ 0, -half_len }, pt_type );
77 }
78
79 // Distance from centre to cap centres
80 const int d_centre_to_cap_centre = half_len - half_width;
81
82 if( aFlags & OVAL_CAP_CENTERS )
83 {
84 // Cap centres
85 pts.emplace_back( VECTOR2I{ 0, d_centre_to_cap_centre }, POINT_TYPE::PT_CENTER );
86 pts.emplace_back( VECTOR2I{ 0, -d_centre_to_cap_centre }, POINT_TYPE::PT_CENTER );
87 }
88
89 if( aFlags & OVAL_SIDE_ENDS )
90 {
91 const auto add_end = [&]( const VECTOR2I& aPt )
92 {
93 pts.emplace_back( aPt, POINT_TYPE::PT_END );
94 };
95
96 // End points of flat sides (always vertical)
97 add_end( { half_width, d_centre_to_cap_centre } );
98 add_end( { half_width, -d_centre_to_cap_centre } );
99 add_end( { -half_width, d_centre_to_cap_centre } );
100 add_end( { -half_width, -d_centre_to_cap_centre } );
101 }
102
103 // Add the quadrant points to the caps only if rotated
104 // (otherwise they're just the tips)
105 if( ( aFlags & OVAL_CARDINAL_EXTREMES ) && !rotation.IsCardinal() )
106 {
107 // We need to find two perpendicular lines from the centres
108 // of each cap to the cap edge, which will hit the points
109 // where the cap is tangent to H/V lines when rotated into place.
110 //
111 // Because we know the oval is always vertical, this means the
112 // two lines are formed between _|, through \/ to |_
113 // where the apex is the cap centre.
114
115 // The vector from a cap centre to the tip (i.e. vertical)
116 const VECTOR2I cap_radial = { 0, half_width };
117
118 // Rotate in the opposite direction to the oval's rotation
119 // (that will be unwound later)
120 EDA_ANGLE radial_line_rotation = rotation;
121
122 radial_line_rotation.Normalize90();
123
124 VECTOR2I cap_radial_to_x_axis = cap_radial;
125 RotatePoint( cap_radial_to_x_axis, radial_line_rotation );
126
127 // Find the other line - it's 90 degrees away, but re-normalise
128 // as it could be to the left or right
129 radial_line_rotation -= ANGLE_90;
130 radial_line_rotation.Normalize90();
131
132 VECTOR2I cap_radial_to_y_axis = cap_radial;
133 RotatePoint( cap_radial_to_y_axis, radial_line_rotation );
134
135 const auto add_quadrant = [&]( const VECTOR2I& aPt )
136 {
137 pts.emplace_back( aPt, POINT_TYPE::PT_QUADRANT );
138 };
139
140 // The quadrant points are then the relevant offsets from each cap centre
141 add_quadrant( VECTOR2I{ 0, d_centre_to_cap_centre } + cap_radial_to_y_axis );
142 add_quadrant( VECTOR2I{ 0, d_centre_to_cap_centre } + cap_radial_to_x_axis );
143 // The opposite cap offsets go from the other cap centre, the other way
144 add_quadrant( VECTOR2I{ 0, -d_centre_to_cap_centre } - cap_radial_to_y_axis );
145 add_quadrant( VECTOR2I{ 0, -d_centre_to_cap_centre } - cap_radial_to_x_axis );
146 }
147
148 for( TYPED_POINT2I& pt : pts )
149 {
150 // Transform to the actual orientation
151 RotatePoint( pt.m_point, -rotation );
152
153 // Translate to the actual position
154 pt.m_point += aOval.GetCenter();
155 }
156
157 return pts;
158}
EDA_ANGLE Normalize90()
Definition eda_angle.h:257
bool IsCardinal() const
Definition eda_angle.cpp:40
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SEG & GetSeg() const
EDA_ANGLE GetAngle() const
int GetWidth() const override
int GetTotalLength() const
Get the total length of the segment, from tip to tip.
VECTOR2I GetCenter() const
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:381
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
std::vector< TYPED_POINT2I > GetOvalKeyPoints(const SHAPE_SEGMENT &aOval, OVAL_KEY_POINT_FLAGS aFlags)
Get a list of interesting points on an oval (rectangle with semicircular end caps)
Definition oval.cpp:46
SHAPE_LINE_CHAIN ConvertToChain(const SHAPE_SEGMENT &aOval)
Definition oval.cpp:31
@ OVAL_SIDE_ENDS
Definition oval.h:48
@ OVAL_CAP_TIPS
Definition oval.h:45
@ OVAL_SIDE_MIDPOINTS
Definition oval.h:47
@ OVAL_CARDINAL_EXTREMES
Definition oval.h:49
@ OVAL_CENTER
Definition oval.h:44
@ OVAL_CAP_CENTERS
Definition oval.h:46
unsigned int OVAL_KEY_POINT_FLAGS
Definition oval.h:53
POINT_TYPE
Meanings that can be assigned to a point in pure geometric terms.
Definition point_types.h:34
@ PT_CENTER
The point is the center of something.
Definition point_types.h:42
@ PT_QUADRANT
The point is on a quadrant of a circle (N, E, S, W points).
Definition point_types.h:54
@ PT_END
The point is at the end of a segment, arc, etc.
Definition point_types.h:46
@ PT_MID
The point is at the middle of a segment, arc, etc.
Definition point_types.h:50
const SHAPE_LINE_CHAIN chain
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
Definition trigo.h:73
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683