Commit 02b1319c authored by Mikhail Karpenko's avatar Mikhail Karpenko
Browse files

Add TEARDROP class

parent b1cd83c1
Loading
Loading
Loading
Loading
+108 −0
Original line number Original line Diff line number Diff line
#include "class_teardrop.h"

TEARDROP::TEARDROP(BOARD_ITEM *aParent) :
    TRACK(aParent, PCB_TRACE_T)
{
    m_type = TEARDROP_NONE;
}

bool TEARDROP::Create(TRACK &aTrack)
{

}

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
    STATUS_FLAGS status = aTrack.IsPointOnEnds(wxPoint(aVia.GetPosition().x, aVia.GetPosition().y), aVia.GetWidth() / 2);
    if (status == STARTPOINT) {
        startPoint = aTrack.GetEnd();
        endPoint = aTrack.GetStart();
    }
    else if (status == ENDPOINT) {
        startPoint = aTrack.GetStart();
        endPoint = aTrack.GetEnd();
    }
    else {
        // The via is too far from any ends or the track is too short
        return false;
    }

    return true;
}

bool TEARDROP::CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment)
{
    VECTOR2I startPoint(0, 0);
    VECTOR2I endPoint(0, 0);

    if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) {
        return false;
    }

    VECTOR2I point(0, 0);
    VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y);
    double coeff = M_PI / 180.0;
    double radius = (aVia.GetWidth() / 2) - (aTrack.GetWidth() / 2);
    double rotationAngle = VECTOR2I(startPoint - endPoint).Angle();
    // Calculate segments of deltoid
    for ( int i = 10; i <= 60; i = i + 10 ) {
        point.x = 2 * radius * cos(coeff * i) + radius * cos(2 * coeff * i);
        point.y = 2 * radius * sin(coeff * i) - radius * sin(2 * coeff * i);
        point = point.Rotate(rotationAngle);
        point += viaCenter;
        upperSegment.push_back(point);
    }
    for ( int i = 300; i <= 350; i = i + 10 ) {
        point.x = 2 * radius * cos(coeff * i) + radius * cos(2 * coeff * i);
        point.y = 2 * radius * sin(coeff * i) - radius * sin(2 * coeff * i);
        point = point.Rotate(rotationAngle);
        point += viaCenter;
        lowerSegment.push_back(point);
    }

    return true;
}

bool TEARDROP::StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment, int distance = 100)
{
    VECTOR2I startPoint(0, 0);
    VECTOR2I endPoint(0, 0);
    VECTOR2I viaCenter(aVia.GetPosition().x, aVia.GetPosition().y);

    if ( !SetVector(aTrack, aVia, startPoint, endPoint) ) {
        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 x = (endPoint.x - startPoint.x) * t + startPoint.x;
    double y = (endPoint.y - startPoint.y) * t + startPoint.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));
    x = (endPoint.x - startPoint.x) * t + startPoint.x;
    y = (endPoint.y - startPoint.y) * t + startPoint.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;

    upperSegment.push_back(linePoint);
    upperSegment.push_back(upperPoint);
    lowerSegment.push_back(linePoint);
    lowerSegment.push_back(lowerPoint);

    return true;
}
+101 −0
Original line number Original line Diff line number Diff line
/*
 * 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/>.
 */

/**
 * @file class_teardrop.h
 * @brief Definitions for teardrops.
 */

#ifndef CLASS_TEARDROP_H
#define CLASS_TEARDROP_H

#include "class_track.h"

class TEARDROP : public TRACK
{
public:
    TEARDROP(BOARD_ITEM *aParent);

    /**
     * @brief 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 deltoid
    } TEARDROP_TYPE;

    /**
     * @brief GetType returns the type of the teardrop.
     * @return TEARDROP_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
     */
    bool Create(TRACK &aTrack);

private:
    ///> Contains the type of teardrop
    TEARDROP_TYPE m_type;
    ///> \a m_upperSegment and \a m_lowerSegment contain actual segments composing a teardrop
    std::vector<TRACK> m_upperSegment;
    std::vector<TRACK> m_lowerSegment;

    /**
     * @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
     * @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
     */
    bool CurvedSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment);

    /**
     * @brief Function \a StraightSegments builds two tangent lines for 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
     * @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
     */
    bool StraightSegments(TRACK &aTrack, const VIA &aVia, std::vector<VECTOR2I> &upperSegment, std::vector<VECTOR2I> &lowerSegment, int distance);

    /**
     * @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
     */
    bool SetVector(TRACK &aTrack, const VIA &aVia, VECTOR2I &startPoint, VECTOR2I &endPoint);
};

#endif // CLASS_TEARDROP_H