diff --git a/Documentation/biu-plan.txt b/Documentation/biu-plan.txt index 9a49bad893..3949d5a5bc 100644 --- a/Documentation/biu-plan.txt +++ b/Documentation/biu-plan.txt @@ -1,6 +1,57 @@ 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: ======= @@ -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 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 -integer. Another way to think of the BIU acronym is "Board Integer Unit" instead -of as Board Internal Unit. +integer. (Another way to think of the BIU acronym is "Board Integer Unit" instead +of as Board Internal Unit, to pave the way for the BFU, discussed below.) Therefore all intermediate products, quotients, trig, and exponential -calculations should be done using some larger floating point type. Distances -that do not have to be rounded back to integer can and should stay as floating -point. The typedef name of this floating point type is BFU (Board Float Units). -The engineering units on a BFU are the 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. +calculations should be done using some larger floating point type. By larger, +bitness or number of bits is meant. Distances that do not have to be rounded +back to integer immediately can and should stay in the larger floating point +"value container" for as long as possible. The typedef name of this floating +point type is BFU (Board Float Unit). The engineering units on a BFU are the +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 -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 -being written to disk in every case that I can think of, 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_BFU. +Format Strings: +============== + +Because all our save to disk functions use printf() style format strings, we +discuss how to construct a format string in the most usable way. There should be +a printf() style format string like "%.6g" for the BFU (cast to a hard coded +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 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 -transition to nanometers. After the transition, only nanometers will be used in -the compilation. No runtime switching is needed or wanted. Again, BIUs can only -be one or the other for a given compilation, and this will swing based on a -single #define. +compiled. It is not a runtime decision. Form 1) is needed only during the +preparation phase of the source code transition to nanometers. After the +transition, only nanometers will be used in the compilation. No runtime +switching is needed or wanted. Again, BIUs can only be one or the other for a +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 -give us the ability to easily modify it. But it might also make the source code +Eventually we may want to actually use "BIU" as our integer type in 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 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 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. 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 -forth between the two for awhile. This means we do not gut existing savers and -loaders until the new ones are debugged and stable. +loaders and savers, so that we can toggle usage back and forth between the two +for awhile. This means we do not gut existing savers and loaders until the new +ones are debugged and stable. The new savers and loaders are to be done in the context of a plug-in 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: ====================== @@ -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 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. +*) 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. +