Commit c5973eb8 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add documentation to .h files and update code formatting

parent c25acdbb
......@@ -11,54 +11,69 @@ TEARDROP::TEARDROP()
m_type = TEARDROP_NONE;
}
bool TEARDROP::Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type = TEARDROP_STRAIGHT)
bool TEARDROP::Create(TRACK& aTrack, ENDPOINT_T aEndPoint, TEARDROP_TYPE aType = TEARDROP_STRAIGHT )
{
bool result = false;
BOARD_CONNECTED_ITEM *anObject = GetObjectOnEnd(aTrack, endPoint);
VIA *aVia = NULL;
if (anObject == NULL) {
BOARD_CONNECTED_ITEM* object = getObjectOnEnd( aTrack, aEndPoint );
VIA* aVia = NULL;
if( object == NULL )
{
return false;
}
else {
switch (anObject->Type()) {
else
{
switch( object->Type() )
{
case PCB_VIA_T:
aVia = dynamic_cast<VIA *>(anObject);
aVia = dynamic_cast<VIA*>( object );
break;
case PCB_PAD_T:
aVia = new VIA(NULL);
aVia->SetLayer(anObject->GetLayer());
aVia->SetPosition(anObject->GetPosition());
aVia->SetWidth(2 * dynamic_cast<D_PAD *>(anObject)->GetBoundingRadius());
aVia = new VIA( NULL );
aVia->SetLayer( object->GetLayer() );
aVia->SetPosition( object->GetPosition() );
aVia->SetWidth( 2 * dynamic_cast<D_PAD*>( object )->GetBoundingRadius() );
break;
default:
break;
}
}
if (type == TEARDROP_STRAIGHT) {
result = StraightSegments(aTrack, *aVia, 100);
if( aType == TEARDROP_STRAIGHT )
{
result = straightSegments( aTrack, *aVia, 100 );
}
else if (type == TEARDROP_CURVED) {
result = CurvedSegments(aTrack, *aVia);
else if( aType == TEARDROP_CURVED )
{
result = curvedSegments( aTrack, *aVia );
}
return result;
}
bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint, VECTOR2I &endPoint)
bool TEARDROP::setVector(TRACK& aTrack, const VIA& aVia, VECTOR2I& aStartPoint, VECTOR2I& aEndPoint )
{
// Decide which end of the track is inside via and set this point as end of vector
STATUS_FLAGS status = aTrack.IsPointOnEnds(aVia.GetPosition(), aVia.GetWidth() / 2);
if (status == STARTPOINT) {
startPoint = aTrack.GetEnd();
endPoint = aTrack.GetStart();
STATUS_FLAGS status = aTrack.IsPointOnEnds( aVia.GetPosition(), aVia.GetWidth() / 2 );
if( status == STARTPOINT )
{
aStartPoint = aTrack.GetEnd();
aEndPoint = aTrack.GetStart();
}
else if (status == ENDPOINT) {
startPoint = aTrack.GetStart();
endPoint = aTrack.GetEnd();
else if( status == ENDPOINT )
{
aStartPoint = aTrack.GetStart();
aEndPoint = aTrack.GetEnd();
}
else {
else
{
// The via is too far from any end or the track is too short
return false;
}
......@@ -66,88 +81,120 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint,
return true;
}
bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia)
bool TEARDROP::curvedSegments( TRACK& aTrack, const VIA& aVia )
{
VECTOR2I startPoint(0, 0);
VECTOR2I endPoint(0, 0);
std::vector<VECTOR2I> upperSegment;
std::vector<VECTOR2I> lowerSegment;
VECTOR2I startPoint( 0, 0 );
VECTOR2I endPoint( 0, 0 );
std::vector<VECTOR2I> lowerSegment;
if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) {
if( !setVector( aTrack, aVia, startPoint, endPoint ) )
{
return false;
}
// Check that the track is not too short
double segOutsideVia = aTrack.GetLength() - (aVia.GetWidth() / 2);
double minLength = (150 * aVia.GetWidth() / 2) / 100;
if (segOutsideVia < minLength) {
if( segOutsideVia < minLength )
{
return false;
}
VECTOR2I point(0, 0);
VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y);
VECTOR2I apertureUpper(0, 0);
VECTOR2I apertureLower(0, 0);
VECTOR2I point( 0, 0 );
VECTOR2I viaCenter( aVia.GetPosition().x, aVia.GetPosition().y );
VECTOR2I apertureUpper( 0, 0 );
VECTOR2I apertureLower( 0, 0 );
double radius = (aVia.GetWidth() / 2) - (aTrack.GetWidth() / 2);
double rotationAngle = VECTOR2I(startPoint - endPoint).Angle();
double rotationAngle = VECTOR2I( startPoint - endPoint ).Angle();
// Calculate the segments of deltoid composing the outline of a teardrop
for ( int i = 10; i <= 60; i = i + 10 ) {
PointOnCurve(i, radius, point);
point = point.Rotate(rotationAngle);
for( int i = 0; i <= 60; i = i + 10 )
{
pointOnCurve( i, radius, point );
point = point.Rotate( rotationAngle );
point += viaCenter;
m_coordinates.push_back(point);
if (i == 50) {
m_coordinates.push_back( point );
if( i == 50 )
{
apertureUpper = point;
}
}
for ( int i = 300; i <= 350; i = i + 10 ) {
PointOnCurve(i, radius, point);
point = point.Rotate(rotationAngle);
for( int i = 300; i <= 360; i = i + 10 )
{
pointOnCurve( i, radius, point );
point = point.Rotate( rotationAngle );
point += viaCenter;
m_coordinates.push_back(point);
if (i == 340) {
m_coordinates.push_back( point );
if( i == 340 )
{
apertureLower = point;
}
}
// Calculate the number of segments needed to fill the area inside the teardrop
if (aVia.GetWidth() / 2 > 2 * aTrack.GetWidth()) {
if( aVia.GetWidth() / 2 > 2 * aTrack.GetWidth() )
{
// First, calculate the distance between two points on both sides of the track and
// number of iterations required to fill the zone
SEG aperture(apertureUpper, apertureLower);
SEG aperture( apertureUpper, apertureLower );
int numSegments = aperture.Length() / aTrack.GetWidth();
int delta = radius / numSegments;
for (int iteration = 0; iteration < numSegments; iteration++) {
// Second, fill the inward teardrop area
for( int iteration = 0; iteration < numSegments; iteration++ )
{
radius = radius - delta;
for ( int i = 10; i <= 60; i = i + 10 ) {
PointOnCurve(i, radius, point);
point = point.Rotate(rotationAngle);
for( int i = 10; i <= 60; i = i + 10 )
{
pointOnCurve( i, radius, point );
point = point.Rotate( rotationAngle );
point += viaCenter;
if (i == 10) {
int distance = SEG(viaCenter, point).Length();
if (distance < aVia.GetWidth() / 2) {
// Stop calculations in case the coordinates are inside the via
if( i == 10 )
{
int distance = SEG( viaCenter, point ).Length();
if( distance < aVia.GetWidth() / 2 )
{
break;
}
}
m_coordinates.push_back(point);
m_coordinates.push_back( point );
}
lowerSegment.clear();
for ( int i = 350; i >= 300; i = i - 10 ) {
PointOnCurve(i, radius, point);
point = point.Rotate(rotationAngle);
for( int i = 350; i >= 300; i = i - 10 )
{
pointOnCurve( i, radius, point );
point = point.Rotate( rotationAngle );
point += viaCenter;
if (i == 350) {
int distance = SEG(viaCenter, point).Length();
if (distance < aVia.GetWidth() / 2) {
// Stop calculations in case the coordinates are inside the via
if( i == 350 )
{
int distance = SEG( viaCenter, point ).Length();
if( distance < aVia.GetWidth() / 2 )
{
break;
}
}
lowerSegment.push_back(point);
lowerSegment.push_back( point );
}
// Revert coordinates order
for (std::vector<VECTOR2I>::reverse_iterator iter = lowerSegment.rbegin(); iter != lowerSegment.rend(); ++iter) {
m_coordinates.push_back(*iter);
// Revert coordinates order. This is necessary to create tracks in correct order later on
for( std::vector<VECTOR2I>::reverse_iterator iter = lowerSegment.rbegin();
iter != lowerSegment.rend();
++iter )
{
m_coordinates.push_back( *iter );
}
}
}
......@@ -155,140 +202,173 @@ bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia)
return true;
}
bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, int distance = 100)
bool TEARDROP::straightSegments(TRACK& aTrack, const VIA& aVia, int aDistance = 100 )
{
VECTOR2I startPoint(0, 0);
VECTOR2I endPoint(0, 0);
VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y);
VECTOR2I startPoint( 0, 0 );
VECTOR2I endPoint( 0, 0 );
VECTOR2I viaCenter( aVia.GetPosition().x, aVia.GetPosition().y );
if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) {
if( !setVector( aTrack, aVia, startPoint, endPoint ) )
{
return false;
}
// Check that the track is not too short
double segOutsideVia = aTrack.GetLength() - (aVia.GetWidth() / 2);
double minLength = (distance * aVia.GetWidth() / 2) / 100;
if (segOutsideVia < minLength) {
double minLength = (aDistance * aVia.GetWidth() / 2) / 100;
if( segOutsideVia < minLength )
{
return false;
}
// Equation coefficients
double r = (aVia.GetWidth() / 2) + ((distance * aVia.GetWidth()) / (2 *100));
double a = pow((endPoint.x - startPoint.x), 2) + pow((endPoint.y - startPoint.y), 2);
double b = 2 * (double)(endPoint.x - startPoint.x) * (double)(startPoint.x - viaCenter.x) + 2 * (double)(endPoint.y - startPoint.y) * (double)(startPoint.y - viaCenter.y);
double c = pow((startPoint.x - viaCenter.x), 2) + pow((startPoint.y - viaCenter.y), 2) - pow(r, 2);
double t = 2 * c / (-b + sqrt(b * b - 4 * a * c));
double r = (aVia.GetWidth() / 2) + ( (aDistance * aVia.GetWidth()) / (2 * 100) );
double a = pow( (endPoint.x - startPoint.x), 2 ) + pow( (endPoint.y - startPoint.y), 2 );
double b = 2 * (double)(endPoint.x - startPoint.x) * (double)(startPoint.x - viaCenter.x) +
2 * (double)(endPoint.y - startPoint.y) * (double)(startPoint.y - viaCenter.y);
double c = pow( (startPoint.x - viaCenter.x), 2 ) + pow( (startPoint.y - viaCenter.y), 2 ) - pow( r, 2 );
double t = 2 * c / (-b + sqrt( b * b - 4 * a * c));
double x = (endPoint.x - startPoint.x) * t + startPoint.x;
double y = (endPoint.y - startPoint.y) * t + startPoint.y;
VECTOR2I linePoint(x, y);
VECTOR2I linePoint( x, y );
int correctedRadius = (aVia.GetWidth() / 2) - (aTrack.GetWidth() / 2);
c = pow((startPoint.x - viaCenter.x), 2) + pow((startPoint.y - viaCenter.y), 2) - pow(correctedRadius, 2);
t = 2 * c / (-b + sqrt(b * b - 4 * a * c));
c = pow( (startPoint.x - viaCenter.x), 2 ) + pow( (startPoint.y - viaCenter.y), 2 ) - pow( correctedRadius, 2 );
t = 2 * c / (-b + sqrt( b * b - 4 * a * c ));
x = (endPoint.x - startPoint.x) * t + startPoint.x;
y = (endPoint.y - startPoint.y) * t + startPoint.y;
VECTOR2I circlePoint(x, y);
VECTOR2I circlePoint( x, y );
VECTOR2I upperPoint = circlePoint - viaCenter;
VECTOR2I lowerPoint = upperPoint;
upperPoint = upperPoint.Rotate(M_PI / 2);
lowerPoint = lowerPoint.Rotate(-M_PI / 2);
upperPoint += viaCenter;
lowerPoint += viaCenter;
VECTOR2I upperPoint = circlePoint - viaCenter;
VECTOR2I lowerPoint = upperPoint;
upperPoint = upperPoint.Rotate( M_PI / 2 );
lowerPoint = lowerPoint.Rotate( -M_PI / 2 );
upperPoint += viaCenter;
lowerPoint += viaCenter;
// Calculate the number of segments needed to fill the area inside the teardrop
std::vector<VECTOR2I> splitPoints;
if (aVia.GetWidth() / 2 > 2 * aTrack.GetWidth()) {
if( aVia.GetWidth() / 2 > 2 * aTrack.GetWidth() )
{
// First, calculate the intersection point of the circle and one hand of the teardrop
r = aVia.GetWidth() / 2;
a = pow((upperPoint.x - startPoint.x), 2) + pow((upperPoint.y - startPoint.y), 2);
b = 2 * (double)(upperPoint.x - startPoint.x) * (double)(startPoint.x - viaCenter.x) + 2 * (double)(upperPoint.y - startPoint.y) * (double)(startPoint.y - viaCenter.y);
c = pow((startPoint.x - viaCenter.x), 2) + pow((startPoint.y - viaCenter.y), 2) - pow(r, 2);
t = 2 * c / (-b + sqrt(b * b - 4 * a * c));
a = pow( (upperPoint.x - startPoint.x), 2 ) + pow( (upperPoint.y - startPoint.y), 2 );
b = 2 * (double)(upperPoint.x - startPoint.x) * (double)(startPoint.x - viaCenter.x) +
2 * (double)(upperPoint.y - startPoint.y) * (double) (startPoint.y - viaCenter.y);
c = pow( (startPoint.x - viaCenter.x), 2 ) + pow( (startPoint.y - viaCenter.y), 2 ) - pow( r, 2 );
t = 2 * c / ( -b + sqrt( b * b - 4 * a * c ) );
x = (upperPoint.x - startPoint.x) * t + startPoint.x;
y = (upperPoint.y - startPoint.y) * t + startPoint.y;
VECTOR2I intersectionPoint((int)x, (int)y);
VECTOR2I intersectionPoint( (int) x, (int) y );
// Second, calculate the distance between the given track and the intersection point
SEG trackSegment(aTrack.GetStart().x, aTrack.GetStart().y, aTrack.GetEnd().x, aTrack.GetEnd().y);
int dist = trackSegment.LineDistance(intersectionPoint);
SEG trackSegment( aTrack.GetStart().x, aTrack.GetStart().y,
aTrack.GetEnd().x, aTrack.GetEnd().y );
int dist = trackSegment.LineDistance( intersectionPoint );
int numSegments = 2 * dist / aTrack.GetWidth();
// Third, subdivide the diameter of the via and build additional segments
SEG segDiameter = SEG(upperPoint, lowerPoint);
SplitSegment(segDiameter, numSegments, splitPoints);
SEG segDiameter = SEG( upperPoint, lowerPoint );
splitSegment( segDiameter, numSegments, splitPoints );
}
std::list<VECTOR2I> outlinePoints;
outlinePoints.push_back(upperPoint);
for (size_t i = 0; i < splitPoints.size(); i++) {
outlinePoints.push_back(splitPoints[i]);
outlinePoints.push_back( upperPoint );
for( size_t i = 0; i < splitPoints.size(); i++ )
{
outlinePoints.push_back( splitPoints[i] );
}
outlinePoints.push_back(lowerPoint);
outlinePoints.push_back( lowerPoint );
// Biuld triangles filling the teardrop
int vertexNum = 0;
std::list<VECTOR2I>::iterator iter = outlinePoints.begin();
while ( iter != outlinePoints.end() ) {
switch (vertexNum) {
while( iter != outlinePoints.end() )
{
switch( vertexNum )
{
case 0:
m_coordinates.push_back(linePoint);
m_coordinates.push_back( linePoint );
vertexNum++;
break;
case 1:
m_coordinates.push_back(*iter);
m_coordinates.push_back( *iter );
vertexNum++;
iter++;
break;
case 2:
m_coordinates.push_back(*iter);
m_coordinates.push_back( *iter );
vertexNum = 0;
iter++;
break;
default:break;
default:
break;
}
}
// Append additional vertexies in order to finish last triangle
if (vertexNum == 0) {
m_coordinates.push_back(linePoint);
if( vertexNum == 0 )
{
m_coordinates.push_back( linePoint );
}
else if (vertexNum == 2) {
m_coordinates.push_back(m_coordinates[m_coordinates.size() - 3]);
m_coordinates.push_back(linePoint);
else if( vertexNum == 2 )
{
m_coordinates.push_back( m_coordinates[m_coordinates.size() - 3] );
m_coordinates.push_back( linePoint );
}
return true;
}
// TODO: m_TracksConnected member is considered a temporary storage. Find another way to get an object
BOARD_CONNECTED_ITEM* TEARDROP::GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoint)
BOARD_CONNECTED_ITEM* TEARDROP::getObjectOnEnd(TRACK& aTrack, ENDPOINT_T aEndPoint )
{
wxPoint trackPoint;
BOARD_CONNECTED_ITEM *item = NULL;
std::vector<TRACK *>::const_iterator iter;
BOARD_CONNECTED_ITEM* item = NULL;
std::vector<TRACK*>::const_iterator iter;
if (endPoint == ENDPOINT_START) {
if( aEndPoint == ENDPOINT_START )
{
trackPoint = aTrack.GetStart();
}
else {
else
{
trackPoint = aTrack.GetEnd();
}
// Check for vias first
for (iter = aTrack.m_TracksConnected.begin(); iter != aTrack.m_TracksConnected.end(); ++iter) {
for( iter = aTrack.m_TracksConnected.begin(); iter != aTrack.m_TracksConnected.end(); ++iter )
{
KICAD_T type = (*iter)->Type();
bool hitTest = (*iter)->HitTest(trackPoint);
if (type == PCB_VIA_T && hitTest == true) {
bool hitTest = (*iter)->HitTest( trackPoint );
if( (type == PCB_VIA_T) && (hitTest == true) )
{
item = *iter;
}
}
// Check for pads if via was not found on this end of the track
if (item == NULL) {
for (std::vector<D_PAD *>::iterator iter = aTrack.m_PadsConnected.begin(); iter != aTrack.m_PadsConnected.end(); ++iter) {
if( item == NULL )
{
for( std::vector<D_PAD*>::iterator iter = aTrack.m_PadsConnected.begin();
iter != aTrack.m_PadsConnected.end();
++iter )
{
PAD_SHAPE_T shape = (*iter)->GetShape();
bool hitTest = (*iter)->HitTest(trackPoint);
if (shape == PAD_CIRCLE && hitTest == true) {
bool hitTest = (*iter)->HitTest( trackPoint );
if( shape == PAD_CIRCLE && hitTest == true )
{
item = *iter;
}
}
......@@ -297,20 +377,28 @@ BOARD_CONNECTED_ITEM* TEARDROP::GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoin
return item;
}
void TEARDROP::SplitSegment(const SEG &segment, int splits, std::vector<VECTOR2I> &points)
void TEARDROP::splitSegment( const SEG& aSegment, int aSplits, std::vector<VECTOR2I>& aPoints )
{
int dX = abs((segment.A.x - segment.B.x) / splits);
int dY = abs((segment.A.y - segment.B.y) / splits);
if (segment.A.x > segment.B.x) {
int dX = abs( (aSegment.A.x - aSegment.B.x) / aSplits );
int dY = abs( (aSegment.A.y - aSegment.B.y) / aSplits );
if( aSegment.A.x > aSegment.B.x )
{
dX = -dX;
}
if (segment.A.y > segment.B.y) {
if( aSegment.A.y > aSegment.B.y )
{
dY = -dY;
}
VECTOR2I delta(dX, dY);
points.push_back(segment.A + delta);
VECTOR2I delta( dX, dY );
aPoints.push_back( aSegment.A + delta );
// The last point is excluded as it will coinside with already built tracks
for (int i = 1; i < splits - 1; i++) {
points.push_back(points.back() + delta);
for( int i = 1; i < aSplits - 1; i++ )
{
aPoints.push_back( aPoints.back() + delta );
}
}
......@@ -17,93 +17,130 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file class_teardrop.h
* @brief Definitions for teardrops.
*/
#ifndef CLASS_TEARDROP_H
#define CLASS_TEARDROP_H
#include "class_track.h"
#include "geometry/seg.h"
/**
* @brief The TEARDROP class
* is base definition of a teardrop. It is intended for calculation and holding of points which
* compose a teardrop. This class does not contain any methods which create actual tracks.
*/
class TEARDROP
{
public:
TEARDROP();
/**
* @brief Defines the type of a teardrop.
* @brief The TEARDROP_TYPE defines the type of a teardrop.
*/
typedef enum {
TEARDROP_NONE, ///< The type is undefined
TEARDROP_STRAIGHT, ///< The teardrop is created by two straight segments
TEARDROP_CURVED ///< The teardrop is created by several segments approximating a curve
typedef enum
{
TEARDROP_NONE, ///< The type is undefined
TEARDROP_STRAIGHT, ///< The teardrop is created by two straight segments
TEARDROP_CURVED ///< The teardrop is created by several segments approximating a curve
} TEARDROP_TYPE;
/**
* @brief GetType returns the type of the teardrop.
* @return TEARDROP_TYPE
* @brief Function \a GetType
* returns the type of the teardrop.
* @return TEARDROP_TYPE - the type of the teardrop
*/
TEARDROP_TYPE GetType() const {return m_type;}
TEARDROP_TYPE GetType() const { return m_type; }
/**
* @brief Function Create creates a teardrop(s) for a given track
* @param aTrack
* @return \a true in case the teardrops were successfully built and \a false otherwise
* @brief Function \a Create
* creates a teardrop(s) for a given track.
* @param [in] aTrack is a track at which teardrop(s) should be created
* @param [in] aEndPoint is an end point at which a teardrop should be created
* @param [in] aType defines the type of a teardrop
* @return bool - \a true in case the teardrops were successfully built and \a false otherwise
*/
bool Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type);
bool Create( TRACK& aTrack, ENDPOINT_T aEndPoint, TEARDROP_TYPE aType );
void GetCoordinates(std::vector<VECTOR2I> &points) const {points = m_coordinates;}
/**
* @brief Function \a GetCoordinates
* returns the coordinates of created teardrop.
* @param [out] aPoints is a container for coordinates
*/
void GetCoordinates( std::vector<VECTOR2I>& aPoints ) const { aPoints = m_coordinates; }
private:
///> Contains the type of teardrop
/// Contains the type of teardrop
TEARDROP_TYPE m_type;
///> \a m_upperSegment and \a m_lowerSegment contain coordinates of segments composing a teardrop
std::vector<VECTOR2I> m_upperSegment;
std::vector<VECTOR2I> m_lowerSegment;
/// Contains the actual coordinates of teardrop
std::vector<VECTOR2I> m_coordinates;
/**
* @brief Function \a CurvedSegments computes several points on deltoid curve and moves
* these points along the vector defined by \a aTrack.
* @brief Function \a curvedSegments
* computes several points on deltoid curve and moves these points along the vector
* defined by \a aTrack.
*
* This function computes the coordinates of points only and does not build actual track segments.
* See deltiod description and its parametric equations on [wiki page](http://en.wikipedia.org/wiki/Deltoid_curve).
* @param [in] aTrack defines a vector along which the curved segments should be built
* @param [in] aVia used as the center of coordinates
* @return \a true in case the segments were successfully built and \a false otherwise
* @return bool - \a true in case the segments were successfully built and \a false otherwise
*/
bool CurvedSegments(TRACK &aTrack, const VIA &aVia);
bool curvedSegments( TRACK& aTrack, const VIA& aVia );
/**
* @brief Function \a StraightSegments builds two tangent lines for a circle from a givent point.
* @brief Function \a straightSegments
* builds two tangent lines to a circle from a givent point.
*
* This function computes the coordinates of points only and does not build actual track segments.
* @param [in] aTrack defines a vector along which the segments should be built
* @param [in] aVia represents a circle to which the segments should be built
* @param [in] distance is distance ratio (in percent) from circle center in respect to its diameter
* @return \a true in case the segments were successfully built and \a false otherwise
* @param [in] aDistance is distance ratio (in percent) from circle center in respect to its diameter
* @return bool - \a true in case the segments were successfully built and \a false otherwise
*/
bool straightSegments( TRACK& aTrack, const VIA& aVia, int aDistance );
/**
* @brief Function \a setVector
* creates a vector from \a aTrack directed into \a aVia.
* @param [in] aTrack is used to create a vector
* @param [in] aVia is an object to which the vector should be pointed to
* @param [out] aStartPoint is start point of resulting vector
* @param [out] aEndPoint is end point of resulting vector
* @return bool - \a true in case the vector is created successfully and \a false otherwise
*/
bool setVector( TRACK& aTrack, const VIA& aVia, VECTOR2I& aStartPoint, VECTOR2I& aEndPoint );
/**
* @brief Function \a getObjectOnEnd
* returns an object (via or pad) at the given end of a track.
* @param [in] aTrack is a reference track
* @param [in] aEndPoint defines the end in question
* @return BOARD_CONNECTED_ITEM - the object found or NULL otherwise
*/
bool StraightSegments(TRACK &aTrack, const VIA &aVia, int distance);
BOARD_CONNECTED_ITEM* getObjectOnEnd( TRACK& aTrack, ENDPOINT_T aEndPoint );
/**
* @brief Function SetVector creates a vector from \a aTrack directed into \a aVia
* @param aTrack is used to create a vector
* @param startPoint is start point of resulting vector
* @param endPoint is end point of resulting vector
* @return \a true in case the vector is created successfully and \a false otherwise
* @brief Function \a splitSegment
* splits a segment into given number of subsegments.
* @param [in] aSegment is a segment to be split
* @param [i] aSplits is a number of splits
* @param [out] aPoints is a container for split points
*/
bool SetVector(TRACK &aTrack, const VIA &aVia, VECTOR2I &startPoint, VECTOR2I &endPoint);
void splitSegment( const SEG& aSegment, int aSplits, std::vector<VECTOR2I>& aPoints );
BOARD_CONNECTED_ITEM* GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoint);
void SplitSegment(const SEG &segment, int splits, std::vector<VECTOR2I> &points);
inline void PointOnCurve(int angle, double radius, VECTOR2I &point) {
/**
* @brief Function \a pointOnCurve
* calculates a single point on a deltoid curve.
* @param [in] aAngle is an angle at which the point should be calculated
* @param [in] aRadius is the radius of a rolling circle
* @param [out] aPoint is a container for calculated point
*/
inline void pointOnCurve( int aAngle, double aRadius, VECTOR2I& aPoint )
{
double coeff = M_PI / 180.0;
point.x = 2 * radius * cos(coeff * angle) + radius * cos(2 * coeff * angle);
point.y = 2 * radius * sin(coeff * angle) - radius * sin(2 * coeff * angle);
aPoint.x = 2 * aRadius * cos( coeff * aAngle ) + aRadius * cos( 2 * coeff * aAngle );
aPoint.y = 2 * aRadius * sin( coeff * aAngle ) - aRadius * sin( 2 * coeff * aAngle );
}
};
#endif // CLASS_TEARDROP_H
#endif // CLASS_TEARDROP_H
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dialog_teardrops.h"
DIALOG_TEARDROPS::DIALOG_TEARDROPS(PCB_EDIT_FRAME *aParent, TEARDROPS_SETTINGS *settings):
DIALOG_TEARDROPS_BASE(aParent)
DIALOG_TEARDROPS::DIALOG_TEARDROPS(PCB_EDIT_FRAME *aParent, TEARDROPS_SETTINGS *aSettings = NULL ):
DIALOG_TEARDROPS_BASE( aParent )
{
m_parent = aParent;
m_settings = settings;
if (m_settings != NULL) {
InitDialogSettings();
m_settings = aSettings;
if( m_settings != NULL )
{
initDialogSettings();
}
}
void DIALOG_TEARDROPS::InitDialogSettings()
void DIALOG_TEARDROPS::initDialogSettings()
{
wxASSERT(m_settings != NULL);
if (m_modeRemove->GetValue() == true) {
assert(m_settings != NULL);
if( m_modeRemove->GetValue() == true )
{
m_settings->m_mode = TEARDROPS_MODE_REMOVE;
}
else {
else
{
m_settings->m_mode = TEARDROPS_MODE_ADD;
}
if (m_tracksAll->GetValue() == true) {
if( m_tracksAll->GetValue() == true )
{
m_settings->m_track = TEARDROPS_TRACKS_ALL;
}
else {
else
{
m_settings->m_track = TEARDROPS_TRACKS_SELECTED;
}
m_settings->m_type = static_cast<TEARDROPS_TYPE>(m_choiceStyle->GetSelection());
m_settings->m_type = static_cast<TEARDROPS_TYPE>( m_choiceStyle->GetSelection() );
m_settings->m_scope = TEARDROPS_SCOPE_NONE;
if (m_scopeVias->IsChecked() == true) {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope | TEARDROPS_SCOPE_VIAS);
if( m_scopeVias->IsChecked() == true )
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope | TEARDROPS_SCOPE_VIAS );
}
if (m_scopePads->IsChecked() == true) {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope | TEARDROPS_SCOPE_PADS);
if( m_scopePads->IsChecked() == true )
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope | TEARDROPS_SCOPE_PADS );
}
if (m_scopeTracks->IsChecked() == true) {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope | TEARDROPS_SCOPE_TRACKS);
if( m_scopeTracks->IsChecked() == true )
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope | TEARDROPS_SCOPE_TRACKS );
}
m_settings->m_clearSelection = m_checkClear->IsChecked();
m_settings->m_ignoreDrc = m_checkIgnore->IsChecked();
}
void DIALOG_TEARDROPS::OnModeAdd(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnModeAdd( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_mode = TEARDROPS_MODE_ADD;
LockOptionsControls(false);
LockTracksControls(false);
LockScopeControls(false);
lockOptionsControls( false );
lockTracksControls( false );
lockScopeControls( false );
}
}
void DIALOG_TEARDROPS::OnModeRemove(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnModeRemove( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_mode = TEARDROPS_MODE_REMOVE;
LockOptionsControls(true);
LockTracksControls(true);
LockScopeControls(true);
lockOptionsControls( true );
lockTracksControls( true );
lockScopeControls( true );
}
}
void DIALOG_TEARDROPS::OnTracksAll(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnTracksAll( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_track = TEARDROPS_TRACKS_ALL;
}
m_checkClear->Enable(false);
m_checkClear->Enable( false );
}
void DIALOG_TEARDROPS::OnTracksSelected(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnTracksSelected( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_track = TEARDROPS_TRACKS_SELECTED;
}
m_checkClear->Enable(true);
m_checkClear->Enable( true );
}
void DIALOG_TEARDROPS::OnScopeVias(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnScopeVias( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
if (m_scopeVias->IsChecked()) {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope | TEARDROPS_SCOPE_VIAS);
aEvent.Skip();
if( m_settings != NULL )
{
if( m_scopeVias->IsChecked() )
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope | TEARDROPS_SCOPE_VIAS );
}
else {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope & (~TEARDROPS_SCOPE_VIAS));
else
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope & (~TEARDROPS_SCOPE_VIAS) );
}
}
}
void DIALOG_TEARDROPS::OnScopePads(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnScopePads( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
if (m_scopePads->IsChecked()) {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope | TEARDROPS_SCOPE_PADS);
aEvent.Skip();
if( m_settings != NULL )
{
if( m_scopePads->IsChecked() )
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope | TEARDROPS_SCOPE_PADS );
}
else {
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>(m_settings->m_scope & (~TEARDROPS_SCOPE_PADS));
else
{
m_settings->m_scope = static_cast<TEARDROPS_SCOPE>( m_settings->m_scope & (~TEARDROPS_SCOPE_PADS) );
}
}
}
void DIALOG_TEARDROPS::OnStyleChanged(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnStyleChanged( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
m_settings->m_type = static_cast<TEARDROPS_TYPE>(m_choiceStyle->GetSelection());
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_type = static_cast<TEARDROPS_TYPE>( m_choiceStyle->GetSelection() );
}
}
void DIALOG_TEARDROPS::OnClearSelection(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnClearSelection( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_clearSelection = m_checkClear->IsChecked();
}
}
void DIALOG_TEARDROPS::OnIgnoreDrc(wxCommandEvent &event)
void DIALOG_TEARDROPS::OnIgnoreDrc( wxCommandEvent &aEvent )
{
event.Skip();
if (m_settings != NULL) {
aEvent.Skip();
if( m_settings != NULL )
{
m_settings->m_ignoreDrc = m_checkIgnore->IsChecked();
}
}
void DIALOG_TEARDROPS::LockOptionsControls(bool state)
void DIALOG_TEARDROPS::lockOptionsControls( bool state )
{
if (state == true) {
if (m_tracksSelected->GetValue() == false) {
m_checkClear->Enable(false);
if( state == true )
{
if( m_tracksSelected->GetValue() == false )
{
m_checkClear->Enable( false );
}
m_checkIgnore->Enable(false);
m_choiceStyle->Enable(false);
}
else {
if (m_tracksSelected->GetValue() == true) {
m_checkClear->Enable(true);
m_checkIgnore->Enable( false );
m_choiceStyle->Enable( false );
}
else
{
if( m_tracksSelected->GetValue() == true )
{
m_checkClear->Enable( true );
}
m_checkIgnore->Enable(true);
m_choiceStyle->Enable(true);
m_checkIgnore->Enable( true );
m_choiceStyle->Enable( true );
}
}
void DIALOG_TEARDROPS::LockTracksControls(bool state)
void DIALOG_TEARDROPS::lockTracksControls( bool state )
{
if (state == true) {
m_tracksAll->Enable(false);
m_tracksSelected->Enable(false);
if( state == true )
{
m_tracksAll->Enable( false );
m_tracksSelected->Enable( false );
}
else {
m_tracksAll->Enable(true);
m_tracksSelected->Enable(true);
else
{
m_tracksAll->Enable( true );
m_tracksSelected->Enable( true );
}
}
void DIALOG_TEARDROPS::LockScopeControls(bool state)
void DIALOG_TEARDROPS::lockScopeControls( bool state )
{
if (state == true) {
m_scopePads->Enable(false);
m_scopeVias->Enable(false);
}
else {
m_scopePads->Enable(true);
m_scopeVias->Enable(true);
if( state == true )
{
m_scopePads->Enable( false );
m_scopeVias->Enable( false );
}
else
{
m_scopePads->Enable( true );
m_scopeVias->Enable( true );
}
}
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIALOG_TEARDROPS_H
#define DIALOG_TEARDROPS_H
......@@ -5,56 +24,108 @@
#include "dialog_teardrops_base.h"
#include "wxPcbStruct.h"
/**
* @brief The DIALOG_TEARDROPS class
* implements teardrop management dialog for current board.
*/
class DIALOG_TEARDROPS : public DIALOG_TEARDROPS_BASE
{
public:
typedef enum {
/**
* @brief The TEARDROPS_MODE
* defines an action to be performed on teardrops.
*/
typedef enum
{
/// Teardrops addition mode
TEARDROPS_MODE_ADD,
/// Teardrops removal mode
TEARDROPS_MODE_REMOVE
} TEARDROPS_MODE;
typedef enum {
/**
* @brief The TEARDROPS_TRACKS
* determines selection processing.
*/
typedef enum
{
/// Process all tracks
TEARDROPS_TRACKS_ALL,
/// Process selected tracks only
TEARDROPS_TRACKS_SELECTED
} TEARDROPS_TRACKS;
typedef enum {
/**
* @brief The TEARDROPS_TYPE
* defines the shape of teardrops.
*/
typedef enum
{
/// The shape is not defined
TEARDROPS_TYPE_NONE = -1,
/// The teardops have straight outlines
TEARDROPS_TYPE_STRAIGHT,
/// The teardrops have curved outlines
TEARDROPS_TYPE_CURVED
} TEARDROPS_TYPE;
typedef enum {
/**
* @brief The TEARDROPS_SCOPE
* defines the types of objects for which teardrops should be created. This is a bit field, each
* bit correcponds to an object type.
*/
typedef enum
{
/// No objects are specified
TEARDROPS_SCOPE_NONE,
/// Create teardrops for vias
TEARDROPS_SCOPE_VIAS = 1,
/// Create teardrops for pads
TEARDROPS_SCOPE_PADS = 2,
/// Create teardrops for tracks (not implemented yet)
TEARDROPS_SCOPE_TRACKS = 4
} TEARDROPS_SCOPE;
typedef struct {
/**
* @brief The TEARDROPS_SETTINGS
* class is a container for all the settings specified by the user.
*/
typedef struct
{
/// The action to be performed (addition, deletion)
TEARDROPS_MODE m_mode;
/// Process selection
TEARDROPS_TRACKS m_track;
/// Objects scope
TEARDROPS_SCOPE m_scope;
/// Teardrops type
TEARDROPS_TYPE m_type;
/// Clear selection after the processing has finished
bool m_clearSelection;
/// Ignore DRC during processing
bool m_ignoreDrc;
} TEARDROPS_SETTINGS;
DIALOG_TEARDROPS(PCB_EDIT_FRAME *aParent, TEARDROPS_SETTINGS *settings);
void OnModeAdd(wxCommandEvent &event);
void OnModeRemove(wxCommandEvent &event);
void OnTracksAll(wxCommandEvent &event);
void OnTracksSelected(wxCommandEvent &event);
void OnStyleChanged(wxCommandEvent &event);
void OnClearSelection(wxCommandEvent &event);
void OnIgnoreDrc(wxCommandEvent &event);
void OnScopeVias(wxCommandEvent &event);
void OnScopePads(wxCommandEvent &event);
DIALOG_TEARDROPS( PCB_EDIT_FRAME *aParent, TEARDROPS_SETTINGS *aSettings );
void OnModeAdd( wxCommandEvent &aEvent );
void OnModeRemove( wxCommandEvent &aEvent );
void OnTracksAll( wxCommandEvent &aEvent );
void OnTracksSelected( wxCommandEvent &aEvent );
void OnStyleChanged( wxCommandEvent &aEvent );
void OnClearSelection( wxCommandEvent &aEvent );
void OnIgnoreDrc( wxCommandEvent &aEvent );
void OnScopeVias( wxCommandEvent &aEvent );
void OnScopePads( wxCommandEvent &aEvent );
private:
PCB_EDIT_FRAME *m_parent;
TEARDROPS_SETTINGS *m_settings;
void InitDialogSettings();
void LockOptionsControls(bool state);
void LockTracksControls(bool state);
void LockScopeControls(bool state);
void initDialogSettings();
void lockOptionsControls( bool aState );
void lockTracksControls( bool aState );
void lockScopeControls( bool aState );
};
#endif // DIALOG_TEARDROPS_H
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "edit_teardrops.h"
#include "class_board.h"
#include "class_module.h"
#include "ratsnest_data.h"
#include "view/view.h"
#include "common_actions.h"
#include "router/pns_utils.h"
#include "router/pns_router.h"
TEARDROPS_EDITOR::TEARDROPS_EDITOR() :
TOOL_BASE(BATCH, TOOL_MANAGER::MakeToolId("pcbnew.TeardropsEditor"), "pcbnew.TeardropsEditor")
TOOL_BASE( BATCH, TOOL_MANAGER::MakeToolId( "pcbnew.TeardropsEditor" ),
"pcbnew.TeardropsEditor" )
{
m_frame = NULL;
m_view = NULL;
m_type = TEARDROP::TEARDROP_STRAIGHT;
m_view = NULL;
m_type = TEARDROP::TEARDROP_STRAIGHT;
m_strategy = DRC_COMPLY;
}
TEARDROPS_EDITOR::~TEARDROPS_EDITOR()
{
}
void TEARDROPS_EDITOR::Reset(RESET_REASON aReason)
void TEARDROPS_EDITOR::Reset( RESET_REASON aReason )
{
m_frame = getEditFrame<PCB_EDIT_FRAME>();
m_view = getView();
m_type = TEARDROP::TEARDROP_STRAIGHT;
m_view = getView();
m_type = TEARDROP::TEARDROP_STRAIGHT;
m_strategy = DRC_COMPLY;
}
void TEARDROPS_EDITOR::FilterSelection(SELECTION &selection)
void TEARDROPS_EDITOR::filterSelection(SELECTION& aSelection )
{
EDA_ITEM *item = NULL;
EDA_ITEM* item = NULL;
for( size_t i = 0; i < aSelection.items.GetCount(); i++ )
{
item = aSelection.items.GetPickedItem( i );
for (size_t i = 0; i < selection.items.GetCount(); i++) {
item = selection.items.GetPickedItem(i);
if ((item != NULL) && (item->Type() != PCB_TRACE_T)) {
selection.items.RemovePicker(i);
if( (item != NULL) && (item->Type() != PCB_TRACE_T) )
{
aSelection.items.RemovePicker( i );
}
}
}
bool TEARDROPS_EDITOR::EditTeardrops(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings)
bool TEARDROPS_EDITOR::EditTeardrops(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings )
{
bool retVal = false;
SELECTION selection = GetManager()->GetTool<SELECTION_TOOL>()->GetSelection();
switch (settings.m_type) {
switch( aSettings.m_type )
{
case DIALOG_TEARDROPS::TEARDROPS_TYPE_CURVED:
m_type = TEARDROP::TEARDROP_CURVED;
break;
default:
m_type = TEARDROP::TEARDROP_STRAIGHT;
}
if (settings.m_ignoreDrc == true) {
if( aSettings.m_ignoreDrc == true )
{
m_strategy = DRC_IGNORE;
}
else {
else
{
m_strategy = DRC_COMPLY;
}
FilterSelection(selection);
if (settings.m_mode == DIALOG_TEARDROPS::TEARDROPS_MODE_ADD) {
if (settings.m_track == DIALOG_TEARDROPS::TEARDROPS_TRACKS_ALL) {
retVal = AddToAll(settings);
filterSelection( selection );
if( aSettings.m_mode == DIALOG_TEARDROPS::TEARDROPS_MODE_ADD )
{
if( aSettings.m_track == DIALOG_TEARDROPS::TEARDROPS_TRACKS_ALL )
{
retVal = addToAll( aSettings );
}
else if (settings.m_track == DIALOG_TEARDROPS::TEARDROPS_TRACKS_SELECTED) {
retVal = AddToSelected(selection, settings);
else if( aSettings.m_track == DIALOG_TEARDROPS::TEARDROPS_TRACKS_SELECTED )
{
retVal = addToSelected( selection, aSettings );
}
}
else if (settings.m_mode == DIALOG_TEARDROPS::TEARDROPS_MODE_REMOVE) {
RemoveAll();
else if( aSettings.m_mode == DIALOG_TEARDROPS::TEARDROPS_MODE_REMOVE )
{
removeAll();
retVal = true;
}
return retVal;
}
bool TEARDROPS_EDITOR::AddToAll(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings)
bool TEARDROPS_EDITOR::addToAll(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings )
{
bool added = false;
// Iterate through all vias and add teardrops to connected tracks
if ((settings.m_scope & DIALOG_TEARDROPS::TEARDROPS_SCOPE_VIAS) == DIALOG_TEARDROPS::TEARDROPS_SCOPE_VIAS) {
for (VIA *via = GetFirstVia(m_frame->GetBoard()->m_Track); via != NULL;
via = GetFirstVia(via->Next())) {
if (IterateTracks(via) == true) {
if( (aSettings.m_scope & DIALOG_TEARDROPS::TEARDROPS_SCOPE_VIAS) ==
DIALOG_TEARDROPS::TEARDROPS_SCOPE_VIAS )
{
for( VIA* via = GetFirstVia( m_frame->GetBoard()->m_Track ); via != NULL;
via = GetFirstVia( via->Next() ) )
{
if( iterateTracks( via ) == true )
{
added = true;
}
}
}
// Iterate through all modules and add teardrops to tracks connected to their pads
if ((settings.m_scope & DIALOG_TEARDROPS::TEARDROPS_SCOPE_PADS) == DIALOG_TEARDROPS::TEARDROPS_SCOPE_PADS) {
for (MODULE *module = m_frame->GetBoard()->m_Modules.GetFirst(); module != NULL; module = module->Next()) {
D_PAD *pad = module->Pads();
while (pad != NULL) {
if ((pad->GetShape() == PAD_CIRCLE) && IterateTracks(pad) == true) {
added = true;
}
pad = pad->Next();
}
if( (aSettings.m_scope & DIALOG_TEARDROPS::TEARDROPS_SCOPE_PADS) ==
DIALOG_TEARDROPS::TEARDROPS_SCOPE_PADS )
{
for( MODULE* module = m_frame->GetBoard()->m_Modules.GetFirst();
module != NULL;
module = module->Next() )
{
D_PAD* pad = module->Pads();
while( pad != NULL )
{
if( (pad->GetShape() == PAD_CIRCLE) && iterateTracks( pad ) == true )
{
added = true;
}
pad = pad->Next();
}
}
}
if (added == true) {
m_frame->SaveCopyInUndoList(m_undoListPicker, UR_NEW);
if( added == true )
{
m_frame->SaveCopyInUndoList( m_undoListPicker, UR_NEW );
m_undoListPicker.ClearItemsList();
}
return added;
}
bool TEARDROPS_EDITOR::AddToSelected(SELECTION &selection, const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings)
bool TEARDROPS_EDITOR::addToSelected(SELECTION& aSelection,
const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings )
{
bool retVal = false;
bool added = false;
int addedNum = 0;
bool retVal = false;
bool added = false;
int addedNum = 0;
for (size_t i = 0; i < selection.items.GetCount(); i++) {
TRACK *track = static_cast<TRACK *>(selection.items.GetPickedItem(i));
for( size_t i = 0; i < aSelection.items.GetCount(); i++ )
{
TRACK* track = static_cast<TRACK*>( aSelection.items.GetPickedItem( i ) );
TEARDROP teardropEnd;
retVal = teardropEnd.Create(*track, ENDPOINT_END, m_type);
if (retVal == true) {
added = DrawSegments(teardropEnd, *track);
if (added == true) {
retVal = teardropEnd.Create( *track, ENDPOINT_END, m_type );
if( retVal == true )
{
added = drawSegments( teardropEnd, *track );
if( added == true )
{
addedNum++;
}
}
TEARDROP teardropStart;
retVal = teardropStart.Create(*track, ENDPOINT_START, m_type);
if (retVal == true) {
added = DrawSegments(teardropStart, *track);
if (added == true) {
retVal = teardropStart.Create( *track, ENDPOINT_START, m_type );
if( retVal == true )
{
added = drawSegments( teardropStart, *track );
if( added == true )
{
addedNum++;
}
}
}
if (settings.m_clearSelection == true) {
GetManager()->RunAction(COMMON_ACTIONS::selectionClear, true);
if( aSettings.m_clearSelection == true )
{
GetManager()->RunAction( COMMON_ACTIONS::selectionClear, true );
}
if (addedNum > 0) {
m_frame->SaveCopyInUndoList(m_undoListPicker, UR_NEW);
if( addedNum > 0 )
{
m_frame->SaveCopyInUndoList( m_undoListPicker, UR_NEW );
m_undoListPicker.ClearItemsList();
}
return added;
}
bool TEARDROPS_EDITOR::IterateTracks(const BOARD_CONNECTED_ITEM *aObject)
bool TEARDROPS_EDITOR::iterateTracks( const BOARD_CONNECTED_ITEM* aObject )
{
assert(aObject);
assert( aObject );
bool retVal = false;
bool flagAdded = false;
for (size_t i = 0; i < aObject->m_TracksConnected.size(); i++) {
TRACK *track = aObject->m_TracksConnected[i];
STATUS_FLAGS objPosition = track->IsPointOnEnds(aObject->GetPosition());
if (objPosition == STARTPOINT || objPosition == ENDPOINT) {
for( size_t i = 0; i < aObject->m_TracksConnected.size(); i++ )
{
TRACK* track = aObject->m_TracksConnected[i];
STATUS_FLAGS objPosition = track->IsPointOnEnds( aObject->GetPosition() );
if( objPosition == STARTPOINT || objPosition == ENDPOINT )
{
ENDPOINT_T endpoint = (objPosition == STARTPOINT ? ENDPOINT_START : ENDPOINT_END);
TEARDROP teardrop;
retVal = teardrop.Create(*track, endpoint, m_type);
if (retVal == true) {
if (DrawSegments(teardrop, *track) == true && flagAdded == false) {
retVal = teardrop.Create( *track, endpoint, m_type );
if( retVal == true )
{
if( drawSegments( teardrop, *track ) == true && flagAdded == false )
{
flagAdded = true;
}
}
}
}
return flagAdded;
}
void TEARDROPS_EDITOR::RemoveAll()
void TEARDROPS_EDITOR::removeAll()
{
ITEM_PICKER picker(NULL, UR_DELETED);
TRACK *nextTrack = NULL;
ITEM_PICKER picker( NULL, UR_DELETED );
TRACK* nextTrack = NULL;
bool removed = false;
for (TRACK *track = m_frame->GetBoard()->m_Track.begin(); track != NULL; ) {
for( TRACK* track = m_frame->GetBoard()->m_Track.begin(); track != NULL; )
{
nextTrack = track->Next();
if (track->GetState(FLAG1) == FLAG1) {
picker.SetItem(track);
m_undoListPicker.PushItem(picker);
if( track->GetState( FLAG1 ) == FLAG1 )
{
picker.SetItem( track );
m_undoListPicker.PushItem( picker );
removed = true;
m_view->Remove(track);
m_frame->GetBoard()->Remove(track);
m_view->Remove( track );
m_frame->GetBoard()->Remove( track );
}
track = nextTrack;
}
m_frame->GetBoard()->GetRatsnest()->Recalculate();
if (removed == true) {
m_frame->SaveCopyInUndoList(m_undoListPicker, UR_DELETED);
if( removed == true )
{
m_frame->SaveCopyInUndoList( m_undoListPicker, UR_DELETED );
m_undoListPicker.ClearItemsList();
}
}
bool TEARDROPS_EDITOR::DrawSegments(TEARDROP &teardrop, TRACK &aTrack)
bool TEARDROPS_EDITOR::drawSegments(TEARDROP& aTeardrop, TRACK& aTrack )
{
bool tracksAdded = true;
bool proceedBuild = true;
ITEM_PICKER picker(NULL, UR_NEW);
PNS_NODE *world = PNS_ROUTER::GetInstance()->GetWorld();
BOARD *board = aTrack.GetBoard();
std::vector<TRACK *> tracks;
ITEM_PICKER picker( NULL, UR_NEW );
PNS_NODE* world = PNS_ROUTER::GetInstance()->GetWorld();
BOARD* board = aTrack.GetBoard();
std::vector<TRACK*> tracks;
std::vector<VECTOR2I> coordinates;
teardrop.GetCoordinates(coordinates);
aTeardrop.GetCoordinates( coordinates );
assert(coordinates.size() != 0);
assert( coordinates.size() != 0 );
wxPoint currentPoint(0, 0);
wxPoint prevPoint(coordinates[0].x, coordinates[0].y);
wxPoint currentPoint( 0, 0 );
wxPoint prevPoint( coordinates[0].x, coordinates[0].y );
for (size_t i = 1; i < coordinates.size(); i++) {
if (m_strategy != DRC_IGNORE) {
PNS_SEGMENT segment(SEG(coordinates[i - 1], coordinates[i]), aTrack.GetNetCode());
segment.SetWidth(aTrack.GetWidth());
segment.SetLayers(PNS_LAYERSET(aTrack.GetLayer()));
segment.SetParent(&aTrack);
for( size_t i = 1; i < coordinates.size(); i++ )
{
if( m_strategy != DRC_IGNORE )
{
PNS_SEGMENT segment( SEG( coordinates[i - 1], coordinates[i] ), aTrack.GetNetCode() );
segment.SetWidth( aTrack.GetWidth() );
segment.SetLayers( PNS_LAYERSET( aTrack.GetLayer() ) );
segment.SetParent( &aTrack );
PNS_NODE::OBSTACLES obstacles;
if (world->QueryColliding(&segment, obstacles, PNS_ITEM::ANY, 1) > 0) {
// DRC violation found, the segment of a teadrop can not be place
if( world->QueryColliding( &segment, obstacles, PNS_ITEM::ANY, 1 ) > 0 )
{
// DRC violation found, the segment of a teadrop can not be placed
tracksAdded = false;
proceedBuild = false;
break;
}
}
if (proceedBuild == true) {
TRACK *track = new TRACK(aTrack);
track->SetWidth(aTrack.GetWidth());
track->SetLayer(aTrack.GetLayer());
track->SetNetCode(aTrack.GetNetCode());
currentPoint = wxPoint(coordinates[i].x, coordinates[i].y);
track->SetStart(prevPoint);
track->SetEnd(currentPoint);
if( proceedBuild == true )
{
TRACK* track = new TRACK( aTrack );
track->SetWidth( aTrack.GetWidth() );
track->SetLayer( aTrack.GetLayer() );
track->SetNetCode( aTrack.GetNetCode() );
currentPoint = wxPoint( coordinates[i].x, coordinates[i].y );
track->SetStart( prevPoint );
track->SetEnd( currentPoint );
track->ClearFlags();
track->SetState(FLAG1, true);
tracks.push_back(track);
track->SetState( FLAG1, true );
tracks.push_back( track );
prevPoint = currentPoint;
picker.SetItem(track);
m_undoListPicker.PushItem(picker);
picker.SetItem( track );
m_undoListPicker.PushItem( picker );
}
prevPoint = currentPoint;
}
if (tracksAdded == true) {
BOOST_FOREACH(TRACK *item, tracks) {
board->Add(item);
m_view->Add(item);
if( tracksAdded == true )
{
// The actual addition is done here
BOOST_FOREACH( TRACK * item, tracks ) {
board->Add( item );
m_view->Add( item );
}
}
else {
else
{
// The teardrop can not be created thus delete all allocated tracks and
// remove them from undo list
BOOST_FOREACH(TRACK *item, tracks) {
BOOST_FOREACH( TRACK * item, tracks ) {
m_undoListPicker.PopItem();
delete item;
}
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Elphel, Inc.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEARDROPS_EDITOR_H
#define TEARDROPS_EDITOR_H
......@@ -7,51 +26,99 @@
#include "class_teardrop.h"
#include "import_export.h"
/**
* @brief The TEARDROPS_EDITOR class
* creates actual tracks on the board in accordance with the preferences provided by
* the DIALOG_TEARDROPS class.
*/
class APIEXPORT TEARDROPS_EDITOR : public TOOL_BASE
{
public:
TEARDROPS_EDITOR();
~TEARDROPS_EDITOR();
bool EditTeardrops(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings);
/**
* @brief Function \a EditTeardrops
* is invoked for any manupulation with the teardrops on current board.
* @param [in] aSettings contains user defined settings provided by teadrops editor dialog window
* @return bool - \a true in case teardrops were successfully created and \a false otherwise
*/
bool EditTeardrops( const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings );
/// @copydoc TOOL_INTERACTIVE::Reset
void Reset(RESET_REASON aReason);
void Reset( RESET_REASON aReason );
private:
typedef enum {
/**
* The DRC_STRATEGY
* defines the strategy when DRC violation is detected during teardop creation.
*/
typedef enum
{
/// Do not violate DRC and quit teardrop building
DRC_COMPLY,
/// Ignore DRC and finish teardop
DRC_IGNORE,
/// Try to adjust the outline or size of a teardop (not implemented)
DRC_ADJUST
} DRC_STRATEGY;
PCB_EDIT_FRAME *m_frame;
KIGFX::VIEW *m_view;
PCB_EDIT_FRAME* m_frame;
KIGFX::VIEW* m_view;
TEARDROP::TEARDROP_TYPE m_type;
PICKED_ITEMS_LIST m_undoListPicker;
DRC_STRATEGY m_strategy;
/**
* @brief FilterSelection filters selected objects and removes all objects except tracks.
* @param selection contains the list of currently selected objects
* @brief Function \a filterSelection
* filters selected objects and removes all objects which can not be processed.
* @param [in,out] aSelection contains the list of currently selected objects on input and
* a list of valid for processing objects on output
*/
void FilterSelection(SELECTION &selection);
void filterSelection( SELECTION& aSelection );
/**
* @brief IterateTracks creates teardrop for all tracks connected to \a aObject
* @param aObject is a board object a which teardrops should be created. Currently such an object can
* @brief Function \a iterateTracks
* creates teardrop(s) for all tracks connected to \a aObject.
* @param [in] aObject is a board object at which teardrops should be created. Currently such an object can
* be via or circular pad.
* @return \a true if at least one teardrop was successfully added and \a false otherwise
*/
bool IterateTracks(const BOARD_CONNECTED_ITEM *aObject);
bool AddToAll(const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings);
bool AddToSelected(SELECTION &selection, const DIALOG_TEARDROPS::TEARDROPS_SETTINGS &settings);
bool iterateTracks( const BOARD_CONNECTED_ITEM* aObject );
/**
* @brief Function \a addToAll
* adds teardrops to all tracks on the board.
* @param [in] aSettings contains user defined settings
* @return bool - \a true in case teardops were successfully added and \a false otherwise
*/
bool addToAll( const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings );
/**
* @brief RemoveAll removes all teardrops form board.
* @brief Function \a addToSelected
* adds teardrops to selected tracks.
* @param [in] aSelection contains a filtered list of selected tracks
* @param [in] aSettings contains user defined settings
* @return bool - \a true in case teardops were successfully added and \a false otherwise
*/
void RemoveAll();
bool addToSelected( SELECTION& aSelection, const DIALOG_TEARDROPS::TEARDROPS_SETTINGS& aSettings );
bool DrawSegments(TEARDROP &teardrop, TRACK &track);
/**
* @brief Function \a RemoveAll
* removes all teardrops form current board.
*/
void removeAll();
/**
* @brief Function \a drawSegments
* adds tracks composing a teardop to the board.
* @param [in] aTeardrop is a teardrop which should be created on the board
* @param [in] aTrack is a parent track, some of its parameters are copied to newly created
* segments
* @return bool - \a true in case all the tracks were successfully added and \a false
* otherwise
*/
bool drawSegments( TEARDROP& aTeardrop, TRACK& aTrack );
};
#endif // TEARDROPS_EDITOR_H
#endif // TEARDROPS_EDITOR_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment