Commit c25acdbb authored by Mikhail Karpenko's avatar Mikhail Karpenko
Browse files

Fill area inside teardrops

parent de8d191c
Loading
Loading
Loading
Loading
+81 −48
Original line number Original line Diff line number Diff line
@@ -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
    }
    }


    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,
    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


    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
    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
        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;
}
}
+9 −8
Original line number Original line Diff line number Diff line
@@ -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:
    ///> \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:
     * 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:
     * @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:


    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
+3 −0
Original line number Original line Diff line number Diff line
@@ -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);