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 )
228#ifdef DIFF_PLACER_EXTRA_VERBOSE
230 wxString::Format(
"init+ prefDiag %d (dims %s) %s/%s cl %d %d %d", aPrefDiagonal ? 1 : 0,
m_dims.Format(),
233 PNS_DBG( dbg, AddShape, &n,
BLUE, 20000, wxT(
"init-" ) );
240 bool entryIsStraight =
false;
241 bool targetIsStraight =
false;
247 if( !( dirMask & dir2.
Mask() ) )
250 failReason = wxT(
"fail-primary-entry" );
261 failReason = wxT(
"fail-primary-target" );
271 failReason = wxT(
"fail-entry-angle" );
299 failReason = wxT(
"fail-exit-angle" );
320 failReason = wxT(
"fail-gap" );
323 float minLength = std::min(
m_p.Length(),
m_n.Length() );
324 if( minLength >= 1.0 )
325 aBestCouplingRatio = coupledLength / minLength;
327 aBestCouplingRatio = 0;
334 if( !fail && ( ip_p || ip_n ) )
336 PNS_DBG( dbg, AddPoint, ip_p->p,
RED, 20000, wxT(
"ip+" ) );
337 PNS_DBG( dbg, AddPoint, ip_n->p,
BLUE, 20000, wxT(
"ip-" ) );
340 failReason = wxT(
"fail-self-intersect" );
344 if( !fail &&
m_p.Intersects(
m_n ) )
347 failReason = wxT(
"fail-intersect" );
349 int distP = 0, distN = 0, threshold = 0;
353 distP =
m_n.Distance(
m_p.CLastPoint() );
354 distN =
m_p.Distance(
m_n.CLastPoint() );
356 threshold = (
m_dims.ViaDiameter() / 2 + 1 ) +
m_dims.MinClearance() -
m_dims.Width() / 2;
358 if( distP < threshold || distN < threshold )
361 failReason = wxString::Format(
"fail-vias dp=%d dn=%d thr=%d cl=%d w=%d", distP, distN, threshold,
367 failReason = wxT(
"OK" );
369 if( entryIsStraight && targetIsStraight )
372#ifdef DIFF_PLACER_EXTRA_VERBOSE
374 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 "
378 aEntry.
IsDiagonal() ? 1 : 0, entryIsStraight ? 1 : 0, targetIsStraight ? 1 : 0,
379 aBestCouplingRatio, aAspectRatio, distP, distN, threshold, aFitVias ? 1 : 0 ),
410 checkP = ( p0.
Angle( p1 ) & aAllowedAngles ) != 0;
422 checkN = ( n0.
Angle( n1 ) & aAllowedAngles ) != 0;
425 return checkP && checkN;
453 int dist =
test.LineDistance( sP.
B,
true );
455 SEG test2( sP.
B, sP.
B + perp );
463 sP.
B =
test.LineProject( sP.
B );
497 const double turnAngle = aWiggle ? 22.6 : 22.5;
499 int leadLen = (int) ( (
double) (gap) *tan( turnAngle *
M_PI / 180.0 ) ) + 1;
502 wxString::Format(
"addturn orig %s gap %d %s %s lead %d",
m_name, gap, dP.
Format(), dN.
Format(),
553 if(
name != wxT(
"" ) )
562 const double widthToMiterRatio = router->Settings().DiffPairWidthToMiterRatio();
563 const int extensionDist = (int) ( widthToMiterRatio * (
double) aGw.
Dimensions().
Width() );
564 std::optional<DP_GATEWAY> extend, turn45_l, turn45_r, turn45_lw, turn45_rw;
565 std::optional<DP_GATEWAY> turn45_le, turn45_re;
567 turn45_l = aGw.
AddTurns(
false,
false,
true,
false );
568 if( turn45_l.has_value() )
571 turn45_le = turn45_l->Extend( extensionDist );
572 if( turn45_le.has_value() )
576 std::optional<DP_GATEWAY> turn90_lel = turn45_le->AddTurns(
false,
false,
true,
false );
577 if( turn90_lel.has_value() )
583 turn45_r = aGw.
AddTurns(
false,
false,
false,
false );
584 if( turn45_r.has_value() )
587 turn45_re = turn45_r->Extend( extensionDist );
588 if( turn45_re.has_value() )
590 std::optional<DP_GATEWAY> turn90_rer = turn45_re->AddTurns(
false,
false,
false,
false );
591 if( turn90_rer.has_value() )
608 VECTOR2I midpoint( ( g.AnchorP() + g.AnchorN() ) / 2 );
609 SEG guide_s( midpoint, midpoint +
VECTOR2I( 1, 0 ) );
610 SEG guide_d( midpoint, midpoint +
VECTOR2I( 1, 1 ) );
615 int dist_s = ( proj_s - aCursorPos ).EuclideanNorm();
616 int dist_d = ( proj_d - aCursorPos ).EuclideanNorm();
618 VECTOR2I proj = ( dist_s < dist_d ? proj_s : proj_d );
627 t.SetPriority( aOrthoScore );
628 t.SetName( wxString::Format(
"ortho-%d", cnt).
ToStdString() );
639 std::vector<DP_GATEWAYS::FIT_RESULT> results;
643 PNS_DBG( dbg, BeginGroup, wxT(
"fit-gateways" ), 0 );
645 for(
bool diagonal : {
true,
false } )
652 result.score = g_entry.Priority();
653 result.score += g_target.Priority();
660 result.diagonal = diagonal;
663 results.push_back(
result );
678 return ( dir.
x == 0 && dir.
y != 0 ) || ( dir.
x == dir.
y ) || ( dir.
y == 0 && dir.
x != 0 );
704 }
while( ( rv * 2 ).EuclideanNorm() < length );
714 int orthoFanDistance = 0;
715 int diagFanDistance = 0;
717 const SHAPE* shP =
nullptr;
719 if( aPair.
PrimP() ==
nullptr || aPair.
PrimN() ==
nullptr )
743 majorDirection = ( p0_p - p0_n ).Perpendicular();
750 switch( shP->
Type() )
753 BuildGeneric ( p0_p, p0_n, colinearityThreshold,
true );
758 int w =
static_cast<const SHAPE_RECT*
>( shP )->GetWidth();
759 int h =
static_cast<const SHAPE_RECT*
>( shP )->GetHeight();
764 orthoFanDistance = ( w + 1 )* 3 / 2;
765 diagFanDistance = ( w - h );
771 int w =
static_cast<const SHAPE_SEGMENT*
>( shP )->GetWidth();
774 orthoFanDistance = w + ( s.
B - s.
A ).EuclideanNorm();
775 diagFanDistance = ( s.
B - s.
A ).EuclideanNorm();
789 orthoFanDistance = ( w + 1 )* 3 / 2;
790 diagFanDistance = ( w - h );
795 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported starting primitive: %d (%s)." ),
803 int padDist = ( p0_p - p0_n ).EuclideanNorm();
805 for(
int k = 0; k < 2; k++ )
814 int d = std::max( 0, padDist - gap );
818 for(
int i = 0; i < 2; i++ )
820 int sign = i ? -1 : 1;
830 gw.SetName( wxString::Format(
"pp-%d-%d", k, i ).
ToStdString() );
831 gw.SetEntryLines( entryP, entryN );
835 gw.SetDimensions(
m_dims );
836 gw.SetPriority( 101 - k );
837 gw.SetDirections( dir1, dir1 );
838 gw.SetPrimaryDirection( dir1 );
841 auto gw_ext = gw.Extend( 400000 );
856 for(
bool diagonal : {
false,
true } )
858 for(
int i = 0; i < 4; i++ )
875 dir =
VECTOR2I( (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ), 0 );
877 dir =
VECTOR2I( 0, (gap + 1) / 2 * ( ( i % 2 ) ? -1 : 1 ) );
883 BuildGeneric( aCursorPos + dir, aCursorPos - dir, 0,
true,
true );
887 DP_GATEWAY gw( aCursorPos + dir, aCursorPos - dir, diagonal );
939 PNS_DBG( dbg, Message, wxString::Format(
"buildDpCont: gap=%d dn=%s dp=%s", gap, dN.
Format(), dP.
Format() ) );
980 SEG st_p[2], st_n[2];
984 const int padToGapThreshold = 3;
985 int padDist = ( p0_n - p0_p ).EuclideanNorm();
1003 for(
int i = 0; i < 2; i++ )
1009 if( straightColl || diagColl )
1013 int prio = ( padDist > padToGapThreshold * gap ) ? 2 : 1;
1028 for(
int i = 0; i < 2; i++ )
1030 for(
int j = 0; j < 2; j++ )
1037 if( d_n[i].Collinear( d_p[j] ) )
1040 if( st_p[i].Collinear( st_p[j] ) )
1047 for(
int k = 0; k < 2; k++ )
1053 if( m != p0_p && m != p0_n )
1055 int prio = ( padDist > padToGapThreshold * gap ? 10 : 20 );
1056 VECTOR2I g_p( ( p0_p - m ).Resize( ceil( (
double) gap * M_SQRT1_2 ) ) );
1057 VECTOR2I g_n( ( p0_n - m ).Resize( ceil( (
double) gap * M_SQRT1_2 ) ) );
1072 auto gw_ext = gw.
Extend( 400000 );
1073 if( gw_ext && !aViaMode )
1083 for(
int k = 0; k < 2; k++ )
1089 if( !aViaMode && m != p0_p && m != p0_n )
1093 g_p = ( p0_p - m ).Resize( ceil( (
double) gap * M_SQRT2 ) );
1094 g_n = ( p0_n - m ).Resize( ceil( (
double) gap ) );
1097 m_gateways.emplace_back( m + g_p, m + g_n,
true );
1099 g_p = ( p0_p - m ).Resize( gap );
1100 g_n = ( p0_n - m ).Resize( ceil( (
double) gap * M_SQRT2 ) );
1103 m_gateways.emplace_back( m + g_p, m + g_n,
true );
1123 return seg->Width();
1125 return arc->Width();
1183 int64_t t_b = p.
TCoef( p.
B );
1185 int64_t tproj_a = p.
TCoef( n_proj_p.
A );
1186 int64_t tproj_b = p.
TCoef( n_proj_p.
B );
1189 std::swap( t_b, t_a );
1191 if( tproj_b < tproj_a )
1192 std::swap( tproj_b, tproj_a );
1194 if( t_b <= tproj_a )
1197 if( t_a >= tproj_b )
1201 std::vector<int64_t> tv( t, t + 4 );
1202 std::sort( tv.begin(), tv.end() );
1207 pClip.
A.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[1], pLenSq );
1208 pClip.
A.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[1], pLenSq );
1210 pClip.
B.
x = p.
A.
x +
rescale( (int64_t)dp.
x, tv[2], pLenSq );
1211 pClip.
B.
y = p.
A.
y +
rescale( (int64_t)dp.
y, tv[2], pLenSq );
1222 return m_p.Length() -
m_n.Length();
1227 bool aUseGapConstraint,
1228 const std::optional<DP_GAP_CONSTRAINT>& aOverrideGapConstraint )
const
1237 gapConstraint.
SetMin( 0 );
1238 gapConstraint.
SetMax( (
int) ( (
double)
m_dims.Width() * threshold ) );
1240 if ( aOverrideGapConstraint )
1241 gapConstraint = aOverrideGapConstraint.value();
1242 else if( aUseGapConstraint )
1243 gapConstraint =
m_dims.GapConstraint();
1245 double opt = gapConstraint.
Opt();
1247 if( !gapConstraint.
HasMax() )
1249 gapConstraint.
SetMax( opt + 10000 );
1252 if( !gapConstraint.
HasMin() )
1254 gapConstraint.
SetMin( opt - 10000 );
1277 SEG test0 ( p_clip.
A, n_clip.
A );
1278 SEG test1 ( p_clip.
B, n_clip.
B );
1295 aPairs.push_back( spair );
1323 return { 0,
false };
1331 if(
m_dims.GapConstraint().Matches( dist ) )
1333 total += p_clip.
Length();
1338 return { total,
true };
1351 l += pair.coupledP.Length();
1358 double lenP =
m_p.Length();
1359 double lenN =
m_n.Length();
1361 return (lenN + lenP ) / 2.0;
1388 std::optional<PNS::DP_PRIMITIVE_PAIR> prims;
1393 for(
auto& cpair : csVec )
1395 if( cpair.coupledN.Contains( pproj ) )
1397 auto cproj = cpair.coupledP.LineProject( pproj );
1399 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1400 prims->SetName( wxT(
"prim-coupled-p" ) );
1403 else if( cpair.coupledP.Contains( pproj ) )
1405 auto cproj = cpair.coupledN.LineProject( pproj );
1407 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1408 prims->SetName( wxT(
"prim-coupled-n" ) );
1416 for(
auto& cpair : csVec )
1428 if( origN.Contains( pproj ) )
1430 auto cproj = origP.LineProject( pproj );
1431 cproj = origP.NearestPoint( cproj );
1433 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1434 prims->SetName( wxT(
"prim-extend-n" ) );
1437 else if( origP.Contains( pproj ) )
1439 auto cproj = origN.LineProject( pproj );
1440 cproj = origN.NearestPoint( cproj );
1442 prims->SetPrimitives( cpair.linkP, cpair.linkN );
1443 prims->SetName( wxT(
"prim-extend-p" ) );
1467 prims->SetName( wxT(
"nearest-fallback" ) );
1476 const int gapTollerance = 100;
1481 std::map<int, int> gapMap;
1483 for(
auto& cs : csVec )
1488 if( !segN || !segP )
1491 int gap = cs.coupledN.LineDistance( cs.coupledP.A ) - ( segP->Width() + segN->Width() ) / 2;
1493 auto iter = gapMap.lower_bound( gap - gapTollerance );
1494 for( ; iter != gapMap.end(); ++iter )
1496 if( iter->first < gap + gapTollerance )
1498 iter->second += cs.coupledN.Length();
1503 if( iter == gapMap.end() )
1504 gapMap[gap] = cs.coupledN.Length();
1510 for(
auto iter : gapMap )
1512 if( bestGapLen < iter.second )
1514 bestGapLen = iter.second;
1515 bestGap = iter.first;
1525 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
bool ContainsLink(const LINKED_ITEM *aItem) const
Check if the segment aLink is a part of the line.
LINKED_ITEM * GetLink(int aIndex) const
int LinkCount() const
Return the number of segments that were assembled together to form this line.
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