KiCad PCB EDA Suite
geometry_utils.h File Reference

a few functions useful in geometry calculations. More...

#include <math/vector2d.h>

Go to the source code of this file.

Macros

#define DOT_WIDTH_MILS   0.0254
 Dashed and dotted line patterns. More...
 
#define DOT_MARK_LEN(aLineWidth)   ( std::max( 1.0, IU_PER_MILS * DOT_WIDTH_MILS - aLineWidth ) )
 
#define DASH_GAP_LEN(aLineWidth)   ( 3.0 * DOT_MARK_LEN( aLineWidth ) + ( 2.0 * aLineWidth ) )
 
#define DASH_MARK_LEN(aLineWidth)   ( std::max( DASH_GAP_LEN( aLineWidth ), 5.0 * DOT_MARK_LEN( aLineWidth ) ) )
 

Functions

int GetArcToSegmentCount (int aRadius, int aErrorMax, double aArcAngleDegree)
 
double GetCircletoPolyCorrectionFactor (int aSegCountforCircle)
 
template<typename T >
VECTOR2< T > GetVectorSnapped45 (const VECTOR2< T > &aVec)
 Snap a vector onto the nearest 0, 45 or 90 degree line. More...
 
bool ClipLine (const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2)
 Test if any part of a line falls within the bounds of a rectangle. More...
 

Detailed Description

a few functions useful in geometry calculations.

Definition in file geometry_utils.h.

Macro Definition Documentation

◆ DASH_GAP_LEN

#define DASH_GAP_LEN (   aLineWidth)    ( 3.0 * DOT_MARK_LEN( aLineWidth ) + ( 2.0 * aLineWidth ) )

Definition at line 130 of file geometry_utils.h.

◆ DASH_MARK_LEN

#define DASH_MARK_LEN (   aLineWidth)    ( std::max( DASH_GAP_LEN( aLineWidth ), 5.0 * DOT_MARK_LEN( aLineWidth ) ) )

Definition at line 133 of file geometry_utils.h.

◆ DOT_MARK_LEN

#define DOT_MARK_LEN (   aLineWidth)    ( std::max( 1.0, IU_PER_MILS * DOT_WIDTH_MILS - aLineWidth ) )

Definition at line 127 of file geometry_utils.h.

◆ DOT_WIDTH_MILS

#define DOT_WIDTH_MILS   0.0254

Dashed and dotted line patterns.

Note: these are all macros because they're included from files with different IU definitions.

Definition at line 125 of file geometry_utils.h.

Function Documentation

◆ ClipLine()

bool ClipLine ( const EDA_RECT aClipBox,
int &  x1,
int &  y1,
int &  x2,
int &  y2 
)

Test if any part of a line falls within the bounds of a rectangle.

Please note that this is only accurate for lines that are one pixel wide.

Parameters
aClipBox- The rectangle to test.
x1- X coordinate of one end of a line.
y1- Y coordinate of one end of a line.
x2- X coordinate of the other end of a line.
y2- Y coordinate of the other end of a line.
Returns
- False if any part of the line lies within the rectangle.

Definition at line 97 of file geometry_utils.cpp.

98 {
99  // Stock Cohen-Sutherland algorithm; check *any* CG book for details
100  int outcode1 = clipOutCode( aClipBox, x1, y1 );
101  int outcode2 = clipOutCode( aClipBox, x2, y2 );
102 
103  while( outcode1 || outcode2 )
104  {
105  // Fast reject
106  if( outcode1 & outcode2 )
107  return true;
108 
109  // Choose a side to clip
110  int thisoutcode, x, y;
111 
112  if( outcode1 )
113  thisoutcode = outcode1;
114  else
115  thisoutcode = outcode2;
116 
117  /* One clip round
118  * Since we use the full range of 32 bit ints, the proportion
119  * computation has to be done in 64 bits to avoid horrible
120  * results */
121  if( thisoutcode & 1 ) // Clip the bottom
122  {
123  y = aClipBox->GetBottom();
124  x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1);
125  }
126  else if( thisoutcode & 2 ) // Clip the top
127  {
128  y = aClipBox->GetY();
129  x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1);
130  }
131  else if( thisoutcode & 8 ) // Clip the right
132  {
133  x = aClipBox->GetRight();
134  y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1);
135  }
136  else // if( thisoutcode & 4), obviously, clip the left
137  {
138  x = aClipBox->GetX();
139  y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1);
140  }
141 
142  // Put the result back and update the boundary code
143  // No ambiguity, otherwise it would have been a fast reject
144  if( thisoutcode == outcode1 )
145  {
146  x1 = x;
147  y1 = y;
148  outcode1 = clipOutCode( aClipBox, x1, y1 );
149  }
150  else
151  {
152  x2 = x;
153  y2 = y;
154  outcode2 = clipOutCode( aClipBox, x2, y2 );
155  }
156  }
157  return false;
158 }
int clipOutCode(const EDA_RECT *aClipBox, int x, int y)
int GetX() const
Definition: eda_rect.h:109
int GetBottom() const
Definition: eda_rect.h:122
int GetRight() const
Definition: eda_rect.h:119
int GetY() const
Definition: eda_rect.h:110

References clipOutCode(), EDA_RECT::GetBottom(), EDA_RECT::GetRight(), EDA_RECT::GetX(), and EDA_RECT::GetY().

Referenced by KIGFX::SCH_PAINTER::draw(), GRCSegm(), GRLineArray(), and WinClipAndDrawLine().

◆ GetArcToSegmentCount()

int GetArcToSegmentCount ( int  aRadius,
int  aErrorMax,
double  aArcAngleDegree 
)
Returns
the number of segments to approximate a arc by segments with a given max error (this number is >= 1)
Parameters
aRadiusis the radius od the circle or arc
aErrorMaxis the max error This is the max distance between the middle of a segment and the circle.
aArcAngleDegreeis the arc angle in degrees

Definition at line 36 of file geometry_utils.cpp.

37 {
38  // calculate the number of segments to approximate a circle by segments
39  // given the max distance between the middle of a segment and the circle
40 
41  // error relative to the radius value:
42  double rel_error = (double)aErrorMax / aRadius;
43  // minimal arc increment in degrees:
44  double arc_increment = 180 / M_PI * acos( 1.0 - rel_error ) * 2;
45 
46  // Ensure a minimal arc increment reasonable value for a circle
47  // (360.0 degrees). For very small radius values, this is mandatory.
48  arc_increment = std::min( 360.0/MIN_SEGCOUNT_FOR_CIRCLE, arc_increment );
49 
50  int segCount = round_nearest( fabs( aArcAngleDegree ) / arc_increment );
51 
52  // Ensure at least one segment is used (can happen for small arcs)
53  return std::max( segCount, 1 );
54 }
static int round_nearest(double v)
Definition: math_util.h:56
#define MIN_SEGCOUNT_FOR_CIRCLE
#define max(a, b)
Definition: auxiliary.h:86
#define min(a, b)
Definition: auxiliary.h:85

References max, min, MIN_SEGCOUNT_FOR_CIRCLE, and round_nearest().

Referenced by SHAPE_POLY_SET::chamferFilletPolygon(), ConvertOutlineToPolygon(), SHAPE_ARC::ConvertToPolyline(), CINFO3D_VISU::GetNrSegmentsCircle(), EAGLE_PLUGIN::loadPolygon(), EAGLE_PLUGIN::loadSignals(), DSN::SPECCTRA_DB::makeIMAGE(), EAGLE_PLUGIN::packagePolygon(), and DRAWSEGMENT::TransformShapeWithClearanceToPolygon().

◆ GetCircletoPolyCorrectionFactor()

double GetCircletoPolyCorrectionFactor ( int  aSegCountforCircle)
Returns
the correction factor to approximate a circle by segments
Parameters
aSegCountforCircleis the number of segments to approximate the circle

When creating a polygon from a circle, the polygon is inside the circle. Only corners are on the circle. This is incorrect when building clearance areas of circles, that need to build the equivalent polygon outside the circle The correction factor is a scaling factor to apply to the radius to build a polygon outside the circle (only the middle of each segment is on the circle

Definition at line 57 of file geometry_utils.cpp.

58 {
59  /* calculates the coeff to compensate radius reduction of circle
60  * due to the segment approx.
61  * For a circle the min radius is radius * cos( 2PI / aSegCountforCircle / 2)
62  * this is the distance between the center and the middle of the segment.
63  * therefore, to move the middle of the segment to the circle (distance = radius)
64  * the correctionFactor is 1 /cos( PI/aSegCountforCircle )
65  */
66  if( aSegCountforCircle < MIN_SEGCOUNT_FOR_CIRCLE )
67  aSegCountforCircle = MIN_SEGCOUNT_FOR_CIRCLE;
68 
69  return 1.0 / cos( M_PI / aSegCountforCircle );
70 }
#define MIN_SEGCOUNT_FOR_CIRCLE

References MIN_SEGCOUNT_FOR_CIRCLE.

Referenced by ZONE_FILLER::buildZoneFeatureHoleList(), ZONE_FILLER::computeRawFilledAreas(), BOARD::ConvertBrdLayerToPolygonalContours(), CINFO3D_VISU::GetCircleCorrectionFactor(), PlotSolderMaskLayer(), DRC::testCopperDrawItem(), and DRC::testCopperTextItem().

◆ GetVectorSnapped45()

template<typename T >
VECTOR2<T> GetVectorSnapped45 ( const VECTOR2< T > &  aVec)

Snap a vector onto the nearest 0, 45 or 90 degree line.

The magnitude of the vector is NOT kept, instead the co-ordinates are set equal (and/or opposite) or to zero as needed. The effect of this is that if the starting vector is on a square grid, the resulting snapped vector will still be on the same grid.

Parameters
avector to be snapped
Returns
the snapped vector

Definition at line 73 of file geometry_utils.h.

74 {
75  auto newVec = aVec;
76  const VECTOR2<T> absVec { std::abs( aVec.x ), std::abs( aVec.y ) };
77 
78  if ( absVec.x > absVec.y * 2 )
79  {
80  // snap along x-axis
81  newVec.y = 0;
82  }
83  else if ( absVec.y > absVec.x * 2 )
84  {
85  // snap onto y-axis
86  newVec.x = 0;
87  }
88  else if ( absVec.x > absVec.y )
89  {
90  // snap away from x-axis towards 45
91  newVec.y = std::copysign( aVec.x, aVec.y );
92  } else
93  {
94  // snap away from y-axis towards 45
95  newVec.x = std::copysign( aVec.y, aVec.x );
96  }
97 
98  return newVec;
99 }
Class VECTOR2 defines a general 2D-vector/point.
Definition: vector2d.h:61
#define abs(a)
Definition: auxiliary.h:84

References abs, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DRAWING_TOOL::constrainDimension(), DRAWING_TOOL::drawSegment(), KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER::SetEnd(), and POLYGON_GEOM_MANAGER::updateLeaderPoints().