This commit is contained in:
Dick Hollenbeck 2011-11-25 09:15:46 -06:00
parent 2fd8613777
commit dea21ba82e
1 changed files with 153 additions and 27 deletions

View File

@ -1,6 +1,57 @@
Proposed Plan for adding Nano Meters into PCBNEW as the Board Internal Unit Proposed Plan for adding Nano Meters into PCBNEW as the Board Internal Unit
=========================================================================== ===========================================================================
Author: Dick Hollenbeck November 25, 2011
Introduction:
============
This document sketches out a plan to move KiCad's PCBNEW program from deci-mil
internal units to nanometer internal units. The changes to the code are
significant enough to describe the basic process before the work is started.
Definitions:
===========
*) Board Internal Units (BIU). This is a pseudonym for the engineering units
used by a BOARD when it is in RAM, and only when it is in RAM. BIU is
essentially equal to nanometers in the future, and equal to deci-mils currently.
A BIU refers typically to a measurement or a position on an XY grid, and this is
because this grid is dimensioned in BIUs along both its X and Y axes. Both X and
Y can be either positive or negative on this grid. In the case of measurements
or scalars, there can be a radius, a diameter, a distance (length), and all of
these can and should be expressed in BIUs, so long we are in RAM and so long as
we are talking about the objects within the class BOARD instance. One special
feature of XY points within the BIU coordinate system is that they will always
be integers. In contrast, distances and other forms of measurements are not
subject to the same limitation by the very nature of physics. Coordinates are
always integers because we used signed whole numbers to represent these BIU
coordinates.
*) Snap grid. A snap grid is a subset of the full set of possible XY coordinates
in the BIU coordinate system. Points falling on the snap grid are evenly spaced
in X and Y directions and are some integer multiple apart in this 2D space,
greater than one BIU.
*) Metric Board. This is a pcb board that has a great number of coordinates and
distances that happen to be some multiple of the BIU that is also a multiple of
a metric engineering unit such as micrometers.
*) Imperial Board. This is a pcb board that has a great number of coordinates and
distances that happen to be some multiple of the BIU that is also a multiple of
an imperial engineering unit such as mils or inches.
Assumptions:
===========
a) It is ok to modify the board file format in order to handle the BIU change.
b) Boards saved on disk in the new format will not be readable using old software.
c) Since we have no backwards compatibility obligation (see b) above), we can
make significant changes to the file format while we have this disruption
opportunity.
General: General:
======= =======
@ -10,38 +61,78 @@ Moreover, because most of the bits within a 32 bit integer can be "used up" to
hold a typical length within a board, it is very likely that if pure 32 bit hold a typical length within a board, it is very likely that if pure 32 bit
integer math is done, such as the multiplication of two integers in order to integer math is done, such as the multiplication of two integers in order to
calculate a hypotenuse, then there will be an overflow within the 32 bit calculate a hypotenuse, then there will be an overflow within the 32 bit
integer. Another way to think of the BIU acronym is "Board Integer Unit" instead integer. (Another way to think of the BIU acronym is "Board Integer Unit" instead
of as Board Internal Unit. of as Board Internal Unit, to pave the way for the BFU, discussed below.)
Therefore all intermediate products, quotients, trig, and exponential Therefore all intermediate products, quotients, trig, and exponential
calculations should be done using some larger floating point type. Distances calculations should be done using some larger floating point type. By larger,
that do not have to be rounded back to integer can and should stay as floating bitness or number of bits is meant. Distances that do not have to be rounded
point. The typedef name of this floating point type is BFU (Board Float Units). back to integer immediately can and should stay in the larger floating point
The engineering units on a BFU are the same as on a BIU. A typedef is nice so "value container" for as long as possible. The typedef name of this floating
that we can toggle between double and "long double" for various compilations, point type is BFU (Board Float Unit). The engineering units on a BFU are the
and so that when performing casts, these are brief. same as on a BIU. A typedef is nice so that we can toggle between double and
"long double" for various compilations, and so that when performing casts, these
are brief textual expressions.
There should be printf() style format strings for the BFU enclosed within Format Strings:
a #define and its name should be FMT_BFU. This format string will be used ==============
at least for saving BOARD and MODULE files, and perhaps more. A define is needed
in case we switch between double and long double. BIUs will be scaled before Because all our save to disk functions use printf() style format strings, we
being written to disk in every case that I can think of, and since scaling is discuss how to construct a format string in the most usable way. There should be
a multiplication, it means casting one of the factors to BFU, and then this a printf() style format string like "%.6g" for the BFU (cast to a hard coded
product is output with a printf() style function using the FMT_BFU. double) enclosed within a #define and its name should be FMT_ENG. This format
string will be used at least for saving BOARD and MODULE files, and perhaps
more.
FMT_ENG stands for "format string for ENGineering units used out in the file". A
define is needed simply to provide consistency across many sites of usage. BIUs
will be scaled before being written to disk in every most every case, and since
scaling is a multiplication, it means casting one of the factors to BFU, and
then this product is output with a printf() style function using the FMT_ENG
string segment.
That is, the FMT_ENG will be suitable for use with a BFU type. When BFU is set
to double, then FMT_ENG will be set to "%.6g". When BFU is set to long double
then FMT_ENG will be set to "%.6lg". For example:
#if USE_DOUBLE_BFU
typedef double BFU;
#define FMT_ENG ".%6g"
#else
typedef long double BFU;
#define FMT_ENG ".%6Lg"
#endif
A format string can then be built up using compile time concatenation of
strings, like this:
fprintf( fp, "Value: " FMT_ENG " " FMT_ENG "\n", BFU( biu1 * scale), BFU( biu2 * scale ) );
The 3rd and 4th arguments are BFUs, and the casting is done after the multiply
since the scaling factor is already a double or perhaps even a long double. The
final argument needs to match the format string, so the final product is wrapped
in a BFU, which could actually be a truncation down to 64 bit float from 80 bit
float. The key points are: the calculation must be done in a float type at least
as bit-wide as BFU, and that the value actually passed to fprintf() must match
the format string.
Choosing BIU Units:
==================
BIUs are only used when a BOARD or MODULE is in RAM. A BIU is equivalent to BIUs are only used when a BOARD or MODULE is in RAM. A BIU is equivalent to
either a 1) deci-mil or 2) nanometer, depending on how the source code is either a 1) deci-mil or 2) nanometer, depending on how the source code is
compiled. Form 1) is needed only during the preparation phase of the source code compiled. It is not a runtime decision. Form 1) is needed only during the
transition to nanometers. After the transition, only nanometers will be used in preparation phase of the source code transition to nanometers. After the
the compilation. No runtime switching is needed or wanted. Again, BIUs can only transition, only nanometers will be used in the compilation. No runtime
be one or the other for a given compilation, and this will swing based on a switching is needed or wanted. Again, BIUs can only be one or the other for a
single #define. given compilation, and this will swing based on a single #define.
We may want to actually use "BIU" as our integer type in source code. This would Eventually we may want to actually use "BIU" as our integer type in source code
give us the ability to easily modify it. But it might also make the source code for those lengths which pertain to the board coordinate space. This would give
us the ability to easily modify it, go to a larger bitness, make the source code
more readable, and keep the type information out of the variable name. This more readable, and keep the type information out of the variable name. This
would mean having a point and/or size class based on BIU as the contained would mean having a point and/or size class based on BIU as the contained
integer types. I think this is a nice to have, but not immediately mandatory. integer types. This is a nice to have, but not immediately mandatory.
There will be a number of places within the source code which will have to be There will be a number of places within the source code which will have to be
doctored up to use the BFU casting. It will take some time to find all these doctored up to use the BFU casting. It will take some time to find all these
@ -98,13 +189,24 @@ In actuality, the source code to all 3 loaders, and to all 3 savers can be the
same source code with a single variable in each case for scaling. same source code with a single variable in each case for scaling.
All 6 loaders and all 6 savers should be written in parallel with existing All 6 loaders and all 6 savers should be written in parallel with existing
loaders and savers for this same purpose, so that we can toggle usage back and loaders and savers, so that we can toggle usage back and forth between the two
forth between the two for awhile. This means we do not gut existing savers and for awhile. This means we do not gut existing savers and loaders until the new
loaders until the new ones are debugged and stable. ones are debugged and stable.
The new savers and loaders are to be done in the context of a plug-in The new savers and loaders are to be done in the context of a plug-in
architecture, described elsewhere. architecture, described elsewhere.
Angles and Rotations:
====================
Internally we are switching from using an int to hold 1/10 of degrees angle to a
typedef called DEGREES. The allowed values that DEGREES can hold will be
enforced by the user interface policy, decided elsewhere. The engineering units
in the DEGREES type is degrees, no longer tenths of degrees.
/// a value used to hold rotations or angles.
typedef double DEGREES;
User Interface Changes: User Interface Changes:
====================== ======================
@ -120,6 +222,30 @@ factor should need be changed in the final state. Up until then, the work
required is to inject the BFU casting where needed along with the scaling required is to inject the BFU casting where needed along with the scaling
factor(s). factor(s).
8) Remove any funky imperial to metric conversion functions which tried to hide/mask *) Remove any funky imperial to metric conversion functions which tried to hide/mask
problems with lack of BIU precision. problems with lack of BIU precision.
*) There may be some fix ups pertaining to "near enough" type testing involving
the user's mouse position, other than bounding box hit testing which should take
care of itself (in BIUs). This has more to do with near-ness to a line type
tests, and these are thought to best be done in screen coordinates anyway, not
BIUs.
Work Tasks:
==========
*) Within PCBNEW, find math expressions involving BIUs and cast them to BFUs
early enough so that the compiler generates code in the BFU realm.
*) Find a way to consistently round values from BFUs back to BIUs, and put that
code in place. This could be done using a set accessor on a BIU, or other way.
*) Fix the User Interface issues mentioned above, and more found later.
*) Write the 4 new load and save functions. Vladimir recently committed code
which can be a starting point for some of these functions, except that the new
ones should reside within a PLUGIN object where we can save the scaling factor
variable as a member field of the plugin. In order to meet the requirements
of all 3 board loaders, we may have to dynamically change the scaling factor
depending on what we find in the *.brd file and how the plugin is compiled.