Commit c25acdbb authored by Mikhail Karpenko's avatar Mikhail Karpenko

Fill area inside teardrops

parent de8d191c
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "class_board_item.h" #include "class_board_item.h"
#include "class_undoredo_container.h" #include "class_undoredo_container.h"
#include "geometry/seg.h" #include "geometry/seg.h"
#include "geometry/shape_circle.h"
#include "router/pns_utils.h" #include "router/pns_utils.h"
TEARDROP::TEARDROP() TEARDROP::TEARDROP()
...@@ -36,22 +37,15 @@ bool TEARDROP::Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type = T ...@@ -36,22 +37,15 @@ bool TEARDROP::Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type = T
} }
if (type == TEARDROP_STRAIGHT) { if (type == TEARDROP_STRAIGHT) {
result = StraightSegments(aTrack, *aVia, m_upperSegment, m_lowerSegment, 100); result = StraightSegments(aTrack, *aVia, 100);
} }
else if (type == TEARDROP_CURVED) { else if (type == TEARDROP_CURVED) {
result = CurvedSegments(aTrack, *aVia, m_upperSegment, m_lowerSegment); result = CurvedSegments(aTrack, *aVia);
} }
return result; return result;
} }
void TEARDROP::GetCoordinates(std::vector<VECTOR2I> &points)
{
// points.insert(points.end(), m_upperSegment.begin(), m_upperSegment.end());
// points.insert(points.end(), m_lowerSegment.begin(), m_lowerSegment.end());
points = vect;
}
bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint, VECTOR2I &endPoint) bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint, VECTOR2I &endPoint)
{ {
// Decide which end of the track is inside via and set this point as end of vector // Decide which end of the track is inside via and set this point as end of vector
...@@ -72,10 +66,12 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint, ...@@ -72,10 +66,12 @@ bool TEARDROP::SetVector(TRACK &aTrack, const VIA & aVia, VECTOR2I &startPoint,
return true; return true;
} }
bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment) bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia)
{ {
VECTOR2I startPoint(0, 0); VECTOR2I startPoint(0, 0);
VECTOR2I endPoint(0, 0); VECTOR2I endPoint(0, 0);
std::vector<VECTOR2I> upperSegment;
std::vector<VECTOR2I> lowerSegment;
if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) { if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) {
return false; return false;
...@@ -90,29 +86,76 @@ bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR ...@@ -90,29 +86,76 @@ bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR
VECTOR2I point(0, 0); VECTOR2I point(0, 0);
VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y); VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y);
double coeff = M_PI / 180.0; VECTOR2I apertureUpper(0, 0);
VECTOR2I apertureLower(0, 0);
double radius = (aVia.GetWidth() / 2) - (aTrack.GetWidth() / 2); double radius = (aVia.GetWidth() / 2) - (aTrack.GetWidth() / 2);
double rotationAngle = VECTOR2I(startPoint - endPoint).Angle(); double rotationAngle = VECTOR2I(startPoint - endPoint).Angle();
// Calculate segments of deltoid // Calculate the segments of deltoid composing the outline of a teardrop
for ( int i = 10; i <= 60; i = i + 10 ) { for ( int i = 10; i <= 60; i = i + 10 ) {
point.x = 2 * radius * cos(coeff * i) + radius * cos(2 * coeff * i); PointOnCurve(i, radius, point);
point.y = 2 * radius * sin(coeff * i) - radius * sin(2 * coeff * i);
point = point.Rotate(rotationAngle); point = point.Rotate(rotationAngle);
point += viaCenter; point += viaCenter;
upperSegment.push_back(point); m_coordinates.push_back(point);
if (i == 50) {
apertureUpper = point;
}
} }
for ( int i = 300; i <= 350; i = i + 10 ) { for ( int i = 300; i <= 350; i = i + 10 ) {
point.x = 2 * radius * cos(coeff * i) + radius * cos(2 * coeff * i); PointOnCurve(i, radius, point);
point.y = 2 * radius * sin(coeff * i) - radius * sin(2 * coeff * i); point = point.Rotate(rotationAngle);
point += viaCenter;
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()) {
// 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);
int numSegments = aperture.Length() / aTrack.GetWidth();
int delta = radius / numSegments;
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);
point += viaCenter;
if (i == 10) {
int distance = SEG(viaCenter, point).Length();
if (distance < aVia.GetWidth() / 2) {
break;
}
}
m_coordinates.push_back(point);
}
lowerSegment.clear();
for ( int i = 350; i >= 300; i = i - 10 ) {
PointOnCurve(i, radius, point);
point = point.Rotate(rotationAngle); point = point.Rotate(rotationAngle);
point += viaCenter; point += viaCenter;
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);
}
}
}
return true; return true;
} }
bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment, int distance = 100) bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, int distance = 100)
{ {
VECTOR2I startPoint(0, 0); VECTOR2I startPoint(0, 0);
VECTOR2I endPoint(0, 0); VECTOR2I endPoint(0, 0);
...@@ -154,12 +197,8 @@ bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECT ...@@ -154,12 +197,8 @@ bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECT
upperPoint += viaCenter; upperPoint += viaCenter;
lowerPoint += viaCenter; lowerPoint += viaCenter;
upperSegment.push_back(linePoint);
upperSegment.push_back(upperPoint);
// Calculate the number of segments needed to fill the area inside the teardrop // Calculate the number of segments needed to fill the area inside the teardrop
std::vector<VECTOR2I> splitPoints; std::vector<VECTOR2I> splitPoints;
int vertexNum = 1;
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 // First, calculate the intersection point of the circle and one hand of the teardrop
r = aVia.GetWidth() / 2; r = aVia.GetWidth() / 2;
...@@ -170,60 +209,54 @@ bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECT ...@@ -170,60 +209,54 @@ bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECT
x = (upperPoint.x - startPoint.x) * t + startPoint.x; x = (upperPoint.x - startPoint.x) * t + startPoint.x;
y = (upperPoint.y - startPoint.y) * t + startPoint.y; y = (upperPoint.y - startPoint.y) * t + startPoint.y;
VECTOR2I intersectionPoint((int)x, (int)y); VECTOR2I intersectionPoint((int)x, (int)y);
DrawDebugPoint(intersectionPoint, 5);
// Second, calculate the distance between the track given and the intersection point // 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); SEG trackSegment(aTrack.GetStart().x, aTrack.GetStart().y, aTrack.GetEnd().x, aTrack.GetEnd().y);
int dist = trackSegment.LineDistance(intersectionPoint); int dist = trackSegment.LineDistance(intersectionPoint);
int numSegments = 2 * dist / aTrack.GetWidth(); int numSegments = 2 * dist / aTrack.GetWidth();
// Third, subdivide radius of the via and build additional segments // Third, subdivide the diameter of the via and build additional segments
SEG segRadius = SEG(upperPoint, lowerPoint); SEG segDiameter = SEG(upperPoint, lowerPoint);
// SEG segRadius = SEG(upperPoint, viaCenter); SplitSegment(segDiameter, numSegments, splitPoints);
SplitSegment(segRadius, numSegments, splitPoints);
} }
std::list<VECTOR2I> pts; std::list<VECTOR2I> outlinePoints;
pts.push_back(upperPoint); outlinePoints.push_back(upperPoint);
for (size_t i = 0; i < splitPoints.size(); i++) { for (size_t i = 0; i < splitPoints.size(); i++) {
pts.push_back(splitPoints[i]); outlinePoints.push_back(splitPoints[i]);
} }
pts.push_back(lowerPoint); outlinePoints.push_back(lowerPoint);
vertexNum = 0; // Biuld triangles filling the teardrop
std::list<VECTOR2I>::iterator iter = pts.begin(); int vertexNum = 0;
while ( iter != pts.end() ) { std::list<VECTOR2I>::iterator iter = outlinePoints.begin();
while ( iter != outlinePoints.end() ) {
switch (vertexNum) { switch (vertexNum) {
case 0: case 0:
vect.push_back(linePoint); m_coordinates.push_back(linePoint);
vertexNum++; vertexNum++;
break; break;
case 1: case 1:
vect.push_back(*iter); m_coordinates.push_back(*iter);
vertexNum++; vertexNum++;
iter++; iter++;
break; break;
case 2: case 2:
vect.push_back(*iter); m_coordinates.push_back(*iter);
vertexNum = 0; vertexNum = 0;
iter++; iter++;
break; break;
default:break; default:break;
} }
} }
// Append additional vertexies in order to finish last triangle
if (vertexNum == 0) { if (vertexNum == 0) {
vect.push_back(linePoint); m_coordinates.push_back(linePoint);
} }
else if (vertexNum == 2) { else if (vertexNum == 2) {
vect.push_back(vect[vect.size() - 3]); m_coordinates.push_back(m_coordinates[m_coordinates.size() - 3]);
vect.push_back(linePoint); m_coordinates.push_back(linePoint);
}
for (size_t i = 0; i < vect.size(); i++) {
printf("%d, %d\n", vect[i].x, vect[i].y);
} }
// lowerSegment.push_back(lowerPoint);
// lowerSegment.push_back(linePoint);
return true; return true;
} }
......
...@@ -55,7 +55,7 @@ public: ...@@ -55,7 +55,7 @@ public:
*/ */
bool Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type); bool Create(TRACK &aTrack, ENDPOINT_T endPoint, TEARDROP_TYPE type);
void GetCoordinates(std::vector<VECTOR2I> &points); void GetCoordinates(std::vector<VECTOR2I> &points) const {points = m_coordinates;}
private: private:
///> Contains the type of teardrop ///> Contains the type of teardrop
...@@ -63,7 +63,7 @@ private: ...@@ -63,7 +63,7 @@ private:
///> \a m_upperSegment and \a m_lowerSegment contain coordinates of segments composing a teardrop ///> \a m_upperSegment and \a m_lowerSegment contain coordinates of segments composing a teardrop
std::vector<VECTOR2I> m_upperSegment; std::vector<VECTOR2I> m_upperSegment;
std::vector<VECTOR2I> m_lowerSegment; std::vector<VECTOR2I> m_lowerSegment;
std::vector<VECTOR2I> vect; std::vector<VECTOR2I> m_coordinates;
/** /**
* @brief Function \a CurvedSegments computes several points on deltoid curve and moves * @brief Function \a CurvedSegments computes several points on deltoid curve and moves
...@@ -73,11 +73,9 @@ private: ...@@ -73,11 +73,9 @@ private:
* See deltiod description and its parametric equations on [wiki page](http://en.wikipedia.org/wiki/Deltoid_curve). * 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] aTrack defines a vector along which the curved segments should be built
* @param [in] aVia used as the center of coordinates * @param [in] aVia used as the center of coordinates
* @param [out] upperSegment vector contains the coordinates of computed segments
* @param [out] lowerSegment vector contains the coordinates of mirrored segments
* @return \a true in case the segments were successfully built and \a false otherwise * @return \a true in case the segments were successfully built and \a false otherwise
*/ */
bool CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment); 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 for a circle from a givent point.
...@@ -86,11 +84,9 @@ private: ...@@ -86,11 +84,9 @@ private:
* @param [in] aTrack defines a vector along which the segments should be built * @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] 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 * @param [in] distance is distance ratio (in percent) from circle center in respect to its diameter
* @param [out] upperSegment vector contains the coordinates of computed segments
* @param [out] lowerSegment vector contains the coordinates of mirrored segments
* @return \a true in case the segments were successfully built and \a false otherwise * @return \a true in case the segments were successfully built and \a false otherwise
*/ */
bool StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment, int distance); bool StraightSegments(TRACK &aTrack, const VIA &aVia, int distance);
/** /**
* @brief Function SetVector creates a vector from \a aTrack directed into \a aVia * @brief Function SetVector creates a vector from \a aTrack directed into \a aVia
...@@ -103,6 +99,11 @@ private: ...@@ -103,6 +99,11 @@ private:
BOARD_CONNECTED_ITEM* GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoint); BOARD_CONNECTED_ITEM* GetObjectOnEnd(TRACK &aTrack, ENDPOINT_T endPoint);
void SplitSegment(const SEG &segment, int splits, std::vector<VECTOR2I> &points); void SplitSegment(const SEG &segment, int splits, std::vector<VECTOR2I> &points);
inline void PointOnCurve(int angle, double radius, VECTOR2I &point) {
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);
}
}; };
#endif // CLASS_TEARDROP_H #endif // CLASS_TEARDROP_H
...@@ -204,6 +204,9 @@ bool TEARDROPS_EDITOR::DrawSegments(TEARDROP &teardrop, TRACK &aTrack) ...@@ -204,6 +204,9 @@ bool TEARDROPS_EDITOR::DrawSegments(TEARDROP &teardrop, TRACK &aTrack)
std::vector<TRACK *> tracks; std::vector<TRACK *> tracks;
std::vector<VECTOR2I> coordinates; std::vector<VECTOR2I> coordinates;
teardrop.GetCoordinates(coordinates); teardrop.GetCoordinates(coordinates);
assert(coordinates.size() != 0);
wxPoint currentPoint(0, 0); wxPoint currentPoint(0, 0);
wxPoint prevPoint(coordinates[0].x, coordinates[0].y); wxPoint prevPoint(coordinates[0].x, coordinates[0].y);
......
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