127 if( aItem->
Anchor( 0 ) == aP )
153 aMidpoint = ( aP + aN ) / 2;
154 aDirection = segP.
B - segP.
A;
155 aDirection = aDirection.
Resize( ( aP - aN ).EuclideanNorm() );
165 aMidpoint = ( aP + aN ) / 2;
166 aDirection = ( aP - aN ).Perpendicular();
168 if( aDirection.
Dot( aCursorPos - aMidpoint ) < 0 )
169 aDirection = -aDirection;
190 return dir_a.
Angle( dir_b );
218 float& aBestCouplingRatio,
float& aAspectRatio )
229 wxString::Format(
"init+ prefDiag %d (dims %s) %s/%s cl %d %d %d", aPrefDiagonal ? 1 : 0,
m_dims.Format(),
232 PNS_DBG( dbg, AddShape, &n,
BLUE, 20000, wxT(
"init-" ) );
238 bool entryIsStraight =
false;
239 bool targetIsStraight =
false;
245 if( !( dirMask & dir2.
Mask() ) )
248 failReason = wxT(
"fail-primary-entry" );
259 failReason = wxT(
"fail-primary-target" );
269 failReason = wxT(
"fail-entry-angle" );
297 failReason = wxT(
"fail-exit-angle" );
318 failReason = wxT(
"fail-gap" );
321 float minLength = std::min(
m_p.Length(),
m_n.Length() );
322 if( minLength >= 1.0 )
323 aBestCouplingRatio = coupledLength / minLength;
325 aBestCouplingRatio = 0;
332 if( !fail && ( ip_p || ip_n ) )
334 PNS_DBG( dbg, AddPoint, ip_p->p,
RED, 20000, wxT(
"ip+" ) );
335 PNS_DBG( dbg, AddPoint, ip_n->p,
BLUE, 20000, wxT(
"ip-" ) );
338 failReason = wxT(
"fail-self-intersect" );
342 if( !fail &&
m_p.Intersects(
m_n ) )
345 failReason = wxT(
"fail-intersect" );
347 int distP = 0, distN = 0, threshold = 0;
351 distP =
m_n.Distance(
m_p.CLastPoint() );
352 distN =
m_p.Distance(
m_n.CLastPoint() );
354 threshold = (
m_dims.ViaDiameter() / 2 + 1 ) +
m_dims.MinClearance() -
m_dims.Width() / 2;
356 if( distP < threshold || distN < threshold )
359 failReason = wxString::Format(
"fail-vias dp=%d dn=%d thr=%d cl=%d w=%d", distP, distN, threshold,
365 failReason = wxT(
"OK" );
367 if( entryIsStraight && targetIsStraight )
372 wxString::Format(
"fit-%s-%s-%s fail=%d gap=[%s] prioE=%d prioT=%d d=%d eis=%d tis=%d cpr=%.2f ar =%.2f v "
376 aEntry.
IsDiagonal() ? 1 : 0, entryIsStraight ? 1 : 0, targetIsStraight ? 1 : 0,
377 aBestCouplingRatio, aAspectRatio, distP, distN, threshold, aFitVias ? 1 : 0 ),
408 checkP = ( p0.
Angle( p1 ) & aAllowedAngles ) != 0;
420 checkN = ( n0.
Angle( n1 ) & aAllowedAngles ) != 0;
423 return checkP && checkN;
451 int dist =
test.LineDistance( sP.
B,
true );
453 SEG test2( sP.
B, sP.
B + perp );
461 sP.
B =
test.LineProject( sP.
B );
495 const double turnAngle = aWiggle ? 22.6 : 22.5;
497 int leadLen = (int) ( (
double) (gap) *tan( turnAngle *
M_PI / 180.0 ) ) + 1;
500 wxString::Format(
"addturn orig %s gap %d %s %s lead %d",
m_name, gap, dP.
Format(), dN.
Format(),
551 if(
name != wxT(
"" ) )
560 const double widthToMiterRatio = router->Settings().DiffPairWidthToMiterRatio();
561 const int extensionDist = (int) ( widthToMiterRatio * (
double) aGw.
Dimensions().
Width() );
562 std::optional<DP_GATEWAY> extend, turn45_l, turn45_r, turn45_lw, turn45_rw;
563 std::optional<DP_GATEWAY> turn45_le, turn45_re;
565 turn45_l = aGw.
AddTurns(
false,
false,
true,
false );
566 if( turn45_l.has_value() )
569 turn45_le = turn45_l->Extend( extensionDist );
570 if( turn45_le.has_value() )
574 std::optional<DP_GATEWAY> turn90_lel = turn45_le->AddTurns(
false,
false,
true,
false );
575 if( turn90_lel.has_value() )
581 turn45_r = aGw.
AddTurns(
false,
false,
false,
false );
582 if( turn45_r.has_value() )
585 turn45_re = turn45_r->Extend( extensionDist );
586 if( turn45_re.has_value() )
588 std::optional<DP_GATEWAY> turn90_rer = turn45_re->AddTurns(
false,
false,
false,
false );
589 if( turn90_rer.has_value() )
606 VECTOR2I midpoint( ( g.AnchorP() + g.AnchorN() ) / 2 );
607 SEG guide_s( midpoint, midpoint +
VECTOR2I( 1, 0 ) );
608 SEG guide_d( midpoint, midpoint +
VECTOR2I( 1, 1 ) );
613 int dist_s = ( proj_s - aCursorPos ).EuclideanNorm();
614 int dist_d = ( proj_d - aCursorPos ).EuclideanNorm();
616 VECTOR2I proj = ( dist_s < dist_d ? proj_s : proj_d );
625 t.SetPriority( aOrthoScore );
626 t.SetName( wxString::Format(
"ortho-%d", cnt).
ToStdString() );
637 std::vector<DP_GATEWAYS::FIT_RESULT> results;
641 PNS_DBG( dbg, BeginGroup, wxT(
"fit-gateways" ), 0 );
643 for(
bool diagonal : {
true,
false } )
650 result.score = g_entry.Priority();
651 result.score += g_target.Priority();
658 result.diagonal = diagonal;
661 results.push_back(
result );
676 return ( dir.
x == 0 && dir.
y != 0 ) || ( dir.
x == dir.
y ) || ( dir.
y == 0 && dir.
x != 0 );
702 }
while( ( rv * 2 ).EuclideanNorm() < length );
712 int orthoFanDistance = 0;
713 int diagFanDistance = 0;
715 const SHAPE* shP =
nullptr;
717 if( aPair.
PrimP() ==
nullptr )
741 majorDirection = ( p0_p - p0_n ).Perpendicular();
748 switch( shP->
Type() )
751 BuildGeneric ( p0_p, p0_n, colinearityThreshold,
true );
756 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
757 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
762 orthoFanDistance = ( w + 1 )* 3 / 2;
763 diagFanDistance = ( w - h );
769 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
772 orthoFanDistance = w + ( s.
B - s.
A ).EuclideanNorm();
773 diagFanDistance = ( s.
B - s.
A ).EuclideanNorm();
787 orthoFanDistance = ( w + 1 )* 3 / 2;
788 diagFanDistance = ( w - h );
793 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
801 int padDist = ( p0_p - p0_n ).EuclideanNorm();
803 for(
int k = 0; k < 2; k++ )
812 int d = std::max( 0, padDist - gap );
816 for(
int i = 0; i < 2; i++ )
818 int sign = i ? -1 : 1;
828 gw.SetName( wxString::Format(
"pp-%d-%d", k, i ).
ToStdString() );
829 gw.SetEntryLines( entryP, entryN );
833 gw.SetDimensions(
m_dims );
834 gw.SetPriority( 101 - k );
835 gw.SetDirections( dir1, dir1 );
836 gw.SetPrimaryDirection( dir1 );
839 auto gw_ext = gw.Extend( 400000 );
854 for(
bool diagonal : {
false,
true } )
856 for(
int i = 0; i < 4; i++ )
873 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
875 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) );
881 BuildGeneric( aCursorPos + dir, aCursorPos - dir, 0,
true,
true );
885 DP_GATEWAY gw( aCursorPos + dir, aCursorPos - dir, diagonal );
937 PNS_DBG( dbg, Message, wxString::Format(
"buildDpCont: gap=%d dn=%s dp=%s", gap, dN.
Format(), dP.
Format() ) );
978 SEG st_p[2], st_n[2];
982 const int padToGapThreshold = 3;
983 int padDist = ( p0_n - p0_p ).EuclideanNorm();
1001 for(
int i = 0; i < 2; i++ )
1007 if( straightColl || diagColl )
1011 int prio = ( padDist > padToGapThreshold * gap ) ? 2 : 1;
1026 for(
int i = 0; i < 2; i++ )
1028 for(
int j = 0; j < 2; j++ )
1035 if( d_n[i].Collinear( d_p[j] ) )
1038 if( st_p[i].Collinear( st_p[j] ) )
1045 for(
int k = 0; k < 2; k++ )
1051 if( m != p0_p && m != p0_n )
1053 int prio = ( padDist > padToGapThreshold * gap ? 10 : 20 );
1054 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double) gap * M_SQRT1_2 ) ) );
1055 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double) gap * M_SQRT1_2 ) ) );
1070 auto gw_ext = gw.
Extend( 400000 );
1071 if( gw_ext && !aViaMode )
1081 for(
int k = 0; k < 2; k++ )
1087 if( !aViaMode && m != p0_p && m != p0_n )
1091 g_p = ( p0_p - m ).Resize( ceil( (
double) gap * M_SQRT2 ) );
1092 g_n = ( p0_n - m ).Resize( ceil( (
double) gap ) );
1095 m_gateways.emplace_back( m + g_p, m + g_n,
true );
1097 g_p = ( p0_p - m ).Resize( gap );
1098 g_n = ( p0_n - m ).Resize( ceil( (
double) gap * M_SQRT2 ) );
1101 m_gateways.emplace_back( m + g_p, m + g_n,
true );
1121 return seg->Width();
1123 return arc->Width();
1181 int64_t t_b = p.
TCoef( p.
B );
1183 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
1184 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
1187 std::swap( t_b, t_a );
1189 if( tproj_b < tproj_a )
1190 std::swap( tproj_b, tproj_a );
1192 if( t_b <= tproj_a )
1195 if( t_a >= tproj_b )
1199 std::vector<int64_t> tv( t, t + 4 );
1200 std::sort( tv.begin(), tv.end() );
1205 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
1206 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
1208 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
1209 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
1220 return m_p.Length() -
m_n.Length();
1225 bool aUseGapConstraint,
1226 const std::optional<DP_GAP_CONSTRAINT>& aOverrideGapConstraint )
const
1235 gapConstraint.
SetMin( 0 );
1236 gapConstraint.
SetMax( (
int) ( (
double)
m_dims.Width() * threshold ) );
1238 if ( aOverrideGapConstraint )
1239 gapConstraint = aOverrideGapConstraint.value();
1240 else if( aUseGapConstraint )
1241 gapConstraint =
m_dims.GapConstraint();
1243 double opt = gapConstraint.
Opt();
1245 if( !gapConstraint.
HasMax() )
1247 gapConstraint.
SetMax( opt + 10000 );
1250 if( !gapConstraint.
HasMin() )
1252 gapConstraint.
SetMin( opt - 10000 );
1275 SEG test0 ( p_clip.
A, n_clip.
A );
1276 SEG test1 ( p_clip.
B, n_clip.
B );
1293 aPairs.push_back( spair );
1321 return { 0,
false };
1329 if(
m_dims.GapConstraint().Matches( dist ) )
1331 total += p_clip.
Length();
1336 return { total,
true };
1349 l += pair.coupledP.Length();
1356 double lenP =
m_p.Length();
1357 double lenN =
m_n.Length();
1359 return (lenN + lenP ) / 2.0;
1386 std::optional<PNS::DP_PRIMITIVE_PAIR> prims;
1391 for(
auto& cpair : csVec )
1393 if( cpair.coupledN.Contains( pproj ) )
1395 auto cproj = cpair.coupledP.LineProject( pproj );
1397 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1398 prims->SetName( wxT(
"prim-coupled-p" ) );
1401 else if( cpair.coupledP.Contains( pproj ) )
1403 auto cproj = cpair.coupledN.LineProject( pproj );
1405 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1406 prims->SetName( wxT(
"prim-coupled-n" ) );
1414 for(
auto& cpair : csVec )
1426 if( origN.Contains( pproj ) )
1428 auto cproj = origP.LineProject( pproj );
1429 cproj = origP.NearestPoint( cproj );
1431 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1432 prims->SetName( wxT(
"prim-extend-n" ) );
1435 else if( origP.Contains( pproj ) )
1437 auto cproj = origN.LineProject( pproj );
1438 cproj = origN.NearestPoint( cproj );
1440 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1441 prims->SetName( wxT(
"prim-extend-p" ) );
1465 prims->SetName( wxT(
"nearest-fallback" ) );
1474 const int gapTollerance = 100;
1479 std::map<int, int> gapMap;
1481 for(
auto& cs : csVec )
1486 if( !segN || !segP )
1489 int gap = cs.coupledN.LineDistance( cs.coupledP.A ) - ( segP->Width() + segN->Width() ) / 2;
1491 auto iter = gapMap.lower_bound( gap - gapTollerance );
1492 for( ; iter != gapMap.end(); ++iter )
1494 if( iter->first < gap + gapTollerance )
1496 iter->second += cs.coupledN.Length();
1501 if( iter == gapMap.end() )
1502 gapMap[gap] = cs.coupledN.Length();
1508 for(
auto iter : gapMap )
1510 if( bestGapLen < iter.second )
1512 bestGapLen = iter.second;
1513 bestGap = iter.first;
1523 wxString ret = wxString::Format(
"w:%d gap:%d vgap:%d vdiam:%d mincl:%d gap:[%s]",
m_width,
m_gap,
m_viaGap,
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
Represent route directions & corner angles in a 45-degree metric.
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
const DIRECTION_45 Left() const
Return the direction on the left side of this (i.e.
static int AllDirectionsMask()
const VECTOR2I ToVector() const
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
const std::string Format() const
Format the direction in a human readable word.
bool IsObtuse(const DIRECTION_45 &aOther) const
DIRECTION_45 Opposite() const
Return a direction opposite (180 degree) to (this).
bool Matches(const T v) const
Basic class for a differential pair.
bool CheckConnectionAngle(const DIFF_PAIR &aOther, int allowedAngles) const
const SHAPE_LINE_CHAIN & CN() const
DP_PRIMITIVE_PAIR EndingPrimitives()
std::vector< COUPLED_SEGMENTS > COUPLED_SEGMENTS_VEC
double CoupledLength() const
DIFF_PAIR(const DP_DIMENSIONS &aDims=DP_DIMENSIONS())
bool BuildInitial(const DP_GATEWAY &aEntry, const DP_GATEWAY &aTarget, bool aPrefDiagonal, bool aFitVias, float &aBestCouplingRatio, float &aAspectRatio)
int GuessMostLikelyGap() const
double TotalLength() const
std::optional< DP_PRIMITIVE_PAIR > BuildMidpairIntersection(PNS::SEGMENT *aStartSeg, const VECTOR2I &aP)
DIRECTION_45 getDirection(bool aIsP, bool aEnd) const
static constexpr int DP_PARALLELITY_THRESHOLD
const SHAPE_LINE_CHAIN & CP() const
void CoupledSegmentPairs(COUPLED_SEGMENTS_VEC &aPairs, bool aUseGapConstraint=true, const std::optional< DP_GAP_CONSTRAINT > &aOverrideGapConstraint=std::optional< DP_GAP_CONSTRAINT >()) const
const wxString Format() const
DP_GAP_CONSTRAINT m_gapConstraint
void BuildForCursor(const VECTOR2I &aCursorPos, int aDirectionMask=-1)
DP_GATEWAYS(const DP_DIMENSIONS &aDims=DP_DIMENSIONS())
void BuildGeneric(const VECTOR2I &p0_p, const VECTOR2I &p0_n, int aColinearityThreshold=0, bool aBuildEntries=false, bool aViaMode=false)
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
void FilterByOrientation(int aDirectionMask)
void buildEntries(DP_GATEWAY &aGw, const VECTOR2I &p0_p, const VECTOR2I &p0_n)
void addGateway(DP_GATEWAY &aGw, const wxString &name=wxT(""), bool aAddTurns=false)
std::vector< DP_GATEWAY > & Gateways()
bool checkDiagonalAlignment(const VECTOR2I &a, const VECTOR2I &b) const
void BuildOrthoProjections(DP_GATEWAYS &aEntries, const VECTOR2I &aCursorPos, int aOrthoScore)
void buildDpContinuation(const DP_PRIMITIVE_PAIR &aPair, bool aIsDiagonal)
std::vector< DP_GATEWAY > m_gateways
std::vector< FIT_RESULT > FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aFitVias)
Define a "gateway" for routing a differential pair - e.g.
SHAPE_LINE_CHAIN m_entryP
bool HasPrimaryDirection() const
std::optional< DP_GATEWAY > AddTurns(bool aSide, bool a90Deg, bool aLeft, bool aWiggle)
const DP_DIMENSIONS & Dimensions() const
void SetName(const wxString &aName)
const SHAPE_LINE_CHAIN & EntryP() const
bool HasEntryLines() const
int AllowedAngles() const
DP_GATEWAY(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN, bool aIsDiagonal, int aAllowedEntryAngles=DIRECTION_45::ANG_OBTUSE, int aPriority=0, int aDirectionMask=0, const wxString aName=wxT(""))
const VECTOR2I & AnchorN() const
void SetAnchors(const VECTOR2I &aP, const VECTOR2I &aN)
int PrimaryDirectionMask() const
SHAPE_LINE_CHAIN m_entryN
void AddPrimaryDirection(DIRECTION_45 aPrimDir)
void SetDimensions(const DP_DIMENSIONS &aDims)
void SetEntryLines(const SHAPE_LINE_CHAIN &aEntryP, const SHAPE_LINE_CHAIN &aEntryN)
const VECTOR2I & AnchorP() const
const SHAPE_LINE_CHAIN & EntryN() const
const DIFF_PAIR Entry() const
std::optional< DP_GATEWAY > Extend(int aLength)
void SetPrimaryDirection(DIRECTION_45 aPrimDir)
const wxString GetName() const
void SetDirections(DIRECTION_45 dP, DIRECTION_45 dN)
void SetPriority(int aPriority)
Store starting/ending primitives (pads, vias or segments) for a differential pair.
DIRECTION_45 DirN() const
const VECTOR2I & AnchorN() const
static constexpr double DP_ASSUME_PRIMS_COLINEAR_FACTOR
const VECTOR2I & AnchorP() const
int GetMinDimension() const
DIRECTION_45 anchorDirection(const ITEM *aItem, const VECTOR2I &aP) const
void CursorOrientation(const VECTOR2I &aCursorPos, VECTOR2I &aMidpoint, VECTOR2I &aDirection) const
DP_PRIMITIVE_PAIR & operator=(const DP_PRIMITIVE_PAIR &aOther)
void SetPrimitives(ITEM *aPrimP, ITEM *aPrimN)
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
DIRECTION_45 DirP() const
Base class for PNS router board items.
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
bool OfKind(int aKindMask) const
virtual VECTOR2I Anchor(int n) const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
const SHAPE_LINE_CHAIN & CLine() const
SEGMENT * FindLinkContainingVertex(const VECTOR2I &aP) const
const SEG CSegment(int aIdx) const
Set line width.
bool IsLinked() const
Check if the segment aLink is a part of the line.
bool ContainsLink(const LINKED_ITEM *aItem) const
LINKED_ITEM * GetLink(int aIndex) const
Erase the linking information. Used to detach the line from the owning node.
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
ROUTER_IFACE * GetInterface() const
ROUTING_SETTINGS & Settings()
static ROUTER * GetInstance()
double DiffPairGapCouplingRecognitionThreshold() const
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
int Length() const
Return the length (this).
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
ecoord TCoef(const VECTOR2I &aP) const
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
ecoord SquaredLength() const
bool ApproxCollinear(const SEG &aSeg, int aDistanceThreshold=1) const
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
bool Contains(const SEG &aSeg) const
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
SHAPE_TYPE Type() const
Return the type of the shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
const std::optional< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
An abstract shape on 2D plane.
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
static std::string ToStdString(const wxString &aStr)
Push and Shove diff pair dimensions (gap) settings dialog.
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
const wxString Format(const MINOPTMAX< int > x)
static int minDimensionForPrimitive(const ITEM *aPrim)
static VECTOR2I makeGapVector(VECTOR2I dir, int length)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
#define PNS_DBG(dbg, method,...)
#define PNS_DBGN(dbg, method)
std::optional< VECTOR2I > OPT_VECTOR2I
@ SH_RECT
axis-aligned rectangle
@ SH_SIMPLE
simple polygon
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
wxString result
Test unit parsing edge cases and error handling.
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
constexpr int sign(T val)
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
VECTOR2< int32_t > VECTOR2I