KiCad PCB EDA Suite
Loading...
Searching...
No Matches
constraint_test_utils.h
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 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, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef QA_PCBNEW_CONSTRAINT_TEST_UTILS_H
21#define QA_PCBNEW_CONSTRAINT_TEST_UTILS_H
22
23#include <cmath>
24#include <optional>
25#include <vector>
26
28
29#include <board.h>
30#include <pcb_shape.h>
31
34
35namespace KI_TEST
36{
37constexpr int MM = 1000000; // 1 mm in IU (nanometres)
38
39
40inline PCB_SHAPE* addSegment( BOARD& aBoard, const VECTOR2I& aStart, const VECTOR2I& aEnd )
41{
42 PCB_SHAPE* seg = new PCB_SHAPE( &aBoard, SHAPE_T::SEGMENT );
43 seg->SetStart( aStart );
44 seg->SetEnd( aEnd );
45 aBoard.Add( seg );
46 return seg;
47}
48
49
50inline PCB_SHAPE* addBezier( BOARD& aBoard, const VECTOR2I& aStart, const VECTOR2I& aCtrl1,
51 const VECTOR2I& aCtrl2, const VECTOR2I& aEnd )
52{
53 PCB_SHAPE* bezier = new PCB_SHAPE( &aBoard, SHAPE_T::BEZIER );
54 bezier->SetStart( aStart );
55 bezier->SetBezierC1( aCtrl1 );
56 bezier->SetBezierC2( aCtrl2 );
57 bezier->SetEnd( aEnd );
59 aBoard.Add( bezier );
60 return bezier;
61}
62
63
64inline PCB_SHAPE* addRect( BOARD& aBoard, const VECTOR2I& aStart, const VECTOR2I& aEnd )
65{
66 PCB_SHAPE* rect = new PCB_SHAPE( &aBoard, SHAPE_T::RECTANGLE );
67 rect->SetStart( aStart );
68 rect->SetEnd( aEnd );
69 aBoard.Add( rect );
70 return rect;
71}
72
73
74inline PCB_SHAPE* addPoly( BOARD& aBoard, const std::vector<VECTOR2I>& aPoints )
75{
76 PCB_SHAPE* poly = new PCB_SHAPE( &aBoard, SHAPE_T::POLY );
77 poly->SetPolyPoints( aPoints );
78 aBoard.Add( poly );
79 return poly;
80}
81
82
83inline PCB_SHAPE* addCircle( BOARD& aBoard, const VECTOR2I& aCenter, int aRadius )
84{
85 PCB_SHAPE* circle = new PCB_SHAPE( &aBoard, SHAPE_T::CIRCLE );
86 circle->SetCenter( aCenter );
87 circle->SetRadius( aRadius );
88 aBoard.Add( circle );
89 return circle;
90}
91
92
93inline PCB_SHAPE* addArc( BOARD& aBoard, const VECTOR2I& aStart, const VECTOR2I& aMid,
94 const VECTOR2I& aEnd )
95{
96 PCB_SHAPE* arc = new PCB_SHAPE( &aBoard, SHAPE_T::ARC );
97 arc->SetArcGeometry( aStart, aMid, aEnd );
98 aBoard.Add( arc );
99 return arc;
100}
101
102
103inline PCB_SHAPE* addEllipse( BOARD& aBoard, const VECTOR2I& aCenter, int aMajor, int aMinor,
104 const EDA_ANGLE& aRotation )
105{
106 PCB_SHAPE* ellipse = new PCB_SHAPE( &aBoard, SHAPE_T::ELLIPSE );
107 ellipse->SetEllipseCenter( aCenter );
108 ellipse->SetEllipseMajorRadius( aMajor );
109 ellipse->SetEllipseMinorRadius( aMinor );
110 ellipse->SetEllipseRotation( aRotation );
111 aBoard.Add( ellipse );
112 return ellipse;
113}
114
115
116inline PCB_SHAPE* addEllipseArc( BOARD& aBoard, const VECTOR2I& aCenter, int aMajor, int aMinor,
117 const EDA_ANGLE& aRotation, const EDA_ANGLE& aStart, const EDA_ANGLE& aEnd )
118{
119 PCB_SHAPE* arc = new PCB_SHAPE( &aBoard, SHAPE_T::ELLIPSE_ARC );
120 arc->SetEllipseCenter( aCenter );
121 arc->SetEllipseMajorRadius( aMajor );
122 arc->SetEllipseMinorRadius( aMinor );
123 arc->SetEllipseRotation( aRotation );
124 arc->SetEllipseStartAngle( aStart );
125 arc->SetEllipseEndAngle( aEnd );
126 aBoard.Add( arc );
127 return arc;
128}
129
130
132inline double ellipseEquationAt( const PCB_SHAPE* aEllipse, const VECTOR2I& aPos )
133{
134 double a = aEllipse->GetEllipseMajorRadius();
135 double b = aEllipse->GetEllipseMinorRadius();
136 double phi = aEllipse->GetEllipseRotation().AsRadians();
137 VECTOR2D d = VECTOR2D( aPos - aEllipse->GetEllipseCenter() );
138 double lx = d.x * std::cos( phi ) + d.y * std::sin( phi );
139 double ly = -d.x * std::sin( phi ) + d.y * std::cos( phi );
140
141 return ( lx / a ) * ( lx / a ) + ( ly / b ) * ( ly / b );
142}
143
144
146 const std::vector<CONSTRAINT_MEMBER>& aMembers,
147 std::optional<double> aValue = std::nullopt )
148{
149 PCB_CONSTRAINT* c = new PCB_CONSTRAINT( &aBoard, aType );
150
151 for( const CONSTRAINT_MEMBER& m : aMembers )
152 c->AddMember( m.m_item, m.m_anchor, m.m_index );
153
154 c->SetValue( aValue );
155 aBoard.Add( c );
156 return c;
157}
158
159
162inline void solveAndApply( BOARD& aBoard, const std::vector<PCB_SHAPE*>& aShapes )
163{
164 std::vector<PCB_CONSTRAINT*> constraints( aBoard.Constraints().begin(), aBoard.Constraints().end() );
165
167 BOOST_REQUIRE( adapter.Build( aShapes, constraints ) );
168 BOOST_REQUIRE( adapter.Solve() );
169 adapter.Apply();
170}
171
172} // namespace KI_TEST
173
174#endif // QA_PCBNEW_CONSTRAINT_TEST_UTILS_H
Translates KiCad board geometry to and from the planegcs solver (issue #2329).
bool Solve(const CONSTRAINT_MEMBER &aDragged, const VECTOR2I &aCursor, bool aStabilize=false, const std::set< KIID > &aEdited={}, const std::optional< std::pair< CONSTRAINT_MEMBER, VECTOR2I > > &aCoDragged=std::nullopt)
Solve the system, pinning a dragged anchor to a cursor position.
bool Build(const std::vector< PCB_SHAPE * > &aShapes, const std::vector< PCB_CONSTRAINT * > &aConstraints, const std::set< KIID > *aFixedShapes=nullptr, const std::vector< PCB_DIMENSION_BASE * > &aDimensions={})
Translate a cluster into a planegcs system.
std::vector< PCB_SHAPE * > Apply(const std::function< void(BOARD_ITEM *)> &aBeforeWrite={})
Write the solved coordinates back into the shapes, de-normalized to IU.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1355
const CONSTRAINTS & Constraints() const
Geometric constraints (#2329) owned by this board.
Definition board.h:465
double AsRadians() const
Definition eda_angle.h:120
int GetEllipseMinorRadius() const
Definition eda_shape.h:310
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:292
int GetEllipseMajorRadius() const
Definition eda_shape.h:301
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:319
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
void SetPolyPoints(const std::vector< VECTOR2I > &aPoints)
A geometric constraint between board items (issue #2329).
void AddMember(const KIID &aItem, CONSTRAINT_ANCHOR aAnchor=CONSTRAINT_ANCHOR::WHOLE, int aIndex=-1)
void SetValue(std::optional< double > aValue)
void SetEllipseCenter(const VECTOR2I &aPt) override
void SetBezierC1(const VECTOR2I &aPt) override
void SetEllipseStartAngle(const EDA_ANGLE &aA) override
void SetEllipseEndAngle(const EDA_ANGLE &aA) override
void SetEnd(const VECTOR2I &aEnd) override
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
void SetEllipseRotation(const EDA_ANGLE &aA) override
void SetEllipseMinorRadius(int aR) override
void SetStart(const VECTOR2I &aStart) override
void SetBezierC2(const VECTOR2I &aPt) override
void SetEllipseMajorRadius(int aR) override
@ ELLIPSE
Definition eda_shape.h:52
@ SEGMENT
Definition eda_shape.h:46
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
@ ELLIPSE_ARC
Definition eda_shape.h:53
PCB_SHAPE * addSegment(BOARD &aBoard, const VECTOR2I &aStart, const VECTOR2I &aEnd)
PCB_SHAPE * addEllipseArc(BOARD &aBoard, const VECTOR2I &aCenter, int aMajor, int aMinor, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStart, const EDA_ANGLE &aEnd)
PCB_SHAPE * addPoly(BOARD &aBoard, const std::vector< VECTOR2I > &aPoints)
double ellipseEquationAt(const PCB_SHAPE *aEllipse, const VECTOR2I &aPos)
Squared-normalized ellipse equation value at aPos: 1.0 exactly on the outline.
PCB_SHAPE * addArc(BOARD &aBoard, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
PCB_SHAPE * addCircle(BOARD &aBoard, const VECTOR2I &aCenter, int aRadius)
PCB_SHAPE * addBezier(BOARD &aBoard, const VECTOR2I &aStart, const VECTOR2I &aCtrl1, const VECTOR2I &aCtrl2, const VECTOR2I &aEnd)
void solveAndApply(BOARD &aBoard, const std::vector< PCB_SHAPE * > &aShapes)
Build the cluster of aShapes against every constraint on aBoard, solve it, and write the result back ...
PCB_SHAPE * addEllipse(BOARD &aBoard, const VECTOR2I &aCenter, int aMajor, int aMinor, const EDA_ANGLE &aRotation)
constexpr int MM
PCB_CONSTRAINT * addConstraint(BOARD &aBoard, PCB_CONSTRAINT_TYPE aType, const std::vector< CONSTRAINT_MEMBER > &aMembers, std::optional< double > aValue=std::nullopt)
PCB_SHAPE * addRect(BOARD &aBoard, const VECTOR2I &aStart, const VECTOR2I &aEnd)
PCB_CONSTRAINT_TYPE
The geometric relationship a PCB_CONSTRAINT enforces between its members.
One participant in a constraint: a referenced board item plus the feature of that item that participa...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682