Commit a273b7bd authored by Vladimir Ur's avatar Vladimir Ur
Browse files

Work on internal (nano)metric length units started.

Added configuartion option KICAD_NANOMETRIC for this.
* With option set to false: *
- it should work and compile as usual
- some values are saved with decimal point (which should be backward/forward compatible as old versions should just drop fractional part)
* With option set to true: *
- lengths in Global Design Rules should be settable 1nm steps.
FROM/TO_LEGACY_LU(_DBL) macros introduced for easy interconnection between old and new units.
parent 311a8186
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ option(KICAD_GOST "enable/disable building using GOST notation for multiple gate
#for those who bored with uppercase
option(KICAD_KEEPCASE "turn-off automatic component name conversion to uppercase if selected")

#highly experimetnal option
option(KICAD_NANOMETRE "set length quantum to 1 nm for PCB")

option(USE_WX_GRAPHICS_CONTEXT
       "Use wxGraphicsContext for rendering (default OFF). Warning, this is experimental")

@@ -99,6 +102,10 @@ if(KICAD_KEEPCASE)
    add_definitions(-DKICAD_KEEPCASE)
endif(KICAD_KEEPCASE)

if(KICAD_NANOMETRE)
    add_definitions(-DKICAD_NANOMETRE)
endif(KICAD_NANOMETRE)

if(USE_WX_OVERLAY OR APPLE)
    add_definitions(-DUSE_WX_OVERLAY)
endif(USE_WX_OVERLAY OR APPLE)
+127 −0
Original line number Diff line number Diff line
@@ -441,6 +441,133 @@ int ReturnValueFromString( EDA_UNITS_T aUnit, const wxString& TextValue,
}


#ifdef KICAD_NANOMETRE

/*
 *New common length functions
 */

const LENGTH_UNIT_DESC g_MillimetreDesc =
{
    LENGTH_UNITS<LENGTH_DEF>::millimetre(),
    _(" mm"),
    wxT("mm"),
    6
};
const LENGTH_UNIT_DESC g_InchDesc =
{
    LENGTH_UNITS<LENGTH_DEF>::inch(),
    _(" \""),
    wxT("in"),
    7
};
const LENGTH_UNIT_DESC g_MilDesc =
{
    LENGTH_UNITS<LENGTH_DEF>::mil(),
    _(" mil"),
    wxT("mil"),
    5
};
const LENGTH_UNIT_DESC g_UnscaledDesc = /* stub */
{
    LENGTH_DEF::quantum(),
    wxT(""),
    wxT(""),
    4
};

const LENGTH_UNIT_DESC *UnitDescription( EDA_UNITS_T aUnit ) {
    switch(aUnit) {
        case INCHES:
            return &g_InchDesc;
        case MILLIMETRES:
            return &g_MillimetreDesc;
        default:
            return &g_UnscaledDesc; /* should not be reached */
    }
}

wxString LengthToString( const LENGTH_UNIT_DESC *aUnit, LENGTH_DEF aValue,
                         bool aAdd_unit_symbol ) {
    wxString StringValue;
    double   value_to_print;
    value_to_print = LENGTH<double>(aValue) / LENGTH<double>(aUnit->m_Value);
    StringValue.Printf( wxT( "%.*f" ), aUnit->m_Precision, value_to_print);
    if( aAdd_unit_symbol ) {
        StringValue += aUnit->m_Postfix;
    }
    return StringValue;
}
LENGTH_DEF StringToLength( const LENGTH_UNIT_DESC *aUnit, const wxString& TextValue )
{

    LENGTH_DEF    Value;
    double dtmp = 0;

    /* Acquire the 'right' decimal point separator */
    const struct lconv* lc = localeconv();
    wxChar decimal_point = lc->decimal_point[0];
    wxString            buf( TextValue.Strip( wxString::both ) );

    /* Convert the period in decimal point */
    buf.Replace( wxT( "." ), wxString( decimal_point, 1 ) );
    // An ugly fix needed by WxWidgets 2.9.1 that sometimes
    // back to a point as separator, although the separator is the comma
    // TODO: remove this line if WxWidgets 2.9.2 fixes this issue
    buf.Replace( wxT( "," ), wxString( decimal_point, 1 ) );

    /* Find the end of the numeric part */
    unsigned brk_point = 0;
    while( brk_point < buf.Len() )
    {
        wxChar ch = buf[brk_point];
        if( !( (ch >= '0' && ch <='9') || (ch == decimal_point)
             || (ch == '-') || (ch == '+') ) )
        {
            break;
        }
        ++brk_point;
    }

    /* Extract the numeric part */
    buf.Left( brk_point ).ToDouble( &dtmp );

    /* Check the optional unit designator (2 ch significant) */
    wxString unit( buf.Mid( brk_point ).Strip( wxString::leading ).Left( 2 ).Lower() );
    if( unit == wxT( "in" ) || unit == wxT( "\"" ) )
    {
        aUnit = &g_InchDesc;
    }
    else if( unit == wxT( "mm" ) )
    {
        aUnit = &g_MillimetreDesc;
    }
    else if( unit == wxT( "mi" ) || unit == wxT( "th" ) ) /* Mils or thous */
    {
        aUnit = &g_MilDesc;
    }
    Value = LENGTH_DEF( dtmp * LENGTH< double, 1 >( aUnit->m_Value ) );

    return Value;
}

void LengthToTextCtrl( wxTextCtrl& TextCtr, LENGTH_DEF Value ) {
    wxString msg = LengthToString( UnitDescription( g_UserUnit ), Value );

    TextCtr.SetValue( msg );
}
LENGTH_DEF LengthFromTextCtrl( const wxTextCtrl& TextCtr )
{
    LENGTH_DEF value;
    wxString msg = TextCtr.GetValue();

    value = StringToLength( UnitDescription( g_UserUnit ), msg );

    return value;
}

#endif

/**
 * Function wxStringSplit
 * Split a String to a String List when founding 'splitter'
+7 −5
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@

#include "pcbstruct.h"      // NB_COLORS

#include "lengthpcb.h"

// Class for handle current printed board design settings
class BOARD_DESIGN_SETTINGS
{
@@ -22,11 +24,11 @@ public:
    int    m_EdgeSegmentWidth;            // current graphic line width (EDGE layer only)
    int    m_PcbTextWidth;                // current Pcb (not module) Text width
    wxSize m_PcbTextSize;                 // current Pcb (not module) Text size
    int    m_TrackMinWidth;               // track min value for width ((min copper size value
    int    m_ViasMinSize;                 // vias (not micro vias) min diameter
    int    m_ViasMinDrill;                // vias (not micro vias) min drill diameter
    int    m_MicroViasMinSize;            // micro vias (not vias) min diameter
    int    m_MicroViasMinDrill;           // micro vias (not vias) min drill diameter
    LENGTH_PCB m_TrackMinWidth;               // track min value for width ((min copper size value
    LENGTH_PCB m_ViasMinSize;                 // vias (not micro vias) min diameter
    LENGTH_PCB m_ViasMinDrill;                // vias (not micro vias) min drill diameter
    LENGTH_PCB m_MicroViasMinSize;            // micro vias (not vias) min diameter
    LENGTH_PCB m_MicroViasMinDrill;           // micro vias (not vias) min drill diameter

    // Global mask margins:
    int    m_SolderMaskMargin;            // Solder mask margin
+27 −0
Original line number Diff line number Diff line
@@ -10,6 +10,11 @@
#include "wx/confbase.h"
#include "wx/fileconf.h"


#ifdef KICAD_NANOMETRE
#include "length.h"
#endif

class wxAboutDialogInfo;
class BASE_SCREEN;
class EDA_DRAW_FRAME;
@@ -321,6 +326,7 @@ wxString ReturnStringFromValue( EDA_UNITS_T aUnit,
                                       int  aInternal_Unit,
                                       bool aAdd_unit_symbol = false );


void            AddUnitSymbol( wxStaticText& Stext, EDA_UNITS_T aUnit = g_UserUnit );

/* Add string "  (mm):" or " ("):" to the static text Stext.
@@ -334,6 +340,27 @@ void PutValueInLocalUnits( wxTextCtrl& TextCtr, int Value,
int             ReturnValueFromTextCtrl( const wxTextCtrl& TextCtr,
                                         int               Internal_Unit );

#ifdef KICAD_NANOMETRE

struct LENGTH_UNIT_DESC
{
    LENGTH_DEF m_Value;
    wxString   m_Postfix;
    wxString   m_IntlSymbol;
    int        m_Precision;
};
extern const LENGTH_UNIT_DESC g_MillimetreDesc, g_InchDesc, g_MilDesc;

const LENGTH_UNIT_DESC *UnitDescription( EDA_UNITS_T aUnit );

LENGTH_DEF       StringToLength( const LENGTH_UNIT_DESC *aUnit, const wxString& TextValue );
wxString         LengthToString( const LENGTH_UNIT_DESC *aUnit, LENGTH_DEF aValue,
                                 bool aAdd_unit_symbol = false );

void             LengthToTextCtrl( wxTextCtrl& TextCtr, LENGTH_DEF Value );
LENGTH_DEF       LengthFromTextCtrl( const wxTextCtrl& TextCtr );
#endif

/* return a String List from a string, with a specific splitter*/
wxArrayString*  wxStringSplit( wxString txt, wxChar splitter );

+54 −8
Original line number Diff line number Diff line
/**
 * The physical length library. Made for nanometer scale.
 * @file length.h
 * @brief The physical length library. Made for nanometer scale.
 */

/* sorry it is not styled correctly, i'll work on it further */
/* sorry if it is not styled correctly, i'll work on it further */

#ifndef LENGTH_H_INCLUDED
#define LENGTH_H_INCLUDED 1

#include "limited_int.h"

/* type to be used by length units by default */
typedef int DEF_LENGTH_VALUE;
typedef LIMITED_INT< int > DEF_LENGTH_VALUE;

/**
 * Length template class
 * Length template class.
 * @param T actual type holding a value (be aware of precision and range!)
 * @param P power of length unit: 1 - length, 2 - area, 3 - volume, -1 - lin. density etc...
 * This class check length dimension in compile time. In runtime it behaves
@@ -47,6 +49,8 @@ typedef int DEF_LENGTH_VALUE;

template < typename T = DEF_LENGTH_VALUE, int P = 1 > class LENGTH;

typedef LENGTH<DEF_LENGTH_VALUE, 1> LENGTH_DEF;

/**
 * Length units contained in this class
 */
@@ -61,6 +65,38 @@ template < typename T, int P > struct LENGTH_TRAITS
    typedef LENGTH<T, P> flat;
};

template < typename T > struct LENGTH_CASTS
{
     template< typename X > static T cast( const X x )
     {
         return T( x );
     }
};

template <> struct LENGTH_CASTS < int >
{
     static int cast( const double x )
     {
         return floor( x + 0.5 );
     }
};

template <> struct LENGTH_CASTS < long >
{
     static long cast( const double x )
     {
         return floor( x + 0.5 );
     }
};

template < typename T > struct LENGTH_CASTS < LIMITED_INT< T > >
{
     static LIMITED_INT< T > cast( const double x )
     {
         return LIMITED_INT< T > ( floor( x + 0.5 ) );
     }
};

template < typename T > struct LENGTH_TRAITS< T, 0 >
{
    /* length dimension to power 0 is just a number, so LENGTH<T, 0> should be automatically converted to T */
@@ -92,7 +128,8 @@ public:
    {
        dimension = P
    };
    LENGTH( const LENGTH <T, P> &orig ) : m_U( orig.m_U )
    template< typename U > LENGTH( const LENGTH< U, P > &orig )
    : m_U( LENGTH_CASTS < T >::cast( orig.m_U ) )
    {
    }
    LENGTH( void ) : m_U()
@@ -104,6 +141,12 @@ public:
        return T(0);
    }

    /* Do not use this, please */
    static LENGTH<T, P> quantum ( void )
    {
        return T(1);
    }

    LENGTH<T, P> & operator = ( const LENGTH<T, P> & y )
    {
        this->m_U = y.m_U;
@@ -111,7 +154,7 @@ public:
    }
    template< typename Y > operator LENGTH< Y, P > ( void )
    {
        return this->m_U;
        return LENGTH< Y, P >( this->m_U );
    }
    /*************************/
    /* comparisons and tests */
@@ -231,6 +274,9 @@ public:
 * to get numeric value of length in specific units you should use a division
 * length/LENGTH_UNITS::metre() gives number of metres in length
 * legnth/LENGTH_UNITS::foot() gives number of feet in length
 *
 * Really these units are used in NEWPCB and printing routines, as EESCHEMA
 * is going to use relative units.
 */

template < typename T = DEF_LENGTH_VALUE > class LENGTH_UNITS {
@@ -275,4 +321,4 @@ template < typename T, int D > class LENGTH_UNITS< LENGTH< T, D > >: public LENG
{
};

#endif
#endif /* def LENGTH_H_INCLUDED */
Loading