Index: tags/0.9.0/AUTHORS =================================================================== --- tags/0.9.0/AUTHORS (nonexistent) +++ tags/0.9.0/AUTHORS (revision 1402) @@ -0,0 +1,3 @@ +route-rnd is written and maintained by Tibor 'Igor2' Palinkas + +Contact: http://igor2.repo.hu/contact.html Index: tags/0.9.0/COPYING =================================================================== --- tags/0.9.0/COPYING (nonexistent) +++ tags/0.9.0/COPYING (revision 1402) @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. Index: tags/0.9.0/INSTALL =================================================================== --- tags/0.9.0/INSTALL (nonexistent) +++ tags/0.9.0/INSTALL (revision 1402) @@ -0,0 +1,11 @@ +0. requirements: + - an ANSI C compiler (the code requires at least C89) + - make (any implementation would do, GNU make is not required) + - POSIX shell with the usual set of utils (e.g. rm, cp, ln) + +1. ./configure (most probably you won't need to edit Makefile.conf) + +2. make + +3. make install + Index: tags/0.9.0/Makefile =================================================================== --- tags/0.9.0/Makefile (nonexistent) +++ tags/0.9.0/Makefile (revision 1402) @@ -0,0 +1,20 @@ +all: + cd src/route-rnd && $(MAKE) all + +clean: + cd src/route-rnd && $(MAKE) clean + +distclean: + cd src/route-rnd && $(MAKE) distclean + +install: + cd src/route-rnd && $(MAKE) install + cd doc && $(MAKE) install + +linstall: + cd src/route-rnd && $(MAKE) linstall + cd doc && $(MAKE) linstall + +uninstall: + cd src/route-rnd && $(MAKE) uninstall + cd doc && $(MAKE) uninstall Index: tags/0.9.0/Makefile.conf.in =================================================================== --- tags/0.9.0/Makefile.conf.in (nonexistent) +++ tags/0.9.0/Makefile.conf.in (revision 1402) @@ -0,0 +1,16 @@ +# Default installation prefix +PREFIX = /usr/local + +# For production enable this: +CFLAGS_CFG = -O3 + +# For debug, comment the above and uncomment this one: +#CFLAGS_CFG = -Wall -g + +# On windows you need to enable this +#EXE=.exe + +# shell utils, most probably no change required: +RM=rm -f +CP=cp +LN=ln -s Index: tags/0.9.0/README =================================================================== --- tags/0.9.0/README (nonexistent) +++ tags/0.9.0/README (revision 1402) @@ -0,0 +1,16 @@ +route-rnd: PCB autorouter for the ringdove suite +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Route-rnd is a generic 'external autorouter' developed for the ringdove suite. +It speaks the tEDAx format (http://www.repo.hu/projects/tedax). A route +request tEDAx document is generated by a PCB editor, then route-rnd is called +and writes the route result tEDAx which then can be fed back to the PCB +editor to create the tracks. This process is demonstrated by ringdove's +pcb-rnd external autorouter feature. + +Route-rnd is a modular router that offers different routing algorithms. + +For more info, open doc/index.html. + + + Index: tags/0.9.0/configure =================================================================== --- tags/0.9.0/configure (nonexistent) +++ tags/0.9.0/configure (revision 1402) @@ -0,0 +1,7 @@ +#!/bin/sh + +if test ! -f Makefile.conf +then + cp Makefile.conf.in Makefile.conf + echo "Optional: if you want to deviate from defaults, you may want to edit your Makefile.conf now." +fi Property changes on: tags/0.9.0/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/0.9.0/doc/Autostyle.html =================================================================== --- tags/0.9.0/doc/Autostyle.html (nonexistent) +++ tags/0.9.0/doc/Autostyle.html (revision 1402) @@ -0,0 +1,15 @@ + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ Index: tags/0.9.0/doc/Autostyle.sh =================================================================== --- tags/0.9.0/doc/Autostyle.sh (nonexistent) +++ tags/0.9.0/doc/Autostyle.sh (revision 1402) @@ -0,0 +1,77 @@ +#!/bin/sh + +autostyle() +{ + awk -v "template=$1" -v "root=$ROOT" ' + BEGIN { + while((getline < template) > 0) { + if (parse_auto(RES, $0)) { + if (RES["action"] == "begin") + curr = RES["ID"] + else + reset_curr = 1 + } + if (curr != "") + AUTO[curr] = AUTO[curr] var_subs($0) "\n" + if (reset_curr) { + curr = "" + reset_curr = 0 + } + } + } + + function var_subs(s) + { + gsub("[$]ROOT[$]", root, s) + return s + } + + function parse_auto(RES, line ,tmp) + { + if (!(line ~ ".*", "", line) + line = tolower(line) + tmp = line + sub("[ \t].*$", "", tmp) + RES["ID"] = tmp + tmp = line + sub("^[^ \t]*[ \t]*", "", tmp) + RES["action"] = tmp + return 1 + } + + { + if (parse_auto(RES, $0)) { + if (RES["action"] == "begin") + skip = 1 + else if (RES["action"] == "end") { + printf("%s", AUTO[RES["ID"]]) + skip = 0 + } + next + } + } + + (!skip) { print $0 } + + ' +} + +for html in $* +do + case $html in + Autostyle.html) ;; + *) + mv $html $html.tmp + autostyle "Autostyle.html" < $html.tmp > $html + if test $? = 0 + then + rm $html.tmp + else + echo "Failed on $html, keeping the original version." + mv $html.tmp $html + fi + esac +done Property changes on: tags/0.9.0/doc/Autostyle.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/0.9.0/doc/GRBS/conc_pp_ea.svg =================================================================== --- tags/0.9.0/doc/GRBS/conc_pp_ea.svg (nonexistent) +++ tags/0.9.0/doc/GRBS/conc_pp_ea.svg (revision 1402) @@ -0,0 +1,777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/0.9.0/doc/GRBS/conc_pp_oa.svg =================================================================== --- tags/0.9.0/doc/GRBS/conc_pp_oa.svg (nonexistent) +++ tags/0.9.0/doc/GRBS/conc_pp_oa.svg (revision 1402) @@ -0,0 +1,962 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/0.9.0/doc/GRBS/geo.svg =================================================================== --- tags/0.9.0/doc/GRBS/geo.svg (nonexistent) +++ tags/0.9.0/doc/GRBS/geo.svg (revision 1402) @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/0.9.0/doc/GRBS/src/Makefile =================================================================== --- tags/0.9.0/doc/GRBS/src/Makefile (nonexistent) +++ tags/0.9.0/doc/GRBS/src/Makefile (revision 1402) @@ -0,0 +1,4 @@ +all: ../geo.svg ../conc_pp_oa.svg ../conc_pp_ea.svg + +../%.svg: %.lht + pcb-rnd -x svg --cam $@=doc $^ Index: tags/0.9.0/doc/GRBS/src/conc_pp_ea.lht =================================================================== --- tags/0.9.0/doc/GRBS/src/conc_pp_ea.lht (nonexistent) +++ tags/0.9.0/doc/GRBS/src/conc_pp_ea.lht (revision 1402) @@ -0,0 +1,447 @@ +ha:pcb-rnd-board-v8 { + + li:styles { + ha:0.5mm { + via_proto = 0 + thickness = 0.5mm + text_thick = 0.0 + text_scale = 200 + clearance = 20.0mil + } + ha:0.2mm { + via_proto = 1 + thickness = 0.2mm + text_thick = 0.0 + text_scale = 100 + clearance = 20.0mil + } + ha:0.075mm { + via_proto = 2 + thickness = 0.075mm + text_thick = 0.0 + text_scale = 100 + clearance = 25.0mil + } + ha:Sig-tight { + via_proto = 3 + thickness = 10.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 120.0mm + y = 84.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=1.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=1.2mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.3 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:doc { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.7 { + x1=59.0mm; y1=18.0mm; x2=61.0mm; y2=18.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.10 { + x1=60.0mm; y1=19.0mm; x2=60.0mm; y2=17.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.13 { + x1=60.0mm; y1=18.0mm; x2=9.1mm; y2=65.3mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.41 { + x1=8.1mm; y1=65.3mm; x2=10.1mm; y2=65.3mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.44 { + x1=9.1mm; y1=66.3mm; x2=9.1mm; y2=64.3mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.51 { + x1=52.844582mm; y1=32.310835mm; x2=24.023249mm; y2=59.529677mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.56 { + x1=52.878655mm; y1=32.278655mm; x2=49.218737mm; y2=28.018737mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.59 { + x1=49.709751mm; y1=28.590248mm; x2=50.2mm; y2=28.1mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.62 { + x1=50.2mm; y1=28.1mm; x2=49.7mm; y2=27.571512mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.65 { + x1=52.85217mm; y1=32.247829mm; x2=60.0mm; y2=18.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.71 { + x1=51.5mm; y1=20.3mm; x2=51.0mm; y2=29.3mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.74 { + x1=51.0mm; y1=29.3mm; x2=2.0in; y2=28.8mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.77 { + x1=51.0mm; y1=29.3mm; x2=51.2mm; y2=28.8mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.83 { + x1=55.75mm; y1=16.75mm; x2=58.0mm; y2=20.75mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.90 { + x1=42.0mm; y1=66.0mm; x2=118.0mm; y2=66.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6 { + x=60.0mm; y=18.0mm; width=16.0mm; height=16.0mm; astart=0.000000; adelta=360.000000; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + lock=1 + } + } + ha:arc.16 { + x=60.0mm; y=18.0mm; width=16.0mm; height=16.0mm; astart=180.000000; adelta=-116.565051; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.47 { + x=9.1mm; y=65.3mm; width=16.0mm; height=16.0mm; astart=201.139825; adelta=-137.704876; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.81 { + x=60.0mm; y=18.0mm; width=4.0mm; height=4.0mm; astart=41.987212; adelta=21.321256; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.54 { + string=inc-inc line; x=22.75mm; y=36.2mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.55 { + string=conc-conc net; x=50.2mm; y=35.3mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.70 { + string=we; x=49.7mm; y=17.1mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.80 { + string=r; x=56.3mm; y=26.4mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.82 { + string=A; x=55.0mm; y=13.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.86 { + string={we: effective distance (coppers + smaller clearance)}; x=42.25mm; y=51.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.87 { + string={sin(A)=we/r}; x=42.0mm; y=56.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.88 { + string={A=asin(we/r)}; x=42.0mm; y=61.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.89 { + string={A: effective angle the concave arc is tuned with}; x=42.0mm; y=69.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#000000} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = global-doc + ha:type { doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=1 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + line_thickness = 200.00 um + via_proto = 1 + text_font_id = 0 + text_scale = 100 + text_thickness = 0 + clearance = 20.00 mil + } + ha:editor { + buffer_number = 0 + all_direction_lines = true + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/GRBS/src/conc_pp_oa.lht =================================================================== --- tags/0.9.0/doc/GRBS/src/conc_pp_oa.lht (nonexistent) +++ tags/0.9.0/doc/GRBS/src/conc_pp_oa.lht (revision 1402) @@ -0,0 +1,507 @@ +ha:pcb-rnd-board-v8 { + + li:styles { + ha:0.5mm { + via_proto = 0 + thickness = 0.5mm + text_thick = 0.0 + text_scale = 200 + clearance = 20.0mil + } + ha:0.2mm { + via_proto = 1 + thickness = 0.2mm + text_thick = 0.0 + text_scale = 100 + clearance = 20.0mil + } + ha:0.075mm { + via_proto = 2 + thickness = 0.075mm + text_thick = 0.0 + text_scale = 100 + clearance = 25.0mil + } + ha:Sig-tight { + via_proto = 3 + thickness = 10.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 117.0mm + y = 84.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=1.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=1.2mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.3 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:doc { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.8 { + x1=36.0mm; y1=53.0mm; x2=84.0mm; y2=7.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.11 { + x1=36.0mm; y1=53.0mm; x2=53.7mm; y2=62.35mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.20 { + x1=53.667282mm; y1=62.332717mm; x2=84.0mm; y2=7.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.29 { + x1=14.0mm; y1=53.0mm; x2=84.0mm; y2=53.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.32 { + x1=53.037433mm; y1=62.0mm; x2=2.1023622in; y2=61.3mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.35 { + x1=2.1023622in; y1=61.3mm; x2=54.044534mm; y2=61.644534mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.38 { + x1=84.0mm; y1=7.0mm; x2=84.0mm; y2=53.0mm; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.44 { + x1=21.378895mm; y1=66.646365mm; x2=3.0mm; y2=47.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.70 { + x1=103.193496mm; y1=12.823952mm; x2=108.0mm; y2=25.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.74 { + x1=65.0mm; y1=63.0mm; x2=59.0mm; y2=63.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.77 { + x1=57.0mm; y1=63.0mm; x2=59.0mm; y2=62.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.80 { + x1=59.0mm; y1=62.0mm; x2=59.0mm; y2=64.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.83 { + x1=59.0mm; y1=64.0mm; x2=57.0mm; y2=63.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.124 { + x1=73.0mm; y1=7.0mm; x2=79.0mm; y2=7.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.127 { + x1=81.0mm; y1=7.0mm; x2=79.0mm; y2=6.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.130 { + x1=79.0mm; y1=6.0mm; x2=79.0mm; y2=8.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.133 { + x1=79.0mm; y1=8.0mm; x2=81.0mm; y2=7.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.137 { + x1=93.0mm; y1=43.0mm; x2=117.0mm; y2=43.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.7 { + x=36.0mm; y=53.0mm; width=20.0mm; height=20.0mm; astart=0.000000; adelta=360.000000; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + lock=1 + } + } + ha:arc.43 { + x=36.0mm; y=53.0mm; width=20.0mm; height=20.0mm; astart=43.025066; adelta=109.129743; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.49 { + x=38.0mm; y=53.0mm; width=3.0mm; height=3.0mm; astart=180.000000; adelta=70.974394; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.50 { + x=38.0mm; y=53.0mm; width=4.0mm; height=4.0mm; astart=180.000000; adelta=-41.054814; thickness=0.075mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.69 { + x=98.621105mm; y=-6.646365mm; width=20.0mm; height=20.0mm; astart=43.025066; adelta=60.190747; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:text.41 { + string={e: from's endpoint}; x=77.0mm; y=1.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.47 { + string=A; x=39.0mm; y=53.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.48 { + string=B; x=38.0mm; y=51.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.51 { + string=dx; x=63.1mm; y=53.7mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.52 { + string=dy; x=85.0mm; y=39.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.53 { + string=a; x=54.5mm; y=32.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.58 { + string=the 'other' arc; x=27.0mm; y=74.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.59 { + string=(previous or next on 2net); x=27.0mm; y=79.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.65 { + string={cos(A+B) = r/a}; x=92.7mm; y=33.9mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.66 { + string={atan2(dy, dx) = B}; x=93.0mm; y=39.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.67 { + string=e is known; x=93.0mm; y=29.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.73 { + string=our new line shall be tangential here; x=66.0mm; y=61.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.87 { + string=we already know the endpoint of 'from'; x=18.0mm; y=5.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.136 { + string={Find: A}; x=93.0mm; y=45.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#000000} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = global-doc + ha:type { doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=1 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + line_thickness = 200.00 um + via_proto = 1 + text_font_id = 0 + text_scale = 100 + text_thickness = 0 + clearance = 20.00 mil + } + ha:editor { + buffer_number = 0 + all_direction_lines = true + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/GRBS/src/geo.lht =================================================================== --- tags/0.9.0/doc/GRBS/src/geo.lht (nonexistent) +++ tags/0.9.0/doc/GRBS/src/geo.lht (revision 1402) @@ -0,0 +1,423 @@ +ha:pcb-rnd-board-v8 { + + li:styles { + ha:0.5mm { + via_proto = 0 + thickness = 0.5mm + text_thick = 0.0 + text_scale = 200 + clearance = 20.0mil + } + ha:0.2mm { + via_proto = 1 + thickness = 0.2mm + text_thick = 0.0 + text_scale = 100 + clearance = 20.0mil + } + ha:0.075mm { + via_proto = 2 + thickness = 0.075mm + text_thick = 0.0 + text_scale = 100 + clearance = 25.0mil + } + ha:Sig-tight { + via_proto = 3 + thickness = 10.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=1.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=1.2mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.3 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:doc { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.6 { + x1=9.0mm; y1=20.0mm; x2=9.0mm; y2=39.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.9 { + x1=9.0mm; y1=20.0mm; x2=30.0mm; y2=20.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.12 { + x1=30.0mm; y1=20.0mm; x2=28.0mm; y2=18.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.15 { + x1=30.0mm; y1=20.0mm; x2=28.0mm; y2=22.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.18 { + x1=9.0mm; y1=39.0mm; x2=7.0mm; y2=37.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.21 { + x1=9.0mm; y1=39.0mm; x2=11.0mm; y2=37.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.28 { + x1=50.0mm; y1=27.0mm; x2=50.0mm; y2=94.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.31 { + x1=14.0mm; y1=60.0mm; x2=83.0mm; y2=60.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.35 { + x1=50.0mm; y1=60.0mm; x2=38.0mm; y2=37.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.38 { + x1=38.0mm; y1=37.0mm; x2=38.0mm; y2=40.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.41 { + x1=38.0mm; y1=37.0mm; x2=41.0mm; y2=39.0mm; thickness=0.2mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.53 { + x1=71.0mm; y1=78.0mm; x2=72.0mm; y2=74.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.56 { + x1=71.0mm; y1=78.0mm; x2=74.0mm; y2=76.0mm; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.27 { + x=50.0mm; y=61.0mm; width=27.0mm; height=27.0mm; astart=0.000000; adelta=360.000000; thickness=0.5mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:text.5 { + string=libgrbs SVG output coord system; x=200.0mil; y=150.0mil; scale=400; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.24 { + string=x+; x=24.0mm; y=15.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.25 { + string=y+; x=4.0mm; y=32.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.34 { + string=center; x=51.0mm; y=56.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.44 { + string=R; x=41.0mm; y=49.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.45 { + string=0; x=79.0mm; y=61.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.48 { + string=1/2 PI (~1.57); x=42.0mm; y=94.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.50 { + string=PI (~3.14); x=2.0mm; y=61.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.52 { + string=3/2 PI (~4.71); x=51.0mm; y=30.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.59 { + string={CW: positive delta angle}; x=76.0mm; y=73.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#000000} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = global-doc + ha:type { doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=1 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + line_thickness = 500.00 um + via_proto = 0 + text_font_id = 0 + text_scale = 200 + text_thickness = 0 + clearance = 20.00 mil + } + ha:editor { + buffer_number = 0 + all_direction_lines = true + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/Makefile =================================================================== --- tags/0.9.0/doc/Makefile (nonexistent) +++ tags/0.9.0/doc/Makefile (revision 1402) @@ -0,0 +1,25 @@ +ROOT=.. + +include $(ROOT)/Makefile.conf + +DOCDIR=$(install_root)$(DESTDIR)$(PREFIX)/share/doc/route-rnd + +all: *.html + @echo -n "HTMLS=" > Makefile.list + @ls *.html | grep -v Autostyle.html | tr "\n" " " >> Makefile.list + @echo "" >> Makefile.list + ROOT="" ./Autostyle.sh *.html + +include ../Makefile.conf +include Makefile.list + +install: + mkdir -p $(DOCDIR) + $(CP) $(HTMLS) $(DOCDIR) + +linstall: + mkdir -p $(DOCDIR) + for n in $(HTMLS); do $(LN) $(PWD)/$$n $(DOCDIR)/$$n; done + +uninstall: + $(RM) $(DOCDIR)/*.html Index: tags/0.9.0/doc/Makefile.list =================================================================== --- tags/0.9.0/doc/Makefile.list (nonexistent) +++ tags/0.9.0/doc/Makefile.list (revision 1402) @@ -0,0 +1 @@ +HTMLS=contact.html doc.html index.html irc.html license.html news.html state.html support.html Index: tags/0.9.0/doc/TRBS/2net.lht =================================================================== --- tags/0.9.0/doc/TRBS/2net.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/2net.lht (revision 1402) @@ -0,0 +1,582 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 50.25mm + y = 39.25mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.69 { + proto=2; x=3.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.70 { + proto=2; x=31.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.71 { + proto=2; x=16.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.72 { + proto=2; x=46.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.73 { + proto=2; x=25.0mm; y=33.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.74 { + proto=2; x=25.0mm; y=3.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.48 { + x1=1.0mm; y1=1.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.51 { + x1=1.0mm; y1=38.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.54 { + x1=49.0mm; y1=38.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.57 { + x1=49.0mm; y1=1.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.75 { + x1=1.0mm; y1=1.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.78 { + x1=3.0mm; y1=16.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.81 { + x1=1.0mm; y1=38.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.84 { + x1=25.0mm; y1=33.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.87 { + x1=49.0mm; y1=38.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.90 { + x1=46.0mm; y1=20.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.93 { + x1=49.0mm; y1=1.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.96 { + x1=25.0mm; y1=3.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.99 { + x1=1.0mm; y1=1.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.102 { + x1=16.0mm; y1=20.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.105 { + x1=16.0mm; y1=20.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.108 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.111 { + x1=16.0mm; y1=20.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.114 { + x1=25.0mm; y1=3.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.117 { + x1=25.0mm; y1=33.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.120 { + x1=31.0mm; y1=16.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.123 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.126 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.129 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.176 { + x1=16.0mm; y1=20.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.179 { + x1=25.0mm; y1=33.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.182 { + x1=16.0mm; y1=20.0mm; x2=17.0mm; y2=18.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.185 { + x1=17.0mm; y1=18.0mm; x2=30.0mm; y2=14.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.188 { + x1=30.0mm; y1=14.0mm; x2=31.0mm; y2=16.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.203 { + x1=25.0mm; y1=33.0mm; x2=33.0mm; y2=18.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.212 { + x1=33.0mm; y1=18.0mm; x2=33.25mm; y2=16.5mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.215 { + x1=33.25mm; y1=16.5mm; x2=32.75mm; y2=14.5mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.221 { + x1=32.75mm; y1=14.5mm; x2=24.698051mm; y2=100.4703937mil; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.224 { + x1=25.0mm; y1=33.0mm; x2=14.5mm; y2=21.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.227 { + x1=14.5mm; y1=21.75mm; x2=14.0mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.230 { + x1=14.0mm; y1=19.5mm; x2=14.25mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.233 { + x1=14.25mm; y1=17.75mm; x2=24.999999mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.236 { + x1=24.999999mm; y1=3.0mm; x2=24.894607mm; y2=3.144607mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.239 { + x1=16.5mm; y1=20.25mm; x2=17.0mm; y2=21.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.242 { + x1=17.0mm; y1=21.5mm; x2=30.5mm; y2=17.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.245 { + x1=30.5mm; y1=17.5mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } + +} Index: tags/0.9.0/doc/TRBS/2net.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/2net.png =================================================================== --- tags/0.9.0/doc/TRBS/2net.png (nonexistent) +++ tags/0.9.0/doc/TRBS/2net.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/2net.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/3net.lht =================================================================== --- tags/0.9.0/doc/TRBS/3net.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/3net.lht (revision 1402) @@ -0,0 +1,583 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 51.0mm + y = 40.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.69 { + proto=2; x=3.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.70 { + proto=2; x=31.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.71 { + proto=2; x=16.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.72 { + proto=2; x=46.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.73 { + proto=2; x=25.0mm; y=33.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.74 { + proto=2; x=25.0mm; y=3.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.48 { + x1=1.0mm; y1=1.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.51 { + x1=1.0mm; y1=38.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.54 { + x1=49.0mm; y1=38.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.57 { + x1=49.0mm; y1=1.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.75 { + x1=1.0mm; y1=1.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.78 { + x1=3.0mm; y1=16.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.81 { + x1=1.0mm; y1=38.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.84 { + x1=25.0mm; y1=33.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.87 { + x1=49.0mm; y1=38.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.90 { + x1=46.0mm; y1=20.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.93 { + x1=49.0mm; y1=1.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.96 { + x1=25.0mm; y1=3.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.99 { + x1=1.0mm; y1=1.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.102 { + x1=16.0mm; y1=20.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.105 { + x1=16.0mm; y1=20.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.108 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.111 { + x1=16.0mm; y1=20.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.114 { + x1=25.0mm; y1=3.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.117 { + x1=25.0mm; y1=33.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.120 { + x1=31.0mm; y1=16.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.123 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.126 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.129 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.176 { + x1=3.0mm; y1=16.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.179 { + x1=16.0mm; y1=20.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.182 { + x1=25.0mm; y1=3.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.185 { + x1=16.0mm; y1=20.0mm; x2=29.0mm; y2=23.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.194 { + x1=29.0mm; y1=23.0mm; x2=46.0mm; y2=20.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.197 { + x1=25.0mm; y1=33.0mm; x2=13.0mm; y2=23.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.200 { + x1=13.0mm; y1=23.0mm; x2=12.0mm; y2=19.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.203 { + x1=12.0mm; y1=19.0mm; x2=14.0mm; y2=17.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.206 { + x1=14.0mm; y1=17.0mm; x2=18.0mm; y2=17.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.212 { + x1=18.0mm; y1=17.0mm; x2=30.0mm; y2=19.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.215 { + x1=30.0mm; y1=19.0mm; x2=33.0mm; y2=18.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.221 { + x1=33.0mm; y1=18.0mm; x2=34.0mm; y2=17.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.224 { + x1=34.0mm; y1=17.0mm; x2=33.0mm; y2=14.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.227 { + x1=33.0mm; y1=14.0mm; x2=25.0mm; y2=3.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.230 { + x1=3.0mm; y1=16.0mm; x2=11.0mm; y2=14.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.233 { + x1=11.0mm; y1=14.0mm; x2=19.0mm; y2=14.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.236 { + x1=19.0mm; y1=14.0mm; x2=31.0mm; y2=16.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 200 + via_thickness = 2.2000 mm + via_drilling_hole = 2.0000 mm + text_thickness = 1000.00 um + line_thickness = 1000.00 um + clearance = 20.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + rubber_band_keep_midlinedir = true + rubber_band_mode = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/3net.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/3net.png =================================================================== --- tags/0.9.0/doc/TRBS/3net.png (nonexistent) +++ tags/0.9.0/doc/TRBS/3net.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/3net.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/BASE.lht =================================================================== --- tags/0.9.0/doc/TRBS/BASE.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/BASE.lht (revision 1402) @@ -0,0 +1,287 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/Makefile =================================================================== --- tags/0.9.0/doc/TRBS/Makefile (nonexistent) +++ tags/0.9.0/doc/TRBS/Makefile (revision 1402) @@ -0,0 +1,7 @@ +DPI=300 +PICS = 2net.png 3net.png passthru1.png passthru2.png passthru3.png tri.png uturn.png path.png astar.png + +all: $(PICS) + +%.png: %.lht + pcb-rnd -x png --dpi $(DPI) --as-shown --cam $@=doc $^ Index: tags/0.9.0/doc/TRBS/astar.lht =================================================================== --- tags/0.9.0/doc/TRBS/astar.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/astar.lht (revision 1402) @@ -0,0 +1,574 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 82.0mm + y = 39.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.5 { + x1=16.0mm; y1=20.0mm; x2=6.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.8 { + x1=6.0mm; y1=7.0mm; x2=20.0mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.11 { + x1=20.0mm; y1=4.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.14 { + x1=16.0mm; y1=20.0mm; x2=29.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.17 { + x1=29.0mm; y1=9.0mm; x2=20.0mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.20 { + x1=16.0mm; y1=20.0mm; x2=22.0mm; y2=31.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.23 { + x1=22.0mm; y1=31.0mm; x2=29.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.26 { + x1=16.0mm; y1=20.0mm; x2=5.0mm; y2=29.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.29 { + x1=5.0mm; y1=29.0mm; x2=22.0mm; y2=31.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.32 { + x1=5.0mm; y1=29.0mm; x2=6.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.92 { + x1=41.0mm; y1=9.0mm; x2=43.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.95 { + x1=43.0mm; y1=33.0mm; x2=54.0mm; y2=10.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.98 { + x1=54.0mm; y1=10.0mm; x2=41.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.131 { + x1=67.0mm; y1=9.0mm; x2=69.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.134 { + x1=69.0mm; y1=33.0mm; x2=80.0mm; y2=10.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.137 { + x1=80.0mm; y1=10.0mm; x2=67.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.106 { + x1=42.0mm; y1=19.0mm; x2=33.0mm; y2=30.0mm; thickness=1.7mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.109 { + x1=42.0mm; y1=19.0mm; x2=54.0mm; y2=10.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.140 { + x1=68.0mm; y1=19.0mm; x2=59.0mm; y2=30.0mm; thickness=1.7mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.166 { + x1=68.0mm; y1=19.0mm; x2=75.0mm; y2=20.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.169 { + x1=68.0mm; y1=19.0mm; x2=74.0mm; y2=9.0mm; thickness=1.0mm; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.38 { + x1=12.0mm; y1=2.0mm; x2=12.75mm; y2=4.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.41 { + x1=12.75mm; y1=4.25mm; x2=12.25mm; y2=3.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.44 { + x1=12.75mm; y1=4.25mm; x2=12.75mm; y2=3.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.65 { + x1=27.524519mm; y1=22.323557mm; x2=25.75mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.68 { + x1=25.75mm; y1=20.75mm; x2=1.0406698in; y2=20.933013mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.71 { + x1=25.75mm; y1=20.75mm; x2=26.125mm; y2=21.399519mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.74 { + x1=2.426443mm; y1=17.274519mm; x2=4.75mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.77 { + x1=4.75mm; y1=17.75mm; x2=4.066987mm; y2=17.933013mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.80 { + x1=4.75mm; y1=17.75mm; x2=4.100481mm; y2=17.375mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.83 { + x1=13.274519mm; y1=32.823557mm; x2=13.75mm; y2=30.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.86 { + x1=13.75mm; y1=30.5mm; x2=13.933013mm; y2=31.183013mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.89 { + x1=13.75mm; y1=30.5mm; x2=13.375mm; y2=31.149519mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.157 { + x1=77.399519mm; y1=23.924038mm; x2=75.625mm; y2=22.350481mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.160 { + x1=75.625mm; y1=22.350481mm; x2=76.308013mm; y2=22.533494mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.163 { + x1=75.625mm; y1=22.350481mm; x2=76.0mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.181 { + x1=78.073557mm; y1=6.975481mm; x2=76.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.184 { + x1=76.5mm; y1=8.75mm; x2=76.683013mm; y2=8.066987mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.187 { + x1=76.5mm; y1=8.75mm; x2=77.149519mm; y2=8.375mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.275 { + x1=27.073557mm; y1=3.975481mm; x2=25.5mm; y2=5.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.278 { + x1=25.5mm; y1=5.75mm; x2=25.683013mm; y2=5.066987mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.281 { + x1=25.5mm; y1=5.75mm; x2=26.149519mm; y2=5.375mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.35 { + string=a; x=16.0mm; y=34.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.37 { + string=S; x=17.0mm; y=19.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.105 { + string=T; x=55.0mm; y=8.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.113 { + string=b; x=43.0mm; y=34.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.147 { + string=c; x=69.0mm; y=34.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 200 + via_thickness = 2.2000 mm + via_drilling_hole = 2.0000 mm + text_thickness = 1000.00 um + line_thickness = 1000.00 um + clearance = 20.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/astar.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/astar.png =================================================================== --- tags/0.9.0/doc/TRBS/astar.png (nonexistent) +++ tags/0.9.0/doc/TRBS/astar.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/astar.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/fail.html =================================================================== --- tags/0.9.0/doc/TRBS/fail.html (nonexistent) +++ tags/0.9.0/doc/TRBS/fail.html (revision 1402) @@ -0,0 +1,31 @@ + + +

The case TRBS can not handle

+

+Spacing is calculated on triangulation edges. This implicitly assumes an edge +is always a radial construct relative to the closest point (e.g. via). In +the following example the almost vertical edge between cr 197 and cr 198, the +starting from pin 1's south-east corner is going too close to pin 2. In +the initial sketch it is not critical: +

+ +

+But after the global puller, the route is identical to that edge: +

+ +

+This route can not consider spacing to pin 2 because there is no near-perpendicular +edge, radial from pin 2 against the route. +

+Fix 1: It would be possible to insert such an edge, detecting a tangential +edge is "too close" to pin 2. However adding such edges that are not radial +from any obstacle may ruin trbs: the edge would be in the middle between pin +rows and if there are enough vertical lines it is not clear where exactly it +should be placed to not interfere with spacing. +

+Fix 2: it would be possible to create an ocatagon for the triangulation at +the round copper of the pin. But that wouldn't necessarily solve the +problem because the tangential line would then be tangential to the corner +of the octagon. + + Index: tags/0.9.0/doc/TRBS/fail1.svg =================================================================== --- tags/0.9.0/doc/TRBS/fail1.svg (nonexistent) +++ tags/0.9.0/doc/TRBS/fail1.svg (revision 1402) @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + P3 + P13 + + + P1 + P2 + + P16 + + + + + + + + P5 + + + + P4 + + + + P15 + P20 + + + P6 + + + + P17 + P7 + + + + + + + + + + + + + + + + + P8 + P21 + + + + + P0 + P10 + + + + P14 + P18 + P19 + P22 + P23 + + + + + + + P9 + P11 + P12 + + + + + + + + + + + + + + + 169 + 170 + 171 + 259 + 260 + 186 + 188 + 189 + 256 + 265 + 270 + 191 + 269 + 197 + 271 + 266 + 253 + 258 + 254 + 255 + 148 + 172 + 185 + 257 + 147 + 150 + 193 + 194 + 196 + 195 + 198 + 199 + 201 + 203 + 206 + 184 + 221 + 223 + 225 + 226 + 228 + 173 + 179 + 182 + 262 + 227 + 230 + 174 + 181 + 267 + 187 + 261 + 263 + 268 + 175 + 214 + 216 + 218 + 176 + 153 + 156 + 180 + 190 + 235 + 264 + 155 + 157 + 158 + 192 + 200 + 224 + 231 + 233 + 159 + 168 + 248 + 160 + 166 + 202 + 161 + 241 + 163 + 164 + 205 + 243 + 165 + 167 + 204 + 244 + 245 + 252 + 246 + 247 + 249 + 177 + 178 + 208 + 229 + 183 + 207 + 210 + 149 + 151 + 152 + 219 + 251 + 209 + 211 + 212 + 213 + 215 + 217 + 220 + 154 + 222 + 236 + 237 + 238 + 162 + 232 + 234 + 242 + 239 + 240 + 250 + + + + + + + + + \ No newline at end of file Index: tags/0.9.0/doc/TRBS/fail2.svg =================================================================== --- tags/0.9.0/doc/TRBS/fail2.svg (nonexistent) +++ tags/0.9.0/doc/TRBS/fail2.svg (revision 1402) @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + P3 + P13 + + + P1 + P2 + + P16 + + + + + + + + P5 + + + + P4 + + + + P15 + P20 + + + P6 + + + + P17 + P7 + + + + + + + + + + + + + + + + + P8 + P21 + + + + + P0 + P10 + + + + P14 + P18 + P19 + P22 + P23 + + + + + + + P9 + P11 + P12 + + + + + + + + + + + + + + + 169 + 170 + 171 + 259 + 260 + 188 + 270 + 269 + 265 + 271 + 186 + 189 + 191 + 256 + 197 + 253 + 258 + 254 + 266 + 255 + 148 + 172 + 185 + 257 + 147 + 150 + 193 + 194 + 196 + 195 + 198 + 199 + 201 + 203 + 206 + 184 + 221 + 223 + 225 + 226 + 228 + 173 + 179 + 182 + 262 + 227 + 230 + 174 + 181 + 267 + 187 + 261 + 263 + 268 + 175 + 214 + 216 + 218 + 176 + 153 + 156 + 180 + 190 + 235 + 264 + 155 + 157 + 158 + 192 + 200 + 224 + 231 + 233 + 159 + 168 + 248 + 160 + 166 + 202 + 161 + 241 + 163 + 164 + 205 + 243 + 165 + 167 + 204 + 244 + 245 + 252 + 246 + 247 + 249 + 177 + 178 + 208 + 229 + 183 + 207 + 210 + 149 + 151 + 152 + 219 + 251 + 209 + 211 + 212 + 213 + 215 + 217 + 220 + 154 + 222 + 236 + 237 + 238 + 162 + 232 + 234 + 242 + 239 + 240 + 250 + + + + + + + + + \ No newline at end of file Index: tags/0.9.0/doc/TRBS/passthru1.lht =================================================================== --- tags/0.9.0/doc/TRBS/passthru1.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru1.lht (revision 1402) @@ -0,0 +1,761 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 74.5mm + y = 71.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.5 { + x1=6.25mm; y1=9.25mm; x2=34.25mm; y2=65.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.8 { + x1=34.25mm; y1=65.25mm; x2=63.25mm; y2=42.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.11 { + x1=63.25mm; y1=42.25mm; x2=6.25mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.14 { + x1=11.25mm; y1=19.25mm; x2=15.25mm; y2=14.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.17 { + x1=15.25mm; y1=14.25mm; x2=15.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.20 { + x1=11.25mm; y1=19.25mm; x2=1.25mm; y2=21.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.23 { + x1=30.25mm; y1=57.25mm; x2=40.25mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.26 { + x1=40.25mm; y1=60.25mm; x2=44.25mm; y2=70.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.29 { + x1=30.25mm; y1=57.25mm; x2=20.25mm; y2=63.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.35 { + x1=43.25mm; y1=58.25mm; x2=65.25mm; y2=69.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.41 { + x1=49.25mm; y1=53.25mm; x2=46.25mm; y2=32.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.44 { + x1=46.25mm; y1=32.25mm; x2=52.25mm; y2=22.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.47 { + x1=49.25mm; y1=53.25mm; x2=69.25mm; y2=66.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.50 { + x1=58.25mm; y1=46.25mm; x2=56.25mm; y2=38.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.53 { + x1=56.25mm; y1=38.25mm; x2=60.25mm; y2=28.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.56 { + x1=58.25mm; y1=46.25mm; x2=73.25mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.71 { + x1=43.25mm; y1=58.25mm; x2=27.25mm; y2=51.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.74 { + x1=27.25mm; y1=51.25mm; x2=14.25mm; y2=55.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.79 { + x1=23.25mm; y1=40.25mm; x2=28.25mm; y2=50.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.82 { + x1=28.25mm; y1=50.25mm; x2=28.25mm; y2=49.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.85 { + x1=28.25mm; y1=50.25mm; x2=27.5mm; y2=49.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.88 { + x1=29.75mm; y1=51.5mm; x2=42.75mm; y2=57.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.91 { + x1=42.75mm; y1=57.0mm; x2=42.5mm; y2=56.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.94 { + x1=42.75mm; y1=57.0mm; x2=42.0mm; y2=57.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.97 { + x1=43.5mm; y1=56.75mm; x2=48.25mm; y2=53.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.100 { + x1=48.25mm; y1=53.0mm; x2=47.75mm; y2=53.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.103 { + x1=48.389705mm; y1=52.889705mm; x2=48.25mm; y2=53.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.106 { + x1=48.25mm; y1=52.25mm; x2=45.5mm; y2=32.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.109 { + x1=45.5mm; y1=32.75mm; x2=45.25mm; y2=33.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.112 { + x1=45.5mm; y1=32.75mm; x2=46.0mm; y2=33.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.115 { + x1=20.0mm; y1=40.0mm; x2=23.25mm; y2=40.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.118 { + x1=29.75mm; y1=54.0mm; x2=31.25mm; y2=56.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.121 { + x1=31.25mm; y1=56.75mm; x2=30.75mm; y2=56.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.124 { + x1=31.25mm; y1=56.75mm; x2=31.25mm; y2=56.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.127 { + x1=32.5mm; y1=57.0mm; x2=39.0mm; y2=59.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.130 { + x1=39.0mm; y1=59.0mm; x2=38.75mm; y2=58.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.133 { + x1=39.0mm; y1=59.0mm; x2=38.5mm; y2=59.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.136 { + x1=40.25mm; y1=59.5mm; x2=41.75mm; y2=58.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.142 { + x1=41.75mm; y1=58.5mm; x2=41.0mm; y2=58.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.145 { + x1=41.75mm; y1=58.5mm; x2=41.5mm; y2=59.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.148 { + x1=40.75mm; y1=58.0mm; x2=29.25mm; y2=53.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.151 { + x1=29.25mm; y1=53.0mm; x2=29.5mm; y2=53.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.157 { + x1=29.25mm; y1=53.0mm; x2=29.75mm; y2=52.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.160 { + x1=29.75mm; y1=54.0mm; x2=27.75mm; y2=54.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.163 { + x1=19.75mm; y1=39.25mm; x2=21.5mm; y2=36.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.166 { + x1=21.5mm; y1=36.75mm; x2=13.0mm; y2=21.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.169 { + x1=13.0mm; y1=21.0mm; x2=13.0mm; y2=21.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.172 { + x1=13.0mm; y1=21.0mm; x2=13.75mm; y2=21.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.175 { + x1=12.25mm; y1=19.25mm; x2=15.25mm; y2=15.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.178 { + x1=15.25mm; y1=15.75mm; x2=14.5mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.181 { + x1=15.25mm; y1=15.75mm; x2=15.25mm; y2=16.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.184 { + x1=16.657738mm; y1=16.842261mm; x2=29.75mm; y2=24.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.187 { + x1=29.75mm; y1=24.5mm; x2=30.0mm; y2=25.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.190 { + x1=30.0mm; y1=25.5mm; x2=31.0mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.193 { + x1=31.0mm; y1=25.0mm; x2=43.75mm; y2=32.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.196 { + x1=43.75mm; y1=32.5mm; x2=44.75mm; y2=32.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.199 { + x1=16.657738mm; y1=16.842261mm; x2=16.5mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.204 { + x1=9.75mm; y1=14.0mm; x2=8.5mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.207 { + x1=8.5mm; y1=12.0mm; x2=8.5mm; y2=12.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.210 { + x1=8.5mm; y1=12.0mm; x2=9.25mm; y2=12.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.213 { + x1=9.75mm; y1=14.0mm; x2=8.5mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.216 { + x1=6.5mm; y1=8.75mm; x2=7.5mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.219 { + x1=7.5mm; y1=8.5mm; x2=10.25mm; y2=10.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.222 { + x1=10.25mm; y1=10.25mm; x2=11.0mm; y2=10.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.225 { + x1=11.0mm; y1=10.0mm; x2=11.25mm; y2=10.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.228 { + x1=11.25mm; y1=10.75mm; x2=14.25mm; y2=12.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.231 { + x1=14.25mm; y1=12.75mm; x2=14.5mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.64 { + string=S2 landing; x=25.035898mm; y=22.767949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.68 { + string=S1; x=7.785898mm; y=13.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 300.000000 + } + ha:text.70 { + string=S2; x=18.785898mm; y=38.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 300.000000 + } + ha:text.78 { + string=S3; x=26.785898mm; y=53.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 300.000000 + } + ha:text.203 { + string=target edge; x=28.285898mm; y=17.017949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.235 { + string=S1 landing; x=2.785898mm; y=0.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.561 { + string=PA; x=2.035898mm; y=7.767949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.562 { + string=PB; x=33.035898mm; y=66.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.563 { + string=PC; x=64.285898mm; y=41.017949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/passthru1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/passthru1.png =================================================================== --- tags/0.9.0/doc/TRBS/passthru1.png (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru1.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/passthru1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/passthru2.lht =================================================================== --- tags/0.9.0/doc/TRBS/passthru2.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru2.lht (revision 1402) @@ -0,0 +1,483 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 74.0mm + y = 73.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.11 { + x1=63.0mm; y1=44.0mm; x2=6.0mm; y2=11.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5 { + x1=6.0mm; y1=11.0mm; x2=34.0mm; y2=67.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.8 { + x1=34.0mm; y1=67.0mm; x2=63.0mm; y2=44.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.370 { + x1=34.0mm; y1=67.0mm; x2=54.5mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.373 { + x1=54.5mm; y1=39.0mm; x2=71.25mm; y2=38.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.79 { + x1=23.0mm; y1=42.0mm; x2=32.25mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.115 { + x1=19.75mm; y1=41.75mm; x2=23.0mm; y2=42.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.169 { + x1=12.75mm; y1=22.75mm; x2=12.75mm; y2=23.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.172 { + x1=12.75mm; y1=22.75mm; x2=13.5mm; y2=23.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.184 { + x1=9.0mm; y1=14.25mm; x2=29.5mm; y2=26.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.187 { + x1=29.5mm; y1=26.25mm; x2=29.75mm; y2=27.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.190 { + x1=29.75mm; y1=27.25mm; x2=30.75mm; y2=26.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.193 { + x1=30.75mm; y1=26.75mm; x2=52.0mm; y2=39.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.166 { + x1=21.25mm; y1=38.5mm; x2=12.75mm; y2=22.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.163 { + x1=19.5mm; y1=41.0mm; x2=21.25mm; y2=38.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.385 { + x1=32.25mm; y1=60.5mm; x2=32.25mm; y2=59.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.388 { + x1=32.25mm; y1=60.5mm; x2=31.5mm; y2=60.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.391 { + x1=34.0mm; y1=65.25mm; x2=51.5mm; y2=41.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.400 { + x1=9.0mm; y1=14.25mm; x2=8.5mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.403 { + x1=52.0mm; y1=39.25mm; x2=52.75mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.406 { + x1=51.5mm; y1=41.5mm; x2=50.5mm; y2=42.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.409 { + x1=51.5mm; y1=41.5mm; x2=51.0mm; y2=42.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.64 { + string=S2 landing; x=975.82275591mil; y=24.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.70 { + string=S2; x=18.535898mm; y=40.267949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 300.000000 + } + ha:text.203 { + string=target edge; x=28.035898mm; y=18.767949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.418 { + string=PA; x=2.035898mm; y=9.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.420 { + string=PB; x=33.035898mm; y=68.267949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.422 { + string=PC; x=64.285898mm; y=42.767949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + } + color = {#cd3700} + } + + ha:wires2 { + lid=4 + group=5 + ha:combining { } + + li:objects { + ha:line.412 { + x1=6.0mm; y1=11.0mm; x2=23.75mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#548b54} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; 4; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/passthru2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/passthru2.png =================================================================== --- tags/0.9.0/doc/TRBS/passthru2.png (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru2.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/passthru2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/passthru3.lht =================================================================== --- tags/0.9.0/doc/TRBS/passthru3.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru3.lht (revision 1402) @@ -0,0 +1,433 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 73.0mm + y = 65.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.11 { + x1=67.0mm; y1=36.0mm; x2=10.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.8 { + x1=38.0mm; y1=59.0mm; x2=67.0mm; y2=36.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5 { + x1=10.0mm; y1=3.0mm; x2=38.0mm; y2=59.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.469 { + x1=13.0mm; y1=9.0mm; x2=58.0mm; y2=43.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.472 { + x1=58.0mm; y1=43.0mm; x2=71.0mm; y2=45.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.475 { + x1=13.0mm; y1=9.0mm; x2=2.0mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.79 { + x1=27.0mm; y1=34.0mm; x2=36.25mm; y2=52.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.115 { + x1=23.75mm; y1=33.75mm; x2=27.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.385 { + x1=36.25mm; y1=52.5mm; x2=36.25mm; y2=51.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.388 { + x1=36.25mm; y1=52.5mm; x2=35.5mm; y2=52.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.478 { + x1=39.0mm; y1=57.0mm; x2=54.0mm; y2=45.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.481 { + x1=54.0mm; y1=45.0mm; x2=53.0mm; y2=45.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.484 { + x1=54.0mm; y1=45.0mm; x2=53.5mm; y2=45.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.487 { + x1=55.75mm; y1=42.5mm; x2=17.5mm; y2=13.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.490 { + x1=17.5mm; y1=13.75mm; x2=17.75mm; y2=14.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.493 { + x1=17.5mm; y1=13.75mm; x2=18.25mm; y2=13.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.70 { + string=S2; x=22.535898mm; y=32.267949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 300.000000 + } + ha:text.203 { + string=target edge; x=32.035898mm; y=423.935mil; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 330.000000 + } + ha:text.418 { + string=PA; x=6.035898mm; y=1.517949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.420 { + string=PB; x=37.035898mm; y=60.267949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + ha:text.422 { + string=PC; x=68.285898mm; y=34.767949mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + thickness = 0.1mm + rot = 0.000000 + } + } + color = {#cd3700} + } + + ha:wires2 { + lid=4 + group=5 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; 4; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/passthru3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/passthru3.png =================================================================== --- tags/0.9.0/doc/TRBS/passthru3.png (nonexistent) +++ tags/0.9.0/doc/TRBS/passthru3.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/passthru3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/path.lht =================================================================== --- tags/0.9.0/doc/TRBS/path.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/path.lht (revision 1402) @@ -0,0 +1,689 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 82.0mm + y = 39.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.5 { + x1=16.0mm; y1=20.0mm; x2=6.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.8 { + x1=6.0mm; y1=7.0mm; x2=20.0mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.11 { + x1=20.0mm; y1=4.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.14 { + x1=16.0mm; y1=20.0mm; x2=29.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.17 { + x1=29.0mm; y1=9.0mm; x2=20.0mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.20 { + x1=16.0mm; y1=20.0mm; x2=22.0mm; y2=31.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.23 { + x1=22.0mm; y1=31.0mm; x2=29.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.26 { + x1=16.0mm; y1=20.0mm; x2=5.0mm; y2=29.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.29 { + x1=5.0mm; y1=29.0mm; x2=22.0mm; y2=31.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.32 { + x1=5.0mm; y1=29.0mm; x2=6.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.266 { + x1=22.0mm; y1=31.0mm; x2=40.0mm; y2=24.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.269 { + x1=40.0mm; y1=24.0mm; x2=29.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.272 { + x1=29.0mm; y1=9.0mm; x2=48.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.275 { + x1=48.0mm; y1=3.0mm; x2=40.0mm; y2=24.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.278 { + x1=40.0mm; y1=24.0mm; x2=46.0mm; y2=35.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.281 { + x1=46.0mm; y1=35.0mm; x2=22.0mm; y2=31.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.284 { + x1=48.0mm; y1=3.0mm; x2=62.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.287 { + x1=62.0mm; y1=17.0mm; x2=40.0mm; y2=24.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.290 { + x1=46.0mm; y1=35.0mm; x2=62.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.293 { + x1=48.0mm; y1=3.0mm; x2=61.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.296 { + x1=61.0mm; y1=1.0mm; x2=62.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.299 { + x1=62.0mm; y1=17.0mm; x2=71.0mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.302 { + x1=71.0mm; y1=13.0mm; x2=61.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.308 { + x1=65.0mm; y1=27.0mm; x2=46.0mm; y2=35.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.311 { + x1=46.0mm; y1=35.0mm; x2=68.0mm; y2=37.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.314 { + x1=62.0mm; y1=17.0mm; x2=68.0mm; y2=37.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.317 { + x1=65.0mm; y1=27.0mm; x2=71.0mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.320 { + x1=71.0mm; y1=13.0mm; x2=76.0mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.323 { + x1=76.0mm; y1=23.0mm; x2=65.0mm; y2=27.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.326 { + x1=68.0mm; y1=37.0mm; x2=76.0mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.334 { + x1=20.0mm; y1=4.0mm; x2=48.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.337 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.340 { + x1=25.0mm; y1=7.0mm; x2=39.0mm; y2=6.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.343 { + x1=39.0mm; y1=6.0mm; x2=46.5mm; y2=6.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.346 { + x1=46.5mm; y1=6.75mm; x2=52.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.349 { + x1=52.0mm; y1=7.0mm; x2=61.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.352 { + x1=61.5mm; y1=8.75mm; x2=66.0mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.355 { + x1=66.0mm; y1=15.0mm; x2=65.0mm; y2=27.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.388 { + x1=24.0mm; y1=20.75mm; x2=26.0mm; y2=22.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.391 { + x1=24.0mm; y1=22.75mm; x2=26.0mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.394 { + x1=32.75mm; y1=25.25mm; x2=34.75mm; y2=27.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.397 { + x1=32.75mm; y1=27.25mm; x2=34.75mm; y2=25.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.400 { + x1=41.5mm; y1=27.5mm; x2=43.5mm; y2=29.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.403 { + x1=41.5mm; y1=29.5mm; x2=43.5mm; y2=27.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.406 { + x1=52.0mm; y1=26.25mm; x2=54.0mm; y2=28.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.409 { + x1=52.0mm; y1=28.25mm; x2=54.0mm; y2=26.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.412 { + x1=24.0mm; y1=6.0mm; x2=26.0mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.415 { + x1=24.0mm; y1=8.0mm; x2=26.0mm; y2=6.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.418 { + x1=38.0mm; y1=5.0mm; x2=40.0mm; y2=7.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.421 { + x1=38.0mm; y1=7.0mm; x2=40.0mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.424 { + x1=45.5mm; y1=5.75mm; x2=47.5mm; y2=7.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.427 { + x1=45.5mm; y1=7.75mm; x2=47.5mm; y2=5.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.430 { + x1=51.0mm; y1=6.0mm; x2=53.0mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.433 { + x1=51.0mm; y1=8.0mm; x2=53.0mm; y2=6.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.436 { + x1=60.5mm; y1=7.75mm; x2=62.5mm; y2=9.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.439 { + x1=60.5mm; y1=9.75mm; x2=62.5mm; y2=7.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.442 { + x1=65.0mm; y1=14.0mm; x2=67.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.445 { + x1=65.0mm; y1=16.0mm; x2=67.0mm; y2=14.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.330 { + string=T; x=66.0mm; y=27.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.449 { + string=S; x=12.0mm; y=18.0mm; scale=250; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#cd3700} + } + + ha:wires2 { + lid=4 + group=5 + ha:combining { } + + li:objects { + ha:line.358 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=21.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.361 { + x1=25.0mm; y1=21.75mm; x2=33.75mm; y2=26.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.364 { + x1=33.75mm; y1=26.25mm; x2=42.5mm; y2=28.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.367 { + x1=42.5mm; y1=28.5mm; x2=53.0mm; y2=27.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.370 { + x1=53.0mm; y1=27.25mm; x2=65.0mm; y2=27.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#548b54} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; 4; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/path.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/path.png =================================================================== --- tags/0.9.0/doc/TRBS/path.png (nonexistent) +++ tags/0.9.0/doc/TRBS/path.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/path.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/trbs.html =================================================================== --- tags/0.9.0/doc/TRBS/trbs.html (nonexistent) +++ tags/0.9.0/doc/TRBS/trbs.html (revision 1402) @@ -0,0 +1,259 @@ + + +

Triangulated Rubber Band Sketch

+ +

+Update: it turned out there is a case that TRBS +can not handle so it can not be used for the toporouter. + +

I. Rationale

+ +

II. Context

+

+netlist -> LAA -> NORD -> TRBS -> embed geometry +

+The Layer Assignment Algorithm (LAA) receives the netlist of the input +board and breaks down the routing problem into independent, single layer +routing problems by assigning network segments (2nets) to specific +layers. All vias, with their final coordinates, are added in this step. +By using multiple layers the LAA resolves many net-net crossings. For +various reasons some of the crossings will be left in the output, and +those crossings will need to be resolved by on-layer detours. +

+The output of the LAA, per layer, is an unordered list of 2nets. A 2net +is described by its two fixed endpoints (vertices) in the 2d space. The +Network Ordering (NORD) step orders the list so that networks with more +direct, more straight-line connections (less detour) come first. +

+The next step, the Triangulated Rubber Band Sketch router (TRBS) +will route 2nets one by one, in the exact order the NORD specified. If a 2net +being routed would cross a 2net already routed, the current 2net needs to +make detour. The TRBS considers multiple detours trying to find the shortest. +If there is no route possible, the TRBS changes the net ordering and tries +again. +

+

+


 
  +

triangulation +

Figure 1: triangulation; grey lines are triangle edges; yellow lines + are three 2nets to route +


 
  +

+

+The TRBS performs these operations on a mixed model: it takes the input +geometry (vias, obstacles, board size) and triangulates it (Figure 1). The triangulation +yields vertices (at obstacles) and edges that connect the vertices +and triangles (defined by 3 vertices or 3 edges). +

+2nets are routed on a path from a starting vertex through edge crossings until it +reaches the ending vertex (Figure 2). Paths are abstract, topological: the exact +coordinates of the 2nets are not considered, only the order of 2net-edge crossings. +

+

+


 
  +

path example +

Figure 2: two possible paths (blue and green) connecting 2net starting + vertex S with ending vertex T; path-edge crossings are indicated with + red X marks +


 
  +

+

+Furthermore each 2net has a required geometry (wire thickness and +clearance), and edges have physical lengths. Local congestion is avoided by +refusing routing a 2net across an edge if the edge ran out of capacity - in +which case an alternate (longer) detour is searched or ultimately network +ordering is changed. +

+Finally, of the TRBS finished routing (Figure 3), the result is a list of topological edge +crossing for each triangulation edge for each 2net on its way between its +start and end vertex. The last step is translating these crossings back +to physical geometry, introducing new edges (spokes) and moving the +2net-edge crossing points on the edge without changing the order of them. +

+

+


 
  +

three nets routed +

Figure 3: three networks (blue) routed by this algorithm; first the two horizontal ones then + the vertical one +


 
  +

+

+This document focuses on the TRBS step. + +

III. TRBS data model

+

+The central data structure describes a crossing of a 2net and an edge. +Each crossing is collected in two ordered doubly linked lists: +

    +
  • on the 2net's path list, as crossings describe the topological path + the 2net is routed on +
  • on the edge's list, as the crossings on the edge describe the order of + 2nets +
+

+There are no restrictions on the number of crossings: any number of +2nets may cross an edge (as long as the capacity of the edge can take the +2nets, i.e. length of the edge justifies the total space taken up by 2net +wire thicknesses and clearances). Walking the path of a 2net, there can +be any number of crossings, from zero up, but any time the 2net is crossing +a triangulation edge, there must be a crossing created. +

+Note: multiple crossing points of the same 2net-edge can occur, as shown on +Figure 3. +

+


 
  +

repeated crossings +

Figure 3: the blue net between A and B need to make detours around + other (blue) nets. On the way, it crosses some edges (marked with red) + twice, at different locations. Blue nets are routed by this algorithm +


 
  +

+

+Each 2net is specified by a starting and an ending triangulation +vertex and an ordered doubly linked list of crossings. Which +terminal/via is the starting vertex and which terminal/via is the ending +vertex is an arbitrary choice of the LAA, but once the choice is made, it +is not changed. +

+In the triangulation each edge is connected to two vertices, has +a known physical length and holds an ordered list of crossing from vertex 1 to +vertex 2. Which triangulation vertex is called 1 is an arbitrary choice made +during triangulation (and never changed later). + +

IV. TRBS algorithm: path finding

+

+A 2net is always starting from a vertex, will cross zero or more edges (last +edge being part of the triangle with the ending vertex), then will connect +to the ending vertex. This path can be searched using the A* algorithm, on +a graph formed by these rules: +

    +
  • case S: start is the 2net starting vertex; if a neighbor vertex is the ending + vertex of the 2net, and the edge connecting the two vertices doesn't + have any crossing, the path is found (that edge, with zero crossing). + Else neighbor nodes for A* are the opposite edge of each triangle the + starting vertex is part of. (See Figure 5/a.) +
  • case T: After an edge crossing, if the triangle (the path just arrived into) + contains the ending vertex, the path is complete. (See Figure 5/b.) +
  • case E: Else jump from edge to edge: A* neighbor nodes are the other two + edges of the triangle the path arrived into by the last edge crossing. + Go on searching for the path. (See Figure 5/c.) +
+

+

+


 
  +

A* path finding examples +

Figure 5: path finding with A*; +
a.: case S: start from vertex S, potential next graph nodes are the + vertices marked with red arrows (assuming T is not on any neighbor + vertex on this drawing) +
b.: thick blue line is the path crossing the left edge of a triangle; + since the triangle contains the end vertex T, the only one next node + is T and the path is completed (thin blue line). +
c.: thick blue line is the path crossing the left edge of a triangle; + since T is not in the triangle, there are two possible ways the path + could continue (thin blue lines); the two affected edges + (marked with red arrows) are the potential next nodes of the A* search graph +
+


 
  +

+

+There are two reasons for excluding the next node from the A* search: +

    +
  • if the next node is an edge crossing and remaining edge capacity is smaller + than required by the current 2net's routing style +
  • there's no straight-line visibility from the current edge to the target + edge or target vertex within the triangle (it is blocked by a 2net + placed earlier); visibility is calculated as described below, in + section V. +
+

+The cost function is path length assuming edge crossing points are located +at where they result in the shortest path, ignoring wire widths and +clearances. The heuristic function is the distance to the 2net's ending vertex. + + +

V. TRBS algorithm: query in-triangle visibility

+

+The path is entering a triangle from a vertex or from a specific point on +an edge. Point on an edge is in the topological sense, not in the +geometrical sense: all points between two existing crossing or edge +endpoint are the same. Main input is the enter point or vertex. +Other input is a target edge (see Figure 5/c, marked with red arrows) +or target vertex within the same triangle (see Figure 5/b, T). +

+

+


 
  +

in-triangle visibility algorithm +

Figure 6: edge-to-edge visibility in a triangle; annotations are + drawn with red, existing paths (routed with this algorithm) are drawn with blue +


 
  +

+

+In case of target edge, the output is a point on that edge (which topologically +means the index on the edge's crossing list, where the new crossing is to be +inserted between edge end vertices or existing crossings). In case of target +vertex, the output is a boolean, whether that vertex is visible or not. +

+The algorithm for determining visibility (e.g. on Figure 6) is: +

+

    +
  • 1. start walking the triangle (edge) from the entering point in + one direction, e.g. CCW +
  • 2. move along an edge until a crossing or vertex is detected +
  • 3. if vertex: +
      +
    • 3a. if it is the target vertex, return true +
    • 3b. else check if any path is starting from the vertex into the + current triangle; if so, go on tracing along that path + (go to step 4) +
    • 3c. else take the next edge from that vertex in the same triangle; + if that is the target edge, return as in 4a, else go on tracing + (go to step 5) +
    +
  • 4. if crossing: from the crossing, follow the path crossing the current triangle: +
      +
    • 4a. if it lands in a vertex, continue on the next edge in the chosen direction: + if that is the target edge, return the result (index is either 0 or + length-of-crossing-list, depending on which vertex the path has hit); + if not the target edge, else continue with step 5 +
    • 4b. if it lands on an edge: if the edge is the target edge, the result + is the next (or previous) index after (or before) the crossing, + else continue with step 5 +
    +
  • 5. if the tracing is back to the same edge or vertex it started from, + there is no visibility, return failure. Else go on tracing + (go to step 2). +
+ +

VI. TRBS algorithm: example cases

+

Case 1: +path (green) going out from a vertex of the current triangle does not +change the result of the visibility test: +

+

+


 
  +

visibility example in a triangle +

Figure 7: blue and green nets (routed by this algorithm) starting from triangle vertices, still + S2 finds its target edge point +


 
  +

+

+On Figure 7, a CW search from S2 first reaches vertex PA then will jump to the edge PA-PC, +which is the target edge. + +

Case 2: +On Figure 7, tracing CCW from S2: because of 3b., the search reaches target edge after +tracing S2's edge, vertex PB and the blue path. + +

Case 3: visibility blocked +

+

+


 
  +

visibility blocked in a triangle +

Figure 8: target edge not visible from S2 because of an existing path +


 
  +

+

+On Figure 8, starting from S2, tracing CCW: trace S2's edge to PB, then switch edge +by 3c, bumping into the blue path by 4, tracing it to edge PA-PB; +this edge is the edge S2 is on. By 5, return failure. Index: tags/0.9.0/doc/TRBS/tri.lht =================================================================== --- tags/0.9.0/doc/TRBS/tri.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/tri.lht (revision 1402) @@ -0,0 +1,497 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 51.0mm + y = 40.0mm + } + ha:grid { + spacing = 1.0mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.69 { + proto=2; x=3.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.70 { + proto=2; x=31.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.71 { + proto=2; x=16.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.72 { + proto=2; x=46.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.73 { + proto=2; x=25.0mm; y=33.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.74 { + proto=2; x=25.0mm; y=3.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.48 { + x1=1.0mm; y1=1.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.51 { + x1=1.0mm; y1=38.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.54 { + x1=49.0mm; y1=38.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.57 { + x1=49.0mm; y1=1.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.75 { + x1=1.0mm; y1=1.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.78 { + x1=3.0mm; y1=16.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.81 { + x1=1.0mm; y1=38.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.84 { + x1=25.0mm; y1=33.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.87 { + x1=49.0mm; y1=38.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.90 { + x1=46.0mm; y1=20.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.93 { + x1=49.0mm; y1=1.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.96 { + x1=25.0mm; y1=3.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.99 { + x1=1.0mm; y1=1.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.102 { + x1=16.0mm; y1=20.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.105 { + x1=16.0mm; y1=20.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.108 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.111 { + x1=16.0mm; y1=20.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.114 { + x1=25.0mm; y1=3.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.117 { + x1=25.0mm; y1=33.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.120 { + x1=31.0mm; y1=16.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.123 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.126 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.129 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.176 { + x1=3.0mm; y1=16.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.179 { + x1=16.0mm; y1=20.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.182 { + x1=25.0mm; y1=33.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 12 + grid = 1000.00 um + buffer_number = 0 + all_direction_lines = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/tri.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/tri.png =================================================================== --- tags/0.9.0/doc/TRBS/tri.png (nonexistent) +++ tags/0.9.0/doc/TRBS/tri.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/tri.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/TRBS/uturn.lht =================================================================== --- tags/0.9.0/doc/TRBS/uturn.lht (nonexistent) +++ tags/0.9.0/doc/TRBS/uturn.lht (revision 1402) @@ -0,0 +1,587 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:realthin { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.25mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 51.0mm + y = 40.0mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.48 { + x1=1.0mm; y1=1.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.51 { + x1=1.0mm; y1=38.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.54 { + x1=49.0mm; y1=38.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.57 { + x1=49.0mm; y1=1.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.75 { + x1=1.0mm; y1=1.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.78 { + x1=3.0mm; y1=16.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.81 { + x1=1.0mm; y1=38.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.84 { + x1=25.0mm; y1=33.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.87 { + x1=49.0mm; y1=38.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.90 { + x1=46.0mm; y1=20.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.93 { + x1=49.0mm; y1=1.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.96 { + x1=25.0mm; y1=3.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.99 { + x1=1.0mm; y1=1.0mm; x2=16.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.102 { + x1=16.0mm; y1=20.0mm; x2=3.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.105 { + x1=16.0mm; y1=20.0mm; x2=1.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.108 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=33.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.111 { + x1=16.0mm; y1=20.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.114 { + x1=25.0mm; y1=3.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.117 { + x1=25.0mm; y1=33.0mm; x2=31.0mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.120 { + x1=31.0mm; y1=16.0mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.123 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.126 { + x1=31.0mm; y1=16.0mm; x2=49.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.129 { + x1=16.0mm; y1=20.0mm; x2=25.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.259 { + x1=3.0mm; y1=16.0mm; x2=10.5mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.262 { + x1=10.5mm; y1=13.0mm; x2=19.75mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.265 { + x1=19.75mm; y1=13.0mm; x2=30.5mm; y2=14.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.268 { + x1=30.5mm; y1=14.5mm; x2=32.25mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.271 { + x1=32.25mm; y1=15.0mm; x2=32.5mm; y2=16.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.274 { + x1=32.5mm; y1=16.25mm; x2=32.25mm; y2=17.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.277 { + x1=32.25mm; y1=17.5mm; x2=29.75mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.292 { + x1=29.75mm; y1=19.5mm; x2=22.25mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.295 { + x1=22.25mm; y1=18.25mm; x2=17.25mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.298 { + x1=17.25mm; y1=17.75mm; x2=14.5mm; y2=18.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.301 { + x1=14.5mm; y1=18.0mm; x2=13.25mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.304 { + x1=13.25mm; y1=19.0mm; x2=1.0mm; y2=37.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.307 { + x1=31.0mm; y1=16.0mm; x2=18.75mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.310 { + x1=18.75mm; y1=15.25mm; x2=12.75mm; y2=15.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.313 { + x1=12.75mm; y1=15.5mm; x2=8.5mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.316 { + x1=8.5mm; y1=17.75mm; x2=2.75mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.319 { + x1=16.0mm; y1=20.0mm; x2=28.25mm; y2=24.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.322 { + x1=28.25mm; y1=24.25mm; x2=37.25mm; y2=23.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.325 { + x1=37.25mm; y1=23.75mm; x2=46.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.337 { + x1=2.75mm; y1=18.5mm; x2=1.75mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.340 { + x1=1.75mm; y1=11.75mm; x2=1.0mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.334 { + x1=9.25mm; y1=11.5mm; x2=15.0mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.343 { + x1=20.75mm; y1=11.0mm; x2=16.5mm; y2=19.0mm; thickness=0.25mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.346 { + string=A; x=3.25mm; y=13.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.347 { + string=B; x=1.0mm; y=38.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#cd3700} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 250.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 0 + all_direction_lines = true + rubber_band_keep_midlinedir = true + rubber_band_mode = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/TRBS/uturn.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/TRBS/uturn.png =================================================================== --- tags/0.9.0/doc/TRBS/uturn.png (nonexistent) +++ tags/0.9.0/doc/TRBS/uturn.png (revision 1402) Property changes on: tags/0.9.0/doc/TRBS/uturn.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/contact.html =================================================================== --- tags/0.9.0/doc/contact.html (nonexistent) +++ tags/0.9.0/doc/contact.html (revision 1402) @@ -0,0 +1,56 @@ + + + + + route-rnd - contact + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +

route-rnd - contact

+ +

Contact the project

+

+Please subscribe to the mailing list by sending "subscribe" to +route-rnd list.repo.hu or join IRC for + live chat (CET daytime) with other users +and developers. + +

Contact the lead developer

+

+Join IRC for live chat (CET daytime) and +look for Igor2. +

+Via email: routernd igor2.repo.hu. + + +
+

+PRIVACY NOTICE: +

+This email address is provided only for personal use, exclusively for +topics directly related to the route-rnd project. +

+Do NOT copy this email address to +software packages, documentation, etc. Permission is NOT granted +for collecting this email address in any list of email addresses. +Since this email address is a personal address, the + +GDPR applies while you are handling it. +

+ + Index: tags/0.9.0/doc/demo/2dip.lht =================================================================== --- tags/0.9.0/doc/demo/2dip.lht (nonexistent) +++ tags/0.9.0/doc/demo/2dip.lht (revision 1402) @@ -0,0 +1,1219 @@ +ha:pcb-rnd-board-v8 { + + li:styles { + ha:Signal { + via_proto = 0 + thickness = 0.2mm + text_thick = 0.0 + text_scale = 100 + clearance = 0.2mm + } + ha:Power { + via_proto = 1 + thickness = 20.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 20.0mil + } + ha:Fat { + via_proto = 2 + thickness = 80.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 25.0mil + } + ha:Sig-tight { + via_proto = 3 + thickness = 10.0mil + text_thick = 0.0 + text_scale = 100 + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 56.515mm + y = 1.725in + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=1.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=1.2mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=3.5mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.3 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=64.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:subc.443 { + ha:attributes { + footprint=8*300 + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -0.9922mm + -0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -0.9922mm + -0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.9844mm; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.9844mm; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.470 { + proto=0; x=500.0mil; y=575.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.471 { + proto=1; x=800.0mil; y=575.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=8 + } + } + ha:padstack_ref.472 { + proto=1; x=500.0mil; y=675.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + ha:padstack_ref.473 { + proto=1; x=800.0mil; y=675.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=7 + } + } + ha:padstack_ref.474 { + proto=1; x=500.0mil; y=775.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + } + } + ha:padstack_ref.475 { + proto=1; x=800.0mil; y=775.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=6 + } + } + ha:padstack_ref.476 { + proto=1; x=500.0mil; y=875.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + } + } + ha:padstack_ref.477 { + proto=1; x=800.0mil; y=875.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=5 + } + } + } + li:layers { + + ha:subc-aux { + lid=0 + ha:combining { } + + li:objects { + ha:line.444 { + x1=500.0mil; y1=575.0mil; x2=13.700001mm; y2=575.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + ha:flags ={ selected=1 + }; } + ha:line.447 { + x1=500.0mil; y1=575.0mil; x2=500.0mil; y2=15.605001mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + ha:flags ={ selected=1 + }; } + ha:line.450 { + x1=500.0mil; y1=575.0mil; x2=500.0mil; y2=575.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + ha:flags ={ selected=1 + }; } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + + ha:top-silk { + lid=1 + ha:combining { } + + li:objects { + ha:line.453 { + x1=450.0mil; y1=525.0mil; x2=450.0mil; y2=925.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.456 { + x1=850.0mil; y1=925.0mil; x2=450.0mil; y2=925.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.459 { + x1=850.0mil; y1=925.0mil; x2=850.0mil; y2=525.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.462 { + x1=450.0mil; y1=525.0mil; x2=600.0mil; y2=525.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.465 { + x1=700.0mil; y1=525.0mil; x2=850.0mil; y2=525.0mil; thickness=10.0mil; clearance=0.0; + } + ha:arc.468 { + x=650.0mil; y=525.0mil; width=50.0mil; height=50.0mil; astart=0.000000; adelta=180.000000; thickness=10.0mil; clearance=0.0; + } + ha:text.469 { + string=%a.parent.refdes%; x=500.0mil; y=475.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + } + } + uid = Prm/FIlakhcnnciUeGTHAAAA + } + ha:subc.583 { + ha:attributes { + footprint=8*300 + refdes=U2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -0.916mm + -0.916mm + 0.916mm + -0.916mm + 0.916mm + 0.916mm + -0.916mm + 0.916mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -0.9922mm + -0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -0.9922mm + -0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + 0.9922mm + -0.9922mm + 0.9922mm + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.8mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.832mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.9844mm; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=1.9844mm; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.610 { + proto=0; x=1.4in; y=775.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.611 { + proto=1; x=1.7in; y=775.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=8 + } + } + ha:padstack_ref.612 { + proto=1; x=1.4in; y=875.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + ha:padstack_ref.613 { + proto=1; x=1.7in; y=875.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=7 + } + } + ha:padstack_ref.614 { + proto=1; x=1.4in; y=975.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + } + } + ha:padstack_ref.615 { + proto=1; x=1.7in; y=975.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=6 + } + } + ha:padstack_ref.616 { + proto=1; x=1.4in; y=27.305mm; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + } + } + ha:padstack_ref.617 { + proto=1; x=1.7in; y=27.305mm; rot=0.000000; xmirror=0; smirror=0; clearance=0.2mm; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=5 + } + } + } + li:layers { + + ha:subc-aux { + lid=0 + ha:combining { } + + li:objects { + ha:line.584 { + x1=1.4in; y1=775.0mil; x2=36.560001mm; y2=775.0mil; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.587 { + x1=1.4in; y1=775.0mil; x2=1.4in; y2=20.685001mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + ha:line.590 { + x1=1.4in; y1=775.0mil; x2=1.4in; y2=775.0mil; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + + ha:top-silk { + lid=1 + ha:combining { } + + li:objects { + ha:line.593 { + x1=1.35in; y1=725.0mil; x2=1.35in; y2=1.125in; thickness=10.0mil; clearance=0.0; + } + ha:line.596 { + x1=44.45mm; y1=1.125in; x2=1.35in; y2=1.125in; thickness=10.0mil; clearance=0.0; + } + ha:line.599 { + x1=44.45mm; y1=1.125in; x2=44.45mm; y2=725.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.602 { + x1=1.35in; y1=725.0mil; x2=38.1mm; y2=725.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.605 { + x1=1.6in; y1=725.0mil; x2=44.45mm; y2=725.0mil; thickness=10.0mil; clearance=0.0; + } + ha:arc.608 { + x=1.55in; y=725.0mil; width=50.0mil; height=50.0mil; astart=0.000000; adelta=180.000000; thickness=10.0mil; clearance=0.0; + } + ha:text.609 { + string=%a.parent.refdes%; x=1.4in; y=675.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + } + } + uid = Prm/FIlakhcnnciUeGTHAAAA + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + ha:attributes { + {pcb-rnd::key::vis}={l; Shiftt} + {pcb-rnd::key::select}={l; t} + } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=8 + ha:combining { } + + ha:attributes { + {pcb-rnd::key::vis}={l; Shiftb} + {pcb-rnd::key::select}={l; b} + } + + li:objects { + } + color = {#3a5fcd} + } + + ha:outline { + lid=2 + group=7 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=3 + group=10 + ha:combining { auto=1; } + + ha:attributes { + {pcb-rnd::key::vis}={l; Shiftx} + {pcb-rnd::key::select}={l; x} + } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=4 + group=1 + ha:combining { auto=1; } + + ha:attributes { + {pcb-rnd::key::vis}={l; Shifts} + {pcb-rnd::key::select}={l; s} + } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=5 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=6 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=7 + group=9 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=8 + group=11 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=9 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=10 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + + ha:top-assy { + lid=11 + group=14 + ha:combining { } + + li:objects { + } + color = {#444444} + } + + ha:bot-assy { + lid=12 + group=15 + ha:combining { } + + li:objects { + } + color = {#444444} + } + + ha:fab { + lid=13 + group=16 + ha:combining { auto=1; } + + li:objects { + } + color = {#222222} + } + } + } + + ha:netlists { + li:netlist_patch { + ha:add_conn { net=pcbrnd1; term=U1-1; } + ha:add_conn { net=pcbrnd1; term=U2-1; } + ha:add_conn { net=pcbrnd1; term=U2-5; } + ha:add_conn { net=pcbrnd2; term=U1-2; } + ha:add_conn { net=pcbrnd2; term=U1-5; } + ha:add_conn { net=pcbrnd3; term=U1-3; } + ha:add_conn { net=pcbrnd3; term=U1-6; } + ha:add_conn { net=pcbrnd3; term=U2-6; } + ha:add_conn { net=pcbrnd4; term=U1-4; } + ha:add_conn { net=pcbrnd4; term=U2-4; } + ha:add_conn { net=pcbrnd4; term=U2-3; } + ha:add_conn { net=pcbrnd5; term=U1-7; } + ha:add_conn { net=pcbrnd5; term=U2-7; } + ha:add_conn { net=pcbrnd6; term=U2-2; } + ha:add_conn { net=pcbrnd6; term=U1-8; } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 5; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 4; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 6; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:5 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:6 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:7 { + name = global_outline + ha:type { boundary=1; } + li:layers { 2; } + purpose = uroute + } + ha:8 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; } + } + ha:9 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 7; } + } + ha:10 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 3; } + } + ha:11 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 8; } + } + ha:12 { + name = pmech + ha:type { mech=1; } + li:layers { 9; } + purpose = proute + } + ha:13 { + name = umech + ha:type { mech=1; } + li:layers { 10; } + purpose = uroute + } + ha:14 { + name = top_assy + ha:type { top=1; doc=1; } + li:layers { 11; } + ha:attributes { + init-invis=1 + } + purpose = assy + } + ha:15 { + name = bot_assy + ha:type { bottom=1; doc=1; } + li:layers { 12; } + ha:attributes { + init-invis=1 + } + purpose = assy + } + ha:16 { + name = fab + ha:type { top=1; doc=1; } + li:layers { 13; } + ha:attributes { + init-invis=1 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + line_thickness = 200.00 um + via_proto = 0 + text_scale = 100 + text_thickness = 0 + clearance = 200.00 um + } + ha:editor { + buffer_number = 0 + grid_unit = mm + show_drc = true + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/demo/2dip.tdx =================================================================== --- tags/0.9.0/doc/demo/2dip.tdx (nonexistent) +++ tags/0.9.0/doc/demo/2dip.tdx (revision 1402) @@ -0,0 +1,92 @@ +tEDAx v1 + +begin stackup v1 board_stackup + layer 3.top_copper top copper + lprop 3.top_copper display-color #8b2323 + layer 8.bottom_copper bottom copper + lprop 8.bottom_copper display-color #3a5fcd +end stackup + +begin polyline v1 pstk_0x56085929b880_0x56085911f3a0 + v -0.916 -0.916 + v 0.916 -0.916 + v 0.916 0.916 + v -0.916 0.916 +end polyline +begin polyline v1 pstk_0x5608592a5be0_0x56085911f3a0 + v -0.916 -0.916 + v 0.916 -0.916 + v 0.916 0.916 + v -0.916 0.916 +end polyline +begin layernet v1 3.top_copper + poly pcb/443/470 pcbrnd1 tmd pstk_0x56085929b880_0x56085911f3a0 12.7 14.605 + line pcb/443/471 pcbrnd6 tmd 20.32 14.605 20.32 14.605 1.832 0.1 + line pcb/443/472 pcbrnd2 tmd 12.7 17.145 12.7 17.145 1.832 0.1 + line pcb/443/473 pcbrnd5 tmd 20.32 17.145 20.32 17.145 1.832 0.1 + line pcb/443/474 pcbrnd3 tmd 12.7 19.685 12.7 19.685 1.832 0.1 + line pcb/443/475 pcbrnd3 tmd 20.32 19.685 20.32 19.685 1.832 0.1 + line pcb/443/476 pcbrnd4 tmd 12.7 22.225 12.7 22.225 1.832 0.1 + line pcb/443/477 pcbrnd2 tmd 20.32 22.225 20.32 22.225 1.832 0.1 + poly pcb/583/610 pcbrnd1 tmd pstk_0x5608592a5be0_0x56085911f3a0 35.56 19.685 + line pcb/583/611 - tmd 43.18 19.685 43.18 19.685 1.832 0.1 + line pcb/583/612 pcbrnd6 tmd 35.56 22.225 35.56 22.225 1.832 0.1 + line pcb/583/613 pcbrnd5 tmd 43.18 22.225 43.18 22.225 1.832 0.1 + line pcb/583/614 pcbrnd4 tmd 35.56 24.765 35.56 24.765 1.832 0.1 + line pcb/583/615 pcbrnd3 tmd 43.18 24.765 43.18 24.765 1.832 0.1 + line pcb/583/616 pcbrnd4 tmd 35.56 27.305 35.56 27.305 1.832 0.1 + line pcb/583/617 pcbrnd1 tmd 43.18 27.305 43.18 27.305 1.832 0.1 +end layernet + +begin polyline v1 pstk_0x56085929b880_0x56085911f5a0 + v -0.916 -0.916 + v 0.916 -0.916 + v 0.916 0.916 + v -0.916 0.916 +end polyline +begin polyline v1 pstk_0x5608592a5be0_0x56085911f5a0 + v -0.916 -0.916 + v 0.916 -0.916 + v 0.916 0.916 + v -0.916 0.916 +end polyline +begin layernet v1 8.bottom_copper + poly pcb/443/470 pcbrnd1 tmd pstk_0x56085929b880_0x56085911f5a0 12.7 14.605 + line pcb/443/471 pcbrnd6 tmd 20.32 14.605 20.32 14.605 1.832 0.1 + line pcb/443/472 pcbrnd2 tmd 12.7 17.145 12.7 17.145 1.832 0.1 + line pcb/443/473 pcbrnd5 tmd 20.32 17.145 20.32 17.145 1.832 0.1 + line pcb/443/474 pcbrnd3 tmd 12.7 19.685 12.7 19.685 1.832 0.1 + line pcb/443/475 pcbrnd3 tmd 20.32 19.685 20.32 19.685 1.832 0.1 + line pcb/443/476 pcbrnd4 tmd 12.7 22.225 12.7 22.225 1.832 0.1 + line pcb/443/477 pcbrnd2 tmd 20.32 22.225 20.32 22.225 1.832 0.1 + poly pcb/583/610 pcbrnd1 tmd pstk_0x5608592a5be0_0x56085911f5a0 35.56 19.685 + line pcb/583/611 - tmd 43.18 19.685 43.18 19.685 1.832 0.1 + line pcb/583/612 pcbrnd6 tmd 35.56 22.225 35.56 22.225 1.832 0.1 + line pcb/583/613 pcbrnd5 tmd 43.18 22.225 43.18 22.225 1.832 0.1 + line pcb/583/614 pcbrnd4 tmd 35.56 24.765 35.56 24.765 1.832 0.1 + line pcb/583/615 pcbrnd3 tmd 43.18 24.765 43.18 24.765 1.832 0.1 + line pcb/583/616 pcbrnd4 tmd 35.56 27.305 35.56 27.305 1.832 0.1 + line pcb/583/617 pcbrnd1 tmd 43.18 27.305 43.18 27.305 1.832 0.1 +end layernet + + +begin route_req v1 - + stackup board_stackup + via pcb/443/470 pcbrnd1 tmd 12.7 14.605 0.8 0 + via pcb/443/471 pcbrnd6 tmd 20.32 14.605 0.8 0 + via pcb/443/472 pcbrnd2 tmd 12.7 17.145 0.8 0 + via pcb/443/473 pcbrnd5 tmd 20.32 17.145 0.8 0 + via pcb/443/474 pcbrnd3 tmd 12.7 19.685 0.8 0 + via pcb/443/475 pcbrnd3 tmd 20.32 19.685 0.8 0 + via pcb/443/476 pcbrnd4 tmd 12.7 22.225 0.8 0 + via pcb/443/477 pcbrnd2 tmd 20.32 22.225 0.8 0 + via pcb/583/610 pcbrnd1 tmd 35.56 19.685 0.8 0 + via pcb/583/611 - tmd 43.18 19.685 0.8 0 + via pcb/583/612 pcbrnd6 tmd 35.56 22.225 0.8 0 + via pcb/583/613 pcbrnd5 tmd 43.18 22.225 0.8 0 + via pcb/583/614 pcbrnd4 tmd 35.56 24.765 0.8 0 + via pcb/583/615 pcbrnd3 tmd 43.18 24.765 0.8 0 + via pcb/583/616 pcbrnd4 tmd 35.56 27.305 0.8 0 + via pcb/583/617 pcbrnd1 tmd 43.18 27.305 0.8 0 + route_all +end route_req Index: tags/0.9.0/doc/detour/1_intro.html =================================================================== --- tags/0.9.0/doc/detour/1_intro.html (nonexistent) +++ tags/0.9.0/doc/detour/1_intro.html (revision 1402) @@ -0,0 +1,26 @@ + + + + + + +

Topo-geometric detour router

+ +

1. Introduction

+

+The topo-geometric detour router is an autorouter intended for single layer +or multi layer printed circuit boards with variable network widths and +clearances. +

+The algorithm presented in this paper is neither a pure topological autorouter +nor a pure geometric autorouter: it is a combination. It uses topology to make +high level decisions about the structure of solution but uses geometry after +each decision to ensure routability of the board. On the topology side the +main idea is to do a path search on a tree of decisions instead of doing +the search in geometric space. In turn this reduces the geometric problem to +find the two possible detour path around an obstacle. +

+While the two aspects of the routing, topology and geometry, are running in +parallel, they are independent in the sense that the algorithm for each aspect +can be replaced without affecting the other aspect. + Index: tags/0.9.0/doc/detour/2_topo.html =================================================================== --- tags/0.9.0/doc/detour/2_topo.html (nonexistent) +++ tags/0.9.0/doc/detour/2_topo.html (revision 1402) @@ -0,0 +1,166 @@ + + + + + + +

Topo-geometric detour router

+ +

2. Detour search

+

+This chapter focuses on the topological (high) level of the router and assumes +the geometric (low) level is available and can calculate the geometry of +a detour of a trace object and a network. + +

2.1. Board state

+

+The routing is driven by the detour search performed on possible +board states. A board state is a specific render of the board, all +two-nets realized with copper tracks. A board state does not need to be free +of short-circuits. Each copper object is explicitly bound to a network. +

+The initial board state is: +

    +
  • all terminals and unmovable objects are placed +
  • all two-nets are connected with straight copper lines on the first layer +
+

+The initial board state usually contains a high number of conflicts: +short circuits caused by objects of different nets crossing, overlapping or +getting too close. + +

2.2. Detours

+

+Each conflict, regarded as an isolated case, considering only the two +two-nets participating needs to be resolved. One way of doing that is +writing an ordered list of resolutions. Figure 2/1 shows the possible resolutions +of a simple crossing. + +

+

+

Figure 2/1. +a. Input: Two 2-nets, N1 and N2 are crossing at #1. Yellow lines are the initial +two-nets, blue lines are final choices, grey lines are alternative choices. +Possible resolutions: +b. N1 goes around N2 on the left or on the right; +c. N2 goes around N1 on the top or on the bottom; +d. two vias are inserted in N1 so it can bypass N2 on another layer; +e. if endpoint terminal of N1 is through-hole, one via can be saved; +f. ... or even both vias can be saved; +(Note: there are three more possibilities with vias where N1 goes to another +layer, these would have been drawn as g., h. i.). +

+ +

+To go from the initial state (a.) to any of the resolved states (b. to i.), +we need to define an operation. For example the operation for b. is +"N1-N2 CW" for the right-side solution and "N1-N2 CCW" for the left-side +solution. "N1-N2 CW" means "on N1 at the first crossing of N2, N1 makes +a detour to go around N2 clock-wise". To be able to determine which is the +"first" crossing on N1, each two-net has one of its endpoint marked as the +starting point. +

+Note: if there are more than 2 layers, each new layer adds 6 more possible +states using vias. + + +

2.3. Choosing between detour options

+

+It is possible to draw a tree of the possible solutions. Each node of +the tree is a board state and each edge of the tree is an operation +which transforms the parent state into the child state. +

+The complete tree for the above example is shown on Figure 2/2. + +

+

+

Figure 2/2. The detour tree of Figure 2/1. +

+ +

+Let us consider a slightly more complicated case with three 2-nets and +two crossings (Figure 2/3). + +

+

+

Figure 2/3. +a. Input: three 2-nets, N1, N2 and N3 are crossing at #1 and #2. +Yellow lines are the initial two-nets, grey lines are final choices, blue lines +are alternative choices. Steps b. and c. shows the search +progress of a possible resolution. +

+ +

+First step, b. tries an N1-N2 CW. This resolves #1. The next step, c. +tries a N1-N3 CW, which resolves #2. So the final script is: +

+N1-N2 CW
+N1-N3 CW
+
+

+An alternative solution in c., drawn with blue, is N3-N1 CWW; +given there is enough space, between N2 and N3, this would also resolve +#2. This would change the second line of the script from CW to CCW. +Another alternative to step c. is leaving N1 as is and make a detour +with N3: N3-N1 CCW. This is a valid solution to the problem and is +drawn on Figure 2/3. d. and the corresponding script is: +

+N1-N2 CW
+N3-N1 CCW
+
+ +

+Another alternative in c. would be to do an N3-N1 CW. This is a valid move, +but introduces a new conflict, marked as #3 on Figure 2/3. e. Since there +is a conflict, state e. is not a solution. However, with one more detour, +N2-N3 CCW it can be a solution: Figure 2/3. e, or as a script: + +

+N1-N2 CW
+N3-N1 CW
+N2-N3 CCW
+
+ +

+The above part of the state tree is drawn on Figure 2/4. + +

+

+

Figure 2/4. The detour tree of Figure 2/3. Initial state is a., states that +are acceptable solutions are marked red, further subtrees omited from are +indicated as "...". +

+ +

+(Note: the tree can grow deeper than the number of crossings, since an operation +can introduce one or more new crossings.) +

+The above example showed three different +valid solutions (and omitted a lot more, including using a second layer). +These solutions differ in cost, which is normally a function of total wire +length and number of vias. If the goal is to find the board state for the +least-cost solution, it is very likely that all possible solutions would need +to be rendered. That is not feasible as the search space explodes +with the number of two-nets growing. +

+However, if it is enough to find a relatively good valid solution, it is +possible consider only a part of the tree. For example it is possible to +implement an A* search on the state tree using the following considerations: +

    +
  • the target, when the search stops, is the first time the number of conflicts is zero +
  • the cost function combines total wire length and number of vias of a board state +
  • heuristics is the a function of the number and severity of conflicts of a board state +
+

+Furthermore there are ways to reduce tree size early on: +

    +
  • if a conflict arises between a two-net and a non-movable object, the state is invalid +
  • when considering a new state, if a two-net introduces a new conflict with another + two-net which it already had a conflict with in any parent state, + check if the same object in the other two-net is affected as in the + parent state; if so, this is likely an oscillation (see section 4.1.7); + this state is invalid and should be discarded +
  • always choose the first conflict on a two-net to resolve, since this + may resolve further conflicts automatically (see section 4.1.2) plus + keeps the decision tree smaller, removing redundant options. +
Index: tags/0.9.0/doc/detour/3_hull.html =================================================================== --- tags/0.9.0/doc/detour/3_hull.html (nonexistent) +++ tags/0.9.0/doc/detour/3_hull.html (revision 1402) @@ -0,0 +1,231 @@ + + + + + + +

Topo-geometric detour router

+ +

3. Convex hull path

+

+This chapter focuses on the geometric (low) level of the router. It +proivides an API that can calculate the geometry of a detour of a trace +object and a network but does not decide which detours should be calculated. + +

3.1. Different detours

+

+A conflict is always between two specific drawing primitives: a trace object +(line or arc) of a two-net (N1) and any type of object of another two-net (N2). The +detour is calculated so that the offending line or arc object of N1 is replaced +by a series of arcs and lines going around all objects of N2. +

+There are 8 different ways a this can be done, depending on how existing +objects are arranged in the current state of the board. The first choice is +made by the caller: switch layer or stay on layer. +

+ +

+

+

Figure 3/1. Decision tree for different possible detours. +

+ +

+In case of vias, there are three different possibilities, all three may be valid. +In case of stay-on-layer, exactly one of the three possibilites is chosen, +depending on how many endpoints of N1 is within the convex hull of N2, but +some of the choices may result in two different potential paths in CW or CCW +directions. + +

3.2. Clearance, spokes, convex hull

+

+Trace objects are specified by their width and clearance. Vias are specified +by their copper radius and clearance - which is equvalent to the specification +of a zero length line or arc width and clearance. When the minimum distance of +centerlines of two objects need to be calculated, the following formula is +used: + +

+D = W1/2 + W2/2 + max(C1, C2);
+
+ +

+where D is the centerline distance, W1 and W2 are the width of object 1 +and object 2 respectively and C1 and C2 are the clearances of those objects. +The max function returns the larger of its two arguments. + +

+

+

+

Figure 3/2. Convex hull based detours. a. yellow dashed two-net line crosses +the blue two-net; we expect the algorithm to come up with two possible detours +D1 and D2; b. clearance spokes inserted on the corners of the blue net; c. convex +hull (red) calculated from spokes and the two endpoints of the dashed yellow +line +

+ + +

+The possible detour paths are sections of the convex hull of carefully chosen +points (Figure 3/2). Calculating the convex hull is normally done in 5 steps: +

    +
  • 1. knowing the parameters of N1 and N2, calculate their mutual D (centerline distance) value (Note: D may be different for terminals, vias and lines of N2) +
  • 2. add spokes to each corner of N2 in 8 directions (n*45 degrees) of length D +
  • 3. use the endpoints of the spokes as input for a convex hull calculation; most of the time the endpoints of the offending N1 line needs to be used as well +
  • 4. most of the cases will requre endpoints of the offending N1 line, or other points added; these points will be the ones that will split the resulting convex hull into two halves (CW and CCW) +
  • 5. calculate the convex hull from these points +
+ +

+Corners are: endpoints of line objects, center of via, every vertex of polygon +objects. TODO: arc. + +

+A convex hull of two-net N2 [in context of offending object of N1] +means: the convex hull of all spokes N2, where spoke lengths are calculated +with D for N1. +

+A naked convex hull of two-net N2 is the convex hull calculated +using only the centerlines of N2 objects, without considering widths +or clearances. + +

3.3. Stay-on-layer cases: S1, S2, S3

+

+First the naked convex hull of N3 is calculated so that the the decision +for S1, S2 or S3 can be made. + +

3.3.1. S1: both ends outside

+

+Both ends of the offending line object of N1 are outside of the naked convex hull +of N3. The two possible detour paths are calculated as: +

    +
  • collect all spoke endpoints of N3, add the two endpoints of the offending trace line object of N1 +
  • calculate the convex hull +
  • split the hull in two at the N1 offending line endpoints +
  • replace the offending N1 line with either the CW or the CCW half of the hull +
+ + +

+

+

+

Figure 3/3. a. case S1 applied to a line segment of N1 already making a +detour around N2 (the current S1 is trying to resolve an N1-N3 conflict); +starting point of N1 is the top terminal; +b. convex hull (red) calculated and split into D1 (CCW) and D2 (CW). +c. new board state if the caller choose D1 (CCW) +

+ +

+Note: originally the endpoint of the offending line is the spoke endpoint +on N2 marked with the little red circle. After resolving the conflict as +of Figure 3/3 c., the detour takes the shortest path from the spokes +calculated for N3 to the original endpoint of the offending line. This shortest +path now gets too close to N2. This is not detected in this step. Instead it +is detected in a subsequent cross detection step which will mark it as a +new (weaker) conflict in the state decision tree, which will let the high +level resolve it with a new detour between N1 and N2, with the offending +object being the new, shorter, almost horizontal yellow line at the little +red square mark. + +

+N1 does not need to cross or even touch N3, it is enough if it gets +closer than the requred clearance. However, this case can be resolved by +the same algorithm, as shown on Figure 3/4. + +

+

+

+

Figure 3/4. a. the same example, expect N1 is not crossing or touching +anything in N3 but getting too close to it; +b., c.: same steps +

+ +

3.3.2. S2: One end outside

+

+One end of the offending line object of N1 is outside of the naked convex hull +of N3, the other end is inside (Figure 3/5, marked P0). The two possible +detour paths are calculated as: +

    +
  • calculate a convex hull of N3 with the offending line outside endpoint (P4) included +
  • find a section of the convex hull of N3 that has a direct line of visibility from the offending object endpoint that is inside +
  • the direct line of sight may not cross spokes of N3 +
  • split the hull in two: +
      +
    • CW: P0-P1-P4 +
    • CCW: P0-P2-P4 +
    +
  • replace the offending N1 line with either the CW or the CCW path from the previous point +
+

+TODO: this path is suboptimal in two places: at P1/P2 and at P4. Maybe we +could add an optimization pull step here. + +

+

+

+

Figure 3/5. a. the same example, modified so the starting endpoint of N1 +is within the convex hull of N3; b. is the new convex hull (red) and line-of-sight +probes (green); c. is the final detour path (yellow) and the possible other +detour path (red). +

+ +

3.3.3. S3: Both ends inside

+

+Both ends of the offending line object of N1 is inside of the naked convex hull +of N3 (Figure 3/6). There is only one possible detour path. +

+First collect the N3 corners that are contributing the violation: +

    +
  • if the offending N1 line crosses any N3 objects, the corners of those N3 objects that are between the two crossings are added (Figure 3/6, b) + (TODO: this doesn't handle junctions, polygons and generally things that are hanging inside N3 from the wall!) +
  • in such crossing, also add the crossing points (Figure 3/6, b) +
  • if the offending N1 line is getting too close to any corner of N3, add those corners too (Figure 3/6, e) +
  • always add both endponits of the offending N1 line +
+

+ +

+

+

Figure 3/6. a. N1 inside N3, crossing edges; b. spokes and convex hull; +c. path chosen; d. same case but no crossing; e. spokes and convex hull; +f. path chosen; +

+

+Once those corners are collected, the path calculation is: +

    +
  • calculate a convex hull using the above corners and their N3-N1 spokes +
  • split the hull in two at the offending line endpoints +
  • one half will cross N3 - throw it away +
  • the other half is the resulting path; replace the offending line with this path +
+ +

+TODO: However, this will break in the following case: +

+

+

Figure 3/x. zig-zag example: if the vertical dashed line is intersected from both +left and right by N3, the hull won't work! probably go "one-by-one"? +

+

+ + + +

3.4. Switch-layer cases: V1, V2, V3

+

+First exclude V1 or V2 depending on the existing objects on offending N1 +line endpoints: +

    +
  • V1 is possible only if both ends of the offending N1 line is on existing vias or terminals that reach multiple layers. +
  • V2 is possible only if one of the endpoints of the offending N1 line is already on a via or through-hole terminal. +
  • V3 is always possible. +
+

+For V2 and V3, the via should be placed as close as possible to the offended +two-net. (Rationale: the policy for state state search is that we are not +going to insert new paths between two tightly packed paths but we will rather +swap the order of routing for them). Close placement is achieved by +calculating the intersection of the offending N1 line and the convex hull +of the offended two-net, using N1 via geometry for spoke D value. The intersection +point is the closest possible point for the via. +

+TODO: draw this! Index: tags/0.9.0/doc/detour/4_appendix.html =================================================================== --- tags/0.9.0/doc/detour/4_appendix.html (nonexistent) +++ tags/0.9.0/doc/detour/4_appendix.html (revision 1402) @@ -0,0 +1,216 @@ + + + + + + +

Topo-geometric detour router

+ +

4. Appendix

+

+This chapter contains material that is not part of the specification, +not required for understanding or implementing the topo-geometric detour +router but may help exploring the problem and practical aspects of the +implementation. + +

4.1. Examples

+ +

4.1.1. Topology: passing by two obstacles

+ +

+

+

+

Figure 4/1. a. initial state; b. adding N1-N2 CW; c. adding N1-N3 CCW +

+

+The decision tree starts from the initial state, with a single crossing, yielding +a number of child states. One of the childe states is drawn on Figure 4/1 b, +which introduces two new conflicts between N1 and N3. There can be multiple +reasons why the search prefers this over direct one-step solutions: +

+

    +
  • there is only one layer available +
  • there are obstacles on other layers +
  • going around in N1-N2 CCW results in a crossing too +
  • weights for the cost function are set so that that the + detour length penalty of N1-N2 CCW or adding vias seems + more expensive than resolving two more conflicts +
+

+Once the decision is made by the decision tree search to explore this case, +the final solution is one step away: an N1-N3 CCW operation creates a state +that is a valid solution. + +

4.1.2. Topology: order of routes in the script

+ +

+

+

+

Figure 4/2. a. initial state for two nets; b. and c. differs only in order of conflict resolution +d. initial state for three nets; e. and f. differs only in order of conflict resolution +

+

+The algorithm never needs to "push" existing copper objects, as it never +needs to insert a new track in between two existing tracks if there is not +enoguh room between them. The algorithm achieves the same result by trying +a different order of similar operations as shown on Figure 4/1 a, b and c. +if conflict #2 is resolved first, the new conflict for N1 is the detour of +N2, which results in the order shown on b. However, this resolution introduces +an extra conflict, which will probably make the tree search algorithm first try +c., where N1 is resolved first (removing one coflict) but then any try to +resolve conflict #2 on N1 within the layer will cause more conflicts, which +will eventually make b. more viable. +

+A vairant of the same idea applied to vias is demonstrated on d, e and f. +TODO: specify how vias are described in the script + +

4.1.3. Topo-geo: the three net conflict

+

+The solution for the classic three net crossing conflict, which a pure +geometric solver can not solve, is shown on Figure 4.3. It is assumed +that there are obstacles around the bounding box of the drawing, i.e. +the outline of the board fits tightly on the 4 outer terminal and only +one layer is available. Starting points of the two-nets are top or left. + +

+

+

+

Figure 4/3. a. initial state; b. resolving #1: N1-N2 CW; +c. resolving #2: N1-N3 CW; d. resolving #3: N2-N1 CW; e. resolving #4: N1-N2 CW +f. the reamining too-close conflict #5, could be resolved by: N3-N1 CW +

+

+The final script is: +

+N1-N2 CW
+N1-N3 CW
+N2-N1 CW
+N1-N2 CW
+N3-N1 CW
+
+

+The alternative paths, N1-N2 CCW in b. or N1-N3 CCW in c. are not available +because the detour path (drawn in red) would cross unmovable objects (board +edge). It may be that the search tries them but those branches of the tree +will die. +

+Both state c and d features the "N1 line is within the naked convex hull of +the offended two-net" case, that's why the seeminlgy non-convex hull. + + + +

4.1.4. Topo-geo: bottleneck

+

+A bottleneck situation can not always be resolved on a single layer. This +example demonstrates that any branch of the search tree that attempts to +resolve the problem by detours on the same layer will fail. This will +eventually force the tree search algorithm to explore possibilities with vias. +N3 is unmovable. +

+

+

+

Figure 4/4. a. initial state; b. resolving #1; c. resoving #2 after #1; +d. resolving new conflict after c will cause oscillation; +e. restart from a, attempt to resolve #2 first; f. resolution for #2 introduces +new N1-N2 conflict #3; g. resolution to #3 would cause N1 to cross unmovable +objects +

+ +

4.1.5. Topology: multiple conflicts

+

+

+

+

Figure 4/5. a. initial state; b. resolving #1 (N1-N2 CCW); c. resolving +#2 (N1-N3 CCW) also resolves #3; d. alternative resolution to c. is +N1-N3 CW; e. then N1-N4 CW f. but that introduces #4, where N1 is too close +to N3 so an N1-N3 CW is required, with the same result as c. +

+

+NOTE: this example did not employ the "resolve first conflict from start" +optimization. With that optimization, the script would be: +

+N1-N2 CCW
+N1-N4 CCW
+N1-N3 CCW
+
+

+and the result would be the same as c. and f. + + + +

4.1.6. Topo-geo: routing through zig-zag labyrinth

+Blu nets N2 and N3 are unmovable, there is only one layer +available and it is impossible to go around. Hence N1 is forced +to find its way bending at P1, P2, P3 and P4. N1 start is top. +

+

+

+

Figure 4/6. a. initial state; b. N1-N2 CW; c. N1-N3 CCW; d. because +of changed line angles, first conflict is N1 getting to close to N2 at P1; +resolve that as N1-N2 CW. +

+

+The final script will include a few operations to resolve the crossings +and a few operations to resolve the new "going near" cases demonstrated on +Figure 4/6. d. The next step after d. would be to resolve the clearance +violation at P3, then resolving the last N1-N3 crossing on the bottom. +The final script is: + +

+N1-N2 CW
+N1-N3 CCW
+N1-N2 CW
+N1-N2 CW
+N1-N3 CCW
+
+ + + +

4.1.7. Topology: oscillation detection

+

+This is an optimization because the algorithm would work without this as +well: in case of oscillation, the script grows long which increases the +cost function which in turn will make other solutions more favorable. However +this would cause a lot of computation wasted on recalculating the oscillation +many times. +

+TODO: finalzie how to detect this. +

+

+

+

Figure 4/7. a. initial state with a gap between N2 and N3 too narrow; b. resolve +N1-N3 introducing a crossing on N1-N2; c. resolve the N1-N2 crossing causing +and N1-N3 crossing. +

+

+When the new N1-N3 crossing is to be resolved, the state will be very similar +to b and the solver could keep oscillating between b. and c. With the hull based +detour calculation this is a bit worse, because not the whole bent network is +moved, only the tiny veryical line segment in the middle between b and c so +the drawing on c becomes something like d. + +

4.1.8. Geometry: blocking spiral

+

+In case of the following spiral (blue net), the low level algorithm is unable +to find the otherwise clearly available path for N1. The reason is that this +is the "one endpoint in the hull, other endpoint outside of the hull" case, +which means a clear sight of line is searched between the inner endpoint +and the naked hull. +

+

+

+

Figure 4/8. Spiral can block the low level hull based algorithm. +

+

+Note: the problem is not present if the blue net is split into two sections +anywhere on the east or south wall (to the right from the conflict), because +each section is searched separately. That is, the inner part of the spiral is +in conflict first, which can be detoured through the second segment, then the +second segment conflict is resolved without considering the first segment, then +the first segment is conflicted again, etc. So the blocker is not that the +final path is a spiral. + +

4.2. Limitations

+ +

4.3. Extras that are easy to implement

+ Index: tags/0.9.0/doc/detour/Makefile =================================================================== --- tags/0.9.0/doc/detour/Makefile (nonexistent) +++ tags/0.9.0/doc/detour/Makefile (revision 1402) @@ -0,0 +1,17 @@ +# pcb-rnd/trunk/util/build_ps.sh +BUILD=./build_ps.sh + +all: + cd img && make + make detour.pdf + +detour.pdf: detour.ps + ps2pdf detour.ps > detour.pdf + +detour.ps: + echo [0-9]*.html > ps.lst + HTML2PS_OPTS="-f pdf.css --toc h" HTML2PS_SED="s/

.*//;" $(BUILD) `cat ps.lst` > detour.ps + + +clean: + rm HTML2PS.html ps.lst detour.ps Index: tags/0.9.0/doc/detour/img/Makefile =================================================================== --- tags/0.9.0/doc/detour/img/Makefile (nonexistent) +++ tags/0.9.0/doc/detour/img/Makefile (revision 1402) @@ -0,0 +1,35 @@ +DPI=200 +LHTS = \ + ex_3net.png \ + ex_bneck.png \ + ex_multi1.png \ + ex_order.png \ + ex_osc.png \ + ex_spiral.png \ + ex_topo.png \ + ex_zigzag.png \ + geo_go_around.png \ + geo_hcross.png \ + geo_hnear.png \ + geo_hpierce.png \ + geo_hwallin.png \ + geo_hwallin_brk.png \ + topo_cross1.png \ + topo_cross2.png + +DOTS = \ + topo_tree2.png \ + topo_tree1.png \ + geo_cases.png + +all: $(LHTS) $(DOTS) + +%.png: %.lht + pcb-rnd -x png --dpi $(DPI) --as-shown --cam $@=doc $^ + +%.png: %.dot + dot -Tpng $^ > $@ + + + + Index: tags/0.9.0/doc/detour/img/base.lht =================================================================== --- tags/0.9.0/doc/detour/img/base.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/base.lht (revision 1402) @@ -0,0 +1,340 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 50.25mm + y = 39.25mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=31.5mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.0mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.1 { + hdia=47.24mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=137.8mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=2.0mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=2.2mm; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.69 { + proto=2; x=3.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.70 { + proto=2; x=31.0mm; y=16.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.71 { + proto=2; x=16.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.72 { + proto=2; x=46.0mm; y=20.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.73 { + proto=2; x=25.0mm; y=33.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + ha:padstack_ref.74 { + proto=2; x=25.0mm; y=3.0mm; rot=0.000000; xmirror=0; smirror=0; clearance=20.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + } + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_3net.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_3net.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_3net.lht (revision 1402) @@ -0,0 +1,1392 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 85.25mm + y = 80.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.1767 { + x1=48.75mm; y1=16.75mm; x2=45.25mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1875 { + x1=72.75mm; y1=15.0mm; x2=77.75mm; y2=15.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2659 { + x1=48.75mm; y1=13.25mm; x2=45.25mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2662 { + x1=47.0mm; y1=12.525126mm; x2=47.0mm; y2=17.474874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2665 { + x1=44.525126mm; y1=15.0mm; x2=49.474874mm; y2=15.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2680 { + x1=32.75mm; y1=16.75mm; x2=29.25mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2683 { + x1=32.75mm; y1=13.25mm; x2=29.25mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2686 { + x1=31.0mm; y1=12.525126mm; x2=31.0mm; y2=17.474874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2689 { + x1=28.525126mm; y1=15.0mm; x2=33.474874mm; y2=15.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2704 { + x1=67.75mm; y1=20.0mm; x2=64.25mm; y2=16.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2707 { + x1=67.75mm; y1=16.5mm; x2=64.25mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2710 { + x1=66.0mm; y1=15.775126mm; x2=66.0mm; y2=20.724874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2713 { + x1=63.525126mm; y1=18.25mm; x2=68.474874mm; y2=18.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2716 { + x1=83.5mm; y1=20.0mm; x2=80.0mm; y2=16.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2719 { + x1=83.5mm; y1=16.5mm; x2=80.0mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2722 { + x1=81.75mm; y1=15.775126mm; x2=81.75mm; y2=20.724874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2725 { + x1=79.275126mm; y1=18.25mm; x2=84.224874mm; y2=18.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3034 { + x1=3.775126mm; y1=62.0mm; x2=8.724874mm; y2=62.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3037 { + x1=6.25mm; y1=59.525126mm; x2=6.25mm; y2=64.474874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3043 { + x1=8.0mm; y1=63.75mm; x2=4.5mm; y2=60.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3046 { + x1=4.525126mm; y1=60.25mm; x2=9.474874mm; y2=60.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3049 { + x1=7.0mm; y1=57.775126mm; x2=7.0mm; y2=62.724874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3052 { + x1=8.75mm; y1=58.5mm; x2=5.25mm; y2=62.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3055 { + x1=8.75mm; y1=62.0mm; x2=5.25mm; y2=58.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3058 { + x1=6.275126mm; y1=59.5mm; x2=11.224874mm; y2=59.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3061 { + x1=8.75mm; y1=57.025126mm; x2=8.75mm; y2=61.974874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3064 { + x1=4.5mm; y1=63.75mm; x2=10.5mm; y2=57.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3067 { + x1=10.5mm; y1=61.25mm; x2=7.0mm; y2=57.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3070 { + x1=17.275126mm; y1=60.5mm; x2=22.224874mm; y2=60.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3076 { + x1=21.5mm; y1=58.75mm; x2=18.0mm; y2=62.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3079 { + x1=21.5mm; y1=62.25mm; x2=18.0mm; y2=58.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3082 { + x1=15.5mm; y1=58.75mm; x2=22.974874mm; y2=58.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3085 { + x1=20.5mm; y1=56.275126mm; x2=20.5mm; y2=61.224874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3088 { + x1=22.25mm; y1=57.0mm; x2=18.75mm; y2=60.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3091 { + x1=22.25mm; y1=60.5mm; x2=18.75mm; y2=57.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3094 { + x1=17.275126mm; y1=57.0mm; x2=22.224874mm; y2=57.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3097 { + x1=19.75mm; y1=62.974874mm; x2=19.75mm; y2=54.525126mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3100 { + x1=21.5mm; y1=55.25mm; x2=18.0mm; y2=58.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3103 { + x1=21.5mm; y1=58.75mm; x2=18.0mm; y2=55.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3106 { + x1=9.525126mm; y1=45.75mm; x2=14.474874mm; y2=45.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3109 { + x1=12.0mm; y1=43.275126mm; x2=12.0mm; y2=48.224874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3112 { + x1=13.75mm; y1=44.0mm; x2=10.25mm; y2=47.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3115 { + x1=13.75mm; y1=47.5mm; x2=10.25mm; y2=44.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3118 { + x1=9.525126mm; y1=75.75mm; x2=14.474874mm; y2=75.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3121 { + x1=12.0mm; y1=73.275126mm; x2=12.0mm; y2=78.224874mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3124 { + x1=13.75mm; y1=74.0mm; x2=10.25mm; y2=77.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3127 { + x1=13.75mm; y1=77.5mm; x2=10.25mm; y2=74.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4682 { + x=2.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=12.0mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=18.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=8.75mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=24.5mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4689 { + x=31.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4690 { + x=12.0mm; y=32.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4692 { + x=37.75mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4693 { + x=47.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=53.5mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=41.0mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=41.0mm; y=32.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=69.25mm; y=32.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=66.0mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=59.25mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=75.25mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=69.25mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=81.75mm; y=18.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4704 { + x=12.0mm; y=45.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4705 { + x=18.0mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4707 { + x=24.5mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4708 { + x=8.75mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4709 { + x=2.0mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4710 { + x=12.0mm; y=75.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4712 { + x=31.0mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4713 { + x=47.0mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4714 { + x=41.0mm; y=45.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4715 { + x=53.5mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4716 { + x=37.75mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4717 { + x=41.0mm; y=75.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4718 { + x=69.25mm; y=75.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4719 { + x=59.25mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4720 { + x=66.0mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4721 { + x=81.75mm; y=62.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4722 { + x=75.25mm; y=58.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4723 { + x=69.25mm; y=45.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.1716 { + string={#1}; x=10.25mm; y=12.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1718 { + string={#2}; x=13.0mm; y=18.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1786 { + string={#2}; x=48.25mm; y=19.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1891 { + string={#4}; x=73.0mm; y=16.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1948 { + string={#3}; x=65.25mm; y=13.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.2887 { + string={#4}; x=16.0mm; y=60.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.2888 { + string={#3}; x=8.0mm; y=56.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.4304 { + string={#4}; x=45.25mm; y=60.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.4409 { + string={#5}; x=75.25mm; y=63.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.1707 { + x1=2.0mm; y1=15.0mm; x2=18.0mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1710 { + x1=8.75mm; y1=18.25mm; x2=24.5mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1713 { + x1=12.0mm; y1=2.0mm; x2=12.0mm; y2=32.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1787 { + x1=31.0mm; y1=15.0mm; x2=47.0mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1790 { + x1=37.75mm; y1=18.25mm; x2=53.5mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1803 { + x1=41.0mm; y1=2.0mm; x2=48.75mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1806 { + x1=48.75mm; y1=13.25mm; x2=49.5mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1809 { + x1=49.5mm; y1=15.0mm; x2=48.75mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1812 { + x1=48.75mm; y1=16.75mm; x2=41.0mm; y2=32.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1892 { + x1=59.25mm; y1=15.0mm; x2=75.25mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1895 { + x1=66.0mm; y1=18.25mm; x2=81.75mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1898 { + x1=69.25mm; y1=2.0mm; x2=77.0mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1901 { + x1=77.0mm; y1=13.25mm; x2=77.75mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1904 { + x1=77.75mm; y1=15.0mm; x2=77.0mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1929 { + x1=66.0mm; y1=15.75mm; x2=64.25mm; y2=16.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1932 { + x1=64.25mm; y1=16.5mm; x2=63.5mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1941 { + x1=63.5mm; y1=18.25mm; x2=64.25mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1944 { + x1=64.25mm; y1=20.0mm; x2=69.25mm; y2=32.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2776 { + x1=66.0mm; y1=15.75mm; x2=77.0mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2889 { + x1=2.0mm; y1=58.75mm; x2=18.0mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2892 { + x1=8.75mm; y1=62.0mm; x2=24.5mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2895 { + x1=12.0mm; y1=45.75mm; x2=19.75mm; y2=57.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2898 { + x1=19.75mm; y1=57.0mm; x2=20.5mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2901 { + x1=20.5mm; y1=58.75mm; x2=19.75mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2904 { + x1=8.75mm; y1=59.5mm; x2=7.0mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2907 { + x1=7.0mm; y1=60.25mm; x2=6.25mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2910 { + x1=6.25mm; y1=62.0mm; x2=7.0mm; y2=63.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2913 { + x1=7.0mm; y1=63.75mm; x2=12.0mm; y2=75.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2916 { + x1=8.75mm; y1=59.5mm; x2=19.75mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3932 { + x1=37.75mm; y1=62.0mm; x2=53.5mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3935 { + x1=41.0mm; y1=45.75mm; x2=48.75mm; y2=57.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3938 { + x1=48.75mm; y1=57.0mm; x2=49.5mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3941 { + x1=49.5mm; y1=58.75mm; x2=48.75mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3944 { + x1=37.75mm; y1=59.5mm; x2=36.0mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3947 { + x1=36.0mm; y1=60.25mm; x2=35.25mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3950 { + x1=35.25mm; y1=62.0mm; x2=36.0mm; y2=63.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3953 { + x1=36.0mm; y1=63.75mm; x2=41.0mm; y2=75.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3956 { + x1=37.75mm; y1=59.5mm; x2=48.75mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4041 { + x1=37.753101mm; y1=57.0mm; x2=36.0mm; y2=57.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4044 { + x1=36.0mm; y1=57.75mm; x2=34.25mm; y2=58.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4047 { + x1=34.25mm; y1=58.5mm; x2=31.0mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4050 { + x1=37.75mm; y1=57.025126mm; x2=47.0mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4356 { + x1=69.25mm; y1=45.75mm; x2=77.0mm; y2=57.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4359 { + x1=77.0mm; y1=57.0mm; x2=77.75mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4362 { + x1=77.75mm; y1=58.75mm; x2=77.0mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4365 { + x1=66.0mm; y1=59.5mm; x2=64.25mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4368 { + x1=64.25mm; y1=60.25mm; x2=63.5mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4371 { + x1=63.5mm; y1=62.0mm; x2=64.25mm; y2=63.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4374 { + x1=64.25mm; y1=63.75mm; x2=69.25mm; y2=75.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4380 { + x1=66.003101mm; y1=57.0mm; x2=64.25mm; y2=57.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4383 { + x1=64.25mm; y1=57.75mm; x2=62.5mm; y2=58.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4386 { + x1=62.5mm; y1=58.5mm; x2=59.25mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4389 { + x1=66.0mm; y1=57.025126mm; x2=75.25mm; y2=58.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4399 { + x1=77.0mm; y1=60.5mm; x2=75.25mm; y2=61.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4402 { + x1=75.25mm; y1=61.25mm; x2=66.0mm; y2=59.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4405 { + x1=66.0mm; y1=62.0mm; x2=81.75mm; y2=62.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.1949 { + string=N1; x=10.0mm; y=5.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1951 { + string=N2; x=3.75mm; y=13.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1953 { + string=N3; x=21.5mm; y=18.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:text.987 { + string=a; x=11.25mm; y=33.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1796 { + string=b; x=40.25mm; y=33.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1910 { + string=c; x=68.5mm; y=33.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.2919 { + string=d; x=11.25mm; y=78.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3959 { + string=e; x=40.25mm; y=77.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4392 { + string=f; x=68.5mm; y=77.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.2734 { + x1=41.0mm; y1=2.0mm; x2=29.25mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2737 { + x1=29.25mm; y1=13.25mm; x2=28.525126mm; y2=15.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2740 { + x1=28.525126mm; y1=15.0mm; x2=29.25mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2743 { + x1=29.25mm; y1=16.75mm; x2=41.0mm; y2=32.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2758 { + x1=81.75mm; y1=15.75mm; x2=83.5mm; y2=16.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2761 { + x1=83.5mm; y1=16.5mm; x2=84.224874mm; y2=18.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2764 { + x1=84.224874mm; y1=18.25mm; x2=83.5mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2767 { + x1=83.5mm; y1=20.0mm; x2=69.25mm; y2=32.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2773 { + x1=77.0mm; y1=16.75mm; x2=81.75mm; y2=15.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3130 { + x1=12.0mm; y1=78.224874mm; x2=10.25mm; y2=77.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3133 { + x1=10.25mm; y1=77.5mm; x2=9.525126mm; y2=75.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3136 { + x1=9.525126mm; y1=75.75mm; x2=4.5mm; y2=63.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3139 { + x1=4.5mm; y1=63.75mm; x2=3.775126mm; y2=62.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3148 { + x1=5.25mm; y1=58.5mm; x2=7.0mm; y2=57.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3151 { + x1=7.0mm; y1=57.75mm; x2=8.75mm; y2=57.025126mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3154 { + x1=8.75mm; y1=57.025126mm; x2=9.525126mm; y2=45.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3157 { + x1=9.525126mm; y1=45.75mm; x2=10.25mm; y2=44.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3160 { + x1=10.25mm; y1=44.0mm; x2=12.0mm; y2=43.275126mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3163 { + x1=12.0mm; y1=43.275126mm; x2=13.75mm; y2=44.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3172 { + x1=21.5mm; y1=55.25mm; x2=22.25mm; y2=57.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3175 { + x1=22.25mm; y1=57.0mm; x2=22.974874mm; y2=58.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3178 { + x1=22.974874mm; y1=58.75mm; x2=22.25mm; y2=60.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3184 { + x1=22.25mm; y1=60.5mm; x2=21.5mm; y2=62.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3193 { + x1=13.75mm; y1=77.5mm; x2=11.957107mm; y2=78.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3196 { + x1=21.5mm; y1=62.25mm; x2=13.75mm; y2=77.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3407 { + x1=13.75mm; y1=44.0mm; x2=21.5mm; y2=55.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4295 { + x1=8.767766mm; y1=57.017766mm; x2=18.0mm; y2=58.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4724 { + x1=77.0mm; y1=16.75mm; x2=69.25mm; y2=32.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4727 { + x1=18.0mm; y1=58.75mm; x2=14.474874mm; y2=75.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4730 { + x1=14.474874mm; y1=75.75mm; x2=13.75mm; y2=77.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3145 { + x1=4.5mm; y1=60.25mm; x2=5.25mm; y2=58.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3142 { + x1=3.775126mm; y1=62.0mm; x2=4.5mm; y2=60.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=7 + ha:combining { } + + li:objects { + ha:line.3416 { + x1=18.0mm; y1=58.75mm; x2=9.0mm; y2=55.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3630 { + x1=4.5mm; y1=55.5mm; x2=4.75mm; y2=58.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3633 { + x1=4.75mm; y1=58.0mm; x2=4.0mm; y2=57.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3636 { + x1=4.75mm; y1=58.0mm; x2=5.25mm; y2=57.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#548b54} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_3net.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_3net.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_3net.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_3net.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_3net.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_bneck.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_bneck.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_bneck.lht (revision 1402) @@ -0,0 +1,1493 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 82.5mm + y = 31.0mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.251 { + x1=30.5mm; y1=3.5mm; x2=30.5mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.254 { + x1=29.5mm; y1=4.5mm; x2=31.5mm; y2=4.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.269 { + x1=31.207107mm; y1=3.792893mm; x2=29.792893mm; y2=5.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.272 { + x1=29.792893mm; y1=3.792893mm; x2=31.207107mm; y2=5.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1462 { + x1=50.5mm; y1=3.5mm; x2=52.5mm; y2=3.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1465 { + x1=72.0mm; y1=2.75mm; x2=72.0mm; y2=4.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1468 { + x1=71.0mm; y1=3.75mm; x2=73.0mm; y2=3.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1471 { + x1=72.707107mm; y1=119.79893701mil; x2=71.292893mm; y2=4.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1474 { + x1=71.292893mm; y1=119.79893701mil; x2=72.707107mm; y2=4.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1477 { + x1=64.75mm; y1=6.0mm; x2=64.75mm; y2=2.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1480 { + x1=66.75mm; y1=4.0mm; x2=62.75mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1483 { + x1=66.164214mm; y1=5.414214mm; x2=63.335786mm; y2=2.585786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1486 { + x1=66.164214mm; y1=2.585786mm; x2=63.335786mm; y2=5.414214mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1489 { + x1=79.5mm; y1=6.0mm; x2=79.5mm; y2=2.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1492 { + x1=81.5mm; y1=4.0mm; x2=77.5mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1495 { + x1=80.914214mm; y1=5.414214mm; x2=78.085786mm; y2=2.585786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1498 { + x1=80.914214mm; y1=2.585786mm; x2=78.085786mm; y2=5.414214mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1501 { + x1=51.5mm; y1=3.5mm; x2=51.5mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1504 { + x1=52.207107mm; y1=3.792893mm; x2=50.792893mm; y2=5.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1507 { + x1=50.792893mm; y1=3.792893mm; x2=52.207107mm; y2=5.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2941 { + x1=10.0mm; y1=19.75mm; x2=10.0mm; y2=21.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2944 { + x1=9.0mm; y1=20.75mm; x2=11.0mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2953 { + x1=10.707107mm; y1=20.042893mm; x2=9.292893mm; y2=21.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2956 { + x1=9.292893mm; y1=20.042893mm; x2=10.707107mm; y2=21.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3031 { + x1=8.75mm; y1=22.5mm; x2=8.75mm; y2=24.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3034 { + x1=7.75mm; y1=23.5mm; x2=9.75mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3037 { + x1=9.457107mm; y1=22.792893mm; x2=316.64933071mil; y2=24.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3040 { + x1=316.64933071mil; y1=22.792893mm; x2=9.457107mm; y2=24.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3043 { + x1=11.5mm; y1=22.5mm; x2=11.5mm; y2=24.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3046 { + x1=10.5mm; y1=23.5mm; x2=12.5mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3049 { + x1=12.207107mm; y1=22.792893mm; x2=10.792893mm; y2=24.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3052 { + x1=10.792893mm; y1=22.792893mm; x2=12.207107mm; y2=24.207107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3162 { + x1=30.5mm; y1=19.75mm; x2=30.5mm; y2=21.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3165 { + x1=29.5mm; y1=20.75mm; x2=31.5mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3168 { + x1=31.207107mm; y1=20.042893mm; x2=29.792893mm; y2=21.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3171 { + x1=29.792893mm; y1=20.042893mm; x2=31.207107mm; y2=21.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3650 { + x1=51.5mm; y1=18.75mm; x2=51.5mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3653 { + x1=50.5mm; y1=19.75mm; x2=52.5mm; y2=19.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3656 { + x1=52.207107mm; y1=19.042893mm; x2=50.792893mm; y2=20.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3659 { + x1=50.792893mm; y1=19.042893mm; x2=52.207107mm; y2=20.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3662 { + x1=50.5mm; y1=19.25mm; x2=50.5mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3665 { + x1=49.5mm; y1=20.25mm; x2=51.5mm; y2=20.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3668 { + x1=51.207107mm; y1=19.542893mm; x2=49.792893mm; y2=20.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3671 { + x1=49.792893mm; y1=19.542893mm; x2=51.207107mm; y2=20.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3674 { + x1=52.75mm; y1=19.25mm; x2=52.75mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3677 { + x1=51.75mm; y1=20.25mm; x2=53.75mm; y2=20.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3680 { + x1=53.457107mm; y1=19.542893mm; x2=52.042893mm; y2=20.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3683 { + x1=52.042893mm; y1=19.542893mm; x2=53.457107mm; y2=20.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3698 { + x1=44.25mm; y1=25.5mm; x2=44.25mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3701 { + x1=46.25mm; y1=23.5mm; x2=42.25mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3704 { + x1=45.664214mm; y1=24.914214mm; x2=42.835786mm; y2=22.085786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3707 { + x1=45.664214mm; y1=22.085786mm; x2=42.835786mm; y2=24.914214mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3710 { + x1=59.0mm; y1=25.5mm; x2=59.0mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3713 { + x1=61.0mm; y1=23.5mm; x2=57.0mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3716 { + x1=60.414214mm; y1=24.914214mm; x2=57.585786mm; y2=22.085786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3719 { + x1=60.414214mm; y1=22.085786mm; x2=57.585786mm; y2=24.914214mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=2.75mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=2.75mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=17.5mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=17.5mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4693 { + x=23.25mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=23.25mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=38.0mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=38.0mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=44.25mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=44.25mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=59.0mm; y=7.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=59.0mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=64.75mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=64.75mm; y=7.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4703 { + x=79.5mm; y=7.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4704 { + x=79.5mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4705 { + x=2.75mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4706 { + x=2.75mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4707 { + x=17.5mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4708 { + x=17.5mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4709 { + x=23.25mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4710 { + x=23.25mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4711 { + x=38.0mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4712 { + x=38.0mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4713 { + x=44.25mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4714 { + x=44.25mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4715 { + x=59.0mm; y=23.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4716 { + x=59.0mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.933 { + string={#1}; x=10.75mm; y=4.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.935 { + string={#2}; x=9.0mm; y=7.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1511 { + string={#3}; x=51.0mm; y=0.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.2226 { + string={#2}; x=29.75mm; y=7.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.2971 { + string={#1, #3}; x=28.0mm; y=15.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.3596 { + string={#1, #3}; x=49.0mm; y=15.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.140 { + x1=2.75mm; y1=3.75mm; x2=17.5mm; y2=3.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.143 { + x1=2.75mm; y1=7.25mm; x2=17.5mm; y2=7.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.211 { + x1=23.25mm; y1=7.25mm; x2=38.0mm; y2=7.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1512 { + x1=44.25mm; y1=7.25mm; x2=50.792893mm; y2=3.792893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1515 { + x1=52.207107mm; y1=3.792893mm; x2=59.0mm; y2=7.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1518 { + x1=64.75mm; y1=7.5mm; x2=71.292893mm; y2=4.292893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1521 { + x1=72.707107mm; y1=4.292893mm; x2=79.5mm; y2=7.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1524 { + x1=71.292893mm; y1=4.292893mm; x2=72.707107mm; y2=4.292893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1527 { + x1=50.75mm; y1=3.815556mm; x2=51.5mm; y2=3.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1530 { + x1=51.5mm; y1=3.5mm; x2=52.207107mm; y2=3.792893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2972 { + x1=2.75mm; y1=20.0mm; x2=17.5mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2975 { + x1=2.75mm; y1=23.5mm; x2=17.5mm; y2=23.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3251 { + x1=23.25mm; y1=23.5mm; x2=29.792893mm; y2=20.042893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3198 { + x1=23.25mm; y1=20.0mm; x2=38.0mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3254 { + x1=29.792893mm; y1=20.042893mm; x2=30.5mm; y2=19.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3257 { + x1=30.5mm; y1=19.75mm; x2=31.25mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3260 { + x1=31.25mm; y1=20.0mm; x2=38.0mm; y2=23.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3597 { + x1=44.25mm; y1=23.5mm; x2=50.792893mm; y2=20.042893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3603 { + x1=50.792893mm; y1=20.042893mm; x2=51.5mm; y2=19.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3606 { + x1=51.5mm; y1=19.75mm; x2=52.25mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3609 { + x1=52.25mm; y1=20.0mm; x2=59.0mm; y2=23.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.171 { + string=N1; x=4.75mm; y=4.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.172 { + string=N2; x=4.75mm; y=5.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.338 { + x1=23.25mm; y1=3.75mm; x2=30.5mm; y2=3.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.341 { + x1=30.5mm; y1=3.5mm; x2=38.0mm; y2=3.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1554 { + x1=51.5mm; y1=3.5mm; x2=59.0mm; y2=3.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1557 { + x1=44.25mm; y1=3.75mm; x2=51.5mm; y2=3.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1581 { + x1=72.0mm; y1=3.75mm; x2=79.5mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1584 { + x1=64.75mm; y1=4.0mm; x2=72.0mm; y2=3.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.2978 { + string=e; x=9.75mm; y=25.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3069 { + string=a; x=10.0mm; y=9.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3070 { + string=b; x=30.5mm; y=9.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3071 { + string=c; x=51.5mm; y=9.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3072 { + string=d; x=72.0mm; y=9.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3204 { + string=f; x=30.25mm; y=25.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3612 { + string=g; x=51.25mm; y=25.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=8 + ha:combining { } + + li:objects { + ha:line.1598 { + x1=79.5mm; y1=6.0mm; x2=81.0mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1601 { + x1=81.0mm; y1=5.5mm; x2=81.5mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1604 { + x1=81.5mm; y1=4.0mm; x2=80.914214mm; y2=2.585786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1607 { + x1=80.914214mm; y1=2.585786mm; x2=79.5mm; y2=2.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1610 { + x1=79.5mm; y1=2.0mm; x2=64.75mm; y2=2.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1613 { + x1=64.75mm; y1=2.0mm; x2=63.335786mm; y2=2.585786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1616 { + x1=63.335786mm; y1=2.585786mm; x2=62.75mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1619 { + x1=62.75mm; y1=4.0mm; x2=63.335786mm; y2=5.414214mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1622 { + x1=63.335786mm; y1=5.414214mm; x2=64.75mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2547 { + x1=64.75mm; y1=6.0mm; x2=79.5mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2979 { + x1=9.292893mm; y1=20.042893mm; x2=10.0mm; y2=19.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2982 { + x1=10.0mm; y1=19.75mm; x2=10.707107mm; y2=20.042893mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3010 { + x1=9.292893mm; y1=20.042893mm; x2=2.75mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3016 { + x1=17.5mm; y1=23.5mm; x2=10.707107mm; y2=20.042893mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3055 { + x1=2.75mm; y1=23.5mm; x2=8.75mm; y2=24.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3058 { + x1=8.75mm; y1=24.5mm; x2=11.5mm; y2=24.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3061 { + x1=11.5mm; y1=24.5mm; x2=17.5mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3722 { + x1=42.25mm; y1=23.5mm; x2=42.835786mm; y2=22.085786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3749 { + x1=60.414214mm; y1=22.085786mm; x2=61.0mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3752 { + x1=61.0mm; y1=23.5mm; x2=60.5mm; y2=25.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3755 { + x1=60.5mm; y1=25.0mm; x2=59.0mm; y2=25.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3761 { + x1=59.0mm; y1=25.5mm; x2=44.25mm; y2=25.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3764 { + x1=44.25mm; y1=25.5mm; x2=42.75mm; y2=25.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3767 { + x1=42.75mm; y1=25.0mm; x2=42.25mm; y2=23.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3770 { + x1=42.835786mm; y1=22.085786mm; x2=44.25mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3773 { + x1=44.25mm; y1=20.0mm; x2=51.5mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3776 { + x1=51.5mm; y1=18.75mm; x2=59.0mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3779 { + x1=59.0mm; y1=20.0mm; x2=60.414214mm; y2=22.085786mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3782 { + x1=30.5mm; y1=3.5mm; x2=23.25mm; y2=3.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3785 { + x1=23.25mm; y1=3.75mm; x2=30.5mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3788 { + x1=30.5mm; y1=5.5mm; x2=38.0mm; y2=3.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3791 { + x1=38.0mm; y1=3.75mm; x2=30.5mm; y2=3.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=6 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + + ha:N3 { + lid=5 + group=7 + ha:combining { } + + li:objects { + ha:line.1578 { + x1=74.25mm; y1=9.0mm; x2=81.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1575 { + x1=63.25mm; y1=9.0mm; x2=70.0mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1572 { + x1=72.0mm; y1=4.75mm; x2=74.25mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1569 { + x1=70.0mm; y1=9.0mm; x2=72.0mm; y2=4.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1566 { + x1=81.0mm; y1=2.5mm; x2=63.25mm; y2=2.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1563 { + x1=81.0mm; y1=9.0mm; x2=81.0mm; y2=2.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1560 { + x1=63.25mm; y1=2.5mm; x2=63.25mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1551 { + x1=53.75mm; y1=8.75mm; x2=60.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1548 { + x1=42.75mm; y1=8.75mm; x2=49.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1545 { + x1=51.5mm; y1=4.5mm; x2=53.75mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1542 { + x1=49.5mm; y1=8.75mm; x2=51.5mm; y2=4.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1539 { + x1=60.5mm; y1=2.25mm; x2=42.75mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1536 { + x1=60.5mm; y1=8.75mm; x2=60.5mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1533 { + x1=42.75mm; y1=2.25mm; x2=42.75mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.234 { + x1=32.75mm; y1=8.75mm; x2=39.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.228 { + x1=30.5mm; y1=4.5mm; x2=32.75mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.225 { + x1=28.5mm; y1=8.75mm; x2=30.5mm; y2=4.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.222 { + x1=39.5mm; y1=2.25mm; x2=21.75mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.219 { + x1=39.5mm; y1=8.75mm; x2=39.5mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.216 { + x1=21.75mm; y1=2.25mm; x2=21.75mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.164 { + x1=12.25mm; y1=8.75mm; x2=19.0mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.161 { + x1=1.25mm; y1=8.75mm; x2=8.0mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.158 { + x1=10.0mm; y1=4.5mm; x2=12.25mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.155 { + x1=8.0mm; y1=8.75mm; x2=10.0mm; y2=4.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.152 { + x1=19.0mm; y1=2.25mm; x2=1.25mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.149 { + x1=19.0mm; y1=8.75mm; x2=19.0mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.146 { + x1=1.25mm; y1=2.25mm; x2=1.25mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2985 { + x1=12.25mm; y1=25.0mm; x2=19.0mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2988 { + x1=1.25mm; y1=25.0mm; x2=8.0mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2991 { + x1=10.0mm; y1=20.75mm; x2=12.25mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2994 { + x1=8.0mm; y1=25.0mm; x2=10.0mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2997 { + x1=19.0mm; y1=18.5mm; x2=1.25mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3000 { + x1=19.0mm; y1=25.0mm; x2=19.0mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3003 { + x1=1.25mm; y1=18.5mm; x2=1.25mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3226 { + x1=32.75mm; y1=25.0mm; x2=39.5mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3229 { + x1=21.75mm; y1=25.0mm; x2=28.5mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3232 { + x1=30.5mm; y1=20.75mm; x2=32.75mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3235 { + x1=28.5mm; y1=25.0mm; x2=30.5mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3238 { + x1=39.5mm; y1=18.5mm; x2=21.75mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3241 { + x1=39.5mm; y1=25.0mm; x2=39.5mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3244 { + x1=21.75mm; y1=18.5mm; x2=21.75mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3613 { + x1=53.75mm; y1=25.0mm; x2=60.5mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3616 { + x1=42.75mm; y1=25.0mm; x2=49.5mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3619 { + x1=51.5mm; y1=20.75mm; x2=53.75mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3622 { + x1=49.5mm; y1=25.0mm; x2=51.5mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3625 { + x1=60.5mm; y1=18.5mm; x2=42.75mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3628 { + x1=60.5mm; y1=25.0mm; x2=60.5mm; y2=18.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3631 { + x1=42.75mm; y1=18.5mm; x2=42.75mm; y2=25.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.231 { + x1=21.75mm; y1=8.75mm; x2=28.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.3263 { + string=N3; x=2.25mm; y=0.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#000000} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 5; } + purpose = fab + } + ha:8 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_bneck.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_bneck.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_bneck.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_bneck.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_bneck.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_multi1.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_multi1.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_multi1.lht (revision 1402) @@ -0,0 +1,792 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 88.5mm + y = 55.0mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.881 { + x1=47.75mm; y1=2.25mm; x2=53.75mm; y2=2.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.884 { + x1=53.75mm; y1=2.5mm; x2=56.25mm; y2=4.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.887 { + x1=56.25mm; y1=4.5mm; x2=57.0mm; y2=9.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.890 { + x1=57.0mm; y1=9.75mm; x2=55.5mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1440 { + x1=76.0mm; y1=2.0mm; x2=82.0mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1443 { + x1=82.0mm; y1=2.25mm; x2=84.5mm; y2=4.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1446 { + x1=84.5mm; y1=4.25mm; x2=85.25mm; y2=9.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1480 { + x1=85.25mm; y1=9.5mm; x2=85.75mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1483 { + x1=85.75mm; y1=12.0mm; x2=84.75mm; y2=14.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1486 { + x1=84.75mm; y1=14.5mm; x2=83.75mm; y2=14.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=2.0mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4685 { + x=24.0mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=18.0mm; y=20.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=18.0mm; y=2.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4692 { + x=31.75mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4693 { + x=53.75mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=47.75mm; y=20.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=47.75mm; y=2.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=60.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=82.0mm; y=15.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=76.0mm; y=20.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=76.0mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=2.0mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=24.0mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=18.0mm; y=49.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4703 { + x=18.0mm; y=31.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4704 { + x=31.75mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4705 { + x=53.75mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4706 { + x=47.75mm; y=49.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4707 { + x=47.75mm; y=31.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4708 { + x=61.5mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4709 { + x=83.5mm; y=44.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4710 { + x=77.5mm; y=49.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4711 { + x=77.5mm; y=31.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.302 { + string={#1}; x=16.0mm; y=13.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.554 { + string={#2}; x=52.25mm; y=7.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.812 { + string={#3}; x=54.25mm; y=10.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1205 { + string={#4}; x=56.75mm; y=38.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1304 { + string={#3}; x=24.5mm; y=39.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1453 { + string={#3}; x=82.5mm; y=10.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.281 { + x1=18.0mm; y1=2.25mm; x2=18.0mm; y2=20.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.284 { + x1=2.0mm; y1=15.25mm; x2=24.0mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.559 { + x1=47.75mm; y1=2.25mm; x2=55.5mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.562 { + x1=55.5mm; y1=15.0mm; x2=55.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.565 { + x1=55.5mm; y1=16.75mm; x2=47.75mm; y2=20.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1207 { + x1=47.75mm; y1=31.5mm; x2=50.5mm; y2=40.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1210 { + x1=55.5mm; y1=46.0mm; x2=47.75mm; y2=49.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1213 { + x1=55.5mm; y1=44.5mm; x2=55.5mm; y2=46.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1216 { + x1=50.5mm; y1=40.0mm; x2=56.75mm; y2=40.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1219 { + x1=56.75mm; y1=40.0mm; x2=58.0mm; y2=41.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1222 { + x1=58.0mm; y1=41.25mm; x2=55.5mm; y2=44.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1305 { + x1=18.0mm; y1=31.5mm; x2=20.75mm; y2=40.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1308 { + x1=20.75mm; y1=40.0mm; x2=25.75mm; y2=43.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1311 { + x1=25.75mm; y1=46.0mm; x2=18.0mm; y2=49.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1314 { + x1=25.75mm; y1=43.5mm; x2=25.75mm; y2=46.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1371 { + x1=85.25mm; y1=46.0mm; x2=77.5mm; y2=49.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1374 { + x1=85.25mm; y1=44.5mm; x2=85.25mm; y2=46.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1457 { + x1=83.75mm; y1=14.75mm; x2=83.75mm; y2=16.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1460 { + x1=83.75mm; y1=16.5mm; x2=76.0mm; y2=20.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1519 { + x1=85.25mm; y1=44.5mm; x2=86.25mm; y2=44.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1504 { + x1=77.5mm; y1=31.5mm; x2=83.5mm; y2=31.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1507 { + x1=83.5mm; y1=31.75mm; x2=86.0mm; y2=33.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1510 { + x1=86.0mm; y1=33.75mm; x2=86.75mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1513 { + x1=86.75mm; y1=39.0mm; x2=87.25mm; y2=41.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1516 { + x1=87.25mm; y1=41.5mm; x2=86.25mm; y2=44.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.305 { + string=N1; x=16.0mm; y=6.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.306 { + string=N2; x=10.5mm; y=16.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.348 { + x1=21.5mm; y1=10.0mm; x2=21.5mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.351 { + x1=21.5mm; y1=10.0mm; x2=26.25mm; y2=10.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.788 { + x1=26.25mm; y1=12.5mm; x2=6.5mm; y2=12.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.799 { + x1=51.25mm; y1=10.0mm; x2=51.25mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.802 { + x1=51.25mm; y1=10.0mm; x2=56.0mm; y2=10.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.808 { + x1=56.0mm; y1=12.5mm; x2=36.25mm; y2=12.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.813 { + x1=31.75mm; y1=15.25mm; x2=53.75mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1240 { + x1=51.25mm; y1=39.25mm; x2=51.25mm; y2=32.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1243 { + x1=51.25mm; y1=39.25mm; x2=56.0mm; y2=39.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1246 { + x1=56.0mm; y1=41.75mm; x2=36.25mm; y2=41.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1249 { + x1=31.75mm; y1=44.5mm; x2=53.75mm; y2=44.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1317 { + x1=21.5mm; y1=39.25mm; x2=21.5mm; y2=32.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1320 { + x1=21.5mm; y1=39.25mm; x2=26.25mm; y2=39.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1323 { + x1=26.25mm; y1=41.75mm; x2=6.5mm; y2=41.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1326 { + x1=2.0mm; y1=44.5mm; x2=24.0mm; y2=44.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1383 { + x1=81.0mm; y1=39.25mm; x2=81.0mm; y2=32.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1386 { + x1=81.0mm; y1=39.25mm; x2=85.75mm; y2=39.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1389 { + x1=85.75mm; y1=41.75mm; x2=66.0mm; y2=41.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1392 { + x1=61.5mm; y1=44.5mm; x2=83.5mm; y2=44.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1463 { + x1=79.5mm; y1=9.75mm; x2=79.5mm; y2=2.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1466 { + x1=79.5mm; y1=9.75mm; x2=84.25mm; y2=9.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1469 { + x1=84.25mm; y1=12.25mm; x2=64.5mm; y2=12.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1472 { + x1=60.0mm; y1=15.0mm; x2=82.0mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.791 { + string=N3; x=22.0mm; y=4.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.792 { + string=N4; x=7.0mm; y=10.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.990 { + string=a; x=14.5mm; y=22.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.991 { + string=b; x=42.75mm; y=22.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1264 { + string=e; x=42.75mm; y=51.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1329 { + string=d; x=13.0mm; y=51.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1395 { + string=f; x=72.5mm; y=51.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1475 { + string=c; x=71.0mm; y=22.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_multi1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_multi1.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_multi1.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_multi1.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_multi1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_order.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_order.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_order.lht (revision 1402) @@ -0,0 +1,1369 @@ +ha:pcb-rnd-board-v7 { + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 73.25mm + y = 43.0mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + ha:layer_stack { + li:groups { + ha:0 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_4 + } + ha:1 { + ha:attributes { + thickness = {0.125mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_6 + } + ha:2 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_8 + } + ha:3 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 0 + } + name = top-doc + } + ha:4 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 1 + } + name = top-doc + } + ha:5 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 2 + } + name = top-doc + } + ha:6 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 3 + } + name = top-doc + } + ha:7 { + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 4 + } + name = top-doc + } + } + } + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 1.5mm + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 0.9mm + clearance = 25.0mil + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + wireframe_draw = false + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 1 + all_direction_lines = true + } + } + } + ha:data { + li:padstack_prototypes { + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + } + li:objects { + } + li:layers { + ha:draft { + lid = 0 + li:objects { + ha:line.5502 { + clearance = 50.0mil + y2 = 6.25mm + thickness = 0.15mm + x1 = 34.75mm + x2 = 39.75mm + ha:flags { + clearline = 1 + } + y1 = 6.25mm + } + ha:line.5541 { + clearance = 50.0mil + y2 = 1.25mm + thickness = 0.15mm + x1 = 37.25mm + x2 = 37.25mm + ha:flags { + clearline = 1 + } + y1 = 8.75mm + } + ha:line.5544 { + clearance = 50.0mil + y2 = 5.5mm + thickness = 0.15mm + x1 = 35.5mm + x2 = 39.0mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5547 { + clearance = 50.0mil + y2 = 2.0mm + thickness = 0.15mm + x1 = 35.25mm + x2 = 39.0mm + ha:flags { + clearline = 1 + } + y1 = 5.75mm + } + ha:line.5550 { + clearance = 50.0mil + y2 = 3.75mm + thickness = 0.15mm + x1 = 34.75mm + x2 = 39.75mm + ha:flags { + clearline = 1 + } + y1 = 3.75mm + } + ha:line.5562 { + clearance = 50.0mil + y2 = 7.0mm + thickness = 0.15mm + x1 = 35.5mm + x2 = 35.5mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5565 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 39.0mm + x2 = 33.75mm + ha:flags { + clearline = 1 + } + y1 = 8.0mm + } + ha:line.5568 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 33.5mm + x2 = 37.25mm + ha:flags { + clearline = 1 + } + y1 = 6.5mm + } + ha:line.5574 { + clearance = 50.0mil + y2 = 7.0mm + thickness = 0.15mm + x1 = 39.0mm + x2 = 39.0mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5577 { + clearance = 50.0mil + y2 = 6.25mm + thickness = 0.15mm + x1 = 37.25mm + x2 = 40.75mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5580 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 35.25mm + x2 = 40.75mm + ha:flags { + clearline = 1 + } + y1 = 8.25mm + } + ha:line.5583 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.15mm + x1 = 33.0mm + x2 = 41.5mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:line.5638 { + clearance = 50.0mil + y2 = 6.25mm + thickness = 0.15mm + x1 = 59.25mm + x2 = 64.25mm + ha:flags { + clearline = 1 + } + y1 = 6.25mm + } + ha:line.5653 { + clearance = 50.0mil + y2 = 7.0mm + thickness = 0.15mm + x1 = 60.0mm + x2 = 60.0mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5656 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 63.5mm + x2 = 58.25mm + ha:flags { + clearline = 1 + } + y1 = 8.0mm + } + ha:line.5659 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 58.0mm + x2 = 61.75mm + ha:flags { + clearline = 1 + } + y1 = 6.5mm + } + ha:line.5665 { + clearance = 50.0mil + y2 = 1.25mm + thickness = 0.15mm + x1 = 61.75mm + x2 = 61.75mm + ha:flags { + clearline = 1 + } + y1 = 8.75mm + } + ha:line.5668 { + clearance = 50.0mil + y2 = 5.5mm + thickness = 0.15mm + x1 = 60.0mm + x2 = 63.5mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5671 { + clearance = 50.0mil + y2 = 2.0mm + thickness = 0.15mm + x1 = 59.75mm + x2 = 63.5mm + ha:flags { + clearline = 1 + } + y1 = 5.75mm + } + ha:line.5674 { + clearance = 50.0mil + y2 = 3.75mm + thickness = 0.15mm + x1 = 59.25mm + x2 = 64.25mm + ha:flags { + clearline = 1 + } + y1 = 3.75mm + } + ha:line.5677 { + clearance = 50.0mil + y2 = 7.0mm + thickness = 0.15mm + x1 = 63.5mm + x2 = 63.5mm + ha:flags { + clearline = 1 + } + y1 = 2.0mm + } + ha:line.5680 { + clearance = 50.0mil + y2 = 6.25mm + thickness = 0.15mm + x1 = 61.75mm + x2 = 65.25mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5683 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.15mm + x1 = 59.75mm + x2 = 65.25mm + ha:flags { + clearline = 1 + } + y1 = 8.25mm + } + ha:line.5686 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.15mm + x1 = 57.5mm + x2 = 66.0mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:arc.6214 { + x=3.5mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6215 { + x=3.5mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6216 { + x=19.75mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6217 { + x=19.75mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6222 { + x=29.0mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6223 { + x=29.0mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6224 { + x=45.25mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6225 { + x=45.25mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6226 { + x=53.5mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6227 { + x=53.5mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6228 { + x=69.75mm; y=11.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6229 { + x=69.75mm; y=7.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6230 { + x=3.5mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6231 { + x=3.5mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6232 { + x=19.75mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6233 { + x=19.75mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6234 { + x=29.0mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6235 { + x=29.0mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6236 { + x=45.25mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6237 { + x=45.25mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6238 { + x=53.5mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6239 { + x=53.5mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6240 { + x=69.75mm; y=32.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6241 { + x=69.75mm; y=29.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6243 { + x=11.75mm; y=24.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6244 { + x=11.75mm; y=37.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6245 { + x=37.25mm; y=37.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6246 { + x=37.25mm; y=24.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6247 { + x=61.75mm; y=24.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6248 { + x=61.75mm; y=37.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6249 { + x=37.25mm; y=27.75mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6250 { + x=37.25mm; y=34.75mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6251 { + x=61.75mm; y=30.75mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6252 { + x=61.75mm; y=34.75mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.5962 { + string={#1}; x=12.75mm; y=5.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.5964 { + string={#2}; x=12.5mm; y=9.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.5967 { + string={#1}; x=12.75mm; y=27.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.5968 { + string={#2}; x=12.5mm; y=31.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.6004 { + string={#1}; x=62.5mm; y=27.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + group = 3 + ha:combining { + } + } + ha:ratlines { + lid = 1 + li:objects { + ha:line.5393 { + clearance = 50.0mil + y2 = 11.25mm + thickness = 0.35mm + x1 = 3.5mm + x2 = 19.75mm + ha:flags { + clearline = 1 + } + y1 = 11.25mm + } + ha:line.5396 { + clearance = 50.0mil + y2 = 7.75mm + thickness = 0.35mm + x1 = 3.5mm + x2 = 19.75mm + ha:flags { + clearline = 1 + } + y1 = 7.75mm + } + ha:line.5505 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.35mm + x1 = 29.0mm + x2 = 35.5mm + ha:flags { + clearline = 1 + } + y1 = 11.25mm + } + ha:line.5508 { + clearance = 50.0mil + y2 = 3.75mm + thickness = 0.35mm + x1 = 35.5mm + x2 = 37.25mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:line.5511 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.35mm + x1 = 37.25mm + x2 = 39.0mm + ha:flags { + clearline = 1 + } + y1 = 3.75mm + } + ha:line.5514 { + clearance = 50.0mil + y2 = 11.25mm + thickness = 0.35mm + x1 = 39.0mm + x2 = 45.25mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:line.5586 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.35mm + x1 = 29.0mm + x2 = 33.75mm + ha:flags { + clearline = 1 + } + y1 = 7.75mm + } + ha:line.5592 { + clearance = 50.0mil + y2 = 1.25mm + thickness = 0.35mm + x1 = 33.75mm + x2 = 37.25mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5598 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.35mm + x1 = 37.25mm + x2 = 40.75mm + ha:flags { + clearline = 1 + } + y1 = 1.25mm + } + ha:line.5601 { + clearance = 50.0mil + y2 = 7.75mm + thickness = 0.35mm + x1 = 40.75mm + x2 = 45.25mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5641 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.35mm + x1 = 53.5mm + x2 = 60.0mm + ha:flags { + clearline = 1 + } + y1 = 7.75mm + } + ha:line.5644 { + clearance = 50.0mil + y2 = 3.75mm + thickness = 0.35mm + x1 = 60.0mm + x2 = 61.75mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:line.5647 { + clearance = 50.0mil + y2 = 4.5mm + thickness = 0.35mm + x1 = 61.75mm + x2 = 63.5mm + ha:flags { + clearline = 1 + } + y1 = 3.75mm + } + ha:line.5650 { + clearance = 50.0mil + y2 = 7.75mm + thickness = 0.35mm + x1 = 63.5mm + x2 = 69.75mm + ha:flags { + clearline = 1 + } + y1 = 4.5mm + } + ha:line.5692 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.35mm + x1 = 53.5mm + x2 = 58.25mm + ha:flags { + clearline = 1 + } + y1 = 11.25mm + } + ha:line.5698 { + clearance = 50.0mil + y2 = 1.25mm + thickness = 0.35mm + x1 = 58.25mm + x2 = 61.75mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5707 { + clearance = 50.0mil + y2 = 2.75mm + thickness = 0.35mm + x1 = 61.75mm + x2 = 65.25mm + ha:flags { + clearline = 1 + } + y1 = 1.25mm + } + ha:line.5710 { + clearance = 50.0mil + y2 = 11.25mm + thickness = 0.35mm + x1 = 65.25mm + x2 = 69.75mm + ha:flags { + clearline = 1 + } + y1 = 2.75mm + } + ha:line.5725 { + clearance = 50.0mil + y2 = 32.5mm + thickness = 0.35mm + x1 = 3.5mm + x2 = 19.75mm + ha:flags { + clearline = 1 + } + y1 = 32.5mm + } + ha:line.5728 { + clearance = 50.0mil + y2 = 29.0mm + thickness = 0.35mm + x1 = 3.5mm + x2 = 19.75mm + ha:flags { + clearline = 1 + } + y1 = 29.0mm + } + ha:line.5752 { + clearance = 50.0mil + y2 = 37.5mm + thickness = 0.35mm + x1 = 11.75mm + x2 = 11.75mm + ha:flags { + clearline = 1 + } + y1 = 24.5mm + } + ha:text.5604 { + scale = 100 + x = 5.25mm + y = 6.0mm + rot = 0.000000 + string = N1 + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5605 { + scale = 100 + x = 5.25mm + y = 9.5mm + rot = 0.000000 + string = N2 + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5731 { + scale = 100 + x = 5.25mm + y = 27.25mm + rot = 0.000000 + string = N1 + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5732 { + scale = 100 + x = 5.25mm + y = 30.75mm + rot = 0.000000 + string = N2 + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5756 { + scale = 100 + x = 9.75mm + y = 26.25mm + rot = 0.000000 + string = N3 + fid = 0 + ha:flags { + clearline = 1 + } + } + } + color = {#d3a232} + group = 4 + ha:combining { + } + } + ha:wires { + lid = 2 + li:objects { + ha:line.5323 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 11.75mm + x2 = 11.75mm + ha:flags { + clearline = 1 + } + y1 = 6.25mm + } + ha:line.5426 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 1.25mm + x2 = 1.25mm + ha:flags { + clearline = 1 + } + y1 = 3.0mm + } + ha:line.5429 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 1.25mm + x2 = 22.0mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5432 { + clearance = 50.0mil + y2 = 3.25mm + thickness = 0.35mm + x1 = 22.0mm + x2 = 22.0mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5464 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 37.25mm + x2 = 37.25mm + ha:flags { + clearline = 1 + } + y1 = 6.25mm + } + ha:line.5467 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 26.75mm + x2 = 26.75mm + ha:flags { + clearline = 1 + } + y1 = 3.0mm + } + ha:line.5470 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 26.75mm + x2 = 47.5mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5473 { + clearance = 50.0mil + y2 = 3.25mm + thickness = 0.35mm + x1 = 47.5mm + x2 = 47.5mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5612 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 61.75mm + x2 = 61.75mm + ha:flags { + clearline = 1 + } + y1 = 6.25mm + } + ha:line.5615 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 51.25mm + x2 = 51.25mm + ha:flags { + clearline = 1 + } + y1 = 3.0mm + } + ha:line.5618 { + clearance = 50.0mil + y2 = 13.0mm + thickness = 0.35mm + x1 = 51.25mm + x2 = 72.0mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5621 { + clearance = 50.0mil + y2 = 3.25mm + thickness = 0.35mm + x1 = 72.0mm + x2 = 72.0mm + ha:flags { + clearline = 1 + } + y1 = 13.0mm + } + ha:line.5740 { + clearance = 50.0mil + y2 = 39.0mm + thickness = 0.35mm + x1 = 2.0mm + x2 = 2.0mm + ha:flags { + clearline = 1 + } + y1 = 23.0mm + } + ha:line.5743 { + clearance = 50.0mil + y2 = 39.0mm + thickness = 0.35mm + x1 = 2.0mm + x2 = 21.25mm + ha:flags { + clearline = 1 + } + y1 = 39.0mm + } + ha:line.5746 { + clearance = 50.0mil + y2 = 23.0mm + thickness = 0.35mm + x1 = 21.25mm + x2 = 21.25mm + ha:flags { + clearline = 1 + } + y1 = 39.0mm + } + ha:line.5749 { + clearance = 50.0mil + y2 = 23.0mm + thickness = 0.35mm + x1 = 21.25mm + x2 = 2.0mm + ha:flags { + clearline = 1 + } + y1 = 23.0mm + } + ha:line.5930 { + x1=27.5mm; y1=23.0mm; x2=27.5mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5933 { + x1=27.5mm; y1=39.0mm; x2=46.75mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5936 { + x1=46.75mm; y1=39.0mm; x2=46.75mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5939 { + x1=46.75mm; y1=23.0mm; x2=27.5mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5952 { + x1=29.0mm; y1=32.5mm; x2=45.25mm; y2=32.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5955 { + x1=37.25mm; y1=24.5mm; x2=37.25mm; y2=27.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6008 { + x1=52.0mm; y1=23.0mm; x2=52.0mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6011 { + x1=52.0mm; y1=39.0mm; x2=71.25mm; y2=39.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6014 { + x1=71.25mm; y1=39.0mm; x2=71.25mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6017 { + x1=71.25mm; y1=23.0mm; x2=52.0mm; y2=23.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6020 { + x1=53.5mm; y1=32.5mm; x2=69.75mm; y2=32.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6023 { + x1=61.75mm; y1=24.5mm; x2=61.75mm; y2=30.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6038 { + x1=29.0mm; y1=29.0mm; x2=45.25mm; y2=29.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6043 { + x1=37.25mm; y1=37.5mm; x2=37.25mm; y2=34.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6052 { + x1=53.5mm; y1=29.0mm; x2=69.75mm; y2=29.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6055 { + x1=61.75mm; y1=34.75mm; x2=61.75mm; y2=37.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.5760 { + scale = 200 + x = 11.25mm + y = 13.75mm + rot = 0.000000 + string = a + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5761 { + scale = 200 + x = 36.75mm + y = 13.75mm + rot = 0.000000 + string = b + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5762 { + scale = 200 + x = 61.25mm + y = 13.75mm + rot = 0.000000 + string = c + fid = 0 + ha:flags { + clearline = 1 + } + } + ha:text.5886 { + string=d; x=11.0mm; y=39.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5942 { + string=e; x=36.5mm; y=39.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6026 { + string=f; x=61.0mm; y=39.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + group = 5 + ha:combining { + } + } + ha:annotation { + lid = 3 + li:objects { + ha:line.6046 { + x1=37.25mm; y1=27.75mm; x2=37.25mm; y2=34.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6049 { + x1=61.75mm; y1=30.75mm; x2=61.75mm; y2=34.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + group = 6 + ha:combining { + } + } + ha:top-doc { + lid = 4 + li:objects { + } + color = {#548b54} + group = 7 + ha:combining { + } + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_order.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_order.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_order.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_order.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_order.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_osc.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_osc.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_osc.lht (revision 1402) @@ -0,0 +1,550 @@ +ha:pcb-rnd-board-v7 { + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 47.0mm + y = 19.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + ha:layer_stack { + li:groups { + ha:0 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_4 + } + ha:1 { + ha:attributes { + thickness = {0.125mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_6 + } + ha:2 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_8 + } + ha:3 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 0 + } + name = top-doc + } + ha:4 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 1 + } + name = top-doc + } + ha:5 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 2 + } + name = top-doc + } + ha:6 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 3 + } + name = top-doc + } + ha:7 { + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 4 + } + name = top-doc + } + } + } + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 1.5mm + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 0.9mm + clearance = 25.0mil + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + wireframe_draw = false + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 1 + all_direction_lines = true + } + } + } + ha:data { + li:padstack_prototypes { + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + } + li:objects { + } + li:layers { + ha:draft { + lid = 0 + li:objects { + ha:arc.6460 { + x=5.25mm; y=3.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6461 { + x=5.25mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6514 { + x=18.25mm; y=3.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6515 { + x=18.25mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6583 { + x=29.75mm; y=3.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6584 { + x=29.75mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6700 { + x=41.75mm; y=3.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6701 { + x=41.75mm; y=15.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + group = 3 + ha:combining { + } + } + ha:ratlines { + lid = 1 + li:objects { + ha:line.6462 { + x1=5.25mm; y1=3.25mm; x2=5.25mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6541 { + x1=18.25mm; y1=15.25mm; x2=17.5mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6544 { + x1=17.5mm; y1=9.25mm; x2=17.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6547 { + x1=17.5mm; y1=8.0mm; x2=18.25mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6625 { + x1=29.75mm; y1=15.25mm; x2=30.5mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6628 { + x1=30.5mm; y1=8.0mm; x2=30.5mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6631 { + x1=30.5mm; y1=8.0mm; x2=29.75mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6702 { + x1=41.75mm; y1=15.25mm; x2=41.0mm; y2=9.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6708 { + x1=41.0mm; y1=7.5mm; x2=41.75mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6733 { + x1=41.0mm; y1=9.5mm; x2=42.5mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6736 { + x1=42.5mm; y1=9.25mm; x2=42.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6739 { + x1=42.5mm; y1=8.0mm; x2=41.0mm; y2=7.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.6465 { + string=N1; x=5.75mm; y=4.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + group = 4 + ha:combining { + } + } + ha:wires { + lid = 2 + li:objects { + ha:line.6466 { + x1=4.75mm; y1=1.25mm; x2=1.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6469 { + x1=1.25mm; y1=1.25mm; x2=1.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6472 { + x1=1.25mm; y1=8.5mm; x2=4.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6475 { + x1=5.75mm; y1=8.5mm; x2=9.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6478 { + x1=9.25mm; y1=8.5mm; x2=9.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6481 { + x1=9.25mm; y1=1.25mm; x2=5.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6520 { + x1=17.75mm; y1=1.25mm; x2=14.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6523 { + x1=14.25mm; y1=1.25mm; x2=14.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6526 { + x1=14.25mm; y1=8.5mm; x2=17.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6529 { + x1=18.75mm; y1=8.5mm; x2=22.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6532 { + x1=22.25mm; y1=8.5mm; x2=22.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6535 { + x1=22.25mm; y1=1.25mm; x2=18.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6595 { + x1=29.25mm; y1=1.25mm; x2=25.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6598 { + x1=25.75mm; y1=1.25mm; x2=25.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6601 { + x1=25.75mm; y1=8.5mm; x2=29.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6604 { + x1=30.25mm; y1=8.5mm; x2=33.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6607 { + x1=33.75mm; y1=8.5mm; x2=33.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6610 { + x1=33.75mm; y1=1.25mm; x2=30.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6711 { + x1=41.25mm; y1=1.25mm; x2=37.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6714 { + x1=37.75mm; y1=1.25mm; x2=37.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6717 { + x1=37.75mm; y1=8.5mm; x2=41.25mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6720 { + x1=42.25mm; y1=8.5mm; x2=45.75mm; y2=8.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6723 { + x1=45.75mm; y1=8.5mm; x2=45.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6726 { + x1=45.75mm; y1=1.25mm; x2=42.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.6484 { + string=a; x=4.75mm; y=16.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6485 { + string=N2; x=1.75mm; y=1.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6486 { + string=N3; x=7.25mm; y=1.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6538 { + string=b; x=17.75mm; y=16.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6613 { + string=c; x=29.25mm; y=16.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.6732 { + string=d; x=41.25mm; y=16.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + group = 5 + ha:combining { + } + } + ha:annotation { + lid = 3 + li:objects { + } + color = {#cd3700} + group = 6 + ha:combining { + } + } + ha:top-doc { + lid = 4 + li:objects { + } + color = {#548b54} + group = 7 + ha:combining { + } + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_osc.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_osc.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_osc.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_osc.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_osc.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_spiral.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_spiral.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_spiral.lht (revision 1402) @@ -0,0 +1,292 @@ +ha:pcb-rnd-board-v7 { + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 17.5mm + y = 22.25mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + ha:layer_stack { + li:groups { + ha:0 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_4 + } + ha:1 { + ha:attributes { + thickness = {0.125mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_6 + } + ha:2 { + ha:attributes { + thickness = {0.7375mm } + } + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_8 + } + ha:3 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 0 + } + name = top-doc + } + ha:4 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 1 + } + name = top-doc + } + ha:5 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 2 + } + name = top-doc + } + ha:6 { + ha:attributes { + init-invis = 0 + } + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 3 + } + name = top-doc + } + ha:7 { + purpose = fab + ha:type { + top = 1 + doc = 1 + } + li:layers { + 4 + } + name = top-doc + } + } + } + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 1.5mm + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 0.9mm + clearance = 25.0mil + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + wireframe_draw = false + grid_unit = mm + grids_idx = 10 + grid = 250.00 um + buffer_number = 1 + all_direction_lines = true + } + } + } + ha:data { + li:padstack_prototypes { + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + unused = 1 + } + li:objects { + } + li:layers { + ha:draft { + lid = 0 + li:objects { + ha:arc.6460 { + x=10.25mm; y=8.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.6461 { + x=10.25mm; y=20.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + group = 3 + ha:combining { + } + } + ha:ratlines { + lid = 1 + li:objects { + ha:line.6462 { + x1=10.25mm; y1=8.25mm; x2=10.25mm; y2=20.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.6465 { + string=N1; x=10.75mm; y=9.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + group = 4 + ha:combining { + } + } + ha:wires { + lid = 2 + li:objects { + ha:line.6812 { + x1=11.75mm; y1=6.0mm; x2=6.25mm; y2=6.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6815 { + x1=6.25mm; y1=6.0mm; x2=6.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6818 { + x1=6.25mm; y1=13.0mm; x2=16.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6830 { + x1=16.25mm; y1=13.0mm; x2=16.25mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.6833 { + x1=16.25mm; y1=1.0mm; x2=1.0mm; y2=1.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#104e8b} + group = 5 + ha:combining { + } + } + ha:annotation { + lid = 3 + li:objects { + } + color = {#cd3700} + group = 6 + ha:combining { + } + } + ha:top-doc { + lid = 4 + li:objects { + } + color = {#548b54} + group = 7 + ha:combining { + } + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_spiral.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_spiral.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_spiral.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_spiral.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_spiral.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_topo.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_topo.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_topo.lht (revision 1402) @@ -0,0 +1,566 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 86.75mm + y = 38.75mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:arc.785 { + x=2.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.787 { + x=18.0mm; y=4.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.788 { + x=18.0mm; y=34.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.789 { + x=24.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.790 { + x=21.5mm; y=11.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.791 { + x=31.75mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.792 { + x=53.75mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.793 { + x=51.25mm; y=11.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.794 { + x=47.75mm; y=4.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.795 { + x=47.75mm; y=34.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.796 { + x=61.25mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.797 { + x=77.25mm; y=34.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.798 { + x=83.25mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.800 { + x=80.75mm; y=11.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.801 { + x=77.25mm; y=4.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.302 { + string={#1}; x=16.0mm; y=14.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.554 { + string={#2}; x=52.0mm; y=8.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.722 { + string={#3}; x=53.75mm; y=12.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.281 { + x1=18.0mm; y1=4.0mm; x2=18.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.284 { + x1=2.0mm; y1=17.0mm; x2=24.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.559 { + x1=47.75mm; y1=4.0mm; x2=55.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.562 { + x1=55.5mm; y1=16.75mm; x2=55.5mm; y2=17.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.565 { + x1=55.5mm; y1=17.5mm; x2=47.75mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.614 { + x1=61.25mm; y1=17.0mm; x2=83.25mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.620 { + x1=85.0mm; y1=16.75mm; x2=85.0mm; y2=17.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.623 { + x1=85.0mm; y1=17.5mm; x2=77.25mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.640 { + x1=85.0mm; y1=16.75mm; x2=78.5mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.643 { + x1=78.5mm; y1=12.0mm; x2=77.25mm; y2=4.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.305 { + string=N1; x=16.0mm; y=8.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.306 { + string=N2; x=10.5mm; y=18.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.568 { + string=N1; x=54.25mm; y=21.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.569 { + string=N2; x=40.25mm; y=18.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.626 { + string=N1; x=83.75mm; y=21.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.627 { + string=N2; x=69.75mm; y=18.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.348 { + x1=21.5mm; y1=11.75mm; x2=21.5mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.351 { + x1=21.5mm; y1=11.75mm; x2=26.25mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.570 { + x1=51.25mm; y1=11.75mm; x2=51.25mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.573 { + x1=51.25mm; y1=11.75mm; x2=56.0mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.628 { + x1=80.75mm; y1=11.75mm; x2=80.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.631 { + x1=80.75mm; y1=11.75mm; x2=85.5mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.311 { + string=a; x=14.5mm; y=35.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.313 { + string=b; x=42.75mm; y=35.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.315 { + string=c; x=71.25mm; y=35.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.864 { + string=N3; x=22.0mm; y=1.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.866 { + string=N3; x=51.75mm; y=1.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.867 { + string=N3; x=81.25mm; y=1.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.646 { + x1=53.75mm; y1=17.0mm; x2=31.75mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.649 { + x1=33.0mm; y1=17.0mm; x2=31.75mm; y2=15.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.652 { + x1=31.75mm; y1=15.75mm; x2=30.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.673 { + x1=33.0mm; y1=17.0mm; x2=31.75mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.676 { + x1=31.75mm; y1=18.25mm; x2=30.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.691 { + x1=55.0mm; y1=17.0mm; x2=53.75mm; y2=15.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.694 { + x1=53.75mm; y1=15.75mm; x2=52.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.697 { + x1=55.0mm; y1=17.0mm; x2=53.75mm; y2=18.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.700 { + x1=53.75mm; y1=18.25mm; x2=52.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.703 { + x1=82.0mm; y1=11.75mm; x2=80.75mm; y2=10.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.706 { + x1=80.75mm; y1=10.5mm; x2=79.5mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.709 { + x1=82.0mm; y1=11.75mm; x2=80.75mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.712 { + x1=80.75mm; y1=13.0mm; x2=79.5mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.715 { + x1=80.75mm; y1=10.5mm; x2=80.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.718 { + x1=82.0mm; y1=11.75mm; x2=85.5mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_topo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_topo.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_topo.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_topo.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_topo.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/ex_zigzag.lht =================================================================== --- tags/0.9.0/doc/detour/img/ex_zigzag.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_zigzag.lht (revision 1402) @@ -0,0 +1,952 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 57.5mm + y = 25.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.4573 { + x1=24.25mm; y1=4.0mm; x2=24.25mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4576 { + x1=23.25mm; y1=5.0mm; x2=25.25mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4579 { + x1=24.957107mm; y1=4.292893mm; x2=23.542893mm; y2=5.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4582 { + x1=23.542893mm; y1=4.292893mm; x2=24.957107mm; y2=5.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4585 { + x1=24.25mm; y1=12.0mm; x2=24.25mm; y2=14.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4588 { + x1=23.25mm; y1=13.0mm; x2=25.25mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4591 { + x1=24.957107mm; y1=12.292893mm; x2=23.542893mm; y2=13.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4594 { + x1=23.542893mm; y1=12.292893mm; x2=24.957107mm; y2=13.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4765 { + x1=33.5mm; y1=7.75mm; x2=33.5mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4768 { + x1=32.5mm; y1=8.75mm; x2=34.5mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4771 { + x1=34.207107mm; y1=316.64933071mil; x2=32.792893mm; y2=9.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4774 { + x1=32.792893mm; y1=316.64933071mil; x2=34.207107mm; y2=9.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4777 { + x1=33.5mm; y1=15.75mm; x2=33.5mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4780 { + x1=32.5mm; y1=16.75mm; x2=34.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4783 { + x1=34.207107mm; y1=16.042893mm; x2=32.792893mm; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4786 { + x1=32.792893mm; y1=16.042893mm; x2=34.207107mm; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5014 { + x1=41.5mm; y1=7.75mm; x2=41.5mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5017 { + x1=40.5mm; y1=8.75mm; x2=42.5mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5020 { + x1=42.207107mm; y1=316.64933071mil; x2=1.60601941in; y2=9.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5023 { + x1=1.60601941in; y1=316.64933071mil; x2=42.207107mm; y2=9.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5026 { + x1=41.5mm; y1=15.75mm; x2=41.5mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5029 { + x1=40.5mm; y1=16.75mm; x2=42.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5032 { + x1=42.207107mm; y1=16.042893mm; x2=1.60601941in; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5035 { + x1=1.60601941in; y1=16.042893mm; x2=42.207107mm; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5158 { + x1=53.0mm; y1=4.25mm; x2=53.0mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5161 { + x1=52.0mm; y1=5.25mm; x2=54.0mm; y2=5.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5164 { + x1=53.707107mm; y1=4.542893mm; x2=52.292893mm; y2=5.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5167 { + x1=52.292893mm; y1=4.542893mm; x2=53.707107mm; y2=5.957107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5368 { + x=6.75mm; y=2.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5369 { + x=6.75mm; y=20.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5372 { + x=21.75mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5373 { + x=21.75mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5374 { + x=35.75mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5375 { + x=35.75mm; y=20.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5376 { + x=50.5mm; y=2.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5377 { + x=50.5mm; y=20.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.4979 { + string=P1; x=9.75mm; y=4.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.4983 { + string=P3; x=9.75mm; y=12.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.4988 { + string=P2; x=2.5mm; y=8.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.4989 { + string=P4; x=2.5mm; y=16.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.4285 { + x1=6.75mm; y1=2.5mm; x2=6.75mm; y2=20.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4597 { + x1=21.75mm; y1=2.0mm; x2=24.957107mm; y2=4.292893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4600 { + x1=24.957107mm; y1=4.292893mm; x2=25.25mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4603 { + x1=25.25mm; y1=5.0mm; x2=25.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4606 { + x1=25.25mm; y1=13.0mm; x2=24.957107mm; y2=13.707107mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4609 { + x1=24.957107mm; y1=13.707107mm; x2=21.75mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4717 { + x1=35.75mm; y1=2.0mm; x2=38.957107mm; y2=4.292893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4720 { + x1=38.957107mm; y1=4.292893mm; x2=39.25mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4726 { + x1=39.25mm; y1=13.0mm; x2=38.957107mm; y2=13.707107mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4729 { + x1=38.957107mm; y1=13.707107mm; x2=35.75mm; y2=20.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4789 { + x1=32.792893mm; y1=316.64933071mil; x2=39.25mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4792 { + x1=32.792893mm; y1=9.457107mm; x2=39.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4795 { + x1=32.792893mm; y1=9.457107mm; x2=32.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4798 { + x1=32.5mm; y1=8.75mm; x2=32.75mm; y2=8.063106mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4894 { + x1=50.5mm; y1=2.25mm; x2=53.707107mm; y2=4.542893mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4897 { + x1=53.707107mm; y1=4.542893mm; x2=54.0mm; y2=5.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4900 { + x1=54.0mm; y1=13.25mm; x2=53.707107mm; y2=13.957107mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4903 { + x1=53.707107mm; y1=13.957107mm; x2=50.5mm; y2=20.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4909 { + x1=47.542893mm; y1=9.707107mm; x2=54.0mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4912 { + x1=47.542893mm; y1=9.707107mm; x2=47.25mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4915 { + x1=47.25mm; y1=9.0mm; x2=47.5mm; y2=8.313106mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4963 { + x1=54.0mm; y1=5.25mm; x2=53.707107mm; y2=5.957107mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4969 { + x1=53.707107mm; y1=5.957107mm; x2=53.0mm; y2=6.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4972 { + x1=53.0mm; y1=6.25mm; x2=47.5mm; y2=8.313106mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.4309 { + string=N1; x=8.25mm; y=2.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.4288 { + x1=9.25mm; y1=5.5mm; x2=1.25mm; y2=5.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4291 { + x1=1.25mm; y1=5.5mm; x2=1.25mm; y2=13.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4294 { + x1=1.25mm; y1=13.5mm; x2=9.25mm; y2=13.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4297 { + x1=4.5mm; y1=17.25mm; x2=12.5mm; y2=17.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4300 { + x1=12.5mm; y1=9.25mm; x2=12.5mm; y2=17.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4303 { + x1=4.5mm; y1=9.25mm; x2=12.5mm; y2=9.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4612 { + x1=24.25mm; y1=5.0mm; x2=16.25mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4615 { + x1=16.25mm; y1=5.0mm; x2=16.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4618 { + x1=16.25mm; y1=13.0mm; x2=24.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4621 { + x1=19.5mm; y1=16.75mm; x2=27.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4624 { + x1=27.5mm; y1=8.75mm; x2=27.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4627 { + x1=19.5mm; y1=8.75mm; x2=27.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4732 { + x1=38.25mm; y1=5.0mm; x2=30.25mm; y2=5.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4735 { + x1=30.25mm; y1=5.0mm; x2=30.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4738 { + x1=30.25mm; y1=13.0mm; x2=38.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4741 { + x1=33.5mm; y1=16.75mm; x2=41.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4744 { + x1=41.5mm; y1=8.75mm; x2=41.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4747 { + x1=33.5mm; y1=8.75mm; x2=41.5mm; y2=8.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4918 { + x1=53.0mm; y1=5.25mm; x2=45.0mm; y2=5.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4921 { + x1=45.0mm; y1=5.25mm; x2=45.0mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4924 { + x1=45.0mm; y1=13.25mm; x2=53.0mm; y2=13.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4927 { + x1=48.25mm; y1=17.0mm; x2=56.25mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4930 { + x1=56.25mm; y1=9.0mm; x2=56.25mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4933 { + x1=48.25mm; y1=9.0mm; x2=56.25mm; y2=9.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.4306 { + string=a; x=6.25mm; y=22.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4310 { + string=N2; x=2.0mm; y=3.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4311 { + string=N3; x=10.5mm; y=7.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4630 { + string=b; x=21.25mm; y=21.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4750 { + string=c; x=35.25mm; y=21.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4936 { + string=d; x=50.0mm; y=22.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=8 + ha:combining { } + + li:objects { + ha:line.5038 { + x1=32.5mm; y1=16.75mm; x2=32.5mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5041 { + x1=32.5mm; y1=8.75mm; x2=32.792893mm; y2=316.64933071mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5044 { + x1=32.792893mm; y1=316.64933071mil; x2=33.5mm; y2=7.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5047 { + x1=33.5mm; y1=7.75mm; x2=41.5mm; y2=7.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5050 { + x1=41.5mm; y1=7.75mm; x2=42.207107mm; y2=316.64933071mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5053 { + x1=42.207107mm; y1=316.64933071mil; x2=42.5mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5056 { + x1=42.5mm; y1=8.75mm; x2=42.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5059 { + x1=42.5mm; y1=16.75mm; x2=42.207107mm; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5062 { + x1=42.207107mm; y1=17.457107mm; x2=41.5mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5065 { + x1=41.5mm; y1=17.75mm; x2=33.5mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5068 { + x1=33.5mm; y1=17.75mm; x2=32.792893mm; y2=17.457107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5071 { + x1=32.792893mm; y1=17.457107mm; x2=32.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5110 { + x1=15.25mm; y1=13.0mm; x2=15.25mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5113 { + x1=15.25mm; y1=5.0mm; x2=15.542893mm; y2=4.292893mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5116 { + x1=15.542893mm; y1=4.292893mm; x2=16.25mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5119 { + x1=16.25mm; y1=4.0mm; x2=24.25mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5122 { + x1=24.25mm; y1=4.0mm; x2=24.957107mm; y2=4.292893mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5125 { + x1=24.957107mm; y1=4.292893mm; x2=25.25mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5128 { + x1=25.25mm; y1=5.0mm; x2=25.25mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5131 { + x1=25.25mm; y1=13.0mm; x2=24.957107mm; y2=13.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5134 { + x1=24.957107mm; y1=13.707107mm; x2=24.25mm; y2=14.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5137 { + x1=24.25mm; y1=14.0mm; x2=16.25mm; y2=14.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5140 { + x1=16.25mm; y1=14.0mm; x2=15.542893mm; y2=13.707107mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5143 { + x1=15.542893mm; y1=13.707107mm; x2=15.25mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=6 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + + ha:N3 { + lid=5 + group=7 + ha:combining { } + + li:objects { + } + color = {#000000} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 5; } + purpose = fab + } + ha:8 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/ex_zigzag.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/ex_zigzag.png =================================================================== --- tags/0.9.0/doc/detour/img/ex_zigzag.png (nonexistent) +++ tags/0.9.0/doc/detour/img/ex_zigzag.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/ex_zigzag.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_cases.dot =================================================================== --- tags/0.9.0/doc/detour/img/geo_cases.dot (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_cases.dot (revision 1402) @@ -0,0 +1,34 @@ +digraph cases { + + conflict [shape=square] + switch [label="switch\nlayer" shape=square] + stay [label="stay on\nlayer" shape=square] + + via0 [label="V1\nno new vias,\nswitch on\nendpoints"] + via1 [label="V2\none new via,\nswitch on\n1 endpoint"] + via2 [label="V3\ntwo\nnew\nvias"] + + in0 [label="both ends\noutside" shape=square] + in1 [label="one end\noutside" shape=square] + in2 [label="both ends\ninside" shape=square] + + cross0 [label="S1\ncrossing\nor too\nclose to\nobstacle\nCW or CCW"] + cross1 [label="S2\ncrossing\nobstacle\nCW or CCW"] + cross2 [label="S3\ncrossing\nor too\nclose to\nobstacle\n"] + + + conflict -> switch + conflict -> stay + + switch -> via0 + switch -> via1 + switch -> via2 + + stay -> in0 + stay -> in1 + stay -> in2 + + in0 -> cross0 + in1 -> cross1 + in2 -> cross2 +} Index: tags/0.9.0/doc/detour/img/geo_cases.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_cases.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_cases.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_cases.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_cases.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_go_around.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_go_around.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_go_around.lht (revision 1402) @@ -0,0 +1,744 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 52.5mm + y = 26.25mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + ha:triangulation { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.605 { + x1=19.75mm; y1=5.5mm; x2=19.75mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.608 { + x1=17.25mm; y1=8.0mm; x2=22.25mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.617 { + x1=17.982233mm; y1=6.232233mm; x2=847.1561811mil; y2=384.55775591mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.620 { + x1=17.982233mm; y1=384.55775591mil; x2=847.1561811mil; y2=6.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.635 { + x1=31.25mm; y1=10.5mm; x2=31.25mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.641 { + x1=29.482233mm; y1=11.232233mm; x2=33.017767mm; y2=581.40814961mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.644 { + x1=29.482233mm; y1=581.40814961mil; x2=33.017767mm; y2=11.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.650 { + x1=27.25mm; y1=8.0mm; x2=32.25mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.653 { + x1=27.982233mm; y1=6.232233mm; x2=31.517767mm; y2=384.55775591mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.656 { + x1=27.982233mm; y1=384.55775591mil; x2=31.517767mm; y2=6.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.659 { + x1=29.75mm; y1=5.5mm; x2=29.75mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.662 { + x1=33.75mm; y1=13.0mm; x2=27.25mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.665 { + x1=27.982233mm; y1=11.232233mm; x2=31.517767mm; y2=581.40814961mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.668 { + x1=27.982233mm; y1=581.40814961mil; x2=31.517767mm; y2=11.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.745 { + x1=37.5mm; y1=5.5mm; x2=37.5mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.748 { + x1=35.0mm; y1=8.0mm; x2=40.0mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.751 { + x1=35.732233mm; y1=6.232233mm; x2=39.267767mm; y2=384.55775591mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.754 { + x1=35.732233mm; y1=384.55775591mil; x2=39.267767mm; y2=6.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.757 { + x1=49.0mm; y1=10.5mm; x2=49.0mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.760 { + x1=47.232233mm; y1=11.232233mm; x2=50.767767mm; y2=581.40814961mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.763 { + x1=47.232233mm; y1=581.40814961mil; x2=50.767767mm; y2=11.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.766 { + x1=45.0mm; y1=8.0mm; x2=50.0mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.769 { + x1=45.732233mm; y1=6.232233mm; x2=49.267767mm; y2=384.55775591mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.772 { + x1=45.732233mm; y1=384.55775591mil; x2=49.267767mm; y2=6.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.775 { + x1=47.5mm; y1=5.5mm; x2=47.5mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.778 { + x1=51.5mm; y1=13.0mm; x2=45.0mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.781 { + x1=45.732233mm; y1=11.232233mm; x2=49.267767mm; y2=581.40814961mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.784 { + x1=45.732233mm; y1=581.40814961mil; x2=49.267767mm; y2=11.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4685 { + x=2.5mm; y=8.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=8.0mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=8.0mm; y=21.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=14.0mm; y=13.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4693 { + x=19.75mm; y=8.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=25.25mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=25.25mm; y=21.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=31.25mm; y=13.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=37.5mm; y=8.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=43.0mm; y=2.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=43.0mm; y=21.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=49.0mm; y=13.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.415 { + x1=8.0mm; y1=2.0mm; x2=13.5mm; y2=7.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.418 { + x1=13.5mm; y1=7.5mm; x2=15.75mm; y2=12.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.421 { + x1=15.75mm; y1=12.75mm; x2=15.25mm; y2=15.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.424 { + x1=15.25mm; y1=15.0mm; x2=8.0mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.427 { + x1=8.0mm; y1=2.0mm; x2=8.0mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.430 { + x1=8.0mm; y1=5.0mm; x2=8.0mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.433 { + x1=8.0mm; y1=7.5mm; x2=8.0mm; y2=9.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.436 { + x1=8.0mm; y1=11.5mm; x2=8.0mm; y2=13.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.442 { + x1=8.0mm; y1=15.25mm; x2=8.0mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.445 { + x1=8.0mm; y1=19.0mm; x2=8.0mm; y2=21.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.456 { + x1=8.0mm; y1=2.0mm; x2=1.25mm; y2=6.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.459 { + x1=1.25mm; y1=6.75mm; x2=0.75mm; y2=8.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.462 { + x1=0.75mm; y1=8.5mm; x2=1.25mm; y2=10.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.465 { + x1=1.25mm; y1=10.25mm; x2=8.0mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.551 { + x1=25.25mm; y1=2.0mm; x2=25.25mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.554 { + x1=25.25mm; y1=5.0mm; x2=25.25mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.557 { + x1=25.25mm; y1=7.5mm; x2=25.25mm; y2=9.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.560 { + x1=25.25mm; y1=11.5mm; x2=25.25mm; y2=13.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.563 { + x1=25.25mm; y1=15.25mm; x2=25.25mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.566 { + x1=25.25mm; y1=19.0mm; x2=25.25mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.787 { + x1=43.0mm; y1=2.0mm; x2=43.0mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.790 { + x1=43.0mm; y1=5.0mm; x2=43.0mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.793 { + x1=43.0mm; y1=7.5mm; x2=43.0mm; y2=9.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.796 { + x1=43.0mm; y1=11.5mm; x2=43.0mm; y2=13.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.799 { + x1=43.0mm; y1=15.25mm; x2=43.0mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.802 { + x1=43.0mm; y1=19.0mm; x2=43.0mm; y2=21.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.468 { + string=D1; x=2.5mm; y=3.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.469 { + string=D2; x=12.5mm; y=4.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.470 { + x1=2.5mm; y1=8.0mm; x2=12.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.476 { + x1=12.5mm; y1=8.0mm; x2=12.5mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.479 { + x1=12.5mm; y1=13.0mm; x2=14.0mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.583 { + x1=19.75mm; y1=8.0mm; x2=29.75mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.586 { + x1=29.75mm; y1=8.0mm; x2=29.75mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.589 { + x1=29.75mm; y1=13.0mm; x2=31.25mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.805 { + x1=37.5mm; y1=8.0mm; x2=47.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.808 { + x1=47.5mm; y1=8.0mm; x2=47.5mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.811 { + x1=47.5mm; y1=13.0mm; x2=49.0mm; y2=13.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.337 { + string=a; x=7.25mm; y=23.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.338 { + string=b; x=24.5mm; y=23.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.814 { + string=c; x=42.25mm; y=23.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.819 { + x1=43.0mm; y1=21.25mm; x2=35.732233mm; y2=384.55775591mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.822 { + x1=35.732233mm; y1=384.55775591mil; x2=35.0mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.828 { + x1=35.0mm; y1=8.0mm; x2=35.732233mm; y2=6.232233mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.831 { + x1=35.732233mm; y1=6.232233mm; x2=43.0mm; y2=2.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.834 { + x1=43.0mm; y1=2.0mm; x2=49.25mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.846 { + x1=49.25mm; y1=6.25mm; x2=50.0mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.849 { + x1=50.0mm; y1=8.0mm; x2=51.5mm; y2=13.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.852 { + x1=51.5mm; y1=13.0mm; x2=50.767767mm; y2=581.40814961mil; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.855 { + x1=50.767767mm; y1=581.40814961mil; x2=43.0mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.860 { + string=D1; x=37.0mm; y=2.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.861 { + string=D2; x=47.5mm; y=3.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_go_around.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_go_around.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_go_around.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_go_around.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_go_around.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_hcross.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_hcross.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hcross.lht (revision 1402) @@ -0,0 +1,789 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 86.5mm + y = 40.75mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.1378 { + x1=53.25mm; y1=19.0mm; x2=55.0mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1381 { + x1=53.25mm; y1=19.0mm; x2=55.0mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1384 { + x1=53.25mm; y1=19.0mm; x2=55.75mm; y2=19.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1387 { + x1=53.25mm; y1=16.5mm; x2=53.25mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1417 { + x1=80.25mm; y1=13.75mm; x2=78.75mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1420 { + x1=77.75mm; y1=13.75mm; x2=80.25mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1423 { + x1=80.25mm; y1=11.25mm; x2=80.25mm; y2=16.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1426 { + x1=78.5mm; y1=12.0mm; x2=82.0mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1456 { + x1=82.75mm; y1=19.0mm; x2=84.5mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1459 { + x1=82.75mm; y1=19.0mm; x2=84.5mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1462 { + x1=82.75mm; y1=19.0mm; x2=85.25mm; y2=19.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1465 { + x1=82.75mm; y1=16.5mm; x2=82.75mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1510 { + x1=24.0mm; y1=19.0mm; x2=25.75mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1513 { + x1=24.0mm; y1=19.0mm; x2=25.75mm; y2=20.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1516 { + x1=24.0mm; y1=19.0mm; x2=26.5mm; y2=19.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1519 { + x1=24.0mm; y1=16.5mm; x2=24.0mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1669 { + x1=50.75mm; y1=11.25mm; x2=50.75mm; y2=16.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1672 { + x1=49.0mm; y1=12.0mm; x2=52.5mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1678 { + x1=49.25mm; y1=15.25mm; x2=52.25mm; y2=12.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1696 { + x1=50.75mm; y1=0.75mm; x2=50.75mm; y2=5.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1699 { + x1=49.0mm; y1=1.5mm; x2=52.5mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1702 { + x1=49.25mm; y1=4.75mm; x2=52.25mm; y2=1.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1735 { + x1=48.25mm; y1=3.25mm; x2=53.25mm; y2=3.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1803 { + x1=55.5mm; y1=11.25mm; x2=55.5mm; y2=16.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1806 { + x1=53.75mm; y1=12.0mm; x2=57.25mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1809 { + x1=54.0mm; y1=15.25mm; x2=57.0mm; y2=12.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1812 { + x1=48.25mm; y1=13.75mm; x2=58.0mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=21.5mm; y=13.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4685 { + x=24.0mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=2.0mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=18.0mm; y=36.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=18.0mm; y=6.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=50.75mm; y=13.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=53.25mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=31.25mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=47.25mm; y=36.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=47.25mm; y=6.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=80.25mm; y=13.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=82.75mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=60.75mm; y=19.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=76.75mm; y=36.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4703 { + x=76.75mm; y=6.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.614 { + x1=60.75mm; y1=19.0mm; x2=82.75mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.643 { + x1=77.75mm; y1=13.75mm; x2=76.75mm; y2=6.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1084 { + x1=77.75mm; y1=13.75mm; x2=78.75mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1429 { + x1=78.75mm; y1=15.25mm; x2=80.25mm; y2=16.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1486 { + x1=84.5mm; y1=17.25mm; x2=85.25mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1489 { + x1=76.75mm; y1=36.0mm; x2=84.5mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1492 { + x1=84.5mm; y1=20.75mm; x2=85.25mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1522 { + x1=18.0mm; y1=6.0mm; x2=25.75mm; y2=17.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1525 { + x1=25.75mm; y1=17.25mm; x2=26.5mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1528 { + x1=26.5mm; y1=19.0mm; x2=25.75mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1531 { + x1=25.75mm; y1=20.75mm; x2=18.0mm; y2=36.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1546 { + x1=47.25mm; y1=6.0mm; x2=55.0mm; y2=17.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1549 { + x1=55.0mm; y1=17.25mm; x2=55.75mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1552 { + x1=55.75mm; y1=19.0mm; x2=55.0mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1555 { + x1=55.0mm; y1=20.75mm; x2=47.25mm; y2=36.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1758 { + x1=18.0mm; y1=6.0mm; x2=18.0mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1761 { + x1=18.0mm; y1=11.75mm; x2=18.0mm; y2=14.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1764 { + x1=18.0mm; y1=18.0mm; x2=18.0mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1767 { + x1=18.0mm; y1=24.25mm; x2=18.0mm; y2=27.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1770 { + x1=18.0mm; y1=36.0mm; x2=18.0mm; y2=32.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1851 { + x1=80.25mm; y1=16.25mm; x2=84.5mm; y2=17.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.2044 { + string=N1; x=16.5mm; y=8.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.981 { + x1=21.5mm; y1=13.75mm; x2=21.5mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.984 { + x1=21.5mm; y1=13.75mm; x2=26.25mm; y2=13.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1326 { + x1=2.0mm; y1=19.0mm; x2=24.0mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.570 { + x1=50.75mm; y1=13.75mm; x2=50.75mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.628 { + x1=80.25mm; y1=13.75mm; x2=80.25mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1648 { + x1=31.25mm; y1=19.0mm; x2=53.25mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1776 { + x1=50.75mm; y1=13.75mm; x2=55.5mm; y2=13.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1836 { + x1=80.25mm; y1=13.75mm; x2=85.0mm; y2=13.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.313 { + string=b; x=42.25mm; y=37.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.315 { + string=c; x=70.75mm; y=37.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.987 { + string=a; x=13.0mm; y=37.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.2043 { + string=N2; x=5.0mm; y=17.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.2045 { + string=N3; x=22.5mm; y=4.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.1714 { + x1=47.25mm; y1=6.0mm; x2=48.25mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1717 { + x1=48.25mm; y1=13.75mm; x2=49.25mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1720 { + x1=49.25mm; y1=15.25mm; x2=50.75mm; y2=16.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1741 { + x1=53.25mm; y1=3.25mm; x2=52.25mm; y2=1.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1744 { + x1=52.25mm; y1=1.75mm; x2=50.75mm; y2=0.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1747 { + x1=50.75mm; y1=0.75mm; x2=49.0mm; y2=1.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1750 { + x1=49.0mm; y1=1.5mm; x2=48.25mm; y2=3.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1753 { + x1=48.25mm; y1=3.25mm; x2=47.25mm; y2=6.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1821 { + x1=57.25mm; y1=15.5mm; x2=58.0mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1830 { + x1=53.25mm; y1=3.25mm; x2=58.0mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1883 { + x1=82.25mm; y1=16.0mm; x2=82.25mm; y2=17.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1886 { + x1=82.25mm; y1=17.0mm; x2=83.25mm; y2=17.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1889 { + x1=83.25mm; y1=17.0mm; x2=83.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1892 { + x1=83.25mm; y1=16.0mm; x2=82.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2037 { + x1=50.75mm; y1=16.25mm; x2=55.0mm; y2=17.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2040 { + x1=55.0mm; y1=17.25mm; x2=57.25mm; y2=15.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1856 { + x=55.0mm; y=17.25mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1858 { + x=84.5mm; y=17.25mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.2047 { + x=25.75mm; y=17.25mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.1756 { + string=D1; x=46.5mm; y=11.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1757 { + string=D2; x=55.5mm; y=6.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_hcross.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_hcross.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_hcross.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hcross.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_hcross.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_hnear.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_hnear.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hnear.lht (revision 1402) @@ -0,0 +1,710 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 86.75mm + y = 38.75mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.1510 { + x1=24.5mm; y1=17.0mm; x2=26.25mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1513 { + x1=24.5mm; y1=17.0mm; x2=26.25mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1516 { + x1=24.5mm; y1=17.0mm; x2=27.0mm; y2=17.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1519 { + x1=24.5mm; y1=14.5mm; x2=24.5mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1712 { + x1=54.0mm; y1=17.0mm; x2=55.75mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1715 { + x1=54.0mm; y1=17.0mm; x2=55.75mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1718 { + x1=54.0mm; y1=17.0mm; x2=56.5mm; y2=17.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1721 { + x1=54.0mm; y1=14.5mm; x2=54.0mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1786 { + x1=51.5mm; y1=5.5mm; x2=51.5mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1831 { + x1=52.0mm; y1=11.75mm; x2=55.5mm; y2=8.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1834 { + x1=52.0mm; y1=8.25mm; x2=55.5mm; y2=11.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1840 { + x1=51.25mm; y1=10.0mm; x2=56.25mm; y2=10.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1858 { + x1=49.75mm; y1=6.25mm; x2=53.25mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1861 { + x1=49.75mm; y1=9.75mm; x2=53.25mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2170 { + x1=83.5mm; y1=17.0mm; x2=85.25mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2173 { + x1=83.5mm; y1=17.0mm; x2=85.25mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2176 { + x1=83.5mm; y1=17.0mm; x2=86.0mm; y2=17.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2179 { + x1=83.5mm; y1=14.5mm; x2=83.5mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2188 { + x1=83.25mm; y1=7.5mm; x2=83.25mm; y2=12.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2191 { + x1=81.5mm; y1=11.75mm; x2=85.0mm; y2=8.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2194 { + x1=81.5mm; y1=8.25mm; x2=85.0mm; y2=11.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2197 { + x1=80.75mm; y1=10.0mm; x2=85.75mm; y2=10.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2185 { + x1=81.0mm; y1=5.5mm; x2=81.0mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2182 { + x1=78.5mm; y1=8.0mm; x2=81.0mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2200 { + x1=79.25mm; y1=6.25mm; x2=82.75mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2203 { + x1=79.25mm; y1=9.75mm; x2=82.75mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2283 { + x1=53.75mm; y1=12.5mm; x2=53.75mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2286 { + x1=52.0mm; y1=9.75mm; x2=55.5mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2289 { + x1=52.0mm; y1=6.25mm; x2=55.5mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2292 { + x1=49.0mm; y1=8.0mm; x2=56.25mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=24.25mm; y=10.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4685 { + x=18.5mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=24.5mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=18.5mm; y=34.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=2.5mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=53.75mm; y=10.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=48.0mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=54.0mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=48.0mm; y=34.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=32.0mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=83.25mm; y=10.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=77.5mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=83.5mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=77.5mm; y=34.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4703 { + x=61.5mm; y=17.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.1522 { + x1=18.5mm; y1=4.0mm; x2=26.25mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1525 { + x1=26.25mm; y1=15.25mm; x2=27.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1528 { + x1=27.0mm; y1=17.0mm; x2=26.25mm; y2=18.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1531 { + x1=26.25mm; y1=18.75mm; x2=18.5mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1727 { + x1=55.75mm; y1=15.25mm; x2=56.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1730 { + x1=56.5mm; y1=17.0mm; x2=55.75mm; y2=18.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1733 { + x1=55.75mm; y1=18.75mm; x2=48.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1724 { + x1=48.0mm; y1=4.0mm; x2=55.75mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2206 { + x1=85.25mm; y1=15.25mm; x2=86.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2209 { + x1=86.0mm; y1=17.0mm; x2=85.25mm; y2=18.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2212 { + x1=85.25mm; y1=18.75mm; x2=77.5mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2259 { + x1=77.5mm; y1=4.0mm; x2=78.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2262 { + x1=78.5mm; y1=8.0mm; x2=79.25mm; y2=9.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2265 { + x1=79.25mm; y1=9.75mm; x2=81.5mm; y2=11.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2268 { + x1=81.5mm; y1=11.75mm; x2=85.25mm; y2=15.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2310 { + x1=18.5mm; y1=4.0mm; x2=18.5mm; y2=9.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2313 { + x1=18.5mm; y1=15.75mm; x2=18.5mm; y2=18.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2316 { + x1=18.5mm; y1=34.0mm; x2=18.5mm; y2=30.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2319 { + x1=18.5mm; y1=25.5mm; x2=18.5mm; y2=24.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2322 { + x1=18.5mm; y1=12.75mm; x2=18.5mm; y2=11.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.1326 { + x1=2.5mm; y1=17.0mm; x2=24.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1662 { + x1=24.25mm; y1=10.0mm; x2=24.25mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1665 { + x1=24.25mm; y1=8.0mm; x2=22.0mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1736 { + x1=32.0mm; y1=17.0mm; x2=54.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1739 { + x1=53.75mm; y1=10.0mm; x2=53.75mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1742 { + x1=53.75mm; y1=8.0mm; x2=51.5mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2218 { + x1=61.5mm; y1=17.0mm; x2=83.5mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2221 { + x1=83.25mm; y1=10.0mm; x2=83.25mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2224 { + x1=83.25mm; y1=8.0mm; x2=81.0mm; y2=8.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.313 { + string=b; x=42.75mm; y=35.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.315 { + string=c; x=71.25mm; y=35.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.987 { + string=a; x=13.5mm; y=35.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.1807 { + x1=49.0mm; y1=8.0mm; x2=49.75mm; y2=9.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1870 { + x1=49.75mm; y1=9.75mm; x2=52.0mm; y2=11.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2066 { + x1=52.0mm; y1=11.75mm; x2=55.75mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2072 { + x1=56.25mm; y1=10.0mm; x2=55.75mm; y2=15.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2075 { + x1=49.0mm; y1=8.0mm; x2=48.0mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2301 { + x1=53.75mm; y1=5.5mm; x2=55.5mm; y2=6.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2304 { + x1=55.5mm; y1=6.25mm; x2=56.25mm; y2=8.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2307 { + x1=56.25mm; y1=8.0mm; x2=56.25mm; y2=10.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2295 { + x1=48.0mm; y1=4.0mm; x2=53.75mm; y2=5.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_hnear.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_hnear.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_hnear.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hnear.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_hnear.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_hpierce.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_hpierce.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hpierce.lht (revision 1402) @@ -0,0 +1,1002 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 90.0mm + y = 41.0mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.1378 { + x1=53.25mm; y1=19.5mm; x2=55.0mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1381 { + x1=53.25mm; y1=19.5mm; x2=55.0mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1384 { + x1=53.25mm; y1=19.5mm; x2=55.75mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1387 { + x1=53.25mm; y1=17.0mm; x2=53.25mm; y2=22.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1510 { + x1=24.0mm; y1=19.5mm; x2=25.75mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1513 { + x1=24.0mm; y1=19.5mm; x2=25.75mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1516 { + x1=24.0mm; y1=19.5mm; x2=26.5mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1519 { + x1=24.0mm; y1=17.0mm; x2=24.0mm; y2=22.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1803 { + x1=55.5mm; y1=11.75mm; x2=55.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1806 { + x1=53.75mm; y1=12.5mm; x2=57.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1809 { + x1=54.0mm; y1=15.75mm; x2=57.0mm; y2=12.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2282 { + x1=45.25mm; y1=0.75mm; x2=45.25mm; y2=5.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2285 { + x1=43.5mm; y1=1.5mm; x2=47.0mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2288 { + x1=43.5mm; y1=5.0mm; x2=46.75mm; y2=1.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2291 { + x1=42.75mm; y1=3.25mm; x2=47.75mm; y2=3.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2336 { + x1=40.5mm; y1=9.5mm; x2=40.5mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2339 { + x1=38.75mm; y1=10.25mm; x2=42.25mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2342 { + x1=38.75mm; y1=13.75mm; x2=42.0mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2345 { + x1=38.0mm; y1=12.0mm; x2=43.0mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2363 { + x1=50.75mm; y1=11.75mm; x2=50.75mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2366 { + x1=49.0mm; y1=12.5mm; x2=52.5mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2369 { + x1=49.0mm; y1=16.0mm; x2=52.25mm; y2=12.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2372 { + x1=48.25mm; y1=14.25mm; x2=53.25mm; y2=14.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3420 { + x1=84.25mm; y1=19.5mm; x2=86.0mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3423 { + x1=84.25mm; y1=19.5mm; x2=86.0mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3426 { + x1=84.25mm; y1=19.5mm; x2=86.75mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3429 { + x1=84.25mm; y1=17.0mm; x2=84.25mm; y2=22.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3432 { + x1=86.5mm; y1=11.75mm; x2=86.5mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3435 { + x1=84.75mm; y1=12.5mm; x2=88.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3438 { + x1=85.0mm; y1=15.75mm; x2=88.0mm; y2=12.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3902 { + x1=86.5mm; y1=14.25mm; x2=89.0mm; y2=14.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4869 { + x1=55.5mm; y1=14.25mm; x2=58.0mm; y2=14.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4942 { + x1=76.25mm; y1=0.75mm; x2=76.25mm; y2=5.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4945 { + x1=74.5mm; y1=1.5mm; x2=78.0mm; y2=5.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4948 { + x1=74.5mm; y1=5.0mm; x2=77.75mm; y2=1.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4951 { + x1=73.75mm; y1=3.25mm; x2=78.5mm; y2=3.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5020 { + x1=71.5mm; y1=9.5mm; x2=71.5mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5023 { + x1=69.75mm; y1=10.25mm; x2=73.25mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5026 { + x1=69.75mm; y1=13.75mm; x2=73.0mm; y2=10.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5029 { + x1=69.0mm; y1=12.0mm; x2=73.75mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4684 { + x=2.0mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4685 { + x=24.0mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4686 { + x=21.5mm; y=14.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4687 { + x=18.0mm; y=6.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4688 { + x=18.0mm; y=36.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4694 { + x=31.25mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4695 { + x=53.25mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4696 { + x=50.75mm; y=14.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4697 { + x=47.25mm; y=6.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4698 { + x=47.25mm; y=36.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4699 { + x=62.25mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4700 { + x=84.25mm; y=19.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4701 { + x=81.75mm; y=14.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4702 { + x=78.25mm; y=6.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.4703 { + x=78.25mm; y=36.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.1522 { + x1=18.0mm; y1=6.5mm; x2=25.75mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1525 { + x1=25.75mm; y1=17.75mm; x2=26.5mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1528 { + x1=26.5mm; y1=19.5mm; x2=25.75mm; y2=21.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1531 { + x1=25.75mm; y1=21.25mm; x2=18.0mm; y2=36.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1546 { + x1=47.25mm; y1=6.5mm; x2=55.0mm; y2=17.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1549 { + x1=55.0mm; y1=17.75mm; x2=55.75mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1552 { + x1=55.75mm; y1=19.5mm; x2=55.0mm; y2=21.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1555 { + x1=55.0mm; y1=21.25mm; x2=47.25mm; y2=36.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1758 { + x1=18.0mm; y1=6.5mm; x2=18.0mm; y2=11.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1761 { + x1=18.0mm; y1=12.25mm; x2=18.0mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1764 { + x1=18.0mm; y1=18.5mm; x2=18.0mm; y2=20.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1767 { + x1=18.0mm; y1=24.75mm; x2=18.0mm; y2=27.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1770 { + x1=18.0mm; y1=36.5mm; x2=18.0mm; y2=32.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3480 { + x1=86.0mm; y1=17.75mm; x2=86.75mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3483 { + x1=86.75mm; y1=19.5mm; x2=86.0mm; y2=21.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3486 { + x1=86.0mm; y1=21.25mm; x2=78.25mm; y2=36.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3563 { + x1=88.0mm; y1=12.75mm; x2=89.0mm; y2=14.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3566 { + x1=89.0mm; y1=14.25mm; x2=88.25mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3569 { + x1=86.0mm; y1=17.75mm; x2=88.25mm; y2=16.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5053 { + x1=85.0mm; y1=9.5mm; x2=88.0mm; y2=12.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5056 { + x1=78.25mm; y1=6.5mm; x2=85.0mm; y2=9.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.2044 { + string=N1; x=16.5mm; y=8.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.1326 { + x1=2.0mm; y1=19.5mm; x2=24.0mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1648 { + x1=31.25mm; y1=19.5mm; x2=53.25mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1776 { + x1=50.75mm; y1=14.25mm; x2=55.5mm; y2=14.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.984 { + x1=21.5mm; y1=14.25mm; x2=26.25mm; y2=14.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2195 { + x1=50.75mm; y1=14.25mm; x2=40.5mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2294 { + x1=40.5mm; y1=12.0mm; x2=45.25mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2303 { + x1=21.5mm; y1=14.25mm; x2=11.25mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2306 { + x1=11.25mm; y1=12.0mm; x2=16.0mm; y2=3.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3489 { + x1=62.25mm; y1=19.5mm; x2=84.25mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3492 { + x1=81.75mm; y1=14.25mm; x2=86.5mm; y2=14.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3495 { + x1=81.75mm; y1=14.25mm; x2=71.5mm; y2=12.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3498 { + x1=71.5mm; y1=12.0mm; x2=76.25mm; y2=3.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.313 { + string=b; x=42.25mm; y=37.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.987 { + string=a; x=13.0mm; y=37.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.2043 { + string=N2; x=5.0mm; y=17.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.2045 { + string=N3; x=22.5mm; y=5.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3501 { + string=c; x=73.25mm; y=37.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.1821 { + x1=57.25mm; y1=16.0mm; x2=58.0mm; y2=14.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2037 { + x1=50.75mm; y1=16.75mm; x2=55.0mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2040 { + x1=55.0mm; y1=17.75mm; x2=57.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2309 { + x1=58.0mm; y1=14.25mm; x2=57.0mm; y2=12.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2315 { + x1=46.75mm; y1=1.75mm; x2=45.25mm; y2=0.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2318 { + x1=45.25mm; y1=0.75mm; x2=43.5mm; y2=1.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2348 { + x1=43.5mm; y1=1.5mm; x2=38.75mm; y2=10.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2351 { + x1=38.75mm; y1=10.25mm; x2=38.0mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2354 { + x1=38.0mm; y1=12.0mm; x2=38.75mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2357 { + x1=38.75mm; y1=13.75mm; x2=40.5mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2360 { + x1=40.5mm; y1=14.5mm; x2=50.75mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.2312 { + x1=57.0mm; y1=12.75mm; x2=46.75mm; y2=1.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4978 { + x1=81.75mm; y1=16.75mm; x2=86.0mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4981 { + x1=74.5mm; y1=1.5mm; x2=69.75mm; y2=10.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4984 { + x1=69.75mm; y1=10.25mm; x2=69.0mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4987 { + x1=69.0mm; y1=12.0mm; x2=69.75mm; y2=13.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4990 { + x1=69.75mm; y1=13.75mm; x2=71.5mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4993 { + x1=71.5mm; y1=14.5mm; x2=81.75mm; y2=16.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4996 { + x1=76.25mm; y1=0.75mm; x2=74.5mm; y2=1.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4999 { + x1=77.75mm; y1=1.75mm; x2=76.25mm; y2=0.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5047 { + x1=77.75mm; y1=1.75mm; x2=79.2mm; y2=3.3mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5050 { + x1=79.2mm; y1=3.3mm; x2=78.25mm; y2=6.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1856 { + x=55.0mm; y=17.75mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.2047 { + x=25.75mm; y=17.75mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.3538 { + x=86.0mm; y=17.75mm; width=0.5mm; height=0.5mm; astart=0.000000; adelta=360.000000; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=7 + ha:combining { } + + li:objects { + ha:line.3174 { + x1=47.25mm; y1=6.5mm; x2=54.0mm; y2=9.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5032 { + x1=47.25mm; y1=6.5mm; x2=48.2mm; y2=3.3mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.3177 { + string=TODO!!; x=52.25mm; y=4.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4864 { + string=P1; x=54.85mm; y=8.85mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4865 { + string=P2; x=48.65mm; y=1.85mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4873 { + string=P1; x=85.75mm; y=8.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4926 { + string=P2; x=79.75mm; y=2.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5060 { + string=P0; x=45.15mm; y=7.6mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5062 { + string=P0; x=76.4mm; y=7.6mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5064 { + string=P4; x=2.2007874in; y=17.1mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5066 { + string=P4; x=86.9mm; y=17.1mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#548b54} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_hpierce.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_hpierce.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_hpierce.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hpierce.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_hpierce.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_hwallin.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_hwallin.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hwallin.lht (revision 1402) @@ -0,0 +1,1015 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 79.0mm + y = 85.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.4159 { + x1=38.75mm; y1=13.5mm; x2=38.75mm; y2=18.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4162 { + x1=37.0mm; y1=14.25mm; x2=40.5mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4165 { + x1=37.0mm; y1=17.75mm; x2=40.25mm; y2=14.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4168 { + x1=36.25mm; y1=16.0mm; x2=41.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4171 { + x1=38.75mm; y1=21.5mm; x2=38.75mm; y2=26.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4174 { + x1=37.0mm; y1=22.25mm; x2=40.5mm; y2=25.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4177 { + x1=37.0mm; y1=25.75mm; x2=40.25mm; y2=22.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4180 { + x1=36.25mm; y1=24.0mm; x2=41.25mm; y2=24.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4183 { + x1=41.0mm; y1=17.0mm; x2=41.0mm; y2=22.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4186 { + x1=39.25mm; y1=17.75mm; x2=42.75mm; y2=21.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4189 { + x1=39.25mm; y1=21.25mm; x2=42.5mm; y2=18.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4192 { + x1=38.5mm; y1=19.5mm; x2=43.5mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4354 { + x1=70.0mm; y1=13.75mm; x2=70.0mm; y2=18.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4357 { + x1=68.25mm; y1=14.5mm; x2=71.75mm; y2=18.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4360 { + x1=68.25mm; y1=18.0mm; x2=71.5mm; y2=14.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4363 { + x1=67.5mm; y1=16.25mm; x2=72.5mm; y2=16.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4366 { + x1=70.0mm; y1=21.75mm; x2=70.0mm; y2=26.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4369 { + x1=68.25mm; y1=22.5mm; x2=71.75mm; y2=26.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4372 { + x1=68.25mm; y1=26.0mm; x2=71.5mm; y2=22.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4375 { + x1=67.5mm; y1=24.25mm; x2=72.5mm; y2=24.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4378 { + x1=72.25mm; y1=17.25mm; x2=72.25mm; y2=22.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4381 { + x1=70.5mm; y1=18.0mm; x2=74.0mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4384 { + x1=70.5mm; y1=21.5mm; x2=73.75mm; y2=18.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4387 { + x1=69.75mm; y1=19.75mm; x2=74.75mm; y2=19.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5042 { + x1=38.0mm; y1=62.75mm; x2=38.0mm; y2=67.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5045 { + x1=36.25mm; y1=63.5mm; x2=39.75mm; y2=67.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5048 { + x1=36.25mm; y1=67.0mm; x2=39.75mm; y2=63.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5051 { + x1=35.5mm; y1=65.25mm; x2=40.5mm; y2=65.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5087 { + x1=69.25mm; y1=63.0mm; x2=69.25mm; y2=68.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5090 { + x1=67.5mm; y1=63.75mm; x2=71.0mm; y2=67.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5093 { + x1=67.5mm; y1=67.25mm; x2=71.0mm; y2=63.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5096 { + x1=66.75mm; y1=65.5mm; x2=71.75mm; y2=65.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5319 { + x=9.75mm; y=33.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5320 { + x=9.75mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5325 { + x=38.75mm; y=34.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5326 { + x=38.75mm; y=4.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5327 { + x=70.0mm; y=34.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5328 { + x=70.0mm; y=4.25mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5329 { + x=9.75mm; y=79.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5330 { + x=9.75mm; y=49.5mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5331 { + x=38.75mm; y=79.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5332 { + x=38.75mm; y=49.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5333 { + x=70.0mm; y=80.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5334 { + x=70.0mm; y=50.0mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.1758 { + x1=9.75mm; y1=3.75mm; x2=9.75mm; y2=8.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1761 { + x1=9.75mm; y1=9.5mm; x2=9.75mm; y2=11.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1764 { + x1=9.75mm; y1=15.75mm; x2=9.75mm; y2=17.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1767 { + x1=9.75mm; y1=22.0mm; x2=9.75mm; y2=24.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1770 { + x1=9.75mm; y1=33.75mm; x2=9.75mm; y2=30.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3950 { + x1=38.75mm; y1=4.0mm; x2=38.75mm; y2=8.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3953 { + x1=38.75mm; y1=9.75mm; x2=38.75mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3956 { + x1=38.75mm; y1=16.0mm; x2=38.75mm; y2=18.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3959 { + x1=38.75mm; y1=22.25mm; x2=38.75mm; y2=25.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3962 { + x1=38.75mm; y1=34.0mm; x2=38.75mm; y2=30.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4390 { + x1=70.0mm; y1=4.25mm; x2=70.0mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4393 { + x1=70.0mm; y1=10.0mm; x2=70.0mm; y2=12.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4396 { + x1=70.0mm; y1=16.25mm; x2=70.0mm; y2=18.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4399 { + x1=70.0mm; y1=22.5mm; x2=70.0mm; y2=25.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4402 { + x1=70.0mm; y1=34.25mm; x2=70.0mm; y2=30.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4468 { + x1=70.0mm; y1=34.25mm; x2=74.75mm; y2=19.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4477 { + x1=74.75mm; y1=19.75mm; x2=70.0mm; y2=4.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4881 { + x1=9.75mm; y1=49.5mm; x2=9.75mm; y2=54.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4884 { + x1=9.75mm; y1=55.25mm; x2=9.75mm; y2=57.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4887 { + x1=9.75mm; y1=61.5mm; x2=9.75mm; y2=63.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4890 { + x1=9.75mm; y1=67.75mm; x2=9.75mm; y2=70.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4893 { + x1=9.75mm; y1=79.5mm; x2=9.75mm; y2=75.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4896 { + x1=38.75mm; y1=49.75mm; x2=38.75mm; y2=54.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4899 { + x1=38.75mm; y1=55.5mm; x2=38.75mm; y2=57.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4902 { + x1=38.75mm; y1=61.75mm; x2=38.75mm; y2=63.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4905 { + x1=38.75mm; y1=68.0mm; x2=38.75mm; y2=70.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4908 { + x1=38.75mm; y1=79.75mm; x2=38.75mm; y2=76.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4911 { + x1=70.0mm; y1=50.0mm; x2=70.0mm; y2=54.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4914 { + x1=70.0mm; y1=55.75mm; x2=70.0mm; y2=58.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4917 { + x1=70.0mm; y1=62.0mm; x2=70.0mm; y2=64.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4920 { + x1=70.0mm; y1=68.25mm; x2=70.0mm; y2=71.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4923 { + x1=70.0mm; y1=80.0mm; x2=70.0mm; y2=76.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4926 { + x1=70.0mm; y1=80.0mm; x2=71.75mm; y2=65.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4929 { + x1=71.75mm; y1=65.5mm; x2=70.0mm; y2=50.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.2044 { + string=N1; x=8.25mm; y=6.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4405 { + string=N1; x=68.5mm; y=6.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4932 { + string=N1; x=8.25mm; y=51.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4933 { + string=N1; x=68.5mm; y=52.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.3896 { + x1=16.5mm; y1=1.25mm; x2=1.25mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3899 { + x1=1.25mm; y1=2.25mm; x2=12.0mm; y2=19.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3902 { + x1=12.0mm; y1=19.25mm; x2=4.75mm; y2=33.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3905 { + x1=4.75mm; y1=33.75mm; x2=10.75mm; y2=38.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3908 { + x1=10.75mm; y1=38.0mm; x2=17.5mm; y2=20.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3911 { + x1=17.5mm; y1=20.75mm; x2=16.5mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3966 { + x1=45.5mm; y1=1.5mm; x2=30.25mm; y2=2.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3969 { + x1=30.25mm; y1=2.5mm; x2=41.0mm; y2=19.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3972 { + x1=41.0mm; y1=19.5mm; x2=33.75mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3975 { + x1=33.75mm; y1=34.0mm; x2=39.75mm; y2=38.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3978 { + x1=39.75mm; y1=38.25mm; x2=46.5mm; y2=21.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3981 { + x1=46.5mm; y1=21.0mm; x2=45.5mm; y2=1.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4406 { + x1=76.75mm; y1=1.75mm; x2=61.5mm; y2=2.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4409 { + x1=61.5mm; y1=2.75mm; x2=72.25mm; y2=19.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4412 { + x1=72.25mm; y1=19.75mm; x2=65.0mm; y2=34.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4415 { + x1=65.0mm; y1=34.25mm; x2=71.0mm; y2=38.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4418 { + x1=71.0mm; y1=38.5mm; x2=77.75mm; y2=21.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4421 { + x1=77.75mm; y1=21.25mm; x2=76.75mm; y2=1.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4934 { + x1=16.5mm; y1=47.0mm; x2=1.25mm; y2=48.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4937 { + x1=1.25mm; y1=48.0mm; x2=9.0mm; y2=65.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4940 { + x1=9.0mm; y1=65.0mm; x2=4.75mm; y2=79.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4943 { + x1=4.75mm; y1=79.5mm; x2=10.75mm; y2=83.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4946 { + x1=10.75mm; y1=83.75mm; x2=17.5mm; y2=66.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4949 { + x1=17.5mm; y1=66.5mm; x2=16.5mm; y2=47.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4952 { + x1=45.5mm; y1=47.25mm; x2=30.25mm; y2=48.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4961 { + x1=33.75mm; y1=79.75mm; x2=39.75mm; y2=84.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4964 { + x1=39.75mm; y1=84.0mm; x2=46.5mm; y2=66.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4967 { + x1=46.5mm; y1=66.75mm; x2=45.5mm; y2=47.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4970 { + x1=76.75mm; y1=47.5mm; x2=61.5mm; y2=48.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4979 { + x1=65.0mm; y1=80.0mm; x2=71.0mm; y2=84.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4982 { + x1=71.0mm; y1=84.25mm; x2=77.75mm; y2=67.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4985 { + x1=77.75mm; y1=67.0mm; x2=76.75mm; y2=47.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5018 { + x1=30.25mm; y1=48.25mm; x2=38.0mm; y2=65.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5021 { + x1=38.0mm; y1=65.25mm; x2=33.75mm; y2=79.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5024 { + x1=61.5mm; y1=48.5mm; x2=69.25mm; y2=65.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5027 { + x1=69.25mm; y1=65.5mm; x2=65.0mm; y2=80.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.313 { + string=b; x=34.0mm; y=35.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.987 { + string=a; x=4.75mm; y=35.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.3501 { + string=c; x=65.0mm; y=35.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4988 { + string=e; x=34.0mm; y=80.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4989 { + string=d; x=4.75mm; y=80.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.4990 { + string=f; x=65.0mm; y=80.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.4222 { + x1=43.5mm; y1=19.5mm; x2=38.75mm; y2=34.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4225 { + x1=38.75mm; y1=34.0mm; x2=36.25mm; y2=24.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4231 { + x1=36.25mm; y1=24.0mm; x2=36.25mm; y2=16.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4237 { + x1=36.25mm; y1=16.0mm; x2=38.75mm; y2=4.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.4207 { + x1=38.75mm; y1=4.0mm; x2=43.5mm; y2=19.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5057 { + x1=35.5mm; y1=65.25mm; x2=38.75mm; y2=49.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5060 { + x1=38.75mm; y1=49.75mm; x2=40.5mm; y2=65.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5063 { + x1=40.5mm; y1=65.25mm; x2=38.75mm; y2=79.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5066 { + x1=38.75mm; y1=79.75mm; x2=35.5mm; y2=65.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_hwallin.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_hwallin.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_hwallin.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hwallin.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_hwallin.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/geo_hwallin_brk.lht =================================================================== --- tags/0.9.0/doc/detour/img/geo_hwallin_brk.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hwallin_brk.lht (revision 1402) @@ -0,0 +1,643 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + ha:thinner { + diameter = 275.6mil + text_scale = 100 + text_thick = 0.0 + thickness = 0.15mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 40.25mm + y = 39.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.5859 { + x1=31.25mm; y1=25.25mm; x2=31.25mm; y2=30.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5865 { + x1=29.5mm; y1=29.5mm; x2=32.75mm; y2=26.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5868 { + x1=28.75mm; y1=27.75mm; x2=33.75mm; y2=27.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5874 { + x1=33.0mm; y1=29.5mm; x2=27.5mm; y2=24.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5877 { + x1=27.5mm; y1=27.5mm; x2=30.75mm; y2=24.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5880 { + x1=26.75mm; y1=25.75mm; x2=31.75mm; y2=25.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5883 { + x1=29.25mm; y1=28.25mm; x2=29.25mm; y2=19.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5886 { + x1=27.5mm; y1=19.75mm; x2=31.0mm; y2=23.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5889 { + x1=27.5mm; y1=23.25mm; x2=30.75mm; y2=20.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5892 { + x1=26.75mm; y1=21.5mm; x2=31.75mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5895 { + x1=31.25mm; y1=18.0mm; x2=31.25mm; y2=23.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5898 { + x1=29.5mm; y1=18.75mm; x2=33.0mm; y2=22.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5901 { + x1=29.5mm; y1=22.25mm; x2=32.75mm; y2=19.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5904 { + x1=28.75mm; y1=20.5mm; x2=33.75mm; y2=20.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5910 { + x1=29.5mm; y1=10.75mm; x2=33.0mm; y2=14.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5913 { + x1=29.5mm; y1=14.25mm; x2=32.75mm; y2=11.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5916 { + x1=28.75mm; y1=12.5mm; x2=33.75mm; y2=12.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5919 { + x1=31.25mm; y1=15.0mm; x2=31.25mm; y2=7.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5922 { + x1=29.5mm; y1=8.5mm; x2=33.0mm; y2=12.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5925 { + x1=29.5mm; y1=12.0mm; x2=32.75mm; y2=8.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5928 { + x1=28.75mm; y1=10.25mm; x2=33.75mm; y2=10.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5931 { + x1=32.75mm; y1=9.0mm; x2=32.75mm; y2=14.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5934 { + x1=31.0mm; y1=9.75mm; x2=34.5mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5937 { + x1=31.0mm; y1=13.25mm; x2=34.25mm; y2=10.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5940 { + x1=30.25mm; y1=11.5mm; x2=35.25mm; y2=11.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5319 { + x=9.75mm; y=33.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5320 { + x=9.75mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5801 { + x=31.25mm; y=33.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.5802 { + x=31.25mm; y=3.75mm; width=0.6mm; height=0.6mm; astart=0.000000; adelta=360.000000; thickness=0.8mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.1758 { + x1=9.75mm; y1=3.75mm; x2=9.75mm; y2=6.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1761 { + x1=9.75mm; y1=9.5mm; x2=9.75mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1764 { + x1=9.75mm; y1=15.5mm; x2=9.75mm; y2=17.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1767 { + x1=9.75mm; y1=19.75mm; x2=9.75mm; y2=22.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1770 { + x1=9.75mm; y1=33.75mm; x2=9.75mm; y2=26.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5803 { + x1=31.25mm; y1=3.75mm; x2=31.25mm; y2=6.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5806 { + x1=31.25mm; y1=9.5mm; x2=31.25mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5809 { + x1=31.25mm; y1=15.5mm; x2=31.25mm; y2=17.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5812 { + x1=31.25mm; y1=19.75mm; x2=31.25mm; y2=22.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5815 { + x1=31.25mm; y1=33.75mm; x2=31.25mm; y2=26.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.2044 { + string=N1; x=8.25mm; y=6.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5818 { + string=N1; x=29.75mm; y=6.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.3896 { + x1=16.5mm; y1=1.25mm; x2=1.25mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3899 { + x1=1.25mm; y1=2.25mm; x2=11.25mm; y2=11.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.3911 { + x1=17.25mm; y1=17.0mm; x2=16.5mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5557 { + x1=11.25mm; y1=11.5mm; x2=4.75mm; y2=16.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5560 { + x1=4.75mm; y1=16.25mm; x2=4.75mm; y2=35.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5563 { + x1=4.75mm; y1=35.5mm; x2=17.5mm; y2=35.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5569 { + x1=17.5mm; y1=35.5mm; x2=7.75mm; y2=25.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5575 { + x1=17.25mm; y1=17.0mm; x2=7.75mm; y2=21.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5578 { + x1=7.75mm; y1=21.5mm; x2=7.75mm; y2=25.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5819 { + x1=38.0mm; y1=1.25mm; x2=22.75mm; y2=2.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5822 { + x1=22.75mm; y1=2.25mm; x2=32.75mm; y2=11.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5825 { + x1=38.75mm; y1=17.0mm; x2=38.0mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5828 { + x1=32.75mm; y1=11.5mm; x2=26.25mm; y2=16.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5831 { + x1=26.25mm; y1=16.25mm; x2=26.25mm; y2=35.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5834 { + x1=26.25mm; y1=35.5mm; x2=39.0mm; y2=35.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5837 { + x1=39.0mm; y1=35.5mm; x2=29.25mm; y2=25.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5840 { + x1=38.75mm; y1=17.0mm; x2=29.25mm; y2=21.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5843 { + x1=29.25mm; y1=21.5mm; x2=29.25mm; y2=25.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.5984 { + string=a; x=4.75mm; y=36.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.5985 { + string=b; x=26.25mm; y=36.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + ha:line.5949 { + x1=31.25mm; y1=33.75mm; x2=27.5mm; y2=27.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5952 { + x1=27.5mm; y1=27.5mm; x2=26.75mm; y2=25.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5955 { + x1=26.75mm; y1=25.75mm; x2=26.75mm; y2=21.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5958 { + x1=26.75mm; y1=21.5mm; x2=28.75mm; y2=12.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5961 { + x1=28.75mm; y1=12.5mm; x2=28.75mm; y2=10.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5964 { + x1=28.75mm; y1=10.25mm; x2=31.25mm; y2=3.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5967 { + x1=31.25mm; y1=3.75mm; x2=35.25mm; y2=11.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5970 { + x1=35.25mm; y1=11.5mm; x2=34.5mm; y2=13.25mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5973 { + x1=34.5mm; y1=13.25mm; x2=33.75mm; y2=20.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5976 { + x1=33.75mm; y1=20.5mm; x2=33.75mm; y2=27.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.5979 { + x1=33.75mm; y1=27.75mm; x2=31.25mm; y2=33.75mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 275.60 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 150.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + wireframe_draw = false + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/geo_hwallin_brk.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/geo_hwallin_brk.png =================================================================== --- tags/0.9.0/doc/detour/img/geo_hwallin_brk.png (nonexistent) +++ tags/0.9.0/doc/detour/img/geo_hwallin_brk.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/geo_hwallin_brk.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/topo_cross1.lht =================================================================== --- tags/0.9.0/doc/detour/img/topo_cross1.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_cross1.lht (revision 1402) @@ -0,0 +1,625 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 1.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 0.7mm + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 83.0mm + y = 78.75mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:draft { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.206 { + x1=54.25mm; y1=17.0mm; x2=46.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.209 { + x1=46.0mm; y1=4.0mm; x2=27.5mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.212 { + x1=27.5mm; y1=16.75mm; x2=46.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.215 { + x1=59.0mm; y1=17.0mm; x2=75.5mm; y2=37.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.218 { + x1=75.5mm; y1=37.5mm; x2=81.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.221 { + x1=81.0mm; y1=17.0mm; x2=75.75mm; y2=1.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.224 { + x1=75.75mm; y1=1.25mm; x2=59.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.203 { + x1=46.0mm; y1=4.0mm; x2=54.25mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.539 { + x=1.75mm; y=16.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.541 { + x=23.75mm; y=16.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.543 { + x=17.75mm; y=3.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.545 { + x=17.75mm; y=33.75mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.546 { + x=30.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.548 { + x=46.0mm; y=4.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.549 { + x=46.0mm; y=34.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.550 { + x=52.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.551 { + x=59.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.552 { + x=75.0mm; y=4.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.553 { + x=75.0mm; y=34.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.554 { + x=81.0mm; y=17.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.555 { + x=17.75mm; y=44.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.556 { + x=17.75mm; y=74.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.557 { + x=1.75mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.558 { + x=23.75mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.559 { + x=30.0mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.560 { + x=52.0mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.561 { + x=59.0mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.562 { + x=46.0mm; y=44.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.563 { + x=46.0mm; y=74.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.564 { + x=75.0mm; y=44.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.565 { + x=75.0mm; y=74.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.567 { + x=81.0mm; y=57.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.570 { + x=17.75mm; y=53.75mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.571 { + x=17.75mm; y=61.25mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.572 { + x=46.0mm; y=61.25mm; width=0.4mm; height=0.4mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.297 { + string=N1-left; x=32.0mm; y=8.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.299 { + string=N1-right; x=50.5mm; y=8.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.302 { + string={#1}; x=15.75mm; y=14.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.304 { + string=N2-top; x=63.25mm; y=5.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.310 { + string=N2-bottom; x=61.75mm; y=30.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.281 { + x1=17.75mm; y1=3.75mm; x2=17.75mm; y2=33.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.284 { + x1=1.75mm; y1=16.75mm; x2=23.75mm; y2=16.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.305 { + string=N1; x=18.75mm; y=8.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.306 { + string=N2; x=10.25mm; y=17.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.361 { + string=N1; x=18.75mm; y=48.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.362 { + string=N2; x=10.25mm; y=58.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.410 { + string=N1; x=47.0mm; y=48.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.411 { + string=N2; x=38.5mm; y=58.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.448 { + string=N1; x=76.0mm; y=48.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.449 { + string=N2; x=67.5mm; y=58.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=6 + ha:combining { } + + li:objects { + ha:line.291 { + x1=30.0mm; y1=17.0mm; x2=52.0mm; y2=17.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.294 { + x1=75.0mm; y1=4.0mm; x2=75.0mm; y2=34.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.479 { + x1=1.75mm; y1=57.25mm; x2=23.75mm; y2=57.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.482 { + x1=17.75mm; y1=44.25mm; x2=17.75mm; y2=53.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.485 { + x1=17.75mm; y1=61.25mm; x2=17.75mm; y2=74.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.488 { + x1=30.0mm; y1=57.25mm; x2=52.0mm; y2=57.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.491 { + x1=46.0mm; y1=61.25mm; x2=46.0mm; y2=74.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.494 { + x1=59.0mm; y1=57.25mm; x2=81.0mm; y2=57.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.311 { + string=a; x=14.25mm; y=35.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.313 { + string=b; x=42.5mm; y=35.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.315 { + string=c; x=71.0mm; y=35.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.363 { + string=d; x=14.25mm; y=75.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.412 { + string=e; x=42.5mm; y=75.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.450 { + string=f; x=71.5mm; y=75.5mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=7 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:top-doc { + lid=4 + group=5 + ha:combining { } + + li:objects { + ha:line.377 { + x1=17.75mm; y1=53.75mm; x2=17.75mm; y2=61.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.413 { + x1=46.0mm; y1=44.0mm; x2=46.0mm; y2=61.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.451 { + x1=75.0mm; y1=44.0mm; x2=75.0mm; y2=74.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#548b54} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 4; } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:7 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 1000.00 um + via_drilling_hole = 700.00 um + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/topo_cross1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/topo_cross1.png =================================================================== --- tags/0.9.0/doc/detour/img/topo_cross1.png (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_cross1.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/topo_cross1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/topo_cross2.lht =================================================================== --- tags/0.9.0/doc/detour/img/topo_cross2.lht (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_cross2.lht (revision 1402) @@ -0,0 +1,796 @@ +ha:pcb-rnd-board-v7 { + + li:styles { + ha:normal { + diameter = 2.2mm + text_scale = 200 + text_thick = 1.0mm + thickness = 1.0mm + hole = 2.0mm + clearance = 20.0mil + } + ha:thick { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 1.7mm + hole = 1.0mm + clearance = 20.0mil + } + ha:thin { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 0.35mm + hole = 47.24mil + clearance = 25.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 97.5mm + y = 126.5mm + } + ha:grid { + spacing = 0.25mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + + unused = 1 + unused = 1 + unused = 1 + } + + li:objects { + } + li:layers { + + + ha:detour { + lid=0 + group=3 + ha:combining { } + + li:objects { + ha:line.179 { + x1=73.75mm; y1=32.0mm; x2=82.25mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.182 { + x1=82.25mm; y1=15.0mm; x2=73.75mm; y2=2.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.961 { + x1=32.5mm; y1=56.5mm; x2=24.0mm; y2=43.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.964 { + x1=32.5mm; y1=56.5mm; x2=47.0mm; y2=59.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.967 { + x1=47.0mm; y1=59.25mm; x2=47.0mm; y2=61.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.970 { + x1=47.0mm; y1=61.5mm; x2=24.0mm; y2=73.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1026 { + x1=73.75mm; y1=73.25mm; x2=82.25mm; y2=56.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1029 { + x1=82.25mm; y1=56.25mm; x2=73.75mm; y2=43.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1032 { + x1=94.75mm; y1=60.25mm; x2=73.0mm; y2=76.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1035 { + x1=73.0mm; y1=76.0mm; x2=64.75mm; y2=60.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1105 { + x1=24.0mm; y1=119.0mm; x2=32.5mm; y2=102.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1108 { + x1=32.5mm; y1=102.0mm; x2=24.0mm; y2=89.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1111 { + x1=15.0mm; y1=106.0mm; x2=23.5mm; y2=86.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1114 { + x1=23.5mm; y1=86.0mm; x2=45.0mm; y2=106.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1117 { + x1=74.5mm; y1=119.0mm; x2=83.0mm; y2=102.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1120 { + x1=83.0mm; y1=102.0mm; x2=74.5mm; y2=89.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1123 { + x1=65.5mm; y1=106.0mm; x2=74.0mm; y2=86.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1126 { + x1=74.0mm; y1=86.0mm; x2=95.5mm; y2=106.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1129 { + x1=52.5mm; y1=102.0mm; x2=65.5mm; y2=109.75mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1132 { + x1=65.5mm; y1=109.75mm; x2=80.5mm; y2=102.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.654 { + x=2.0mm; y=15.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.656 { + x=30.0mm; y=15.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.657 { + x=24.0mm; y=2.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.658 { + x=15.0mm; y=19.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.659 { + x=45.0mm; y=19.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.661 { + x=24.0mm; y=32.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.663 { + x=51.75mm; y=15.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.664 { + x=64.75mm; y=19.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.665 { + x=79.75mm; y=15.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.666 { + x=73.75mm; y=2.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.667 { + x=73.75mm; y=32.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.668 { + x=94.75mm; y=19.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.973 { + x=2.0mm; y=56.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.974 { + x=30.0mm; y=56.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.975 { + x=24.0mm; y=43.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.976 { + x=45.0mm; y=60.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.977 { + x=15.0mm; y=60.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.978 { + x=24.0mm; y=73.5mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1038 { + x=51.75mm; y=56.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1039 { + x=73.75mm; y=43.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1040 { + x=79.75mm; y=56.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1041 { + x=64.75mm; y=60.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1042 { + x=73.75mm; y=73.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1043 { + x=94.75mm; y=60.25mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1135 { + x=2.0mm; y=102.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1136 { + x=30.0mm; y=102.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1137 { + x=15.0mm; y=106.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1138 { + x=24.0mm; y=89.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1139 { + x=24.0mm; y=119.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1140 { + x=45.0mm; y=106.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1141 { + x=52.5mm; y=102.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1142 { + x=65.5mm; y=106.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1143 { + x=80.5mm; y=102.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1144 { + x=74.5mm; y=119.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1145 { + x=95.5mm; y=106.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.1146 { + x=74.5mm; y=89.0mm; width=0.8mm; height=0.8mm; astart=0.000000; adelta=360.000000; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.96 { + string={#1}; x=22.0mm; y=12.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.98 { + string={#2}; x=24.75mm; y=19.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.185 { + string={#2}; x=81.0mm; y=19.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + ha:text.1147 { + string={#3}; x=14.75mm; y=100.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + thickness = 4.0mil + rot = 0.000000 + } + } + color = {#757575} + } + ha:ratlines { + lid=1 + group=4 + ha:combining { } + + li:objects { + ha:line.75 { + x1=2.0mm; y1=15.0mm; x2=30.0mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.78 { + x1=15.0mm; y1=19.0mm; x2=45.0mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.84 { + x1=24.0mm; y1=2.0mm; x2=24.0mm; y2=32.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.189 { + x1=64.75mm; y1=19.0mm; x2=94.75mm; y2=19.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.186 { + x1=51.75mm; y1=15.0mm; x2=79.75mm; y2=15.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.979 { + x1=2.0mm; y1=56.5mm; x2=30.0mm; y2=56.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.982 { + x1=15.0mm; y1=60.5mm; x2=45.0mm; y2=60.5mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1044 { + x1=51.75mm; y1=56.25mm; x2=79.75mm; y2=56.25mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1148 { + x1=2.0mm; y1=102.0mm; x2=30.0mm; y2=102.0mm; thickness=0.35mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.87 { + string=N1; x=22.25mm; y=5.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.88 { + string=N2; x=7.25mm; y=13.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.89 { + string=N3; x=38.0mm; y=19.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.192 { + string=N1; x=72.0mm; y=5.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.193 { + string=N2; x=57.0mm; y=13.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.194 { + string=N3; x=87.75mm; y=19.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.985 { + string=N1; x=28.75mm; y=47.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.986 { + string=N2; x=7.25mm; y=54.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.987 { + string=N3; x=38.0mm; y=61.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1047 { + string=N1; x=72.0mm; y=47.0mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1048 { + string=N2; x=57.0mm; y=54.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1049 { + string=N3; x=87.75mm; y=60.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1151 { + string=N1; x=26.0mm; y=95.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1152 { + string=N2; x=7.25mm; y=100.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1153 { + string=N3; x=17.75mm; y=92.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1154 { + string=N1; x=79.0mm; y=112.25mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1155 { + string=N2; x=56.5mm; y=106.5mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1156 { + string=N3; x=68.25mm; y=92.75mm; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#d3a232} + } + + ha:wires { + lid=2 + group=5 + ha:combining { } + + li:objects { + ha:line.988 { + x1=32.5mm; y1=56.5mm; x2=30.0mm; y2=58.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.991 { + x1=30.0mm; y1=58.5mm; x2=12.75mm; y2=59.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.994 { + x1=12.75mm; y1=59.0mm; x2=14.25mm; y2=63.0mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.997 { + x1=14.25mm; y1=63.0mm; x2=24.0mm; y2=73.5mm; thickness=0.15mm; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:text.266 { + string=a; x=23.25mm; y=34.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.268 { + string=b; x=73.0mm; y=34.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1000 { + string=c; x=23.25mm; y=75.75mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1050 { + string=d; x=73.0mm; y=78.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1157 { + string=e; x=23.25mm; y=123.25mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.1158 { + string=f; x=74.0mm; y=123.0mm; scale=200; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#104e8b} + } + + ha:annotation { + lid=3 + group=6 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:1 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.125mm } + } + } + ha:2 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + ha:attributes { + thickness={0.7375mm } + } + } + ha:3 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 0; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:4 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 1; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:5 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 2; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + ha:6 { + name = top-doc + ha:type { top=1; doc=1; } + li:layers { 3; } + ha:attributes { + init-invis=0 + } + purpose = fab + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 137.80 mil + via_drilling_hole = 47.24 mil + text_thickness = 0 + line_thickness = 350.00 um + clearance = 25.00 mil + } + ha:editor { + grid_unit = mm + buffer_number = 0 + all_direction_lines = true + grids_idx = 10 + grid = 250.00 um + } + } + } + ha:pixmaps { + } +} Index: tags/0.9.0/doc/detour/img/topo_cross2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/topo_cross2.png =================================================================== --- tags/0.9.0/doc/detour/img/topo_cross2.png (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_cross2.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/topo_cross2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/topo_tree1.dot =================================================================== --- tags/0.9.0/doc/detour/img/topo_tree1.dot (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_tree1.dot (revision 1402) @@ -0,0 +1,10 @@ +digraph tree { + a -> b + a -> c + a -> d + a -> e + a -> f + a -> g + a -> h + a -> i +} \ No newline at end of file Index: tags/0.9.0/doc/detour/img/topo_tree1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/topo_tree1.png =================================================================== --- tags/0.9.0/doc/detour/img/topo_tree1.png (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_tree1.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/topo_tree1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/img/topo_tree2.dot =================================================================== --- tags/0.9.0/doc/detour/img/topo_tree2.dot (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_tree2.dot (revision 1402) @@ -0,0 +1,20 @@ +digraph tree { + etc1 [label="..."] + etc2 [label="..."] + etc3 [label="..."] + + c [color=red] + d [color=red] + f [color=red] + + a -> b + a -> etc1 + + b -> c + b -> d + b -> e + b -> etc2 + + e -> f + e -> etc3 +} \ No newline at end of file Index: tags/0.9.0/doc/detour/img/topo_tree2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/detour/img/topo_tree2.png =================================================================== --- tags/0.9.0/doc/detour/img/topo_tree2.png (nonexistent) +++ tags/0.9.0/doc/detour/img/topo_tree2.png (revision 1402) Property changes on: tags/0.9.0/doc/detour/img/topo_tree2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/detour/index.html =================================================================== --- tags/0.9.0/doc/detour/index.html (nonexistent) +++ tags/0.9.0/doc/detour/index.html (revision 1402) @@ -0,0 +1,12 @@ + + +

Topo-geometric detour router

+ +

ToC

+ + Index: tags/0.9.0/doc/detour/pdf.css =================================================================== --- tags/0.9.0/doc/detour/pdf.css (nonexistent) +++ tags/0.9.0/doc/detour/pdf.css (revision 1402) @@ -0,0 +1,25 @@ +H1 { + border-bottom-style: solid; + border-bottom-width: 3px; +} + +H2 { + border-bottom-style: solid; + border-bottom-width: 1px; +} + +P { + text-align: justify; + margin-left: 20px; +} + +PRE { + margin-left: 20px; +} + + +div.img { + font-style: italic; + max-width: 700px; + margin: 100px auto; +} Index: tags/0.9.0/doc/detour/web.css =================================================================== --- tags/0.9.0/doc/detour/web.css (nonexistent) +++ tags/0.9.0/doc/detour/web.css (revision 1402) @@ -0,0 +1,33 @@ +body { + max-width: 800px; + margin: auto; +} + +H1 { + border-bottom-style: solid; + border-bottom-width: 3px; +} + +H2 { + border-bottom-style: solid; + border-bottom-width: 1px; +} + + +div.img { + font-style: italic; + margin: 100px auto; +} + +div.img p { + text-align: center; +} + + +P { + text-align: justify; +} + +PRE { + margin-left: 20px; +} Index: tags/0.9.0/doc/doc.html =================================================================== --- tags/0.9.0/doc/doc.html (nonexistent) +++ tags/0.9.0/doc/doc.html (revision 1402) @@ -0,0 +1,31 @@ + + + + route-rnd - documentation + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +
+ +

route-rnd documentation

+

+No documentation availble yet. + + + Index: tags/0.9.0/doc/index.html =================================================================== --- tags/0.9.0/doc/index.html (nonexistent) +++ tags/0.9.0/doc/index.html (revision 1402) @@ -0,0 +1,77 @@ + + + + route-rnd - main + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +
+ + +
+

Summary

+ +
+
[route-rnd logo]route-rnd
+
+ is a free/open source, flexible, modular autorouter for Printed Circuit Boards +

using the extremely simple and freely available tEDAx file format. +

is part of the ringdove suite and works smoothly from pcb-rnd. + + + +

Version Control svn://repo.hu/route-rnd/trunk +
Download source releases +
Comments, feedback, patches live chat with the developer
or contact the lead developer +
Contribution and support +
A major supporter is NLnet + +
Key features + generic external autorouter for Printed Circuit Boards +
modular, supports different routing algorithms +
fits well in a UNIXy workflow +
the designed-for-simplicity file format makes it easy to interface +
fully CLI, no GUI required +
active development, frequent releases +
free/open source software license (GPL2) + +
Supported platforms + +
+ any POSIX-like system with c89 support (various Linux and BSD distributions, from source) + +
+
+ + +
+ + + +

What is -rnd?

+
+ This project is part of the ringdove EDA suite. + That means it is guaranteed to be usable with the other software found in + ringdove, i.e. with pcb-rnd. + However, all parts of the ringdove suite is written with modularity and toolkit + approach and UNIXy workflows in mind so route-rnd can potentially interface + other PCB editors as well in the future. + + + Index: tags/0.9.0/doc/irc.html =================================================================== --- tags/0.9.0/doc/irc.html (nonexistent) +++ tags/0.9.0/doc/irc.html (revision 1402) @@ -0,0 +1,47 @@ + + + + route-rnd - IRC + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +

Live support via IRC (chat)

+
Irc server: repo.hu       Port: 6667       Channel: #pcb-rnd +
  +

I'm normally online as Igor2 between 5:00 CET and 19:00 CET; on Sunday there's an AFK-window between 11:00 CET and 16:00 CET. If I don't answer in a few minutes I'm probably away doing something, please be patient; say hi before you type your long question so you see if I'm available. +


+

+Below is an iframe of +kiwiirc irc client configured with the above settings. If it doesn't +work, please visit their page and +try to manually configure it, it's just 4 fields. +

+Using the web client: you should change your nickname (or using the +/nick myname command if you are already connected); there's no password +or registration or channel key or ssl of any form. Your real IP won't be +shown on the IRC network (check kiwiirc's page about their privacy +policy). +

+Connecting with the web client may take some time, give it a minute. +


+ + + + + Index: tags/0.9.0/doc/license.html =================================================================== --- tags/0.9.0/doc/license.html (nonexistent) +++ tags/0.9.0/doc/license.html (revision 1402) @@ -0,0 +1,48 @@ + + + + route-rnd - license + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +

route-rnd - license

+Route-rnd is a Free Software, Open source, under the terms of GPL version 2. +

+See file +trunk/COPYING for more details on the license terms. Route-rnd +incorporates a few mini-libs with various, GPL-compatible licenses, mostly +BSD, MIT and public domain. +

+For users: the resulting software is distributable under the GNU GPL version 2 +(or later versions), the usual GPL terms and conditions apply. +

+Contribution: by contributing, you agree to submit patches that are conforming +to the license terms (e.g. don't copy random code from other projects). We +are keeping track of copyright: each contributor holds the copyright for and +is responsible for their part. Contributors agree to license their contribution +under the same term as the subproject they are adding to, which is typically +GPL2+ for core and plugins and utilities. +

+Re-licensing under different conditions: route-rnd's GPL2+ allows the user +to upgrade to GPL3 or later versions of the GPL (as long as new versions +don't contradict with the license of the mini-libs). It is possible to request +relicensing route-rnd and/or some of the mini-libs under different terms +(contact the author). + + Index: tags/0.9.0/doc/news.html =================================================================== --- tags/0.9.0/doc/news.html (nonexistent) +++ tags/0.9.0/doc/news.html (revision 1402) @@ -0,0 +1,45 @@ + + + + route-rnd - news + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +
+ +

News

+ +
+ + + + + +
+
+ + + Index: tags/0.9.0/doc/resources/at.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/0.9.0/doc/resources/at.png =================================================================== --- tags/0.9.0/doc/resources/at.png (nonexistent) +++ tags/0.9.0/doc/resources/at.png (revision 1402) Property changes on: tags/0.9.0/doc/resources/at.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/0.9.0/doc/state.html =================================================================== --- tags/0.9.0/doc/state.html (nonexistent) +++ tags/0.9.0/doc/state.html (revision 1402) @@ -0,0 +1,53 @@ + + + + route-rnd - current state + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +

route-rnd current state

+ +

version 0.9.0

+ +
router algo state + +
horver + Make sure pin/pad centers are aligned on a (preferrably >=100mil) grid. + Precise grid alignment is essential for this router. Make sure you do + not have any pin larger than your via setting. +

+ Bug: some escape lines will run too close to the pin. + +

rt_topo/trbs + Bug: depending on the triangulation, some line segments may run too + close to the corner of rectangular pads or to round pads. + +
rt_topo/crbs + Limitations: +
    +
  • because of the convex-only approach currently implemented, + some traces include unnecessary curves, especially around rectangular + pads. +
  • because of the same convex-only limitation and missing corridor + code, some rats are not routed or go around far away obstacles in + long detours +
+ + + Index: tags/0.9.0/doc/support.html =================================================================== --- tags/0.9.0/doc/support.html (nonexistent) +++ tags/0.9.0/doc/support.html (revision 1402) @@ -0,0 +1,50 @@ + + + + route-rnd - news + + + + + + + + + + +
Main + News + Doc | State + Support + route-rnd + +
+ + +
+ +

route-rnd support

+ +

Get support

+ +Option 1: mailing me +

+Option 2: real-time chat with the developers and hard core users: IRC ; please pick a meaningful nickname, join, say +hi, state your question and be patient; someone will react in at most +3..4 hours. If nobody reacts but you see traffic, repeat your question. +Leaving there an idler client is okay. +

+The generic rule is that over whatever channel you can reach us, that's +also the right place to ask questions about route-rnd and we will answer there. +Currently these are the channels where we can be reached: +

+ +
type address +
public IRC channel repo.hu:6667 #pcb-rnd +
private email Igor2's email address +
private IRC Igor2 on repo.hu or on ircnet +
+ + + Index: tags/0.9.0/src/plugins/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/Makefile.inc (revision 1402) @@ -0,0 +1,13 @@ +PLG=$(ROOT)/src/plugins/ +THIRD=$(ROOT)/src_3rd + +include $(PLG)/io_tedax/Makefile.inc +include $(PLG)/export_animator/Makefile.inc +include $(PLG)/export_svg/Makefile.inc +include $(PLG)/rt_horver/Makefile.inc +include $(PLG)/rt_topo/Makefile.inc +#include $(PLG)/rt_hace/Makefile.inc + +BUILDIN_O = $(PLG)/buildin.o $(BUILDIN_IO_TEDAX) $(BUILDIN_EXPORT_ANIMATOR) $(BUILDIN_EXPORT_SVG) $(BUILDIN_RT_HORVER) $(BUILDIN_RT_TOPO) $(BUILDIN_RT_HACE) + +$(PLG)/buildin.o: $(PLG)/buildin.c $(PLG)/buildin.h Index: tags/0.9.0/src/plugins/buildin.c =================================================================== --- tags/0.9.0/src/plugins/buildin.c (nonexistent) +++ tags/0.9.0/src/plugins/buildin.c (revision 1402) @@ -0,0 +1,16 @@ +extern void io_tedax_init(void); +extern void export_animator_init(void); +extern void export_svg_init(void); +extern void rt_horver_init(void); +extern void rt_topo_init(void); +/*extern void rt_hace_init(void);*/ + +void rtrnd_buildin_init(void) +{ + io_tedax_init(); + export_animator_init(); + export_svg_init(); + rt_horver_init(); + rt_topo_init(); +/* rt_hace_init();*/ +} Index: tags/0.9.0/src/plugins/buildin.h =================================================================== --- tags/0.9.0/src/plugins/buildin.h (nonexistent) +++ tags/0.9.0/src/plugins/buildin.h (revision 1402) @@ -0,0 +1 @@ +void rtrnd_buildin_init(void); Index: tags/0.9.0/src/plugins/export_animator/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/export_animator/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/export_animator/Makefile.inc (revision 1402) @@ -0,0 +1,2 @@ +BUILDIN_EXPORT_ANIMATOR = \ + $(PLG)/export_animator/export_animator.o Index: tags/0.9.0/src/plugins/export_animator/export_animator.c =================================================================== --- tags/0.9.0/src/plugins/export_animator/export_animator.c (nonexistent) +++ tags/0.9.0/src/plugins/export_animator/export_animator.c (revision 1402) @@ -0,0 +1,184 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * animator export plugin - save the board (or a layer) in an animator(1) script + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include "data.h" + +#define ERROR "route-rnd animator error: " + + +typedef struct wr_ctx_s { + rtrnd_t *ctx; + FILE *f; + char *fn; + const char *clr; +} wr_ctx_t; + +static void anim_wr_head(wr_ctx_t *wctx) +{ + fprintf(wctx->f, "macro board\n"); +} + +static void anim_wr_foot(wr_ctx_t *wctx) +{ + fprintf(wctx->f, "endmacro\n"); + fprintf(wctx->f, "viewport board\n"); + fprintf(wctx->f, "frame\n"); + fprintf(wctx->f, "invoke board\n"); + fprintf(wctx->f, "flush\n"); +} + +static void anim_color(wr_ctx_t *wctx, const char *clr) +{ + if ((wctx->clr != NULL) && ((wctx->clr == clr) || (strcmp(wctx->clr, clr) == 0))) + return; + fprintf(wctx->f, "color %s\n", clr); + wctx->clr = clr; +} + +static void anim_wr_via(wr_ctx_t *wctx, rtrnd_via_t *via) +{ + int verts = 10; + if (via->dia > 2) + verts = 20; + + anim_color(wctx, "#111111"); + fprintf(wctx->f, "fillcircle %f %f %f %d\n", via->x, -via->y, via->dia/2, verts); +} + +static void anim_wr_layer(wr_ctx_t *wctx, rtrnd_layer_t *layer, int draw_vias) +{ + rtrnd_rtree_it_t it; + rtrnd_any_obj_t *obj; + rtp_vertex_t *v; + int verts = 10; + double r, vx, vy, nx, ny, l; + + fprintf(wctx->f, "! --- layer '%s' ---\n", layer->name); + anim_color(wctx, layer->color); + + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) { + switch(obj->hdr.type) { + case RTRND_LINE: + if (obj->line.thickness > 2) + verts = 20; + r = obj->line.thickness/2; + vx = obj->line.cline.p2.x - obj->line.cline.p1.x; vy = obj->line.cline.p2.y - obj->line.cline.p1.y; + if ((vx != 0) || (vy != 0)) { + l = sqrt(vx*vx + vy * vy); + nx = -vy / l; + ny = vx / l; + fprintf(wctx->f, "poly %f %f %f %f %f %f %f %f\n", + obj->line.cline.p1.x + nx*r, -(obj->line.cline.p1.y + ny*r), + obj->line.cline.p2.x + nx*r, -(obj->line.cline.p2.y + ny*r), + obj->line.cline.p2.x - nx*r, -(obj->line.cline.p2.y - ny*r), + obj->line.cline.p1.x - nx*r, -(obj->line.cline.p1.y - ny*r)); + } + fprintf(wctx->f, "fillcircle %f %f %f %d\n", obj->line.cline.p1.x, -obj->line.cline.p1.y, r, verts); + fprintf(wctx->f, "fillcircle %f %f %f %d\n", obj->line.cline.p2.x, -obj->line.cline.p2.y, r, verts); + break; + case RTRND_POLY: + fprintf(wctx->f, "poly"); + for(v = gdl_first(&obj->poly.rtpoly.lst); v != NULL; v = gdl_next(&obj->poly.rtpoly.lst, v)) + fprintf(wctx->f, " %f %f", v->x, -v->y); + fprintf(wctx->f, "\n"); + break; + + case RTRND_ARC: + default: /* can't be on layer */ + break; + } + } + + if (draw_vias) { + rtrnd_via_t *via; + for(via = rtrnd_rtree_all_first(&it, &wctx->ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) + if (rtrnd_via_touches_layer(layer, via)) + anim_wr_via(wctx, via); + } +} + +static int anim_export(rtrnd_t *ctx, const char *basename, rtrnd_layer_t *layer, vtp0_t *annots) +{ + wr_ctx_t wctx; + int res = 0, len = strlen(basename), n; + + wctx.fn = malloc(len + 32); + memcpy(wctx.fn, basename, len); + strcpy(wctx.fn + len, ".anim"); + wctx.clr = ""; + wctx.ctx = ctx; + wctx.f = fopen(wctx.fn, "w"); + if (wctx.f == NULL) { + fprintf(stderr, ERROR "can't open '%s' for write\n", wctx.fn); + goto err; + } + + anim_wr_head(&wctx); + if (layer == NULL) { + if ((ctx->board != NULL) && (ctx->board->layers.used > 0)) { + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + + for(n = ctx->board->layers.used-1; n >=0 ; n--) + anim_wr_layer(&wctx, ctx->board->layers.array[n], 0); + for(via = rtrnd_rtree_all_first(&it, &ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) + anim_wr_via(&wctx, via); + } + else + fprintf(wctx.f, "! --- (empty board - no layers!) ---\n"); + } + else + anim_wr_layer(&wctx, layer, 1); + + if (annots != NULL) + for(n = 0; n < annots->used; n++) + anim_wr_layer(&wctx, annots->array[n], 0); + + anim_wr_foot(&wctx); + + err:; + free(wctx.fn); + if (wctx.f != NULL) + fclose(wctx.f); + return res; +} + + +static const rtrnd_export_t exp_anim = { + "animator", + anim_export +}; + +void export_animator_init(void) +{ + vtp0_append(&rtrnd_all_export, (void *)&exp_anim); +} Index: tags/0.9.0/src/plugins/export_svg/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/export_svg/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/export_svg/Makefile.inc (revision 1402) @@ -0,0 +1,2 @@ +BUILDIN_EXPORT_SVG = \ + $(PLG)/export_svg/export_svg.o Index: tags/0.9.0/src/plugins/export_svg/export_svg.c =================================================================== --- tags/0.9.0/src/plugins/export_svg/export_svg.c (nonexistent) +++ tags/0.9.0/src/plugins/export_svg/export_svg.c (revision 1402) @@ -0,0 +1,194 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * animator export plugin - save the board (or a layer) in an animator(1) script + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include "data.h" + +#define ERROR "route-rnd animator error: " + +#undef VIEWBOX +#define SV(a) ((a)) +#define SVX(x) SV(x) +#define SVY(y) SV(y) + +static double translucent = 0.8; + +typedef struct wr_ctx_s { + rtrnd_t *ctx; + FILE *f; + char *fn; +} wr_ctx_t; + +static void svg_wr_head(wr_ctx_t *wctx) +{ + double mx, my; + g2d_box_t bb; + + rtrnd_board_bbox(&bb, wctx->ctx->board); + mx = (bb.p2.x - bb.p1.x) * 0.15; + my = (bb.p2.y - bb.p1.y) * 0.15; + fprintf(wctx->f, "\n"); + fprintf(wctx->f, "f, " viewBox=\"%f %f %f %f\"", SVX(bb.p1.x-mx), SVY(bb.p1.y-my), SVX(bb.p2.x+mx), SVY(bb.p2.y+my)); +#endif + fprintf(wctx->f, ">\n"); +} + +static void svg_wr_foot(wr_ctx_t *wctx) +{ + fprintf(wctx->f, ""); +} + +static void svg_wr_via(wr_ctx_t *wctx, rtrnd_via_t *via) +{ + fprintf(wctx->f, " \n", + SVX(via->x), SVY(via->y), SV((double)via->dia/2)); +} + +static void svg_wr_layer(wr_ctx_t *wctx, rtrnd_layer_t *layer, int draw_vias) +{ + rtrnd_rtree_it_t it; + rtrnd_any_obj_t *obj; + rtp_vertex_t *v; + + fprintf(wctx->f, "\n", layer->name, translucent); + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) { + switch(obj->hdr.type) { + case RTRND_LINE: + fprintf(wctx->f, " \n", + SVX(obj->line.cline.p1.x), SVY(obj->line.cline.p1.y), + SVX(obj->line.cline.p2.x), SVY(obj->line.cline.p2.y), + SV(obj->line.thickness), layer->color); + break; + case RTRND_TEXT: + fprintf(wctx->f, " %s\n", + SVX(obj->text.x), SVY(obj->text.y), SV(obj->text.size), SV(obj->text.size/50.0), + layer->color, layer->color, obj->text.hdr.oid); + break; + case RTRND_POLY: + fprintf(wctx->f, " \n", layer->color); + break; + case RTRND_ARC: + { + double sa = obj->arc.carc.start; + double da = obj->arc.carc.delta; + double ea = sa + da; + double r = obj->arc.carc.r; + double diff = 0, x1, y1, x2, y2; + int large = (fabs(da) > M_PI); + int sweep = !(da > 0.0); + + if (fabs(da) <= 0.001) { da = 0.001; diff=0.001; } + rtrnd_arc_xy(&obj->arc, sa, &x2, &y2); + rtrnd_arc_xy(&obj->arc, ea, &x1, &y1); + + x1 += diff; y1 += diff; + + fprintf(wctx->f, "\n", + SVX(x1), SVY(y1), SV(r), SV(r), large, sweep, SVX(x2), SVY(y2), + SV(obj->arc.thickness), layer->color); + } + + default: /* can't be on layer */ + break; + } + } + + if (draw_vias) { + rtrnd_via_t *via; + for(via = rtrnd_rtree_all_first(&it, &wctx->ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) + if (rtrnd_via_touches_layer(layer, via)) + svg_wr_via(wctx, via); + } + + fprintf(wctx->f, "\n"); +} + +static int svg_export(rtrnd_t *ctx, const char *basename, rtrnd_layer_t *layer, vtp0_t *annots) +{ + wr_ctx_t wctx; + int res = 0, len = strlen(basename), n; + + wctx.fn = malloc(len + 32); + memcpy(wctx.fn, basename, len); + strcpy(wctx.fn + len, ".svg"); + wctx.ctx = ctx; + wctx.f = fopen(wctx.fn, "w"); + if (wctx.f == NULL) { + fprintf(stderr, ERROR "can't open '%s' for write\n", wctx.fn); + goto err; + } + + svg_wr_head(&wctx); + if (layer == NULL) { + if ((ctx->board != NULL) && (ctx->board->layers.used > 0)) { + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + + for(n = ctx->board->layers.used-1; n >=0 ; n--) + svg_wr_layer(&wctx, ctx->board->layers.array[n], 0); + fprintf(wctx.f, "\n", translucent); + for(via = rtrnd_rtree_all_first(&it, &ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) + svg_wr_via(&wctx, via); + fprintf(wctx.f, ""); + } + else + fprintf(wctx.f, "\n"); + } + else + svg_wr_layer(&wctx, layer, 1); + + if (annots != NULL) + for(n = 0; n < annots->used; n++) + svg_wr_layer(&wctx, annots->array[n], 0); + svg_wr_foot(&wctx); + + err:; + free(wctx.fn); + if (wctx.f != NULL) + fclose(wctx.f); + return res; +} + + +static const rtrnd_export_t exp_svg = { + "svg", + svg_export +}; + +void export_svg_init(void) +{ + vtp0_append(&rtrnd_all_export, (void *)&exp_svg); +} Index: tags/0.9.0/src/plugins/io_tedax/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/io_tedax/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/io_tedax/Makefile.inc (revision 1402) @@ -0,0 +1,3 @@ +BUILDIN_IO_TEDAX = \ + $(PLG)/io_tedax/parse.o \ + $(PLG)/io_tedax/io_tedax.o Index: tags/0.9.0/src/plugins/io_tedax/io_tedax.c =================================================================== --- tags/0.9.0/src/plugins/io_tedax/io_tedax.c (nonexistent) +++ tags/0.9.0/src/plugins/io_tedax/io_tedax.c (revision 1402) @@ -0,0 +1,584 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * tedax IO plugin - load and save files in the tEDAx format + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "data.h" +#include "parse.h" +#include "compat_misc.h" +#include "conf.h" + +#define ERROR "route-rnd tEDAx error: " + +typedef struct { + rtrnd_t *ctx; + FILE *f; + char line[520], *argv[16]; + + htsp_t stackups, layers, polylines; + char *stackup_name; +} load_ctx_t; + +#define TEDAX_GETLINE(lctx) \ + tedax_getline(lctx->f, lctx->line, sizeof(lctx->line), lctx->argv, (sizeof(lctx->argv)/sizeof(lctx->argv[0]))) + +#define setup_loader(ht, type, locvar, blockname, name, namedup) \ +do { \ + locvar = htsp_get(ht, name); \ + if (locvar != NULL) { \ + fprintf(stderr, ERROR "multiple " blockname " with the same name: %s\n", name); \ + return -1; \ + } \ + locvar = calloc(sizeof(type), 1); \ + htsp_set(ht, (char *)(namedup = rnd_strdup(name)), locvar); \ +} while(0) + +typedef struct { + vts0_t layers; + gds_t layer_locs; + htss_t colors; /* layer name -> color string */ +} stackup_t; + +int tedax_load_stackup(load_ctx_t *lctx, const char *name) +{ + int argc; + stackup_t *stackup; + const char *namedup; + + setup_loader(&lctx->stackups, stackup_t, stackup, "stackup", name, namedup); + htss_init(&stackup->colors, strhash, strkeyeq); + + while((argc = TEDAX_GETLINE(lctx)) >= 0) { + if ((argc > 3) && (strcmp(lctx->argv[0], "layer") == 0) && (strcmp(lctx->argv[3], "copper") == 0)) { + vts0_append(&stackup->layers, rnd_strdup(lctx->argv[1])); + gds_append(&stackup->layer_locs, lctx->argv[2][0]); + } + if ((argc > 3) && (strcmp(lctx->argv[0], "lprop") == 0) && (strcmp(lctx->argv[2], "display-color") == 0)) { + const char *clr = htss_get(&stackup->colors, lctx->argv[1]); + if (clr == NULL) { + char *s = lctx->argv[3]; + int len, valid = 1; + if (*s != '#') valid = 0; + for(s++, len = 0; *s != '\0'; s++,len++) { + if (len >= 6) { + valid = 0; + break; + } + if (isdigit(*s) || ((*s >= 'a') && (*s <= 'f')) || ((*s >= 'A') && (*s <= 'F'))) + continue; + valid = 0; + break; + } + if (valid) + htss_set(&stackup->colors, rnd_strdup(lctx->argv[1]), rnd_strdup(lctx->argv[3])); + else + fprintf(stderr, ERROR "invalid color '%s' ignored for layer %s in layerstack %s\n", lctx->argv[3], lctx->argv[1], namedup); + } + else + fprintf(stderr, ERROR "duplicate color ignored for layer %s in layerstack %s\n", lctx->argv[1], namedup); + } + else if ((argc == 2) && (strcmp(lctx->argv[0], "end") == 0) && (strcmp(lctx->argv[1], "stackup") == 0)) + return 0; + } + fprintf(stderr, ERROR "unterminated stackup\n"); + return -1; +} + +int tedax_load_polyline(load_ctx_t *lctx, const char *name) +{ + char *dname; + vtd0_t *v; + int argc; + + v = htsp_get(&lctx->polylines, name); + if (v != NULL) { + fprintf(stderr, ERROR "Duplicate polyline: '%s'\n", name); + return -1; + } + + v = calloc(sizeof(vtd0_t), 1); + dname = rnd_strdup(name); + htsp_set(&lctx->polylines, dname, v); + + while((argc = TEDAX_GETLINE(lctx)) >= 0) { + if ((argc > 2) && (strcmp(lctx->argv[0], "v") == 0)) { + char *end; + double x, y; + x = strtod(lctx->argv[1], &end); + if (*end != '\0') { + fprintf(stderr, ERROR "Invalid polyline x coord: '%s' in polyline '%s'\n", lctx->argv[1], dname); + return -1; + } + y = strtod(lctx->argv[2], &end); + if (*end != '\0') { + fprintf(stderr, ERROR "Invalid polyline y coord: '%s' in polyline '%s'\n", lctx->argv[2], dname); + return -1; + } + vtd0_append(v, x); + vtd0_append(v, y); + } + else if ((argc == 2) && (strcmp(lctx->argv[0], "end") == 0) && (strcmp(lctx->argv[1], "polyline") == 0)) { + if (v->used < 6) { + fprintf(stderr, ERROR "Invalid polyline '%s': too few corners (%ld/2)\n", dname, v->used); + return -1; + } + return 0; + } + } + + fprintf(stderr, ERROR "unterminated polyline '%s'\n", dname); + return -1; +} + + +#define conv_coord(dst, src) \ +do { \ + char *end; \ + dst = strtod(lctx->argv[src], &end); \ + if (*end != '\0') { \ + fprintf(stderr, ERROR "invalid coord '%s'\n", lctx->argv[src]); \ + return -1; \ + } \ +} while(0) + +#define conv_net(dst, src) \ +do { \ + const char *netname = lctx->argv[src]; \ + if ((netname[0] == '-') && (netname[1] == '\0')) dst = NULL; \ + else { \ + dst = htsp_get(&lctx->ctx->board->nets, netname); \ + if (dst == NULL) { \ + dst = calloc(sizeof(rtrnd_net_t), 1); \ + dst->hdr.oid = rnd_strdup(netname); \ + htsp_set(&lctx->ctx->board->nets, dst->hdr.oid, dst); \ + } \ + } \ +} while(0) + +#define conv_constraints(dst, src) \ +do { \ + const char *s; \ + for(s = lctx->argv[src]; *s != '\0'; s++) { \ + switch(*s) { \ + case 'd': dst->hdr.cnst_del = 1; break; \ + case 'm': dst->hdr.cnst_move = 1; break; \ + case 't': dst->hdr.terminal = 1; break; \ + } \ + } \ +} while(0) + +int tedax_load_layernet(load_ctx_t *lctx, const char *name) +{ + int argc; + rtrnd_any_obj_t *obj; + rtrnd_layer_t *layer; + rtrnd_net_t *net; + const char *namedup; + + setup_loader(&lctx->layers, rtrnd_layer_t, layer, "layernet", name, namedup); + rtrnd_layer_init(layer, name); + + while((argc = TEDAX_GETLINE(lctx)) >= 0) { + if ((argc > 9) && (strcmp(lctx->argv[0], "line") == 0)) { + double x1, y1, x2, y2, thick, clr; + + conv_net(net, 2); + conv_coord(x1, 4); conv_coord(y1, 5); + conv_coord(x2, 6); conv_coord(y2, 7); + conv_coord(thick, 8); conv_coord(clr, 9); + + obj = (rtrnd_any_obj_t *)rtrnd_line_new(layer, lctx->argv[1], net, x1, y1, x2, y2, thick, clr); + + conv_constraints(obj, 3); + } + else if ((argc > 10) && (strcmp(lctx->argv[0], "arc") == 0)) { + double cx, cy, r, sa, da, thick, clr; + + conv_net(net, 2); + conv_coord(cx, 4); conv_coord(cy, 5); + conv_coord(r, 6); + conv_coord(sa, 7); conv_coord(da, 8); + conv_coord(thick, 9); conv_coord(clr, 10); + + sa = RTRND_DEG2RAD(180.0-sa); + da = -RTRND_DEG2RAD(da); + + obj = (rtrnd_any_obj_t *)rtrnd_arc_new(layer, lctx->argv[1], net, cx, cy, r, sa, da, thick, clr); + } + else if ((argc > 3) && (strcmp(lctx->argv[0], "poly") == 0)) { + double ox, oy; + vtd0_t *v; + + v = htsp_get(&lctx->polylines, lctx->argv[4]); + if (v == NULL) { + fprintf(stderr, ERROR "invalid layernet poly %s: no such polyline defined\n", lctx->line); + return -1; + } + + conv_net(net, 2); + conv_coord(ox, 5); conv_coord(oy, 6); + + obj = (rtrnd_any_obj_t *)rtrnd_poly_new_from_xys(layer, lctx->argv[1], net, v->array, v->used, ox, oy); + + conv_constraints(obj, 3); + } + else if ((argc == 2) && (strcmp(lctx->argv[0], "end") == 0) && (strcmp(lctx->argv[1], "layernet") == 0)) { + return 0; + } + else { + fprintf(stderr, ERROR "invalid layernet line '%s' in layernet '%s'\n", lctx->line, namedup); + return -1; + } + } + fprintf(stderr, ERROR "unterminated stackup %s\n", namedup); + return -1; +} + +int tedax_load_via(load_ctx_t *lctx) +{ + + double x, y, dia, clr; + rtrnd_any_obj_t *obj; + rtrnd_net_t *net; + + conv_net(net, 2); + conv_coord(x, 4); conv_coord(y, 5); + conv_coord(dia, 6); conv_coord(clr, 7); + +#warning TODO: Ignores bbvia aspects + + obj = (rtrnd_any_obj_t *)rtrnd_via_new(lctx->ctx->board, lctx->argv[1], net, x, y, dia, clr); + + conv_constraints(obj, 3); + return 0; +} + + +int tedax_load_route_req(load_ctx_t *lctx, const char *name) +{ + int argc; + + lctx->ctx->name = rnd_strdup(name); + + while((argc = TEDAX_GETLINE(lctx)) >= 0) { + if ((argc > 1) && (strcmp(lctx->argv[0], "stackup") == 0)) { + lctx->stackup_name = rnd_strdup(lctx->argv[1]); + } + else if (strcmp(lctx->argv[0], "via") == 0) { + if (tedax_load_via(lctx) != 0) + return -1; + } + else if ((argc > 0) && (strcmp(lctx->argv[0], "route_all") == 0)) { + /* TODO */ + } + else if ((argc > 0) && (strcmp(lctx->argv[0], "conf") == 0)) { + if (rtrnd_conf_set(lctx->ctx->rt->conf, lctx->argv[1], lctx->argv[2]) != 0) + fprintf(stderr, ERROR "invalid conf setting for '%s' (ignored)\n", lctx->argv[1]); + } + else if ((argc == 2) && (strcmp(lctx->argv[0], "end") == 0) && (strcmp(lctx->argv[1], "route_req") == 0)) { + return 0; + } + else { + fprintf(stderr, ERROR "invalid route_req line %s\n", lctx->line); + return -1; + } + } + + return -1; +} + +static int tedax_apply_stackup(load_ctx_t *lctx) +{ + stackup_t *istack; + long n; + + printf("apply stackup %s\n", lctx->stackup_name); + if (lctx->stackup_name == NULL) { + fprintf(stderr, ERROR "invalid route_req: no stackup named\n"); + return -1; + } + + istack = htsp_get(&lctx->stackups, lctx->stackup_name); + if (istack == NULL) { + fprintf(stderr, ERROR "invalid route_req: stackup '%s' is not defined\n", lctx->stackup_name); + return -1; + } + + + for(n = 0; n < istack->layers.used; n++) { + const char *layername = istack->layers.array[n], *clr; + char loc = istack->layer_locs.array[n]; + htsp_entry_t *e = htsp_popentry(&lctx->layers, layername); + rtrnd_layer_t *layer; + if (e == NULL) { + fprintf(stderr, ERROR "invalid stackup '%s': refers to non-existent copper layernet '%s'\n", lctx->stackup_name, layername); + return -1; + } + free(e->key); + layer = e->value; + vtp0_append(&lctx->ctx->board->layers, layer); + clr = htss_get(&istack->colors, layername); + if (clr != NULL) + strcpy(layer->color, clr); + else + strcpy(layer->color, "#990000"); + switch(loc) { + case 't': layer->loc = RTRND_LLOC_TOP; break; + case 'i': layer->loc = RTRND_LLOC_INTERN; break; + case 'b': layer->loc = RTRND_LLOC_BOTTOM; break; + } + } + + return 0; +} + +static int tedax_load(rtrnd_t *ctx, FILE *f) +{ + load_ctx_t lctx; + int argc, res = 0; + + memset(&lctx, 0, sizeof(lctx)); + lctx.ctx = ctx; + lctx.f = f; + + lctx.ctx->board = rtrnd_board_new(); + + htsp_init(&lctx.stackups, strhash, strkeyeq); + htsp_init(&lctx.layers, strhash, strkeyeq); + htsp_init(&lctx.polylines, strhash, strkeyeq); + + while((argc = tedax_getline(f, lctx.line, sizeof(lctx.line), lctx.argv, sizeof(lctx.argv)/sizeof(lctx.argv[0]))) >= 0) { + if (strcmp(lctx.argv[0], "begin") == 0) { + if ((strcmp(lctx.argv[1], "stackup") == 0) && (tedax_load_stackup(&lctx, lctx.argv[3]) != 0)) { + res = -1; + break; + } + if ((strcmp(lctx.argv[1], "layernet") == 0) && (tedax_load_layernet(&lctx, lctx.argv[3]) != 0)) { + res = -1; + break; + } + if ((strcmp(lctx.argv[1], "polyline") == 0) && (tedax_load_polyline(&lctx, lctx.argv[3]) != 0)) { + res = -1; + break; + } + if ((strcmp(lctx.argv[1], "route_req") == 0) && (tedax_load_route_req(&lctx, lctx.argv[3]) != 0)) { + res = -1; + break; + } + } + } + + if (res == 0) + res = tedax_apply_stackup(&lctx); + + genht_uninit_deep(htsp, &lctx.stackups, { /* remove layers of unused stacks */ + int n; + stackup_t *stackup = htent->value; + for(n = 0; n < stackup->layers.used; n++) + free(stackup->layers.array[n]); + vts0_uninit(&stackup->layers); + gds_uninit(&stackup->layer_locs); + genht_uninit_deep(htss, &stackup->colors, { /* remove layer colors */ + free(htent->key); + free(htent->value); + }); + free(stackup); + free(htent->key); + }); + free(lctx.stackup_name); + + genht_uninit_deep(htsp, &lctx.polylines, { + vtd0_t *v = htent->value; + vtd0_uninit(v); + free(v); + free(htent->key); + }); + + genht_uninit_deep(htsp, &lctx.layers, { + free(htent->key); + free(htent->value); + }); + + return res; +} + +static int tedax_save_begin(rtrnd_t *ctx, FILE *f) +{ + fprintf(f, "tEDAx v1\n"); + fprintf(f, "begin route_res v1 "); + tedax_fprint_escape(f, ctx->name); + fprintf(f, "\n"); + return 0; +} + +static int tedax_save_add(rtrnd_t *ctx, FILE *f, const rtrnd_any_obj_t *obj) +{ + switch(obj->hdr.type) { + case RTRND_LINE: + fprintf(f, " add "); + tedax_fprint_escape(f, obj->hdr.parent->layer.name); + fprintf(f, " line "); + tedax_fprint_escape(f, obj->hdr.oid); + fprintf(f, " "); + tedax_fprint_escape(f, obj->hdr.net == NULL ? "-" : obj->hdr.net->hdr.oid); + fprintf(f, " %f %f %f %f %f %f\n", + obj->line.cline.p1.x, obj->line.cline.p1.y, + obj->line.cline.p2.x, obj->line.cline.p2.y, + obj->line.thickness, obj->line.clearance); + return 0; + + case RTRND_VIA: + fprintf(f, " add - via "); + tedax_fprint_escape(f, obj->hdr.oid); + fprintf(f, " "); + tedax_fprint_escape(f, obj->hdr.net == NULL ? "-" : obj->hdr.net->hdr.oid); + fprintf(f, " %f %f %f %f\n", + obj->via.x, obj->via.y, + obj->via.dia, obj->via.clearance); + + return 0; + + case RTRND_ARC: + fprintf(f, " add "); + tedax_fprint_escape(f, obj->hdr.parent->layer.name); + fprintf(f, " arc "); + tedax_fprint_escape(f, obj->hdr.oid); + fprintf(f, " "); + tedax_fprint_escape(f, obj->hdr.net == NULL ? "-" : obj->hdr.net->hdr.oid); + fprintf(f, " %f %f %f %f %f %f %f %f %f %f %f\n", + obj->arc.carc.c.x, obj->arc.carc.c.y, obj->arc.carc.r, + 180.0-RTRND_RAD2DEG(obj->arc.carc.start), -RTRND_RAD2DEG(obj->arc.carc.delta), + obj->arc.thickness, obj->arc.clearance, + obj->arc.carc.c.x + cos(obj->arc.carc.start) * obj->arc.carc.r, obj->arc.carc.c.y + sin(obj->arc.carc.start) * obj->arc.carc.r, + obj->arc.carc.c.x + cos(obj->arc.carc.start + obj->arc.carc.delta) * obj->arc.carc.r, obj->arc.carc.c.y + sin(obj->arc.carc.start + obj->arc.carc.delta) * obj->arc.carc.r); + + break; + + case RTRND_POLY: +#warning TODO + break; + + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + break; + } + return -1; +} + +int tedax_save_log(rtrnd_t *ctx, FILE *f, char level, char *msg, int len) +{ + switch(level) { + case 'I': case 'W': case 'E': + if (len > 500) + strcpy(msg+496, "..."); + fprintf(f, " log %c ", level); + tedax_fprint_escape(f, msg); + fprintf(f, " "); + break; + } + return 0; +} + +static int tedax_save_confkey(rtrnd_t *ctx, FILE *f, const rtrnd_conf_t *item) +{ + fprintf(f, " confkey "); + tedax_fprint_escape(f, item->name); + fprintf(f, " %s", rtrnd_conf_type2name(item->type)); + + /* print default:min:max, per type */ + switch(item->type) { + case RTRND_CT_BOOLEAN: + fprintf(f, " %d", (int)item->defval.dval); + break; + case RTRND_CT_INTEGER: + fprintf(f, " %ld", (long)item->defval.dval); + if (item->min != RTRND_CONF_NOVAL) { + fprintf(f, ":%ld", (long)item->min); + if (item->max != RTRND_CONF_NOVAL) + fprintf(f, ":%ld", (long)item->max); + } + break; + case RTRND_CT_DOUBLE: + case RTRND_CT_COORD: + fprintf(f, " %f", item->defval.dval); + if (item->min != RTRND_CONF_NOVAL) { + fprintf(f, ":%f", item->min); + if (item->max != RTRND_CONF_NOVAL) + fprintf(f, ":%f", item->max); + } + break; + case RTRND_CT_STRING: + fprintf(f, " "); + tedax_fprint_escape(f, item->defval.sval); + break; + case RTRND_CT_TERMINATOR: + default: + fprintf(f, " -"); + break; + } + + /* print desc" */ + fprintf(f, " "); + tedax_fprint_escape(f, item->desc); + fprintf(f, "\n"); + + return 0; +} + +static int tedax_save_end(rtrnd_t *ctx, FILE *f) +{ + fprintf(f, "end route_res\n"); + return 0; +} + + +static const rtrnd_io_t io_tedax = { + "tEDAx", + rtrnd_tedax_test_parse, + tedax_load, + tedax_save_begin, + tedax_save_add, + tedax_save_log, + tedax_save_confkey, + tedax_save_end +}; + +void io_tedax_init(void) +{ + vtp0_append(&rtrnd_all_io, (void *)&io_tedax); +} Index: tags/0.9.0/src/plugins/io_tedax/parse.c =================================================================== --- tags/0.9.0/src/plugins/io_tedax/parse.c (nonexistent) +++ tags/0.9.0/src/plugins/io_tedax/parse.c (revision 1402) @@ -0,0 +1,210 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * pcb-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * This file was copied from pcb-rnd, interactive printed circuit board design + * + * tedax IO plugin - low level parser, similar to the reference implementation + * pcb-rnd Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "parse.h" + +#define ERROR "route-rnd tEDAx error: " + + +int tedax_getline(FILE *f, char *buff, int buff_size, char *argv[], int argv_size) +{ + int argc; + + for(;;) { + char *s, *o; + + if (fgets(buff, buff_size, f) == NULL) + return -1; + + s = buff; + if (*s == '#') /* comment */ + continue; + ltrim(s); + rtrim(s); + if (*s == '\0') /* empty line */ + continue; + + /* argv split */ + for(argc = 0, o = argv[0] = s; *s != '\0';) { + if (*s == '\\') { + s++; + switch(*s) { + case 'r': *o = '\r'; break; + case 'n': *o = '\n'; break; + case 't': *o = '\t'; break; + default: *o = *s; + } + o++; + s++; + continue; + } + if ((argc+1 < argv_size) && ((*s == ' ') || (*s == '\t'))) { + *o = *s = '\0'; + s++; + o++; + while((*s == ' ') || (*s == '\t')) + s++; + argc++; + argv[argc] = o; + } + else { + *o = *s; + s++; + o++; + } + } + *o = '\0'; + return argc+1; /* valid line, split up */ + } + + return -1; /* can't get here */ +} + +int tedax_seek_hdr(FILE *f, char *buff, int buff_size, char *argv[], int argv_size) +{ + int argc; + + /* look for the header */ + if ((argc = tedax_getline(f, buff, buff_size, argv, argv_size)) < 2) { + fprintf(stderr, ERROR "Can't find tEDAx header (no line)\n"); + return -1; + } + + if ((argv[1] == NULL) || (rnd_strcasecmp(argv[0], "tEDAx") != 0) || (rnd_strcasecmp(argv[1], "v1") != 0)) { + fprintf(stderr, ERROR "Can't find tEDAx header (wrong line)\n"); + return -1; + } + + return argc; +} + + +int tedax_seek_block(FILE *f, const char *blk_name, const char *blk_ver, const char *blk_id, int silent, char *buff, int buff_size, char *argv[], int argv_size) +{ + int argc; + + /* seek block begin */ + while((argc = tedax_getline(f, buff, buff_size, argv, argv_size)) >= 0) + if ((argc > 2) && (strcmp(argv[0], "begin") == 0) && (strcmp(argv[1], blk_name) == 0) && ((blk_ver == NULL) || (strcmp(argv[2], blk_ver) == 0)) && ((blk_id == NULL) || (strcmp(argv[3], blk_id) == 0))) + break; + + if (argc < 2) { + if (!silent) + fprintf(stderr, ERROR "Can't find %s %s block in tEDAx\n", blk_ver, blk_name); + return -1; + } + + return argc; +} + +void tedax_fprint_escape(FILE *f, const char *val) +{ + if ((val == NULL) || (*val == '\0')) { + fputc('-', f); + return; + } + for(; *val != '\0'; val++) { + switch(*val) { + case '\\': fputc('\\', f); fputc('\\', f); break; + case '\n': fputc('\\', f); fputc('n', f); break; + case '\r': fputc('\\', f); fputc('r', f); break; + case '\t': fputc('\\', f); fputc('t', f); break; + case ' ': fputc('\\', f); fputc(' ', f); break; + default: + fputc(*val, f); + } + } +} + +#define APPEND(c) \ + do { \ + if (dstlen == 0) { \ + res = -1; \ + goto quit; \ + } \ + *d = c; \ + d++; \ + dstlen--; \ + } while(0) + +int tedax_strncpy_escape(char *dst, int dstlen, const char *val) +{ + int res = 0; + char *d = dst; + + assert(dstlen > 2); + if ((val == NULL) || (*val == '\0')) { + dst[0] = '-'; + dst[1] = '\0'; + return 0; + } + dstlen--; /* one for \0 */ + for(; *val != '\0'; val++) { + switch(*val) { + case '\\': APPEND('\\'); APPEND('\\'); break; + case '\n': APPEND('\\'); APPEND('n'); break; + case '\r': APPEND('\\'); APPEND('r'); break; + case '\t': APPEND('\\'); APPEND('t'); break; + case ' ': APPEND('\\'); APPEND(' '); break; + default: + APPEND(*val); + } + } + quit:; + *d = '\0'; + return res; +} + + +int rtrnd_tedax_test_parse(FILE *f) +{ + char line[515], *s; + int n; + for(n = 0; n < 32; n++) { + s = fgets(line, sizeof(line), f); + if (s == NULL) + return 0; + while(isspace(*s)) s++; + if (*s == '#') + continue; + if (strncmp(s, "tEDAx", 5) == 0) { + s += 5; + while(isspace(*s)) s++; + if ((s[0] == 'v') && (s[1] == '1')) + return 1; /* support version 1 only */ + } + } + return 0; +} Index: tags/0.9.0/src/plugins/io_tedax/parse.h =================================================================== --- tags/0.9.0/src/plugins/io_tedax/parse.h (nonexistent) +++ tags/0.9.0/src/plugins/io_tedax/parse.h (revision 1402) @@ -0,0 +1,32 @@ +#include +#include +#include + +/* remove leading whitespace */ +#define ltrim(s) while(isspace(*s)) s++ + +/* remove trailing newline;; trailing backslash is an error */ +#define rtrim(s) \ + do { \ + char *end; \ + for(end = s + strlen(s) - 1; (end >= s) && ((*end == '\r') || (*end == '\n')); end--) \ + *end = '\0'; \ + if (*end == '\\') \ + return -1; \ + } while(0) + +#define null_empty(s) ((s) == NULL ? "" : (s)) + +int tedax_getline(FILE *f, char *buff, int buff_size, char *argv[], int argv_size); + +int tedax_seek_hdr(FILE *f, char *buff, int buff_size, char *argv[], int argv_size); +int tedax_seek_block(FILE *f, const char *blk_name, const char *blk_ver, const char *blk_id, int silent, char *buff, int buff_size, char *argv[], int argv_size); + + +/* print val with special chars escaped. Prints a single dash if val is NULL or empty. */ +void tedax_fprint_escape(FILE *f, const char *val); +int tedax_strncpy_escape(char *dst, int dstlen, const char *val); + +/* Returns non-zero if the file looks like a tEDAx document (cheap test-parse) */ +int rtrnd_tedax_test_parse(FILE *f); + Index: tags/0.9.0/src/plugins/rt_hace/Makefile =================================================================== --- tags/0.9.0/src/plugins/rt_hace/Makefile (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/Makefile (revision 1402) @@ -0,0 +1,6 @@ +all_: + make all + +%: + cd ../../route-rnd && make $@ + Index: tags/0.9.0/src/plugins/rt_hace/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/rt_hace/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/Makefile.inc (revision 1402) @@ -0,0 +1,7 @@ +BUILDIN_RT_HACE = \ + $(PLG)/rt_hace/rnd_rtree.o \ + $(PLG)/rt_hace/heap.o \ + $(PLG)/rt_hace/vector.o \ + $(PLG)/rt_hace/mtspace.o \ + $(PLG)/rt_hace/autoroute.o + Index: tags/0.9.0/src/plugins/rt_hace/autoroute.c =================================================================== --- tags/0.9.0/src/plugins/rt_hace/autoroute.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/autoroute.c (revision 1402) @@ -0,0 +1,4649 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, autoroute.c, was written and is + * Copyright (c) 2001 C. Scott Ananian + * Copyright (c) 2006 harry eaton + * Copyright (c) 2009 harry eaton + * + * Updated for pcb-rnd for subcircuits, padstacks and netlist + * Copyright (c) 2018,2019 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* + *------------------------------------------------------------------- + * This file implements a rectangle-expansion router, based on + * "A Method for Gridless Routing of Printed Circuit Boards" by + * A. C. Finch, K. J. Mackenzie, G. J. Balsdon, and G. Symonds in the + * 1985 Proceedings of the 22nd ACM/IEEE Design Automation Conference. + * This reference is available from the ACM Digital Library at + * http://www.acm.org/dl for those with institutional or personal + * access to it. It's also available from your local engineering + * library. + * + * The code is much closer to what is described in the paper now, + * in that expansion areas can grow from corners and in all directions + * at once. Previously, these were emulated with discrete boxes moving + * in the cardinal directions. With the new method, there are fewer but + * larger expansion boxes that one might do a better job of routing in. + *-------------------------------------------------------------------- + */ +#define NET_HEAP 1 +#include "config.h" + +#include +#include + +#include "data.h" +#include "heap.h" +#include "rnd_rtree.h" +#include "route_res.h" +#include "mtspace.h" +#include "vector.h" +#include "util_rat.h" +#include + +#define ERROR "route-rnd rt-hace error: " +#define WARNING "route-rnd rt-hace warning: " +#define INFO "route-rnd rt-hace info: " + +#define MAPPED(obj) ((obj)->hdr.rt_data.l[0]) + +/* #defines to enable some debugging output */ +/* +#define ROUTE_VERBOSE +*/ + +/* +#define ROUTE_DEBUG +//#define DEBUG_SHOW_ROUTE_BOXES +#define DEBUG_SHOW_EXPANSION_BOXES +//#define DEBUG_SHOW_EDGES +//#define DEBUG_SHOW_VIA_BOXES +#define DEBUG_SHOW_TARGETS +#define DEBUG_SHOW_SOURCES +//#define DEBUG_SHOW_ZIGZAG +*/ + +#warning TODO: check/set up these: +#define PCB_MAX_LAYERGRP 128 +#define RND_MAX_COORD HUGE_VAL +#define RTRND_VOID 0 +static rtrnd_board_t *PCB; + +static double wire_thick, wire_clr, via_dia, via_clr; +static rtrnd_conf_t hace_cfg_desc[] = { + RTRND_CONF_COORD("wire_thick", 0.25, 0.01, 10, "signal wire thickness", &wire_thick) + RTRND_CONF_COORD("wire_clr", 0.25, 0.01, 10, "clearance around signal wire", &wire_clr) + RTRND_CONF_COORD("via_dia", 1.6, 0.01, 10, "via copper ring outer diameter", &via_dia) + RTRND_CONF_COORD("via_clr", 0.25, 0.01, 10, "clearance around via copper", &via_clr) + RTRND_CONF_TERMINATE +}; + + +typedef long rnd_layergrp_id_t; + +typedef enum { + RND_NORTH = 0, RND_EAST = 1, RND_SOUTH = 2, RND_WEST = 3, + RND_NE = 4, RND_SE = 5, RND_SW = 6, RND_NW = 7, RND_ANY_DIR = 8 +} rnd_direction_t; + +static rnd_direction_t directionIncrement(rnd_direction_t dir) +{ + switch (dir) { + case RND_NORTH: + dir = RND_EAST; + break; + case RND_EAST: + dir = RND_SOUTH; + break; + case RND_SOUTH: + dir = RND_WEST; + break; + case RND_WEST: + dir = RND_NE; + break; + case RND_NE: + dir = RND_SE; + break; + case RND_SE: + dir = RND_SW; + break; + case RND_SW: + dir = RND_NW; + break; + case RND_NW: + dir = RND_ANY_DIR; + break; + case RND_ANY_DIR: + dir = RND_NORTH; + break; + } + return dir; +} + +#ifdef ROUTE_DEBUG +rnd_hid_t *ddraw = NULL; +static rnd_hid_gc_t ar_gc = 0; +#endif + +#define EXPENSIVE 3e28 +/* round up "half" thicknesses */ +#define HALF_THICK(x) (((x)+1)/2) +/* a styles maximum bloat is its clearance plus the larger of its via radius + * or line half-thickness. */ +#define BLOAT(style)\ + ((style)->Clearance + HALF_THICK((style)->Thickness)) +/* conflict penalty is less for traces laid down during previous pass than + * it is for traces already laid down in this pass. */ +#define CONFLICT_LEVEL(rb)\ + (((rb)->flags.is_odd==AutoRouteParameters.is_odd) ?\ + HI_CONFLICT : LO_CONFLICT ) +#define CONFLICT_PENALTY(rb)\ + ((CONFLICT_LEVEL(rb)==HI_CONFLICT ? \ + AutoRouteParameters.ConflictPenalty : \ + CONFLICT_LEVEL(rb)==LO_CONFLICT ? \ + AutoRouteParameters.LastConflictPenalty : 1) * (rb)->pass) + +#define _NORTH 1 +#define _EAST 2 +#define _SOUTH 4 +#define _WEST 8 + +#define PCB_END_LOOP }} while (0) + +#define LIST_LOOP(init, which, x) do {\ + routebox_t *__next_one__ = (init);\ + x = NULL;\ + if (!__next_one__)\ + assert(__next_one__);\ + else\ + while (!x || __next_one__ != (init)) {\ + x = __next_one__;\ + /* save next one first in case the command modifies or frees it */\ + __next_one__ = x->which.next + +#define FOREACH_SUBNET(net, p) do {\ + routebox_t *_pp_;\ + /* iterate through *distinct* subnets */\ + LIST_LOOP(net, same_net, p); \ + if (!p->flags.subnet_processed) {\ + LIST_LOOP(p, same_subnet, _pp_);\ + _pp_->flags.subnet_processed=1;\ + PCB_END_LOOP +#define END_FOREACH(net, p) \ + }; \ + PCB_END_LOOP;\ + /* reset subnet_processed flags */\ + LIST_LOOP(net, same_net, p); \ + p->flags.subnet_processed=0;\ + PCB_END_LOOP;\ +} while (0) +#define SWAP(t, f, s) do { t a=s; s=f; f=a; } while (0) +/* notes: + * all rectangles are assumed to be closed on the top and left and + * open on the bottom and right. That is, they include their top-left + * corner but don't include their bottom and right edges. + * + * expansion regions are always half-closed. This means that when + * tracing paths, you must steer clear of the bottom and right edges., + * because these are not actually in the allowed box. + * + * All routeboxes *except* EXPANSION_AREAS now have their "box" bloated by + * their particular required clearance. This simplifies the tree searching. + * the "sbox" contains the unbloated box. + */ + +/* enumerated type for conflict levels */ +typedef enum { NO_CONFLICT = 0, LO_CONFLICT = 1, HI_CONFLICT = 2 } conflict_t; + +typedef struct routebox_s routebox_t; + +typedef struct routebox_list_s { + routebox_t *next, *prev; +} routebox_list_t; + +typedef enum etype { TERM, VIA, VIA_SHADOW, LINE, OTHER, EXPANSION_AREA, PLANE, THERMAL } etype; + +typedef struct { + double Thickness, Clearance, Diameter; +} pcb_route_style_t; + +struct routebox_s { + rtrnd_rtree_box_t box, sbox; + struct { + double x1, y1, x2, y2; + } line; /* exact coords of the line we are going to draw if type is line; reverse engineering these from the bounding box using halfthick and other hacks lead to rounding errors, a few LSB flicker in coords, e.g. breaking rubber band */ + union { + rtrnd_via_t *via; + rtrnd_any_obj_t *term; + routebox_t *via_shadow; /* points to the via in r-tree which + * points to the rtrnd_via_t in the PCB. */ + rtrnd_line_t *line; + void *generic; /* 'other' is polygon, arc */ + routebox_t *expansion_area; /* previous expansion area in search */ + } parent; + unsigned short group; + unsigned short layer; + rtrnd_netseg_t *ns; + etype type; + struct { + unsigned nonstraight:1; + unsigned fixed:1; + /* for searches */ + unsigned source:1; + unsigned target:1; + /* rects on same net as source and target don't need clearance areas */ + unsigned nobloat:1; + /* mark circular pins, so that we be sure to connect them up properly */ + unsigned circular:1; + /* we sometimes create routeboxen that don't actually belong to a + * r-tree yet -- make sure refcount of homelesss is set properly */ + unsigned homeless:1; + /* was this nonfixed obstacle generated on an odd or even pass? */ + unsigned is_odd:1; + /* fixed route boxes that have already been "routed through" in this + * search have their "touched" flag set. */ + unsigned touched:1; + /* this is a status bit for iterating through *different* subnets */ + unsigned subnet_processed:1; + /* some expansion_areas represent via candidates */ + unsigned is_via:1; + /* mark non-straight lines which go from bottom-left to upper-right, + * instead of from upper-left to bottom-right. */ + unsigned bl_to_ur:1; + /* mark polygons which are "transparent" for via-placement; that is, + * vias through the polygon will automatically be given a clearance + * and will not electrically connect to the polygon. */ + unsigned clear_poly:1; + /* this marks "conflicting" routes that must be torn up to obtain + * a correct routing. This flag allows us to return a correct routing + * even if the user cancels auto-route after a non-final pass. */ + unsigned is_bad:1; + /* for assertion that 'box' is never changed after creation */ + unsigned inited:1; + /* indicate this expansion ares is a thermal between the pin and plane */ + unsigned is_thermal; + } flags; + /* indicate the direction an expansion box came from */ + rnd_heap_cost_t cost; + rnd_cheap_point_t cost_point; + /* reference count for homeless routeboxes; free when refcount==0 */ + int refcount; + /* when routing with conflicts, we keep a record of what we're + * conflicting with. + */ + vector_t *conflicts_with; + /* route style of the net associated with this routebox */ + pcb_route_style_t *style; + /* congestion values for the edges of an expansion box */ + unsigned char n, e, s, w; + /* what pass this this track was laid down on */ + unsigned char pass; + /* the direction this came from, if any */ + rnd_direction_t came_from; + /* circular lists with connectivity information. */ + routebox_list_t same_net, same_subnet, original_subnet, different_net; +}; + +typedef struct routedata_s { + rtrnd_t *ctx; + + /* one rtree per layer *group */ + rtrnd_rtree_t *layergrouptree[PCB_MAX_LAYERGRP]; /* no silkscreen layers here =) */ + rtrnd_layer_t *annot[PCB_MAX_LAYERGRP]; + rtrnd_layer_t *annot_via, *annot_rats; + /* root pointer into connectivity information */ + routebox_t *first_net; + /* default routing style */ + pcb_route_style_t defaultstyle; + /* what is the maximum bloat (clearance+line half-width or + * clearance+via_radius) for any style we've seen? */ + double max_bloat; + double max_keep; + mtspace_t *mtspace; + rtrnd_ratsnest_t nest; +} routedata_t; + +typedef struct edge_struct_s { + routebox_t *rb; /* path expansion edges are real routeboxen. */ + rnd_cheap_point_t cost_point; + rnd_heap_cost_t pcb_cost_to_point; /* from source */ + rnd_heap_cost_t cost; /* cached edge cost */ + routebox_t *minpcb_cost_target; /* minimum cost from cost_point to any target */ + vetting_t *work; /* for via search edges */ + rnd_direction_t expand_dir; + struct { + /* this indicates that this 'edge' is a via candidate. */ + unsigned is_via:1; + /* record "conflict level" of via candidates, in case we need to split + * them later. */ + unsigned via_conflict_level:2; /* conflict_t */ + /* when "routing with conflicts", sometimes edge is interior. */ + unsigned is_interior:1; + /* this is a fake edge used to defer searching for via spaces */ + unsigned via_search:1; + /* this is a via edge in a plane where the cost point moves for free */ + unsigned in_plane:1; + } flags; +} edge_t; + +static struct AutoRouteParameters_s { + /* net style parameters */ + pcb_route_style_t *style; + /* the present bloat */ + double bloat; + /* cost parameters */ + rnd_heap_cost_t ViaCost, /* additional "length" cost for using a via */ + LastConflictPenalty, /* length mult. for routing over last pass' trace */ + ConflictPenalty, /* length multiplier for routing over another trace */ + JogPenalty, /* additional "length" cost for changing direction */ + CongestionPenalty, /* (rational) length multiplier for routing in */ + NewLayerPenalty, /* penalty for routing on a previously unused layer */ + MinPenalty; /* smallest Direction Penalty */ + /* maximum conflict incidence before calling it "no path found" */ + int hi_conflict; + /* are vias allowed? */ + rtrnd_bool_t use_vias; + /* is this an odd or even pass? */ + rtrnd_bool_t is_odd; + /* permit conflicts? */ + rtrnd_bool_t with_conflicts; + /* is this a final "smoothing" pass? */ + rtrnd_bool_t is_smoothing; + /* rip up nets regardless of conflicts? */ + rtrnd_bool_t rip_always; + rtrnd_bool_t last_smooth; + unsigned char pass; +} AutoRouteParameters; + +typedef struct routeone_state_s { + /* heap of all candidate expansion edges */ + rnd_heap_t *workheap; + /* information about the best path found so far. */ + routebox_t *best_path, *best_target; + rnd_heap_cost_t best_cost; +} routeone_state_t; + + +static routebox_t *CreateExpansionArea(const rtrnd_rtree_box_t * area, long group, + routebox_t * parent, rtrnd_bool_t relax_edge_requirements, edge_t * edge); + +static rnd_heap_cost_t edge_cost(const edge_t * e, const rnd_heap_cost_t too_big); +static void best_path_candidate(routeone_state_t *s, edge_t * e, routebox_t * best_target); + +static rtrnd_rtree_box_t edge_to_box(const routebox_t * rb, rnd_direction_t expand_dir); + +static void add_or_destroy_edge(routeone_state_t *s, edge_t * e); + +static void +RD_DrawThermal(routedata_t * rd, double X, double Y, long group, long layer, routebox_t * subnet, rtrnd_bool_t is_bad); +static void ResetSubnet(routebox_t * net); +#ifdef ROUTE_DEBUG +static int showboxen = -2; +static int aabort = 0; +static void showroutebox(routebox_t * rb); +#endif + +/* group number of groups that hold surface mount pads */ +static rnd_layergrp_id_t front, back; +static rtrnd_bool_t usedGroup[PCB_MAX_LAYERGRP]; +static int x_cost[PCB_MAX_LAYERGRP], y_cost[PCB_MAX_LAYERGRP]; +static rtrnd_bool_t is_layer_group_active[PCB_MAX_LAYERGRP]; +static int ro = 0; +static int smoothes = 1; +static int passes = 12; +static int routing_layers = 0; +static float total_wire_length = 0; +static int total_via_count = 0; + +RTRND_INLINE long pcb_max_group(rtrnd_board_t *pcb) +{ + return pcb->layers.used; +} + +/* assertion helper for routeboxen */ +#ifndef NDEBUG +static int __routepcb_box_is_good(routebox_t * rb) +{ + assert(rb && (rb->group < pcb_max_group(PCB)) && + (rb->box.x1 <= rb->box.x2) && (rb->box.y1 <= rb->box.y2) && + (rb->flags.homeless ? + (rb->box.x1 != rb->box.x2) || (rb->box.y1 != rb->box.y2) : (rb->box.x1 != rb->box.x2) && (rb->box.y1 != rb->box.y2))); + assert((rb->flags.source ? rb->flags.nobloat : 1) && + (rb->flags.target ? rb->flags.nobloat : 1) && + (rb->flags.homeless ? !rb->flags.touched : rb->refcount == 0) && (rb->flags.touched ? rb->type != EXPANSION_AREA : 1)); + assert((rb->flags.is_odd ? (!rb->flags.fixed) && + (rb->type == VIA || rb->type == VIA_SHADOW || rb->type == LINE || rb->type == PLANE) : 1)); + assert(rb->flags.clear_poly ? ((rb->type == OTHER || rb->type == PLANE) && rb->flags.fixed && !rb->flags.homeless) : 1); + assert(rb->flags.inited); +/* run through conflict list showing none are homeless, targets or sources */ + if (rb->conflicts_with) { + int i; + for (i = 0; i < vector_size(rb->conflicts_with); i++) { + routebox_t *c = vector_element(rb->conflicts_with, i); + assert(!c->flags.homeless && !c->flags.source && !c->flags.target && !c->flags.fixed); + } + } + assert(rb->style != NULL && rb->style != NULL); + assert(rb->type == EXPANSION_AREA + || (rb->same_net.next && rb->same_net.prev && rb->same_subnet.next + && rb->same_subnet.prev && rb->original_subnet.next + && rb->original_subnet.prev && rb->different_net.next && rb->different_net.prev)); + return 1; +} + +static int __edge_is_good(edge_t * e) +{ + assert(e && e->rb && __routepcb_box_is_good(e->rb)); + assert((e->rb->flags.homeless ? e->rb->refcount > 0 : 1)); + assert((0 <= e->expand_dir) && (e->expand_dir < 9) + && (e->flags.is_interior ? (e->expand_dir == RND_ANY_DIR && e->rb->conflicts_with) : 1)); + assert((e->flags.is_via ? e->rb->flags.is_via : 1) + && (e->flags.via_conflict_level >= 0 && e->flags.via_conflict_level <= 2) + && (e->flags.via_conflict_level != 0 ? e->flags.is_via : 1)); + assert((e->pcb_cost_to_point >= 0) && e->cost >= 0); + return 1; +} + +int no_planes(const rtrnd_rtree_box_t * b, void *cl) +{ + routebox_t *rb = (routebox_t *) b; + if (rb->type == PLANE) + return 0; + return 1; +} +#endif /* !NDEBUG */ + +/*--------------------------------------------------------------------- + * route utility functions. + */ + +enum boxlist { NET, SUBNET, ORIGINAL, DIFFERENT_NET }; +static routebox_list_t *__select_list(routebox_t * r, enum boxlist which) +{ + assert(r); + switch (which) { + default: + assert(0); + case NET: + return &(r->same_net); + case SUBNET: + return &(r->same_subnet); + case ORIGINAL: + return &(r->original_subnet); + case DIFFERENT_NET: + return &(r->different_net); + } +} + +static void InitLists(routebox_t * r) +{ + static enum boxlist all[] = { NET, SUBNET, ORIGINAL, DIFFERENT_NET } + , *p; + for (p = all; p < all + (sizeof(all) / sizeof(*p)); p++) { + routebox_list_t *rl = __select_list(r, *p); + rl->prev = rl->next = r; + } +} + +static void MergeNets(routebox_t * a, routebox_t * b, enum boxlist which) +{ + routebox_list_t *al, *bl, *anl, *bnl; + routebox_t *an, *bn; + assert(a && b); + assert(a != b); + assert(a->type != EXPANSION_AREA); + assert(b->type != EXPANSION_AREA); + al = __select_list(a, which); + bl = __select_list(b, which); + assert(al && bl); + an = al->next; + bn = bl->next; + assert(an && bn); + anl = __select_list(an, which); + bnl = __select_list(bn, which); + assert(anl && bnl); + bl->next = an; + anl->prev = b; + al->next = bn; + bnl->prev = a; +} + +static void RemoveFromNet(routebox_t * a, enum boxlist which) +{ + routebox_list_t *al, *anl, *apl; + routebox_t *an, *ap; + assert(a); + al = __select_list(a, which); + assert(al); + an = al->next; + ap = al->prev; + if (an == a || ap == a) + return; /* not on any list */ + assert(an && ap); + anl = __select_list(an, which); + apl = __select_list(ap, which); + assert(anl && apl); + anl->prev = ap; + apl->next = an; + al->next = al->prev = a; + return; +} + +static void init_const_box(routebox_t * rb, double X1, double Y1, double X2, double Y2, double clearance) +{ + rtrnd_rtree_box_t *bp = (rtrnd_rtree_box_t *) & rb->box; /* note discarding const! */ + assert(!rb->flags.inited); + assert(X1 <= X2 && Y1 <= Y2); + assert(clearance >= 0); + bp->x1 = X1 - clearance; + bp->y1 = Y1 - clearance; + bp->x2 = X2 + clearance; + bp->y2 = Y2 + clearance; + bp = (rtrnd_rtree_box_t *) & rb->sbox; + bp->x1 = X1; + bp->y1 = Y1; + bp->x2 = X2; + bp->y2 = Y2; + if (bp->x1 == bp->x2) bp->x2 += DELTA; + if (bp->y1 == bp->y2) bp->y2 += DELTA; + rb->flags.inited = 1; +} + +static inline rtrnd_rtree_box_t shrink_routebox(const routebox_t * rb) +{ + return rb->sbox; +} + +static inline rnd_heap_cost_t box_area(const rtrnd_rtree_box_t b) +{ + rnd_heap_cost_t ans = b.x2 - b.x1; + return ans * (b.y2 - b.y1); +} + +static inline rnd_cheap_point_t closest_point_in_routebox(const rnd_cheap_point_t * from, const routebox_t * rb) +{ + return rnd_closest_cheap_point_in_box(from, &rb->sbox); +} + +static inline rtrnd_bool_t point_in_shrunk_box(const routebox_t * box, double X, double Y) +{ + rtrnd_rtree_box_t b = shrink_routebox(box); + return rnd_point_in_box(&b, X, Y); +} + +static int layer_id(rtrnd_layer_t *layer) +{ + long n; + for(n = 0; n < PCB->layers.used; n++) + if (PCB->layers.array[n] == layer) + return n; + return -1; +} + +RTRND_INLINE double obj_clearance_at(rtrnd_board_t *board, rtrnd_any_obj_t *obj, rtrnd_layer_t *layer) +{ + switch(obj->hdr.type) { + case RTRND_LINE: return obj->line.clearance; + case RTRND_ARC: return obj->arc.clearance; + case RTRND_POLY: return 0; + case RTRND_VIA: +#warning TODO: bbvia + return obj->via.clearance; + default: + return 0; + } +} + +/*--------------------------------------------------------------------- + * routedata initialization functions. + */ +static routebox_t *AddTerm_(vtp0_t layergroupboxes[], rtrnd_any_obj_t *term, pcb_route_style_t *style, rtrnd_layer_t *layer) +{ + routebox_t **rbpp; + int layergroup = -1; + double clr; + + if ((layer->loc != RTRND_LLOC_TOP) && (layer->loc != RTRND_LLOC_BOTTOM)) { + if (term->hdr.type != RTRND_VIA) { + /*fprintf(stderr, WARNING "trying to route to SMD pad on internal layer");*/ + /* silenlty ignore internal pads of a padstack */ + return NULL; + } + } + + layergroup = layer_id(layer); + assert(layergroup >= 0); + + rbpp = (routebox_t **)vtp0_alloc_append(&layergroupboxes[layergroup], 1); + assert(rbpp); + *rbpp = (routebox_t *)calloc(sizeof(**rbpp), 1); + assert(*rbpp); + (*rbpp)->group = layergroup; + clr = obj_clearance_at(PCB, term, layer); + init_const_box(*rbpp, + /*X1 */ term->hdr.bbox.x1, + /*Y1 */ term->hdr.bbox.y1, + /*X2 */ term->hdr.bbox.x2, + /*Y2 */ term->hdr.bbox.y2, + style->Clearance); + /* kludge for non-manhattan pads (which are not allowed at present) */ +#warning old-TODO term +/* + if (pad->cline.p1.x != pad->cline.p2.x && pad->cline.p1.y != pad->cline.p2.y) + (*rbpp)->flags.nonstraight = 1; +*/ + (*rbpp)->flags.nonstraight = 0; /* otherwise the autorouter just ignores it */ + /* set aux. properties */ + (*rbpp)->type = TERM; + (*rbpp)->parent.term = term; + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = RND_ANY_DIR; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddTerm(vtp0_t layergroupboxes[], rtrnd_any_obj_t *term, pcb_route_style_t *style) +{ + assert(term->hdr.parent->hdr.type == RTRND_LAYER); + return AddTerm_(layergroupboxes, term, style, &term->hdr.parent->layer); +} + +static routebox_t *AddVia(vtp0_t layergroupboxes[], rtrnd_via_t *ps, pcb_route_style_t *style) +{ + int i; + routebox_t *r, *last = NULL; + + for (i = 0; i < PCB->layers.used; i++) { + rtrnd_layer_t *ly = PCB->layers.array[i]; + if (rtrnd_via_touches_layer(ly, ps)) { + r = AddTerm_(layergroupboxes, (rtrnd_any_obj_t *)ps, style, ly); + if (r != NULL) { + if (last != NULL) { + MergeNets(r, last, NET); + MergeNets(r, last, SUBNET); + MergeNets(r, last, ORIGINAL); + } + last = r; + } + } + } + + return last; +} + + +static routebox_t *AddLine(vtp0_t layergroupboxes[], int layergroup, rtrnd_line_t *line, + rtrnd_line_t *ptr, pcb_route_style_t * style) +{ + routebox_t **rbpp; + assert(layergroupboxes && line); + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + + rbpp = (routebox_t **) vtp0_alloc_append(&layergroupboxes[layergroup], 1); + *rbpp = (routebox_t *) malloc(sizeof(**rbpp)); + memset(*rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = layergroup; + init_const_box(*rbpp, + /*X1 */ RND_MIN(line->cline.p1.x, + line->cline.p2.x) - HALF_THICK(line->thickness), + /*Y1 */ RND_MIN(line->cline.p1.y, + line->cline.p2.y) - HALF_THICK(line->thickness), + /*X2 */ RND_MAX(line->cline.p1.x, + line->cline.p2.x) + HALF_THICK(line->thickness), + /*Y2 */ RND_MAX(line->cline.p1.y, + line->cline.p2.y) + HALF_THICK(line->thickness), style->Clearance); + /* kludge for non-manhattan lines */ + if (line->cline.p1.x != line->cline.p2.x && line->cline.p1.y != line->cline.p2.y) { + (*rbpp)->flags.nonstraight = 1; + (*rbpp)->flags.bl_to_ur = + (RND_MIN(line->cline.p1.x, line->cline.p2.x) == line->cline.p1.x) != (RND_MIN(line->cline.p1.y, line->cline.p2.y) == line->cline.p1.y); +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ZIGZAG) + showroutebox(*rbpp); +#endif + } + /* set aux. properties */ + (*rbpp)->type = LINE; + (*rbpp)->line.x1 = line->cline.p1.x; + (*rbpp)->line.y1 = line->cline.p1.y; + (*rbpp)->line.x2 = line->cline.p2.x; + (*rbpp)->line.y2 = line->cline.p2.y; + (*rbpp)->parent.line = ptr; + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = RND_ANY_DIR; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddIrregularObstacle(vtp0_t layergroupboxes[], + double X1, double Y1, + double X2, double Y2, long layergroup, void *parent, pcb_route_style_t * style) +{ + routebox_t **rbpp; + double keep = style->Clearance; + assert(layergroupboxes && parent); + assert(X1 <= X2 && Y1 <= Y2); + assert(0 <= layergroup && layergroup < PCB->layers.used); + + rbpp = (routebox_t **) vtp0_alloc_append(&layergroupboxes[layergroup], 1); + *rbpp = (routebox_t *) malloc(sizeof(**rbpp)); + memset(*rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = layergroup; + init_const_box(*rbpp, X1, Y1, X2, Y2, keep); + (*rbpp)->flags.nonstraight = 1; + (*rbpp)->type = OTHER; + (*rbpp)->parent.generic = parent; + (*rbpp)->flags.fixed = 1; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddPolygon(vtp0_t layergroupboxes[], long layer, rtrnd_poly_t *polygon, pcb_route_style_t * style) +{ + int is_not_rectangle = 1; + rnd_layergrp_id_t layergroup = layer; + routebox_t *rb; + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + rb = AddIrregularObstacle(layergroupboxes, + polygon->hdr.bbox.x1, + polygon->hdr.bbox.y1, + polygon->hdr.bbox.x2, polygon->hdr.bbox.y2, layergroup, polygon, style); + if (polygon->rtpoly.lst.length == 4) { /* common case: check if a 4-corner polygon is an axis aligned rectangle */ + double X[4], Y[4]; + int n; + rtp_vertex_t *v; + for(n = 0, v = gdl_first(&polygon->rtpoly.lst); v != NULL; v = v->link.next, n++) { + X[n] = v->x; + Y[n] = v->y; + } + if ((X[0] == X[1] || Y[0] == Y[1]) && + (X[1] == X[2] || Y[1] == Y[2]) && + (X[2] == X[3] || Y[2] == Y[3]) && + (X[3] == X[0] || Y[3] == Y[0])) + is_not_rectangle = 0; + } + rb->flags.nonstraight = is_not_rectangle; + rb->layer = layer; + rb->came_from = RND_ANY_DIR; +#warning TODO: at the moment any poly is a clearing poly + /*if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon))*/ { + rb->flags.clear_poly = 1; + if (!is_not_rectangle) + rb->type = PLANE; + } + return rb; +} + +static routebox_t *AddArc(vtp0_t layergroupboxes[], long layergroup, rtrnd_arc_t *arc, pcb_route_style_t * style) +{ + return AddIrregularObstacle(layergroupboxes, + arc->hdr.bbox.x1, arc->hdr.bbox.y1, + arc->hdr.bbox.x2, arc->hdr.bbox.y2, layergroup, arc, style); +} + +struct rb_info { + rtrnd_rtree_box_t query; + routebox_t *winner; + jmp_buf env; +}; + +static rnd_r_dir_t __found_one_on_lg(const rtrnd_rtree_box_t * box, void *cl) +{ + struct rb_info *inf = (struct rb_info *) cl; + routebox_t *rb = (routebox_t *) box; + rtrnd_rtree_box_t sb; + + if (rb->flags.nonstraight) + return RND_R_DIR_NOT_FOUND; + sb = rnd_shrink_box(&rb->box, rb->style->Clearance); + if (inf->query.x1 >= sb.x2 || inf->query.x2 <= sb.x1 || inf->query.y1 >= sb.y2 || inf->query.y2 <= sb.y1) + return RND_R_DIR_NOT_FOUND; + inf->winner = rb; + if (rb->type == PLANE) + return RND_R_DIR_FOUND_CONTINUE; /* keep looking for something smaller if a plane was found */ + longjmp(inf->env, 1); + return RND_R_DIR_NOT_FOUND; +} + +static routebox_t *FindRouteBoxOnLayerGroup(routedata_t * rd, double X, double Y, long layergroup) +{ + struct rb_info info; + info.winner = NULL; + info.query = rnd_point_box(X, Y); + if (setjmp(info.env) == 0) + rnd_r_search(rd->layergrouptree[layergroup], &info.query, NULL, __found_one_on_lg, &info, NULL); + return info.winner; +} + +#ifdef ROUTE_DEBUG_VERBOSE +static void DumpRouteBox(routebox_t * rb) +{ + fprintf(stderr, INFO "RB: %f;%f-%%f;%f l%d; ", rb->box.x1, rb->box.y1, rb->box.x2, rb->box.y2, (int) rb->group); + switch (rb->type) { + case TERM: + fprintf(stderr, INFO "TERM[%s] ", rb->parent.term->term); + break; + case LINE: + fprintf(stderr, INFO "LINE "); + break; + case OTHER: + fprintf(stderr, INFO "OTHER "); + break; + case EXPANSION_AREA: + fprintf(stderr, INFO "EXPAREA "); + break; + default: + fprintf(stderr, INFO "UNKNOWN "); + break; + } + if (rb->flags.nonstraight) + fprintf(stderr, INFO "(nonstraight) "); + if (rb->flags.fixed) + fprintf(stderr, INFO "(fixed) "); + if (rb->flags.source) + fprintf(stderr, INFO "(source) "); + if (rb->flags.target) + fprintf(stderr, INFO "(target) "); + if (rb->flags.homeless) + fprintf(stderr, INFO "(homeless) "); + printf("\n"); +} +#endif + +static routebox_t *crd_add_line(routedata_t *rd, vtp0_t *layergroupboxes, rnd_layergrp_id_t group, rtrnd_any_obj_t *obj, routebox_t **last_in_net, routebox_t **last_in_subnet) +{ + routebox_t *rb = NULL; + rtrnd_line_t *line = (rtrnd_line_t *) obj; + + /* dice up non-straight lines into many tiny obstacles */ + if (line->cline.p1.x != line->cline.p2.x && line->cline.p1.y != line->cline.p2.y) { + rtrnd_line_t fake_line = *line; + double dx = (line->cline.p2.x - line->cline.p1.x); + double dy = (line->cline.p2.y - line->cline.p1.y); + int segs = RND_MAX(fabs(dx), fabs(dy)) / (4 * BLOAT(&rd->defaultstyle) + 1); + int qq; + segs = RND_CLAMP(segs, 1, 32); /* don't go too crazy */ + dx /= segs; + dy /= segs; + for (qq = 0; qq < segs - 1; qq++) { + fake_line.cline.p2.x = fake_line.cline.p1.x + dx; + fake_line.cline.p2.y = fake_line.cline.p1.y + dy; + if (fake_line.cline.p2.x == line->cline.p2.x && fake_line.cline.p2.y == line->cline.p2.y) + break; + rb = AddLine(layergroupboxes, group, &fake_line, line, &rd->defaultstyle); + if (*last_in_subnet && rb != *last_in_subnet) + MergeNets(*last_in_subnet, rb, ORIGINAL); + if (*last_in_net && rb != *last_in_net) + MergeNets(*last_in_net, rb, NET); + *last_in_subnet = *last_in_net = rb; + fake_line.cline.p1 = fake_line.cline.p2; + } + fake_line.cline.p2 = line->cline.p2; + rb = AddLine(layergroupboxes, group, &fake_line, line, &rd->defaultstyle); + } + else + rb = AddLine(layergroupboxes, group, line, line, &rd->defaultstyle); + + return rb; +} + +static routebox_t *crd_add_misc(routedata_t *rd, vtp0_t *layergroupboxes, rtrnd_any_obj_t *obj) +{ + routebox_t *rb = NULL; + + switch (obj->hdr.type) { + case RTRND_VIA: + rb = AddVia(layergroupboxes, (rtrnd_via_t *)obj, &rd->defaultstyle); + break; + case RTRND_POLY: + { + rtrnd_poly_t *poly = (rtrnd_poly_t *)obj; + rtrnd_layer_t *layer = &obj->hdr.parent->layer; + if (poly->hdr.terminal) + rb = AddTerm(layergroupboxes, obj, &rd->defaultstyle); + else + rb = AddPolygon(layergroupboxes, layer_id(layer), poly, &rd->defaultstyle); + } + break; + case RTRND_LINE: + case RTRND_ARC: + if (obj->hdr.terminal) + rb = AddTerm(layergroupboxes, obj, &rd->defaultstyle); + break; + + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + break; /* don't care about these */ + } + return rb; +} + +static void CreateRouteData_obstacles(routedata_t *rd, vtp0_t *layergroupboxes) +{ + rtrnd_board_t *board = rd->ctx->board; + rtrnd_netseg_t *ns; + + for(ns = gdl_first(&board->orphaned_segments); ns != NULL; ns = gdl_next(&board->orphaned_segments, ns)) { + rtrnd_any_obj_t *obj; + for(obj = gdl_first(&ns->objs); obj != NULL; obj = gdl_next(&ns->objs, obj)) { + if (MAPPED(obj)) continue; + switch(obj->hdr.type) { + case RTRND_LINE: +#warning TODO: split up non-axis-aligned lines + AddLine(layergroupboxes, layer_id(&obj->hdr.parent->layer), &obj->line, &obj->line, &rd->defaultstyle); + break; + case RTRND_POLY: + AddPolygon(layergroupboxes, layer_id(&obj->hdr.parent->layer), &obj->poly, &rd->defaultstyle); + break; + case RTRND_ARC: +#warning TODO: split up to smaller sections + AddArc(layergroupboxes, layer_id(&obj->hdr.parent->layer), &obj->arc, &rd->defaultstyle); + break; + case RTRND_VIA: + AddVia(layergroupboxes, &obj->via, &rd->defaultstyle); + break; + default:; + } + } + } +} + + +static void CreateRouteData_subnet(routedata_t *rd, vtp0_t *layergroupboxes, rtrnd_net_t *net, routebox_t **last_in_net) +{ + routebox_t *last_in_subnet = NULL; + rtrnd_any_obj_t *obj; + size_t oi; + + for(oi = 0, obj = gdl_first(&net->objs); obj != NULL; obj = gdl_next(&net->objs, obj), oi++) { + routebox_t *rb = NULL; + + if (obj->hdr.terminal) + last_in_subnet = NULL; + + MAPPED(obj) = 1; + + if ((obj->hdr.type == RTRND_LINE) && (obj->hdr.terminal)) + rb = AddTerm(layergroupboxes, obj, &rd->defaultstyle); + else if (obj->hdr.type == RTRND_LINE) + rb = crd_add_line(rd, layergroupboxes, layer_id(&obj->hdr.parent->layer), obj, last_in_net, &last_in_subnet); + else + rb = crd_add_misc(rd, layergroupboxes, obj); + + if (rb == NULL) + continue; + + rb->ns = obj->hdr.netseg; + assert(rb); + + /* update circular connectivity lists */ + if (last_in_subnet && rb != last_in_subnet) + MergeNets(last_in_subnet, rb, ORIGINAL); + if (*last_in_net && rb != *last_in_net) + MergeNets(*last_in_net, rb, NET); + last_in_subnet = *last_in_net = rb; + rd->max_bloat = RND_MAX(rd->max_bloat, BLOAT(rb->style)); + rd->max_keep = RND_MAX(rd->max_keep, rb->style->Clearance); + } +} + +static void CreateRouteData_nets(routedata_t *rd, vtp0_t *layergroupboxes) +{ + htsp_entry_t *e; + routebox_t *last_net = NULL; + + for(e = htsp_first(&PCB->nets); e != NULL; e = htsp_next(&PCB->nets, e)) { + routebox_t *last_in_net = NULL; + rtrnd_net_t *net = e->value; + rtrnd_netseg_t *ns; + + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) + CreateRouteData_subnet(rd, layergroupboxes, net, &last_in_net); + + if (last_net && last_in_net) + MergeNets(last_net, last_in_net, DIFFERENT_NET); + last_net = last_in_net; + } + rd->first_net = last_net; + + /* reset all nets to "original" connectivity (which we just set) */ + { + routebox_t *net; + LIST_LOOP(rd->first_net, different_net, net); + ResetSubnet(net); + PCB_END_LOOP; + } +} + +static routedata_t *CreateRouteData(rtrnd_t *ctx) +{ + vtp0_t layergroupboxes[PCB_MAX_LAYERGRP]; + routedata_t *rd; + int group, i; + + /* create routedata */ + rd = calloc(sizeof(*rd), 1); + rd->ctx = ctx; + + /* check which layers are active first */ + routing_layers = 0; + for (group = 0; group < pcb_max_group(PCB); group++) { + rtrnd_layer_t *ly = PCB->layers.array[group]; + routing_layers++; + is_layer_group_active[group] = rtrnd_true; + + rd->annot[group] = rtrnd_annot_new(ctx, ly->name); + strcpy(rd->annot[group]->color, ly->color); + } + + rd->annot_via = rtrnd_annot_new(ctx, "vias"); + strcpy(rd->annot_via->color, "#BBBBBB"); + + /* if via visibility is turned off, don't use them */ + AutoRouteParameters.use_vias = routing_layers > 1; + + front = 0; + back = pcb_max_group(PCB) - 1; + + /* determine preferred routing direction on each group */ + for (i = 0; i < pcb_max_group(PCB); i++) { + if (i != back && i != front) { + x_cost[i] = (i & 1) ? 2 : 1; + y_cost[i] = (i & 1) ? 1 : 2; + } + else if (i == back) { + x_cost[i] = 4; + y_cost[i] = 2; + } + else { + x_cost[i] = 2; + y_cost[i] = 2; + } + } + +#warning TODO: load these from settings + /* create default style */ + rd->defaultstyle.Thickness = wire_thick; + rd->defaultstyle.Clearance = wire_clr; + rd->defaultstyle.Diameter = via_dia; + rd->max_bloat = BLOAT(&rd->defaultstyle); + rd->max_keep = rd->defaultstyle.Clearance; + + /* initialize pointer vectors */ + for (i = 0; i < pcb_max_group(PCB); i++) { + rtrnd_layer_t *layer = PCB->layers.array[i]; + vtp0_init(&layergroupboxes[i]); + if (RND_RTREE_EMPTY(&layer->objs)) + usedGroup[i] = rtrnd_false; + else + usedGroup[i] = rtrnd_true; + } + usedGroup[front] = rtrnd_true; + usedGroup[back] = rtrnd_true; + + CreateRouteData_nets(rd, layergroupboxes); + CreateRouteData_obstacles(rd, layergroupboxes); + + /* create r-trees from pointer lists */ + for (i = 0; i < pcb_max_group(PCB); i++) { + /* create the r-tree */ + rd->layergrouptree[i] = rnd_r_create_tree(); + rnd_r_insert_array(rd->layergrouptree[i], (const rtrnd_rtree_box_t **) layergroupboxes[i].array, vtp0_len(&layergroupboxes[i])); + } + + if (AutoRouteParameters.use_vias) { + rd->mtspace = mtspace_create(); + + /* create "empty-space" structures for via placement (now that we know + * appropriate clearances for all the fixed elements) */ + for (i = 0; i < pcb_max_group(PCB); i++) { + int ip; + for(ip = 0; ip < vtp0_len(&layergroupboxes[i]); ip++) { + void **ptr = &layergroupboxes[i].array[ip]; + routebox_t *rb = (routebox_t *) * ptr; + if (!rb->flags.clear_poly) + mtspace_add(rd->mtspace, &rb->box, FIXED, rb->style->Clearance); + } + } + } + /* free pointer lists */ + for (i = 0; i < pcb_max_group(PCB); i++) + vtp0_uninit(&layergroupboxes[i]); + /* done! */ + return rd; +} + +void DestroyRouteData(routedata_t ** rd) +{ + int i; + for (i = 0; i < pcb_max_group(PCB); i++) { + rnd_r_free_tree_data((*rd)->layergrouptree[i], free); + rnd_r_destroy_tree(&(*rd)->layergrouptree[i]); + } + if (AutoRouteParameters.use_vias) + mtspace_destroy(&(*rd)->mtspace); +/* free((*rd)->layergrouptree);*/ + free(*rd); + *rd = NULL; +} + +/*----------------------------------------------------------------- + * routebox reference counting. + */ + +/* increment the reference count on a routebox. */ +static void RB_up_count(routebox_t * rb) +{ + assert(rb->flags.homeless); + rb->refcount++; +} + +/* decrement the reference count on a routebox, freeing if this box becomes + * unused. */ +static void RB_down_count(routebox_t * rb) +{ + assert(rb->type == EXPANSION_AREA); + assert(rb->flags.homeless); + assert(rb->refcount > 0); + if (--rb->refcount == 0) { + if (rb->parent.expansion_area->flags.homeless) + RB_down_count(rb->parent.expansion_area); + free(rb); + } +} + +/*----------------------------------------------------------------- + * Rectangle-expansion routing code. + */ + +static void ResetSubnet(routebox_t * net) +{ + routebox_t *rb; + /* reset connectivity of everything on this net */ + LIST_LOOP(net, same_net, rb); + rb->same_subnet = rb->original_subnet; + PCB_END_LOOP; +} + +static inline rnd_heap_cost_t pcb_cost_to_point_on_layer(const rnd_cheap_point_t * p1, const rnd_cheap_point_t * p2, long point_layer) +{ + rnd_heap_cost_t x_dist = p1->X - p2->X, y_dist = p1->Y - p2->Y, r; + x_dist *= x_cost[point_layer]; + y_dist *= y_cost[point_layer]; + /* cost is proportional to orthogonal distance. */ + r = RND_ABS(x_dist) + RND_ABS(y_dist); + if (p1->X != p2->X && p1->Y != p2->Y) + r += AutoRouteParameters.JogPenalty; + return r; +} + +static rnd_heap_cost_t pcb_cost_to_point(const rnd_cheap_point_t * p1, long point_layer1, const rnd_cheap_point_t * p2, long point_layer2) +{ + rnd_heap_cost_t r = pcb_cost_to_point_on_layer(p1, p2, point_layer1); + /* apply via cost penalty if layers differ */ + if (point_layer1 != point_layer2) + r += AutoRouteParameters.ViaCost; + return r; +} + +/* return the minimum *cost* from a point to a box on any layer. + * It's safe to return a smaller than minimum cost + */ +static rnd_heap_cost_t pcb_cost_to_layerless_box(const rnd_cheap_point_t * p, long point_layer, const rtrnd_rtree_box_t * b) +{ + rnd_cheap_point_t p2 = rnd_closest_cheap_point_in_box(p, b); + register rnd_heap_cost_t c1, c2; + + c1 = p2.X - p->X; + c2 = p2.Y - p->Y; + + c1 = RND_ABS(c1); + c2 = RND_ABS(c2); + if (c1 < c2) + return c1 * AutoRouteParameters.MinPenalty + c2; + else + return c2 * AutoRouteParameters.MinPenalty + c1; +} + +/* get to actual pins/pad target coordinates */ +rtrnd_bool_t TargetPoint(rnd_cheap_point_t * nextpoint, const routebox_t * target) +{ +/* if (target->type == PIN) { + nextpoint->X = target->parent.pin->X; + nextpoint->Y = target->parent.pin->Y; + return rtrnd_true; + }*/ + nextpoint->X = RND_BOX_CENTER_X(target->sbox); + nextpoint->Y = RND_BOX_CENTER_Y(target->sbox); + return rtrnd_false; +} + +/* return the *minimum cost* from a point to a route box, including possible + * via costs if the route box is on a different layer. + * assume routbox is bloated unless it is an expansion area + */ +static rnd_heap_cost_t pcb_cost_to_routebox(const rnd_cheap_point_t * p, long point_layer, const routebox_t * rb) +{ + register rnd_heap_cost_t trial = 0; + rnd_cheap_point_t p2 = closest_point_in_routebox(p, rb); + if (!usedGroup[point_layer] || !usedGroup[rb->group]) + trial = AutoRouteParameters.NewLayerPenalty; + if ((p2.X - p->X) * (p2.Y - p->Y) != 0) + trial += AutoRouteParameters.JogPenalty; + /* special case for defered via searching */ + if (point_layer > pcb_max_group(PCB) || point_layer == rb->group) + return trial + fabs(p2.X - p->X) + fabs(p2.Y - p->Y); + /* if this target is only a via away, then the via is cheaper than the congestion */ + if (p->X == p2.X && p->Y == p2.Y) + return trial + 1; + trial += AutoRouteParameters.ViaCost; + trial += fabs(p2.X - p->X) + fabs(p2.Y - p->Y); + return trial; +} + + +static rtrnd_rtree_box_t bloat_routebox(routebox_t * rb) +{ + rtrnd_rtree_box_t r; + double clearance; + assert(__routepcb_box_is_good(rb)); + + if (rb->flags.nobloat) + return rb->sbox; + + /* Obstacle exclusion zones get bloated by the larger of + * the two required clearances plus half the track width. + */ + clearance = RND_MAX(AutoRouteParameters.style->Clearance, rb->style->Clearance); + r = rnd_bloat_box(&rb->sbox, clearance + HALF_THICK(AutoRouteParameters.style->Thickness)); + return r; +} + + +#ifdef ROUTE_DEBUG /* only for debugging expansion areas */ + +typedef short pcb_dimension_t; +/* makes a line on the solder layer silk surrounding the box */ +static void showbox(rtrnd_rtree_box_t b, pcb_dimension_t thickness, int group) +{ + rtrnd_line_t *line; + rtrnd_layer_t *csl, *SLayer = pcb_get_layer(PCB->Data, group); + rnd_layer_id_t cs_id; + if (showboxen < -1) + return; + if (showboxen != -1 && showboxen != group) + return; + + if (ddraw != NULL) { + ddraw->set_line_width(ar_gc, thickness); + ddraw->set_line_cap(ar_gc, rnd_cap_round); + ddraw->set_color(ar_gc, SLayer->Color); + + ddraw->draw_line(ar_gc, b.x1, b.y1, b.x2, b.y1); + ddraw->draw_line(ar_gc, b.x1, b.y2, b.x2, b.y2); + ddraw->draw_line(ar_gc, b.x1, b.y1, b.x1, b.y2); + ddraw->draw_line(ar_gc, b.x2, b.y1, b.x2, b.y2); + } + +#if 1 + if (pcb_layer_find(PCB_LYT_TOP | PCB_LYT_SILK, &cs_id, 1) > 0) { + csl = pcb_get_layer(PCB->Data, cs_id); + if (b.y1 == b.y2 || b.x1 == b.x2) + thickness = 5; + line = pcb_line_new(csl, b.x1, b.y1, b.x2, b.y1, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(csl, line, line); + if (b.y1 != b.y2) { + line = pcb_line_new(csl, b.x1, b.y2, b.x2, b.y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + } + line = pcb_line_new(csl, b.x1, b.y1, b.x1, b.y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + if (b.x1 != b.x2) { + line = pcb_line_new(csl, b.x2, b.y1, b.x2, b.y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + } + } +#endif +} +#endif + +#if defined(ROUTE_DEBUG) +static void showedge(edge_t * e) +{ + rtrnd_rtree_box_t *b = (rtrnd_rtree_box_t *) e->rb; + + if (ddraw == NULL) + return; + + ddraw->set_line_cap(ar_gc, rnd_cap_round); + ddraw->set_line_width(ar_gc, 1); + ddraw->set_color(ar_gc, Settings.MaskColor); + + switch (e->expand_dir) { + case RND_NORTH: + ddraw->draw_line(ar_gc, b->X1, b->Y1, b->X2, b->Y1); + break; + case RND_SOUTH: + ddraw->draw_line(ar_gc, b->X1, b->Y2, b->X2, b->Y2); + break; + case RND_WEST: + ddraw->draw_line(ar_gc, b->X1, b->Y1, b->X1, b->Y2); + break; + case RND_EAST: + ddraw->draw_line(ar_gc, b->X2, b->Y1, b->X2, b->Y2); + break; + default: + break; + } +} +#endif + +#if defined(ROUTE_DEBUG) +static void showroutebox(routebox_t * rb) +{ + pcb_layerid_t cs_id; + if (pcb_layer_find(PCB_LYT_TOP | PCB_LYT_SILK, &cs_id, 1) > 0) + showbox(rb->sbox, rb->flags.source ? 20 : (rb->flags.target ? 10 : 1), rb->flags.is_via ? pcb_get_layer(PCB->Data, cs_id) : rb->group); +} +#endif + +/* return a "parent" of this edge which immediately precedes it in the route.*/ +static routebox_t *route_parent(routebox_t * rb) +{ + while (rb->flags.homeless && !rb->flags.is_via && !rb->flags.is_thermal) { + assert(rb->type == EXPANSION_AREA); + rb = rb->parent.expansion_area; + assert(rb); + } + return rb; +} + +static vector_t *path_conflicts(routebox_t * rb, routebox_t * conflictor, rtrnd_bool_t branch) +{ + if (branch) + rb->conflicts_with = vector_duplicate(rb->conflicts_with); + else if (!rb->conflicts_with) + rb->conflicts_with = vector_create(); + vector_append(rb->conflicts_with, conflictor); + return rb->conflicts_with; +} + +/* Touch everything (except fixed) on each net found + * in the conflicts vector. If the vector is different + * from the last one touched, untouch the last batch + * and touch the new one. Always call with touch=1 + * (except for recursive call). Call with NULL, 1 to + * clear the last batch touched. + * + * touched items become invisible to current path + * so we don't encounter the same conflictor more + * than once + */ + +static void touch_conflicts(vector_t * conflicts, int touch) +{ + static vector_t *last = NULL; + static int last_size = 0; + int i, n; + i = 0; + if (touch) { + if (last && conflicts != last) + touch_conflicts(last, 0); + if (!conflicts) + return; + last = conflicts; + i = last_size; + } + n = vector_size(conflicts); + for (; i < n; i++) { + routebox_t *rb = (routebox_t *) vector_element(conflicts, i); + routebox_t *p; + LIST_LOOP(rb, same_net, p); + if (!p->flags.fixed) + p->flags.touched = touch; + PCB_END_LOOP; + } + if (!touch) { + last = NULL; + last_size = 0; + } + else + last_size = n; +} + +/* return a "parent" of this edge which resides in a r-tree somewhere */ +/* -- actually, this "parent" *may* be a via box, which doesn't live in + * a r-tree. -- */ +static routebox_t *nonhomeless_parent(routebox_t * rb) +{ + return route_parent(rb); +} + +/* some routines to find the minimum *cost* from a cost point to + * a target (any target) */ +struct minpcb_cost_target_closure { + const rnd_cheap_point_t *CostPoint; + long CostPointLayer; + routebox_t *nearest; + rnd_heap_cost_t nearest_cost; +}; +static rnd_r_dir_t __region_within_guess(const rtrnd_rtree_box_t * region, void *cl) +{ + struct minpcb_cost_target_closure *mtc = (struct minpcb_cost_target_closure *) cl; + rnd_heap_cost_t pcb_cost_to_region; + if (mtc->nearest == NULL) + return RND_R_DIR_FOUND_CONTINUE; + pcb_cost_to_region = pcb_cost_to_layerless_box(mtc->CostPoint, mtc->CostPointLayer, region); + assert(pcb_cost_to_region >= 0); + /* if no guess yet, all regions are "close enough" */ + /* note that cost is *strictly more* than minimum distance, so we'll + * always search a region large enough. */ + return (pcb_cost_to_region < mtc->nearest_cost) ? RND_R_DIR_FOUND_CONTINUE : RND_R_DIR_NOT_FOUND; +} + +static rnd_r_dir_t __found_new_guess(const rtrnd_rtree_box_t * box, void *cl) +{ + struct minpcb_cost_target_closure *mtc = (struct minpcb_cost_target_closure *) cl; + routebox_t *guess = (routebox_t *) box; + rnd_heap_cost_t pcb_cost_to_guess = pcb_cost_to_routebox(mtc->CostPoint, mtc->CostPointLayer, guess); + assert(pcb_cost_to_guess >= 0); + /* if this is cheaper than previous guess... */ + if (pcb_cost_to_guess < mtc->nearest_cost) { + mtc->nearest = guess; + mtc->nearest_cost = pcb_cost_to_guess; /* this is our new guess! */ + return RND_R_DIR_FOUND_CONTINUE; + } + else + return RND_R_DIR_NOT_FOUND; /* not less expensive than our last guess */ +} + +/* target_guess is our guess at what the nearest target is, or NULL if we + * just plum don't have a clue. */ +static routebox_t *minpcb_cost_target_to_point(const rnd_cheap_point_t * CostPoint, + long CostPointLayer, rtrnd_rtree_t * targets, routebox_t * target_guess) +{ + struct minpcb_cost_target_closure mtc; + assert(target_guess == NULL || target_guess->flags.target); /* this is a target, right? */ + mtc.CostPoint = CostPoint; + mtc.CostPointLayer = CostPointLayer; + mtc.nearest = target_guess; + if (mtc.nearest) + mtc.nearest_cost = pcb_cost_to_routebox(mtc.CostPoint, mtc.CostPointLayer, mtc.nearest); + else + mtc.nearest_cost = EXPENSIVE; + rnd_r_search(targets, NULL, __region_within_guess, __found_new_guess, &mtc, NULL); + assert(mtc.nearest != NULL && mtc.nearest_cost >= 0); + assert(mtc.nearest->flags.target); /* this is a target, right? */ + return mtc.nearest; +} + +/* create edge from field values */ +/* minpcb_cost_target_guess can be NULL */ +static edge_t *CreateEdge(routebox_t * rb, + double CostPointX, double CostPointY, + rnd_heap_cost_t pcb_cost_to_point, routebox_t * minpcb_cost_target_guess, rnd_direction_t expand_dir, rtrnd_rtree_t * targets) +{ + edge_t *e; + assert(__routepcb_box_is_good(rb)); + e = (edge_t *) malloc(sizeof(*e)); + memset((void *) e, 0, sizeof(*e)); + assert(e); + e->rb = rb; + if (rb->flags.homeless) + RB_up_count(rb); + e->cost_point.X = CostPointX; + e->cost_point.Y = CostPointY; + e->pcb_cost_to_point = pcb_cost_to_point; + e->flags.via_search = 0; + /* if this edge is created in response to a target, use it */ + if (targets) + e->minpcb_cost_target = minpcb_cost_target_to_point(&e->cost_point, rb->group, targets, minpcb_cost_target_guess); + else + e->minpcb_cost_target = minpcb_cost_target_guess; + e->expand_dir = expand_dir; + assert(e->rb && e->minpcb_cost_target); /* valid edge? */ + assert(!e->flags.is_via || e->expand_dir == RND_ANY_DIR); + /* cost point should be on edge (unless this is a plane/via/conflict edge) */ +#if 0 + assert(rb->type == PLANE || rb->conflicts_with != NULL || rb->flags.is_via + || rb->flags.is_thermal + || ((expand_dir == RND_NORTH || expand_dir == RND_SOUTH) ? rb->sbox.x1 <= + CostPointX && CostPointX < rb->sbox.x2 && CostPointY == (expand_dir == RND_NORTH ? rb->sbox.y1 : rb->sbox.y2 - DELTA) : + /* expand_dir==EAST || expand_dir==WEST */ + rb->sbox.y1 <= CostPointY && CostPointY < rb->sbox.y2 && + CostPointX == (expand_dir == RND_EAST ? rb->sbox.x2 - DELTA : rb->sbox.x1))); +#endif + assert(__edge_is_good(e)); + /* done */ + return e; +} + +/* create edge, using previous edge to fill in defaults. */ +/* most of the work here is in determining a new cost point */ +static edge_t *CreateEdge2(routebox_t * rb, rnd_direction_t expand_dir, + edge_t * previous_edge, rtrnd_rtree_t * targets, routebox_t * guess) +{ + rtrnd_rtree_box_t thisbox; + rnd_cheap_point_t thiscost, prevcost; + rnd_heap_cost_t d; + + assert(rb && previous_edge); + /* okay, find cheapest costpoint to costpoint of previous edge */ + thisbox = edge_to_box(rb, expand_dir); + prevcost = previous_edge->cost_point; + /* find point closest to target */ + thiscost = rnd_closest_cheap_point_in_box(&prevcost, &thisbox); + /* compute cost-to-point */ + d = pcb_cost_to_point_on_layer(&prevcost, &thiscost, rb->group); + /* add in jog penalty */ + if (previous_edge->expand_dir != expand_dir) + d += AutoRouteParameters.JogPenalty; + /* okay, new edge! */ + return CreateEdge(rb, thiscost.X, thiscost.Y, + previous_edge->pcb_cost_to_point + d, guess ? guess : previous_edge->minpcb_cost_target, expand_dir, targets); +} + +/* create via edge, using previous edge to fill in defaults. */ +static edge_t *CreateViaEdge(const rtrnd_rtree_box_t * area, long group, + routebox_t * parent, edge_t * previous_edge, + conflict_t to_site_conflict, conflict_t through_site_conflict, rtrnd_rtree_t * targets) +{ + routebox_t *rb; + rnd_cheap_point_t costpoint; + rnd_heap_cost_t d; + edge_t *ne; + rnd_heap_cost_t scale[3]; + + scale[0] = 1; + scale[1] = AutoRouteParameters.LastConflictPenalty; + scale[2] = AutoRouteParameters.ConflictPenalty; + + assert(rnd_box_is_good(area)); + assert(AutoRouteParameters.with_conflicts || (to_site_conflict == NO_CONFLICT && through_site_conflict == NO_CONFLICT)); + rb = CreateExpansionArea(area, group, parent, rtrnd_true, previous_edge); + rb->flags.is_via = 1; + rb->came_from = RND_ANY_DIR; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_VIA_BOXES) + showroutebox(rb); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_VIA_BOXES */ + /* for planes, choose a point near the target */ + if (previous_edge->flags.in_plane) { + routebox_t *target; + rnd_cheap_point_t pnt; + /* find a target near this via box */ + pnt.X = RND_BOX_CENTER_X(*area); + pnt.Y = RND_BOX_CENTER_Y(*area); + target = minpcb_cost_target_to_point(&pnt, rb->group, targets, previous_edge->minpcb_cost_target); + /* now find point near the target */ + pnt.X = RND_BOX_CENTER_X(target->box); + pnt.Y = RND_BOX_CENTER_Y(target->box); + costpoint = closest_point_in_routebox(&pnt, rb); + /* we moved from the previous cost point through the plane which is free travel */ + d = (scale[through_site_conflict] * pcb_cost_to_point(&costpoint, group, &costpoint, previous_edge->rb->group)); + ne = CreateEdge(rb, costpoint.X, costpoint.Y, previous_edge->pcb_cost_to_point + d, target, RND_ANY_DIR, NULL); + ne->minpcb_cost_target = target; + } + else { + routebox_t *target; + target = previous_edge->minpcb_cost_target; + costpoint = closest_point_in_routebox(&previous_edge->cost_point, rb); + d = + (scale[to_site_conflict] * + pcb_cost_to_point_on_layer(&costpoint, &previous_edge->cost_point, + previous_edge->rb->group)) + + (scale[through_site_conflict] * pcb_cost_to_point(&costpoint, group, &costpoint, previous_edge->rb->group)); + /* if the target is just this via away, then this via is cheaper */ + if (target->group == group && point_in_shrunk_box(target, costpoint.X, costpoint.Y)) + d -= AutoRouteParameters.ViaCost / 2; + ne = + CreateEdge(rb, costpoint.X, costpoint.Y, previous_edge->pcb_cost_to_point + d, previous_edge->minpcb_cost_target, RND_ANY_DIR, targets); + } + ne->flags.is_via = 1; + ne->flags.via_conflict_level = to_site_conflict; + assert(__edge_is_good(ne)); + return ne; +} + +/* create "interior" edge for routing with conflicts */ +/* Presently once we "jump inside" the conflicting object + * we consider it a routing highway to travel inside since + * it will become available if the conflict is elliminated. + * That is why we ignore the interior_edge argument. + */ +static edge_t *CreateEdgeWithConflicts(const rtrnd_rtree_box_t * interior_edge, + routebox_t * container, edge_t * previous_edge, + rnd_heap_cost_t cost_penalty_to_box, rtrnd_rtree_t * targets) +{ + routebox_t *rb; + rnd_cheap_point_t costpoint; + rnd_heap_cost_t d; + edge_t *ne; + assert(interior_edge && container && previous_edge && targets); + assert(!container->flags.homeless); + assert(AutoRouteParameters.with_conflicts); + assert(container->flags.touched == 0); + assert(previous_edge->rb->group == container->group); + /* use the caller's idea of what this box should be */ + rb = CreateExpansionArea(interior_edge, previous_edge->rb->group, previous_edge->rb, rtrnd_true, previous_edge); + path_conflicts(rb, container, rtrnd_true); /* crucial! */ + costpoint = rnd_closest_cheap_point_in_box(&previous_edge->cost_point, interior_edge); + d = pcb_cost_to_point_on_layer(&costpoint, &previous_edge->cost_point, previous_edge->rb->group); + d *= cost_penalty_to_box; + d += previous_edge->pcb_cost_to_point; + ne = CreateEdge(rb, costpoint.X, costpoint.Y, d, NULL, RND_ANY_DIR, targets); + ne->flags.is_interior = 1; + assert(__edge_is_good(ne)); + return ne; +} + +static void KillEdge(void *edge) +{ + edge_t *e = (edge_t *) edge; + assert(e); + if (e->rb->flags.homeless) + RB_down_count(e->rb); + if (e->flags.via_search) + mtsFreeWork(&e->work); + free(e); +} + +static void DestroyEdge(edge_t ** e) +{ + assert(e && *e); + KillEdge(*e); + *e = NULL; +} + +/* cost function for an edge. */ +static rnd_heap_cost_t edge_cost(const edge_t * e, const rnd_heap_cost_t too_big) +{ + rnd_heap_cost_t penalty = e->pcb_cost_to_point; + if (e->rb->flags.is_thermal || e->rb->type == PLANE) + return penalty; /* thermals are cheap */ + if (penalty > too_big) + return penalty; + + /* pcb_cost_to_routebox adds in our via correction, too. */ + return penalty + pcb_cost_to_routebox(&e->cost_point, e->rb->group, e->minpcb_cost_target); +} + +/* given an edge of a box, return a box containing exactly the points on that + * edge. Note that the return box is treated as closed; that is, the bottom and + * right "edges" consist of points (just barely) not in the (half-open) box. */ +static rtrnd_rtree_box_t edge_to_box(const routebox_t * rb, rnd_direction_t expand_dir) +{ + rtrnd_rtree_box_t b = shrink_routebox(rb); + /* narrow box down to just the appropriate edge */ + switch (expand_dir) { + case RND_NORTH: + b.y2 = b.y1 + DELTA; + break; + case RND_EAST: + b.x1 = b.x2 - DELTA; + break; + case RND_SOUTH: + b.y1 = b.y2 - DELTA; + break; + case RND_WEST: + b.x2 = b.x1 + DELTA; + break; + default: + /* This used to be an assert(0), but it seems a polygon connected to + a terminal triggers it while simply falling through doesn't cause + any problem. This bug is present in both the 2011 version of + PCB and in PCB 4.2.0 as well. */ + break; + } + /* done! */ + return b; +} + +struct broken_boxes { + rtrnd_rtree_box_t left, center, right; + rtrnd_bool_t is_valid_left, is_valid_center, is_valid_right; +}; + +static struct broken_boxes break_box_edge(const rtrnd_rtree_box_t * original, rnd_direction_t which_edge, routebox_t * breaker) +{ + rtrnd_rtree_box_t origbox, breakbox; + struct broken_boxes result; + + assert(original && breaker); + + origbox = *original; + breakbox = bloat_routebox(breaker); + RND_BOX_ROTATE_TO_NORTH(origbox, which_edge); + RND_BOX_ROTATE_TO_NORTH(breakbox, which_edge); + result.right.y1 = result.center.y1 = result.left.y1 = origbox.y1; + result.right.y2 = result.center.y2 = result.left.y2 = origbox.y1 + DELTA; + /* validity of breaker is not important because the boxes are marked invalid */ + /*assert (breakbox.x1 <= origbox.x2 && breakbox.x2 >= origbox.x1); */ + /* left edge piece */ + result.left.x1 = origbox.x1; + result.left.x2 = breakbox.x1; + /* center (ie blocked) edge piece */ + result.center.x1 = RND_MAX(breakbox.x1, origbox.x1); + result.center.x2 = RND_MIN(breakbox.x2, origbox.x2); + /* right edge piece */ + result.right.x1 = breakbox.x2; + result.right.x2 = origbox.x2; + /* validity: */ + result.is_valid_left = (result.left.x1 < result.left.x2); + result.is_valid_center = (result.center.x1 < result.center.x2); + result.is_valid_right = (result.right.x1 < result.right.x2); + /* rotate back */ + RND_BOX_ROTATE_FROM_NORTH(result.left, which_edge); + RND_BOX_ROTATE_FROM_NORTH(result.center, which_edge); + RND_BOX_ROTATE_FROM_NORTH(result.right, which_edge); + /* done */ + return result; +} + +#ifndef NDEBUG +static int share_edge(const rtrnd_rtree_box_t * child, const rtrnd_rtree_box_t * parent) +{ + return + (child->x1 == parent->x2 || child->x2 == parent->x1 || + child->y1 == parent->y2 || child->y2 == parent->y1) && + ((parent->x1 <= child->x1 && child->x2 <= parent->x2) || (parent->y1 <= child->y1 && child->y2 <= parent->y2)); +} + +static int edge_intersect(const rtrnd_rtree_box_t * child, const rtrnd_rtree_box_t * parent) +{ + return (child->x1 <= parent->x2) && (child->x2 >= parent->x1) && (child->y1 <= parent->y2) && (child->y2 >= parent->y1); +} +#endif + +/* area is the expansion area, on layer group 'group'. 'parent' is the + * immediately preceding expansion area, for backtracing. 'lastarea' is + * the last expansion area created, we string these together in a loop + * so we can remove them all easily at the end. */ +static routebox_t *CreateExpansionArea(const rtrnd_rtree_box_t * area, long group, + routebox_t * parent, rtrnd_bool_t relax_edge_requirements, edge_t * src_edge) +{ + routebox_t *rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(area && parent); + init_const_box(rb, area->x1, area->y1, area->x2, area->y2, 0); + rb->group = group; + rb->type = EXPANSION_AREA; + /* should always share edge or overlap with parent */ +#ifndef NDEBUG + { + /* work around rounding errors: grow both boxes by a few nm */ + rtrnd_rtree_box_t b1 = rb->sbox, b2 = parent->sbox; + double r = DELTA; + b1.x1-=r;b1.y1-=r;b1.x2+=r;b1.y2+=r; + b2.x1-=r;b2.y1-=r;b2.x2+=r;b2.y2+=r; + assert(relax_edge_requirements ? rnd_box_intersect(&b1, &b2) + : share_edge(&rb->sbox, &parent->sbox)); + } +#endif + rb->parent.expansion_area = route_parent(parent); + rb->cost_point = rnd_closest_cheap_point_in_box(&rb->parent.expansion_area->cost_point, area); + rb->cost = + rb->parent.expansion_area->cost + + pcb_cost_to_point_on_layer(&rb->parent.expansion_area->cost_point, &rb->cost_point, rb->group); + assert(relax_edge_requirements ? edge_intersect(&rb->sbox, &parent->sbox) + : share_edge(&rb->sbox, &parent->sbox)); + if (rb->parent.expansion_area->flags.homeless) + RB_up_count(rb->parent.expansion_area); + rb->flags.homeless = 1; + rb->flags.nobloat = 1; + rb->style = AutoRouteParameters.style; + rb->conflicts_with = parent->conflicts_with; +/* we will never link an EXPANSION_AREA into the nets because they + * are *ONLY* used for path searching. No need to call InitLists () + */ + rb->came_from = src_edge->expand_dir; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EXPANSION_BOXES) + showroutebox(rb); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_EXPANSION_BOXES */ + return rb; +} + +/*------ Expand ------*/ +struct E_result { + routebox_t *parent; + routebox_t *n, *e, *s, *w; + double keep, bloat; + rtrnd_rtree_box_t inflated, orig; + int done; +}; + +/* test method for Expand() + * this routebox potentially is a blocker limiting expansion + * if this is so, we limit the inflate box so another exactly + * like it wouldn't be seen. We do this while keep the inflated + * box as large as possible. + */ +static rnd_r_dir_t __Expand_this_rect(const rtrnd_rtree_box_t * box, void *cl) +{ + struct E_result *res = (struct E_result *) cl; + routebox_t *rb = (routebox_t *) box; + rtrnd_rtree_box_t rbox; + double dn, de, ds, dw, bloat; + + /* we don't see conflicts already encountered */ + if (rb->flags.touched) + return RND_R_DIR_NOT_FOUND; + + /* The inflated box outer edges include its own + * track width plus its own clearance. + * + * To check for intersection, we need to expand + * anything with greater clearance by its excess + * clearance. + * + * If something has nobloat then we need to shrink + * the inflated box back and see if it still touches. + */ + + if (rb->flags.nobloat) { + rbox = rb->sbox; + bloat = res->bloat; + if (rbox.x2 <= res->inflated.x1 + bloat || + rbox.x1 >= res->inflated.x2 - bloat || rbox.y1 >= res->inflated.y2 - bloat || rbox.y2 <= res->inflated.y1 + bloat) + return RND_R_DIR_NOT_FOUND; /* doesn't touch */ + } + else { + if (rb->style->Clearance > res->keep) + rbox = rnd_bloat_box(&rb->sbox, rb->style->Clearance - res->keep); + else + rbox = rb->sbox; + + if (rbox.x2 <= res->inflated.x1 || rbox.x1 >= res->inflated.x2 + || rbox.y1 >= res->inflated.y2 || rbox.y2 <= res->inflated.y1) + return RND_R_DIR_NOT_FOUND; /* doesn't touch */ + bloat = 0; + } + + /* this is an intersecting box; it has to jump through a few more hoops */ + if (rb == res->parent || rb->parent.expansion_area == res->parent) + return RND_R_DIR_NOT_FOUND; /* don't see what we came from */ + + /* if we are expanding a source edge, don't let other sources + * or their expansions stop us. + */ +#if 1 + if (res->parent->flags.source) + if (rb->flags.source || (rb->type == EXPANSION_AREA && rb->parent.expansion_area->flags.source)) + return RND_R_DIR_NOT_FOUND; +#endif + + /* we ignore via expansion boxes because maybe its + * cheaper to get there without the via through + * the path we're exploring now. + */ + if (rb->flags.is_via && rb->type == EXPANSION_AREA) + return RND_R_DIR_NOT_FOUND; + + if (rb->type == PLANE) { /* expanding inside a plane is not good */ + if (rbox.x1 < res->orig.x1 && rbox.x2 > res->orig.x2 && rbox.y1 < res->orig.y1 && rbox.y2 > res->orig.y2) { + res->inflated = rnd_bloat_box(&res->orig, res->bloat); + return RND_R_DIR_FOUND_CONTINUE; + } + } + /* calculate the distances from original box to this blocker */ + dn = de = ds = dw = 0; + if (!(res->done & _NORTH) && rbox.y1 <= res->orig.y1 && rbox.y2 > res->inflated.y1) + dn = res->orig.y1 - rbox.y2; + if (!(res->done & _EAST) && rbox.x2 >= res->orig.x2 && rbox.x1 < res->inflated.x2) + de = rbox.x1 - res->orig.x2; + if (!(res->done & _SOUTH) && rbox.y2 >= res->orig.y2 && rbox.y1 < res->inflated.y2) + ds = rbox.y1 - res->orig.y2; + if (!(res->done & _WEST) && rbox.x1 <= res->orig.x1 && rbox.x2 > res->inflated.x1) + dw = res->orig.x1 - rbox.x2; + if (dn <= 0 && de <= 0 && ds <= 0 && dw <= 0) + return RND_R_DIR_FOUND_CONTINUE; + /* now shrink the inflated box to the largest blocking direction */ + if (dn >= de && dn >= ds && dn >= dw) { + res->inflated.y1 = rbox.y2 - bloat; + res->n = rb; + } + else if (de >= ds && de >= dw) { + res->inflated.x2 = rbox.x1 + bloat; + res->e = rb; + } + else if (ds >= dw) { + res->inflated.y2 = rbox.y1 + bloat; + res->s = rb; + } + else { + res->inflated.x1 = rbox.x2 - bloat; + res->w = rb; + } + return RND_R_DIR_FOUND_CONTINUE; +} + +static rtrnd_bool_t boink_box(routebox_t * rb, struct E_result *res, rnd_direction_t dir) +{ + double bloat; + if (rb->style->Clearance > res->keep) + bloat = res->keep - rb->style->Clearance; + else + bloat = 0; + if (rb->flags.nobloat) + bloat = res->bloat; + switch (dir) { + case RND_NORTH: + case RND_SOUTH: + if (rb->sbox.x2 <= res->inflated.x1 + bloat || rb->sbox.x1 >= res->inflated.x2 - bloat) + return rtrnd_false; + return rtrnd_true; + case RND_EAST: + case RND_WEST: + if (rb->sbox.y1 >= res->inflated.y2 - bloat || rb->sbox.y2 <= res->inflated.y1 + bloat) + return rtrnd_false; + return rtrnd_true; + break; + default: + assert(0); + } + return rtrnd_false; +} + +/* main Expand routine. + * + * The expansion probe edge includes the clearance and half thickness + * as the search is performed in order to see everything relevant. + * The result is backed off by this amount before being returned. + * Targets (and other no-bloat routeboxes) go all the way to touching. + * This is accomplished by backing off the probe edge when checking + * for touch against such an object. Usually the expanding edge + * bumps into neighboring pins on the same device that require a + * clearance, preventing seeing a target immediately. Rather than await + * another expansion to actually touch the target, the edge breaker code + * looks past the clearance to see these targets even though they + * weren't actually touched in the expansion. + */ +struct E_result *Expand(rtrnd_rtree_t * rtree, edge_t * e, const rtrnd_rtree_box_t * box) +{ + static struct E_result ans; + int noshrink; /* bit field of which edges to not shrink */ + + ans.bloat = AutoRouteParameters.bloat; + ans.orig = *box; + ans.n = ans.e = ans.s = ans.w = NULL; + + /* the inflated box must be bloated in all directions that it might + * hit something in order to guarantee that we see object in the + * tree it might hit. The tree holds objects bloated by their own + * clearance so we are guaranteed to honor that. + */ + switch (e->expand_dir) { + case RND_ANY_DIR: + ans.inflated.x1 = (e->rb->came_from == RND_EAST ? ans.orig.x1 : 0); + ans.inflated.y1 = (e->rb->came_from == RND_SOUTH ? ans.orig.y1 : 0); + ans.inflated.x2 = (e->rb->came_from == RND_WEST ? ans.orig.x2 : PCB->hdr.bbox.x2); + ans.inflated.y2 = (e->rb->came_from == RND_NORTH ? ans.orig.y2 : PCB->hdr.bbox.y2); + if (e->rb->came_from == RND_NORTH) + ans.done = noshrink = _SOUTH; + else if (e->rb->came_from == RND_EAST) + ans.done = noshrink = _WEST; + else if (e->rb->came_from == RND_SOUTH) + ans.done = noshrink = _NORTH; + else if (e->rb->came_from == RND_WEST) + ans.done = noshrink = _EAST; + else + ans.done = noshrink = 0; + break; + case RND_NORTH: + ans.done = _SOUTH + _EAST + _WEST; + noshrink = _SOUTH; + ans.inflated.x1 = box->x1 - ans.bloat; + ans.inflated.x2 = box->x2 + ans.bloat; + ans.inflated.y2 = box->y2; + ans.inflated.y1 = 0; /* far north */ + break; + case RND_NE: + ans.done = _SOUTH + _WEST; + noshrink = 0; + ans.inflated.x1 = box->x1 - ans.bloat; + ans.inflated.x2 = PCB->hdr.bbox.x2; + ans.inflated.y2 = box->y2 + ans.bloat; + ans.inflated.y1 = 0; + break; + case RND_EAST: + ans.done = _NORTH + _SOUTH + _WEST; + noshrink = _WEST; + ans.inflated.y1 = box->y1 - ans.bloat; + ans.inflated.y2 = box->y2 + ans.bloat; + ans.inflated.x1 = box->x1; + ans.inflated.x2 = PCB->hdr.bbox.x2; + break; + case RND_SE: + ans.done = _NORTH + _WEST; + noshrink = 0; + ans.inflated.x1 = box->x1 - ans.bloat; + ans.inflated.x2 = PCB->hdr.bbox.x2; + ans.inflated.y2 = PCB->hdr.bbox.y2; + ans.inflated.y1 = box->y1 - ans.bloat; + break; + case RND_SOUTH: + ans.done = _NORTH + _EAST + _WEST; + noshrink = _NORTH; + ans.inflated.x1 = box->x1 - ans.bloat; + ans.inflated.x2 = box->x2 + ans.bloat; + ans.inflated.y1 = box->y1; + ans.inflated.y2 = PCB->hdr.bbox.y2; + break; + case RND_SW: + ans.done = _NORTH + _EAST; + noshrink = 0; + ans.inflated.x1 = 0; + ans.inflated.x2 = box->x2 + ans.bloat; + ans.inflated.y2 = PCB->hdr.bbox.y2; + ans.inflated.y1 = box->y1 - ans.bloat; + break; + case RND_WEST: + ans.done = _NORTH + _SOUTH + _EAST; + noshrink = _EAST; + ans.inflated.y1 = box->y1 - ans.bloat; + ans.inflated.y2 = box->y2 + ans.bloat; + ans.inflated.x1 = 0; + ans.inflated.x2 = box->x2; + break; + case RND_NW: + ans.done = _SOUTH + _EAST; + noshrink = 0; + ans.inflated.x1 = 0; + ans.inflated.x2 = box->x2 + ans.bloat; + ans.inflated.y2 = box->y2 + ans.bloat; + ans.inflated.y1 = 0; + break; + default: + noshrink = ans.done = 0; + assert(0); + } + ans.keep = e->rb->style->Clearance; + ans.parent = nonhomeless_parent(e->rb); + rnd_r_search(rtree, &ans.inflated, NULL, __Expand_this_rect, &ans, NULL); +/* because the overlaping boxes are found in random order, some blockers + * may have limited edges prematurely, so we check if the blockers realy + * are blocking, and make another try if not + */ + if (ans.n && !boink_box(ans.n, &ans, RND_NORTH)) + ans.inflated.y1 = 0; + else + ans.done |= _NORTH; + if (ans.e && !boink_box(ans.e, &ans, RND_EAST)) + ans.inflated.x2 = PCB->hdr.bbox.x2; + else + ans.done |= _EAST; + if (ans.s && !boink_box(ans.s, &ans, RND_SOUTH)) + ans.inflated.y2 = PCB->hdr.bbox.y2; + else + ans.done |= _SOUTH; + if (ans.w && !boink_box(ans.w, &ans, RND_WEST)) + ans.inflated.x1 = 0; + else + ans.done |= _WEST; + if (ans.done != _NORTH + _EAST + _SOUTH + _WEST) { + rnd_r_search(rtree, &ans.inflated, NULL, __Expand_this_rect, &ans, NULL); + } + if ((noshrink & _NORTH) == 0) + ans.inflated.y1 += ans.bloat; + if ((noshrink & _EAST) == 0) + ans.inflated.x2 -= ans.bloat; + if ((noshrink & _SOUTH) == 0) + ans.inflated.y2 -= ans.bloat; + if ((noshrink & _WEST) == 0) + ans.inflated.x1 += ans.bloat; + return &ans; +} + +/* blocker_to_heap puts the blockers into a heap so they + * can be retrieved in clockwise order. If a blocker + * is also a target, it gets put into the vector too. + * It returns 1 for any fixed blocker that is not part + * of this net and zero otherwise. + */ +static int blocker_to_heap(rnd_heap_t * heap, routebox_t * rb, rtrnd_rtree_box_t * box, rnd_direction_t dir) +{ + rtrnd_rtree_box_t b = rb->sbox; + if (rb->style->Clearance > AutoRouteParameters.style->Clearance) + b = rnd_bloat_box(&b, rb->style->Clearance - AutoRouteParameters.style->Clearance); + b = rnd_clip_box(&b, box); + assert(rnd_box_is_good(&b)); + /* we want to look at the blockers clockwise around the box */ + switch (dir) { + /* we need to use the other coordinate fraction to resolve + * ties since we want the shorter of the furthest + * first. + */ + case RND_NORTH: + rnd_heap_insert(heap, b.x1 - b.x1 / (b.x2 + DELTA), rb); + break; + case RND_EAST: + rnd_heap_insert(heap, b.y1 - b.y1 / (b.y2 + DELTA), rb); + break; + case RND_SOUTH: + rnd_heap_insert(heap, -(b.x2 + b.x1 / (b.x2 + DELTA)), rb); + break; + case RND_WEST: + rnd_heap_insert(heap, -(b.y2 + b.y1 / (b.y2 + DELTA)), rb); + break; + default: + assert(0); + } + if (rb->flags.fixed && !rb->flags.target && !rb->flags.source) + return 1; + return 0; +} + +/* this creates an EXPANSION_AREA to bridge small gaps or, + * (more commonly) create a supper-thin box to provide a + * home for an expansion edge. + */ +static routebox_t *CreateBridge(const rtrnd_rtree_box_t * area, routebox_t * parent, rnd_direction_t dir) +{ + routebox_t *rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(area && parent); + init_const_box(rb, area->x1, area->y1, area->x2, area->y2, 0); + rb->group = parent->group; + rb->type = EXPANSION_AREA; + rb->came_from = dir; + rb->cost_point = rnd_closest_cheap_point_in_box(&parent->cost_point, area); + rb->cost = parent->cost + pcb_cost_to_point_on_layer(&parent->cost_point, &rb->cost_point, rb->group); + rb->parent.expansion_area = route_parent(parent); + if (rb->parent.expansion_area->flags.homeless) + RB_up_count(rb->parent.expansion_area); + rb->flags.homeless = 1; + rb->flags.nobloat = 1; + rb->style = parent->style; + rb->conflicts_with = parent->conflicts_with; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EDGES) + showroutebox(rb); +#endif + return rb; +} + +/* moveable_edge prepares the new search edges based on the + * starting box, direction and blocker if any. + */ +void +moveable_edge(vector_t * result, const rtrnd_rtree_box_t * box, rnd_direction_t dir, + routebox_t * rb, + routebox_t * blocker, edge_t * e, rtrnd_rtree_t * targets, + routeone_state_t *s, rtrnd_rtree_t * tree, vector_t * area_vec) +{ + rtrnd_rtree_box_t b; + assert(rnd_box_is_good(box)); + b = *box; + /* for the cardinal directions, move the box to overlap the + * the parent by 1 unit. Corner expansions overlap more + * and their starting boxes are pre-prepared. + * Check if anything is headed off the board edges + */ + switch (dir) { + default: + break; + case RND_NORTH: + b.y2 = b.y1; + b.y1-=DELTA; + if (b.y1 <= AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case RND_EAST: + b.x1 = b.x2; + b.x2+=DELTA; + if (b.x2 >= PCB->hdr.bbox.x2 - AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case RND_SOUTH: + b.y1 = b.y2; + b.y2+=DELTA; + if (b.y2 >= PCB->hdr.bbox.y2 - AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case RND_WEST: + b.x2 = b.x1; + b.x1-=DELTA; + if (b.x1 <= AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case RND_NE: + if (b.y1 <= AutoRouteParameters.bloat + DELTA && b.x2 >= PCB->hdr.bbox.x2 - AutoRouteParameters.bloat - DELTA) + return; /* off board edge */ + if (b.y1 <= AutoRouteParameters.bloat + DELTA) + dir = RND_EAST; /* north off board edge */ + if (b.x2 >= PCB->hdr.bbox.x2 - AutoRouteParameters.bloat - DELTA) + dir = RND_NORTH; /* east off board edge */ + break; + case RND_SE: + if (b.y2 >= PCB->hdr.bbox.y2 - AutoRouteParameters.bloat - DELTA && b.x2 >= PCB->hdr.bbox.x2 - AutoRouteParameters.bloat - DELTA) + return; /* off board edge */ + if (b.y2 >= PCB->hdr.bbox.y2 - AutoRouteParameters.bloat - DELTA) + dir = RND_EAST; /* south off board edge */ + if (b.x2 >= PCB->hdr.bbox.x2 - AutoRouteParameters.bloat - DELTA) + dir = RND_SOUTH; /* east off board edge */ + break; + case RND_SW: + if (b.y2 >= PCB->hdr.bbox.y2 - AutoRouteParameters.bloat - DELTA && b.x1 <= AutoRouteParameters.bloat + DELTA) + return; /* off board edge */ + if (b.y2 >= PCB->hdr.bbox.y2 - AutoRouteParameters.bloat - DELTA) + dir = RND_WEST; /* south off board edge */ + if (b.x1 <= AutoRouteParameters.bloat + 1) + dir = RND_SOUTH; /* west off board edge */ + break; + case RND_NW: + if (b.y1 <= AutoRouteParameters.bloat + DELTA && b.x1 <= AutoRouteParameters.bloat + DELTA) + return; /* off board edge */ + if (b.y1 <= AutoRouteParameters.bloat + DELTA) + dir = RND_WEST; /* north off board edge */ + if (b.x1 <= AutoRouteParameters.bloat + DELTA) + dir = RND_NORTH; /* west off board edge */ + break; + } + + if (!blocker) { + edge_t *ne; + routebox_t *nrb = CreateBridge(&b, rb, dir); + /* move the cost point in corner expansions + * these boxes are bigger, so move close to the target + */ + if (dir == RND_NE || dir == RND_SE || dir == RND_SW || dir == RND_NW) { + rnd_cheap_point_t p; + p = rnd_closest_cheap_point_in_box(&nrb->cost_point, &e->minpcb_cost_target->sbox); + p = rnd_closest_cheap_point_in_box(&p, &b); + nrb->cost += pcb_cost_to_point_on_layer(&p, &nrb->cost_point, nrb->group); + nrb->cost_point = p; + } + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, NULL, dir, targets); + vector_append(result, ne); + } + else if (AutoRouteParameters.with_conflicts && !blocker->flags.target + && !blocker->flags.fixed && !blocker->flags.touched && !blocker->flags.source && blocker->type != EXPANSION_AREA) { + edge_t *ne; + routebox_t *nrb; + /* make a bridge to the edge of the blocker + * in all directions from there + */ + switch (dir) { + case RND_NORTH: + b.y1 = blocker->sbox.y2 - DELTA; + break; + case RND_EAST: + b.x2 = blocker->sbox.x1 + DELTA; + break; + case RND_SOUTH: + b.y2 = blocker->sbox.y1 + DELTA; + break; + case RND_WEST: + b.x1 = blocker->sbox.x2 - DELTA; + break; + default: + assert(0); + } + if (!rnd_box_is_good(&b)) + return; /* how did this happen ? */ + nrb = CreateBridge(&b, rb, dir); + rnd_r_insert_entry(tree, &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + /* mark this one as conflicted */ + path_conflicts(nrb, blocker, rtrnd_true); + /* and make an expansion edge */ + nrb->cost_point = rnd_closest_cheap_point_in_box(&nrb->cost_point, &blocker->sbox); + nrb->cost += + pcb_cost_to_point_on_layer(&nrb->parent.expansion_area->cost_point, &nrb->cost_point, nrb->group) * CONFLICT_PENALTY(blocker); + + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, NULL, RND_ANY_DIR, targets); + ne->flags.is_interior = 1; + vector_append(result, ne); + } +#if 1 + else if (blocker->type == EXPANSION_AREA) { + if (blocker->cost < rb->cost || blocker->cost <= rb->cost + + pcb_cost_to_point_on_layer(&blocker->cost_point, &rb->cost_point, rb->group)) + return; + if (blocker->conflicts_with || rb->conflicts_with) + return; + /* does the blocker overlap this routebox ?? */ + /* does this re-parenting operation leave a memory leak? */ + if (blocker->parent.expansion_area->flags.homeless) + RB_down_count(blocker->parent.expansion_area); + blocker->parent.expansion_area = rb; + return; + } +#endif + else if (blocker->flags.target) { + routebox_t *nrb; + edge_t *ne; + b = rnd_bloat_box(&b, DELTA); + if (!rnd_box_intersect(&b, &blocker->sbox)) { + /* if the expansion edge stopped before touching, expand the bridge */ + switch (dir) { + case RND_NORTH: + b.y1 -= AutoRouteParameters.bloat + DELTA; + break; + case RND_EAST: + b.x2 += AutoRouteParameters.bloat + DELTA; + break; + case RND_SOUTH: + b.y2 += AutoRouteParameters.bloat + DELTA; + break; + case RND_WEST: + b.x1 -= AutoRouteParameters.bloat + DELTA; + break; + default: + assert(0); + } + } + assert(rnd_box_intersect(&b, &blocker->sbox)); + b = rnd_shrink_box(&b, DELTA); + nrb = CreateBridge(&b, rb, dir); + rnd_r_insert_entry(tree, &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, blocker, dir, NULL); + best_path_candidate(s, ne, blocker); + DestroyEdge(&ne); + } +} + +struct break_info { + rnd_heap_t *heap; + routebox_t *parent; + rtrnd_rtree_box_t box; + rnd_direction_t dir; + rtrnd_bool_t ignore_source; +}; + +static rnd_r_dir_t __GatherBlockers(const rtrnd_rtree_box_t * box, void *cl) +{ + routebox_t *rb = (routebox_t *) box; + struct break_info *bi = (struct break_info *) cl; + rtrnd_rtree_box_t b; + + if (bi->parent == rb || rb->flags.touched || bi->parent->parent.expansion_area == rb) + return RND_R_DIR_NOT_FOUND; + if (rb->flags.source && bi->ignore_source) + return RND_R_DIR_NOT_FOUND; + b = rb->sbox; + if (rb->style->Clearance > AutoRouteParameters.style->Clearance) + b = rnd_bloat_box(&b, rb->style->Clearance - AutoRouteParameters.style->Clearance); + if (b.x2 <= bi->box.x1 || b.x1 >= bi->box.x2 || b.y1 >= bi->box.y2 || b.y2 <= bi->box.y1) + return RND_R_DIR_NOT_FOUND; + if (blocker_to_heap(bi->heap, rb, &bi->box, bi->dir)) + return RND_R_DIR_FOUND_CONTINUE; + return RND_R_DIR_NOT_FOUND; +} + +/* shrink the box to the last limit for the previous direction, + * i.e. if dir is SOUTH, then this means fixing up an EAST leftover + * edge, which would be the southern most edge for that example. + */ +static inline rtrnd_rtree_box_t previous_edge(double last, rnd_direction_t i, const rtrnd_rtree_box_t * b) +{ + rtrnd_rtree_box_t db = *b; + switch (i) { + case RND_EAST: + db.x1 = last; + break; + case RND_SOUTH: + db.y1 = last; + break; + case RND_WEST: + db.x2 = last; + break; + default: + fprintf(stderr, ERROR "previous edge bogus direction!"); + assert(0); + } + return db; +} + +/* Break all the edges of the box that need breaking, handling + * targets as they are found, and putting any moveable edges + * in the return vector. + */ +vector_t *BreakManyEdges(routeone_state_t * s, rtrnd_rtree_t * targets, rtrnd_rtree_t * tree, + vector_t * area_vec, struct E_result * ans, routebox_t * rb, edge_t * e) +{ + struct break_info bi; + vector_t *edges; + rnd_heap_t *heap[4]; + double first, last; + double bloat; + rnd_direction_t dir; + routebox_t fake; + + edges = vector_create(); + bi.ignore_source = rb->parent.expansion_area->flags.source; + bi.parent = rb; + /* we add 2 to the bloat. + * 1 will get us to the actual blocker that Expand() hit + * but 1 more is needed because the new expansion edges + * move out by 1 so they don't overlap their parents + * this extra expansion could "trap" the edge if + * there is a blocker 2 units from the original rb, + * it is 1 unit from the new expansion edge which + * would prevent expansion. So we want to break the + * edge on it now to avoid the trap. + */ + + bloat = AutoRouteParameters.bloat + DELTA * 2; + /* for corner expansion, we need to have a fake blocker + * to prevent expansion back where we came from since + * we still need to break portions of all 4 edges + */ + if (e->expand_dir == RND_NE || e->expand_dir == RND_SE || e->expand_dir == RND_SW || e->expand_dir == RND_NW) { + rtrnd_rtree_box_t *fb = (rtrnd_rtree_box_t *) & fake.sbox; + memset(&fake, 0, sizeof(fake)); + *fb = e->rb->sbox; + fake.flags.fixed = 1; /* this stops expansion there */ + fake.type = LINE; + fake.style = AutoRouteParameters.style; +#ifndef NDEBUG + /* the routbox_is_good checker wants a lot more! */ + fake.flags.inited = 1; + fb = (rtrnd_rtree_box_t *) & fake.box; + *fb = e->rb->sbox; + fake.same_net.next = fake.same_net.prev = &fake; + fake.same_subnet.next = fake.same_subnet.prev = &fake; + fake.original_subnet.next = fake.original_subnet.prev = &fake; + fake.different_net.next = fake.different_net.prev = &fake; +#endif + } + /* gather all of the blockers in heaps so they can be accessed + * in clockwise order, which allows finding corners that can + * be expanded. + */ + for (dir = RND_NORTH; dir <= RND_WEST; dir = directionIncrement(dir)) { + int tmp; + /* don't break the edge we came from */ + if (e->expand_dir != ((dir + 2) % 4)) { + heap[dir] = rnd_heap_create(); + bi.box = rnd_bloat_box(&rb->sbox, bloat); + bi.heap = heap[dir]; + bi.dir = dir; + /* convert to edge */ + switch (dir) { + case RND_NORTH: + bi.box.y2 = bi.box.y1 + bloat + DELTA; + /* for corner expansion, block the start edges and + * limit the blocker search to only the new edge segment + */ + if (e->expand_dir == RND_SE || e->expand_dir == RND_SW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == RND_SE) + bi.box.x1 = e->rb->sbox.x2; + if (e->expand_dir == RND_SW) + bi.box.x2 = e->rb->sbox.x1; + rnd_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->n = tmp; + break; + case RND_EAST: + bi.box.x1 = bi.box.x2 - bloat - DELTA; + /* corner, same as above */ + if (e->expand_dir == RND_SW || e->expand_dir == RND_NW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == RND_SW) + bi.box.y1 = e->rb->sbox.y2; + if (e->expand_dir == RND_NW) + bi.box.y2 = e->rb->sbox.y1; + rnd_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->e = tmp; + break; + case RND_SOUTH: + bi.box.y1 = bi.box.y2 - bloat - DELTA; + /* corner, same as above */ + if (e->expand_dir == RND_NE || e->expand_dir == RND_NW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == RND_NE) + bi.box.x1 = e->rb->sbox.x2; + if (e->expand_dir == RND_NW) + bi.box.x2 = e->rb->sbox.x1; + rnd_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->s = tmp; + break; + case RND_WEST: + bi.box.x2 = bi.box.x1 + bloat + DELTA; + /* corner, same as above */ + if (e->expand_dir == RND_NE || e->expand_dir == RND_SE) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == RND_SE) + bi.box.y1 = e->rb->sbox.y2; + if (e->expand_dir == RND_NE) + bi.box.y2 = e->rb->sbox.y1; + rnd_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->w = tmp; + break; + default: + assert(0); + } + } + else + heap[dir] = NULL; + } +#if 1 + rb->cost += (rb->n + rb->e + rb->s + rb->w) * AutoRouteParameters.CongestionPenalty / box_area(rb->sbox); +#endif +/* now handle the blockers: + * Go around the expansion area clockwise (North->East->South->West) + * pulling blockers from the heap (which makes them come out in the right + * order). Break the edges on the blocker and make the segments and corners + * moveable as possible. + */ + first = last = -1; + for (dir = RND_NORTH; dir <= RND_WEST; dir = directionIncrement(dir)) { + if (heap[dir] && !rnd_heap_is_empty(heap[dir])) { + /* pull the very first one out of the heap outside of the + * heap loop because it is special; it can be part of a corner + */ + routebox_t *blk = (routebox_t *) rnd_heap_remove_smallest(heap[dir]); + rtrnd_rtree_box_t b = rb->sbox; + struct broken_boxes broke = break_box_edge(&b, dir, blk); + if (broke.is_valid_left) { + /* if last > 0, then the previous edge had a segment + * joining this one, so it forms a valid corner expansion + */ + if (last > 0) { + /* make a corner expansion */ + rtrnd_rtree_box_t db = b; + switch (dir) { + case RND_EAST: + /* possible NE expansion */ + db.x1 = last; + db.y2 = RND_MIN(db.y2, broke.left.y2); + break; + case RND_SOUTH: + /* possible SE expansion */ + db.y1 = last; + db.x1 = RND_MAX(db.x1, broke.left.x1); + break; + case RND_WEST: + /* possible SW expansion */ + db.x2 = last; + db.y1 = RND_MAX(db.y1, broke.left.y1); + break; + default: + assert(0); + break; + } + moveable_edge(edges, &db, (rnd_direction_t) (dir + 3), rb, NULL, e, targets, s, NULL, NULL); + } + else if (dir == RND_NORTH) { /* north is start, so nothing "before" it */ + /* save for a possible corner once we've + * finished circling the box + */ + first = RND_MAX(b.x1, broke.left.x2); + } + else { + /* this is just a boring straight expansion + * since the orthogonal segment was blocked + */ + moveable_edge(edges, &broke.left, dir, rb, NULL, e, targets, s, NULL, NULL); + } + } /* broke.is_valid_left */ + else if (last > 0) { + /* if the last one didn't become a corner, + * we still want to expand it straight out + * in the direction of the previous edge, + * which it belongs to. + */ + rtrnd_rtree_box_t db = previous_edge(last, dir, &rb->sbox); + moveable_edge(edges, &db, (rnd_direction_t) (dir - 1), rb, NULL, e, targets, s, NULL, NULL); + } + if (broke.is_valid_center && !blk->flags.source) + moveable_edge(edges, &broke.center, dir, rb, blk, e, targets, s, tree, area_vec); + /* this is the heap extraction loop. We break out + * if there's nothing left in the heap, but if we * are blocked all the way to the far edge, we can + * just leave stuff in the heap when it is destroyed + */ + while (broke.is_valid_right) { + /* move the box edge to the next potential free point */ + switch (dir) { + case RND_NORTH: + last = b.x1 = RND_MAX(broke.right.x1, b.x1); + break; + case RND_EAST: + last = b.y1 = RND_MAX(broke.right.y1, b.y1); + break; + case RND_SOUTH: + last = b.x2 = RND_MIN(broke.right.x2, b.x2); + break; + case RND_WEST: + last = b.y2 = RND_MIN(broke.right.y2, b.y2); + break; + default: + assert(0); + } + if (rnd_heap_is_empty(heap[dir])) + break; + blk = (routebox_t *) rnd_heap_remove_smallest(heap[dir]); + broke = break_box_edge(&b, dir, blk); + if (broke.is_valid_left) + moveable_edge(edges, &broke.left, dir, rb, NULL, e, targets, s, NULL, NULL); + if (broke.is_valid_center && !blk->flags.source) + moveable_edge(edges, &broke.center, dir, rb, blk, e, targets, s, tree, area_vec); + } + if (!broke.is_valid_right) + last = -1; + } + else { /* if (heap[dir]) */ + + /* nothing touched this edge! Expand the whole edge unless + * (1) it hit the board edge or (2) was the source of our expansion + * + * for this case (of hitting nothing) we give up trying for corner + * expansions because it is likely that they're not possible anyway + */ + if ((e->expand_dir == RND_ANY_DIR ? e->rb->came_from : e->expand_dir) != ((dir + 2) % 4)) { + /* ok, we are not going back on ourselves, and the whole edge seems free */ + moveable_edge(edges, &rb->sbox, dir, rb, NULL, e, targets, s, NULL, NULL); + } + + if (last > 0) { + /* expand the leftover from the prior direction */ + rtrnd_rtree_box_t db = previous_edge(last, dir, &rb->sbox); + moveable_edge(edges, &db, (rnd_direction_t) (dir - 1), rb, NULL, e, targets, s, NULL, NULL); + } + last = -1; + } + } /* for loop */ + /* finally, check for the NW corner now that we've come full circle */ + if (first > 0 && last > 0) { + rtrnd_rtree_box_t db = rb->sbox; + db.x2 = first; + db.y2 = last; + moveable_edge(edges, &db, RND_NW, rb, NULL, e, targets, s, NULL, NULL); + } + else { + if (first > 0) { + rtrnd_rtree_box_t db = rb->sbox; + db.x2 = first; + moveable_edge(edges, &db, RND_NORTH, rb, NULL, e, targets, s, NULL, NULL); + } + else if (last > 0) { + rtrnd_rtree_box_t db = rb->sbox; + db.y2 = last; + moveable_edge(edges, &db, RND_WEST, rb, NULL, e, targets, s, NULL, NULL); + } + } + /* done with all expansion edges of this box */ + for (dir = RND_NORTH; dir <= RND_WEST; dir = directionIncrement(dir)) { + if (heap[dir]) + rnd_heap_destroy(&heap[dir]); + } + return edges; +} + +static routebox_t *rb_source(routebox_t * rb) +{ + while (rb && !rb->flags.source) { + assert(rb->type == EXPANSION_AREA); + rb = rb->parent.expansion_area; + } + assert(rb); + return rb; +} + +/* ------------ */ + +struct foib_info { + const rtrnd_rtree_box_t *box; + routebox_t *intersect; + jmp_buf env; +}; + +static rnd_r_dir_t foib_rect_in_reg(const rtrnd_rtree_box_t * box, void *cl) +{ + struct foib_info *foib = (struct foib_info *) cl; + rtrnd_rtree_box_t rbox; + routebox_t *rb = (routebox_t *) box; + if (rb->flags.touched) + return RND_R_DIR_NOT_FOUND; +/* if (rb->type == EXPANSION_AREA && !rb->flags.is_via)*/ + /* return RND_R_DIR_NOT_FOUND; */ + rbox = bloat_routebox(rb); + if (!rnd_box_intersect(&rbox, foib->box)) + return RND_R_DIR_NOT_FOUND; + /* this is an intersector! */ + foib->intersect = (routebox_t *) box; + longjmp(foib->env, 1); /* skip to the end! */ + return RND_R_DIR_FOUND_CONTINUE; +} + +static routebox_t *FindOneInBox(rtrnd_rtree_t * rtree, routebox_t * rb) +{ + struct foib_info foib; + rtrnd_rtree_box_t r; + + r = rb->sbox; + foib.box = &r; + foib.intersect = NULL; + + if (setjmp(foib.env) == 0) + rnd_r_search(rtree, &r, NULL, foib_rect_in_reg, &foib, NULL); + return foib.intersect; +} + +struct therm_info { + routebox_t *plane; + rtrnd_rtree_box_t query; + jmp_buf env; +}; +static rnd_r_dir_t ftherm_rect_in_reg(const rtrnd_rtree_box_t * box, void *cl) +{ + routebox_t *rbox = (routebox_t *) box; + struct therm_info *ti = (struct therm_info *) cl; + rtrnd_rtree_box_t sq, sb; + + if (rbox->type != TERM) + return RND_R_DIR_NOT_FOUND; + if (rbox->group != ti->plane->group) + return RND_R_DIR_NOT_FOUND; + + sb = shrink_routebox(rbox); + switch (rbox->type) { + case TERM: + case VIA_SHADOW: + sq = rnd_shrink_box(&ti->query, rbox->style->Diameter); + if (!rnd_box_intersect(&sb, &sq)) + return RND_R_DIR_NOT_FOUND; + sb.x1 = RND_BOX_CENTER_X(sb); + sb.y1 = RND_BOX_CENTER_Y(sb); + break; + default: + assert(0); + } + ti->plane = rbox; + longjmp(ti->env, 1); + return RND_R_DIR_FOUND_CONTINUE; +} + +/* check for a pin or via target that a polygon can just use a thermal to connect to */ +routebox_t *FindThermable(rtrnd_rtree_t * rtree, routebox_t * rb) +{ + struct therm_info info; + + info.plane = rb; + info.query = shrink_routebox(rb); + + if (setjmp(info.env) == 0) { + rnd_r_search(rtree, &info.query, NULL, ftherm_rect_in_reg, &info, NULL); + return NULL; + } + return info.plane; +} + +/*-------------------------------------------------------------------- + * Route-tracing code: once we've got a path of expansion boxes, trace + * a line through them to actually create the connection. + */ +static void RD_DrawThermal(routedata_t * rd, double X, double Y, long group, long layer, routebox_t * subnet, rtrnd_bool_t is_bad) +{ + routebox_t *rb; + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + init_const_box(rb, X, Y, X + DELTA, Y + DELTA, 0); + rb->group = group; + rb->layer = layer; + rb->flags.fixed = 0; + rb->flags.is_bad = is_bad; + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.circular = 0; + rb->style = AutoRouteParameters.style; + rb->type = THERMAL; + InitLists(rb); + MergeNets(rb, subnet, NET); + MergeNets(rb, subnet, SUBNET); + /* add it to the r-tree, this may be the whole route! */ + rnd_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + rb->flags.homeless = 0; +} + +static void RD_DrawVia(routedata_t * rd, double X, double Y, double radius, routebox_t * subnet, rtrnd_bool_t is_bad) +{ + routebox_t *rb, *first_via = NULL; + int i; + int ka = AutoRouteParameters.style->Clearance; + + /* a via cuts through every layer group */ + for (i = 0; i < pcb_max_group(PCB); i++) { + if (!is_layer_group_active[i]) + continue; + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + init_const_box(rb, + /*X1 */ X - radius, /*Y1 */ Y - radius, + /*X2 */ X + radius + DELTA, /*Y2 */ Y + radius + DELTA, ka); + rb->group = i; + rb->flags.fixed = 0; /* indicates that not on PCB yet */ + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.is_bad = is_bad; + rb->came_from = RND_ANY_DIR; + rb->flags.circular = rtrnd_true; + rb->style = AutoRouteParameters.style; + rb->pass = AutoRouteParameters.pass; + if (first_via == NULL) { + rb->type = VIA; + rb->parent.via = NULL; /* indicates that not on PCB yet */ + first_via = rb; + /* only add the first via to mtspace, not the shadows too */ + mtspace_add(rd->mtspace, &rb->box, rb->flags.is_odd ? ODD : EVEN, rb->style->Clearance); + } + else { + rb->type = VIA_SHADOW; + rb->parent.via_shadow = first_via; + } + InitLists(rb); + /* add these to proper subnet. */ + MergeNets(rb, subnet, NET); + MergeNets(rb, subnet, SUBNET); + assert(__routepcb_box_is_good(rb)); + /* and add it to the r-tree! */ + rnd_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + rb->flags.homeless = 0; /* not homeless anymore */ + } +} + +static void +RD_DrawLine(routedata_t * rd, + double X1, double Y1, double X2, + double Y2, double halfthick, long group, routebox_t * subnet, rtrnd_bool_t is_bad, rtrnd_bool_t is_45) +{ + /* we hold the line in a queue to concatenate segments that + * ajoin one another. That reduces the number of things in + * the trees and allows conflict boxes to be larger, both of + * which are really useful. + */ + static double qX1 = -1, qY1, qX2, qY2; + static double qhthick; + static long qgroup; + static rtrnd_bool_t qis_45, qis_bad; + static routebox_t *qsn; + + routebox_t *rb; + double ka = AutoRouteParameters.style->Clearance; + + /* don't draw zero-length segments. */ + if (X1 == X2 && Y1 == Y2) + return; + if (qX1 == -1) { /* first ever */ + qX1 = X1; + qY1 = Y1; + qX2 = X2; + qY2 = Y2; + qhthick = halfthick; + qgroup = group; + qis_45 = is_45; + qis_bad = is_bad; + qsn = subnet; + return; + } + /* Check if the lines concatenat. We only check the + * normal expected nextpoint=lastpoint condition + */ + if (X1 == qX2 && Y1 == qY2 && qhthick == halfthick && qgroup == group) { + if (qX1 == qX2 && X1 == X2) { /* everybody on the same X here */ + qY2 = Y2; + return; + } + if (qY1 == qY2 && Y1 == Y2) { /* same Y all around */ + qX2 = X2; + return; + } + } + /* dump the queue, no match here */ + if (qX1 == -1) + return; /* but not this! */ + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(is_45 ? (fabs(qX2 - qX1) == fabs(qY2 - qY1)) /* line must be 45-degrees */ + : (qX1 == qX2 || qY1 == qY2) /* line must be ortho */ ); + init_const_box(rb, + /*X1 */ RND_MIN(qX1, qX2) - qhthick, + /*Y1 */ RND_MIN(qY1, qY2) - qhthick, + /*X2 */ RND_MAX(qX1, qX2) + qhthick + DELTA, + /*Y2 */ RND_MAX(qY1, qY2) + qhthick + DELTA, ka); + rb->group = qgroup; + rb->type = LINE; + rb->line.x1 = qX1; + rb->line.x2 = qX2; + rb->line.y1 = qY1; + rb->line.y2 = qY2; + rb->parent.line = NULL; /* indicates that not on PCB yet */ + rb->flags.fixed = 0; /* indicates that not on PCB yet */ + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.is_bad = qis_bad; + rb->came_from = RND_ANY_DIR; + rb->flags.homeless = 0; /* we're putting this in the tree */ + rb->flags.nonstraight = qis_45; + rb->flags.bl_to_ur = ((qX2 >= qX1 && qY2 <= qY1) + || (qX2 <= qX1 && qY2 >= qY1)); + rb->style = AutoRouteParameters.style; + rb->pass = AutoRouteParameters.pass; + InitLists(rb); + /* add these to proper subnet. */ + MergeNets(rb, qsn, NET); + MergeNets(rb, qsn, SUBNET); + assert(__routepcb_box_is_good(rb)); + /* and add it to the r-tree! */ + rnd_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + + /* and to the via space structures */ + if (AutoRouteParameters.use_vias) + mtspace_add(rd->mtspace, &rb->box, rb->flags.is_odd ? ODD : EVEN, rb->style->Clearance); + usedGroup[rb->group] = rtrnd_true; + /* and queue this one */ + qX1 = X1; + qY1 = Y1; + qX2 = X2; + qY2 = Y2; + qhthick = halfthick; + qgroup = group; + qis_45 = is_45; + qis_bad = is_bad; + qsn = subnet; +} + +static rtrnd_bool_t +RD_DrawManhattanLine(routedata_t * rd, + const rtrnd_rtree_box_t * box1, const rtrnd_rtree_box_t * box2, + rnd_cheap_point_t start, rnd_cheap_point_t end, + double halfthick, long group, routebox_t * subnet, rtrnd_bool_t is_bad, rtrnd_bool_t last_was_x) +{ + rnd_cheap_point_t knee = start; + if (end.X == start.X) { + RD_DrawLine(rd, start.X, start.Y, end.X, end.Y, halfthick, group, subnet, is_bad, rtrnd_false); + return rtrnd_false; + } + else if (end.Y == start.Y) { + RD_DrawLine(rd, start.X, start.Y, end.X, end.Y, halfthick, group, subnet, is_bad, rtrnd_false); + return rtrnd_true; + } + /* find where knee belongs */ + if (rnd_point_in_box(box1, end.X, start.Y) + || rnd_point_in_box(box2, end.X, start.Y)) { + knee.X = end.X; + knee.Y = start.Y; + } + else { + knee.X = start.X; + knee.Y = end.Y; + } + if ((knee.X == end.X && !last_was_x) && (rnd_point_in_box(box1, start.X, end.Y) + || rnd_point_in_box(box2, start.X, end.Y))) { + knee.X = start.X; + knee.Y = end.Y; + } + assert(AutoRouteParameters.is_smoothing || rnd_point_in_box(box1, knee.X, knee.Y) + || rnd_point_in_box(box2, knee.X, knee.Y)); + + if (1 || !AutoRouteParameters.is_smoothing) { + /* draw standard manhattan paths */ + RD_DrawLine(rd, start.X, start.Y, knee.X, knee.Y, halfthick, group, subnet, is_bad, rtrnd_false); + RD_DrawLine(rd, knee.X, knee.Y, end.X, end.Y, halfthick, group, subnet, is_bad, rtrnd_false); + } + else { + /* draw 45-degree path across knee */ + double len45 = RND_MIN(fabs(start.X - end.X), fabs(start.Y - end.Y)); + rnd_cheap_point_t kneestart = knee, kneeend = knee; + if (kneestart.X == start.X) + kneestart.Y += (kneestart.Y > start.Y) ? -len45 : len45; + else + kneestart.X += (kneestart.X > start.X) ? -len45 : len45; + if (kneeend.X == end.X) + kneeend.Y += (kneeend.Y > end.Y) ? -len45 : len45; + else + kneeend.X += (kneeend.X > end.X) ? -len45 : len45; + RD_DrawLine(rd, start.X, start.Y, kneestart.X, kneestart.Y, halfthick, group, subnet, is_bad, rtrnd_false); + RD_DrawLine(rd, kneestart.X, kneestart.Y, kneeend.X, kneeend.Y, halfthick, group, subnet, is_bad, rtrnd_true); + RD_DrawLine(rd, kneeend.X, kneeend.Y, end.X, end.Y, halfthick, group, subnet, is_bad, rtrnd_false); + } + return (knee.X != end.X); +} + +/* for smoothing, don't pack traces to min clearance gratuitously */ +#if 0 +static void add_clearance(rnd_cheap_point_t * nextpoint, const rtrnd_rtree_box_t * b) +{ + if (nextpoint->X == b->X1) { + if (nextpoint->X + AutoRouteParameters.style->Clearance < (b->X1 + b->X2) / 2) + nextpoint->X += AutoRouteParameters.style->Clearance; + else + nextpoint->X = (b->X1 + b->X2) / 2; + } + else if (nextpoint->X == b->X2) { + if (nextpoint->X - AutoRouteParameters.style->Clearance > (b->X1 + b->X2) / 2) + nextpoint->X -= AutoRouteParameters.style->Clearance; + else + nextpoint->X = (b->X1 + b->X2) / 2; + } + else if (nextpoint->Y == b->Y1) { + if (nextpoint->Y + AutoRouteParameters.style->Clearance < (b->Y1 + b->Y2) / 2) + nextpoint->Y += AutoRouteParameters.style->Clearance; + else + nextpoint->Y = (b->Y1 + b->Y2) / 2; + } + else if (nextpoint->Y == b->Y2) { + if (nextpoint->Y - AutoRouteParameters.style->Clearance > (b->Y1 + b->Y2) / 2) + nextpoint->Y -= AutoRouteParameters.style->Clearance; + else + nextpoint->Y = (b->Y1 + b->Y2) / 2; + } +} +#endif + +/* This back-traces the expansion boxes along the best path + * it draws the lines that will make the actual path. + * during refinement passes, it should try to maximize the area + * for other tracks so routing completion is easier. + * + * during smoothing passes, it should try to make a better path, + * possibly using diagonals, etc. The path boxes are larger on + * average now so there is more possiblity to decide on a nice + * path. Any combination of lines and arcs is possible, so long + * as they don't poke more than half thick outside the path box. + */ + +static void TracePath(routedata_t * rd, routebox_t * path, const routebox_t * target, routebox_t * subnet, rtrnd_bool_t is_bad) +{ + rtrnd_bool_t last_x = rtrnd_false; + double halfwidth = HALF_THICK(AutoRouteParameters.style->Thickness); + double radius = HALF_THICK(AutoRouteParameters.style->Diameter); + rnd_cheap_point_t lastpoint, nextpoint; + routebox_t *lastpath; + rtrnd_rtree_box_t b; + + assert(subnet->style == AutoRouteParameters.style); + /*XXX: because we round up odd thicknesses, there's the possibility that + * a connecting line end-point might be 0.005 mil off the "real" edge. + * don't worry about this because line *thicknesses* are always >= 0.01 mil. */ + + /* if we start with a thermal the target was a plane + * or the target was a pin and the source a plane + * in which case this thermal is the whole path + */ + if (path->flags.is_thermal) { + /* the target was a plane, so we need to find a good spot for the via + * now. It's logical to place it close to the source box which + * is where we're utlimately headed on this path. However, it + * must reside in the plane as well as the via area too. + */ + nextpoint.X = RND_BOX_CENTER_X(path->sbox); + nextpoint.Y = RND_BOX_CENTER_Y(path->sbox); + if (path->parent.expansion_area->flags.is_via) { + TargetPoint(&nextpoint, rb_source(path)); + /* nextpoint is the middle of the source terminal now */ + b = rnd_clip_box(&path->sbox, &path->parent.expansion_area->sbox); + nextpoint = rnd_closest_cheap_point_in_box(&nextpoint, &b); + /* now it's in the via and plane near the source */ + } + else { /* no via coming, target must have been a pin */ + + assert(target->type == TERM); + TargetPoint(&nextpoint, target); + } + assert(rnd_point_in_box(&path->sbox, nextpoint.X, nextpoint.Y)); + RD_DrawThermal(rd, nextpoint.X, nextpoint.Y, path->group, path->layer, subnet, is_bad); + } + else { + /* start from best place of target box */ + lastpoint.X = RND_BOX_CENTER_X(target->sbox); + lastpoint.Y = RND_BOX_CENTER_Y(target->sbox); + TargetPoint(&lastpoint, target); + if (AutoRouteParameters.last_smooth && rnd_box_in_box(&path->sbox, &target->sbox)) + path = path->parent.expansion_area; + b = path->sbox; + if (path->flags.circular) + b = rnd_shrink_box(&b, RND_MIN(b.x2 - b.x1, b.y2 - b.y1) / 5); + nextpoint = rnd_closest_cheap_point_in_box(&lastpoint, &b); + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, rtrnd_true); + else + last_x = RD_DrawManhattanLine(rd, &target->sbox, &path->sbox, + lastpoint, nextpoint, halfwidth, path->group, subnet, is_bad, last_x); + } +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ROUTE_BOXES) + showroutebox(path); +#if defined(ROUTE_VERBOSE) + rnd_printf("TRACEPOINT start %#mD\n", nextpoint.X, nextpoint.Y); +#endif +#endif + + do { + lastpoint = nextpoint; + lastpath = path; + assert(path->type == EXPANSION_AREA); + path = path->parent.expansion_area; + b = path->sbox; + if (path->flags.circular) + b = rnd_shrink_box(&b, RND_MIN(b.x2 - b.x1, b.y2 - b.y1) / 5); + assert(b.x1 != b.x2 && b.y1 != b.y2); /* need someplace to put line! */ + /* find point on path perimeter closest to last point */ + /* if source terminal, try to hit a good place */ + nextpoint = rnd_closest_cheap_point_in_box(&lastpoint, &b); +#if 0 + /* leave more clearance if this is a smoothing pass */ + if (AutoRouteParameters.is_smoothing && (nextpoint.X != lastpoint.X || nextpoint.Y != lastpoint.Y)) + add_clearance(&nextpoint, &b); +#endif + if (path->flags.source && path->type != PLANE) + TargetPoint(&nextpoint, path); + assert(rnd_point_in_box(&lastpath->box, lastpoint.X, lastpoint.Y)); + assert(rnd_point_in_box(&path->box, nextpoint.X, nextpoint.Y)); +#if defined(ROUTE_DEBUG_VERBOSE) + fprintf(stderr, INFO "TRACEPATH: "); + DumpRouteBox(path); + fprintf(stderr, INFO "TRACEPATH: point %f %f to point %f %f layer %d\n", + lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, path->group); +#endif + + /* draw orthogonal lines from lastpoint to nextpoint */ + /* knee is placed in lastpath box */ + /* should never cause line to leave union of lastpath/path boxes */ + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, rtrnd_true); + else + last_x = RD_DrawManhattanLine(rd, &lastpath->sbox, &path->sbox, + lastpoint, nextpoint, halfwidth, path->group, subnet, is_bad, last_x); + if (path->flags.is_via) { /* if via, then add via */ +#ifdef ROUTE_VERBOSE + fprintf(stderr, INFO " (vias)"); +#endif + assert(rnd_point_in_box(&path->box, nextpoint.X, nextpoint.Y)); + RD_DrawVia(rd, nextpoint.X, nextpoint.Y, radius, subnet, is_bad); + } + + assert(lastpath->flags.is_via || path->group == lastpath->group); + +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ROUTE_BOXES) + showroutebox(path); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_ROUTE_BOXES */ + /* if this is connected to a plane, draw the thermal */ + if (path->flags.is_thermal || path->type == PLANE) + RD_DrawThermal(rd, lastpoint.X, lastpoint.Y, path->group, path->layer, subnet, is_bad); + /* when one hop from the source, make an extra path in *this* box */ + if (path->type == EXPANSION_AREA && path->parent.expansion_area->flags.source && path->parent.expansion_area->type != PLANE) { + /* find special point on source (if it exists) */ + if (TargetPoint(&lastpoint, path->parent.expansion_area)) { + lastpoint = closest_point_in_routebox(&lastpoint, path); + b = shrink_routebox(path); +#if 0 + if (AutoRouteParameters.is_smoothing) + add_clearance(&lastpoint, &b); +#else + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, rtrnd_true); + else +#endif + last_x = RD_DrawManhattanLine(rd, &b, &b, nextpoint, lastpoint, halfwidth, path->group, subnet, is_bad, last_x); +#if defined(ROUTE_DEBUG_VERBOSE) + fprintf(stderr, INFO "TRACEPATH: "); + DumpRouteBox(path); + fprintf(stderr, INFO "TRACEPATH: (to source) point %f %f to point %f %f layer %d\n", + nextpoint.X, nextpoint.Y, lastpoint.X, lastpoint.Y, path->group); +#endif + + nextpoint = lastpoint; + } + } + } + while (!path->flags.source); + /* flush the line queue */ + RD_DrawLine(rd, -1, 0, 0, 0, 0, 0, NULL, rtrnd_false, rtrnd_false); + +#ifdef ROUTE_DEBUG + if (ddraw != NULL) + ddraw->flush_debug_draw(); +#endif +} + +/* create a fake "edge" used to defer via site searching. */ +static void +CreateSearchEdge(routeone_state_t *s, vetting_t * work, edge_t * parent, + routebox_t * rb, conflict_t conflict, rtrnd_rtree_t * targets, rtrnd_bool_t in_plane) +{ + routebox_t *target; + rtrnd_rtree_box_t b; + rnd_heap_cost_t cost; + assert(__routepcb_box_is_good(rb)); + /* find the cheapest target */ +#if 0 + target = minpcb_cost_target_to_point(&parent->cost_point, pcb_max_group(PCB) + DELTA, targets, parent->minpcb_cost_target); +#else + target = parent->minpcb_cost_target; +#endif + b = shrink_routebox(target); + cost = parent->pcb_cost_to_point + AutoRouteParameters.ViaCost + pcb_cost_to_layerless_box(&rb->cost_point, 0, &b); + if (cost < s->best_cost) { + edge_t *ne; + ne = (edge_t *) malloc(sizeof(*ne)); + memset((void *) ne, 0, sizeof(*ne)); + assert(ne); + ne->flags.via_search = 1; + ne->flags.in_plane = in_plane; + ne->rb = rb; + if (rb->flags.homeless) + RB_up_count(rb); + ne->work = work; + ne->minpcb_cost_target = target; + ne->flags.via_conflict_level = conflict; + ne->pcb_cost_to_point = parent->pcb_cost_to_point; + ne->cost_point = parent->cost_point; + ne->cost = cost; + rnd_heap_insert(s->workheap, ne->cost, ne); + } + else { + mtsFreeWork(&work); + } +} + +static void add_or_destroy_edge(routeone_state_t *s, edge_t * e) +{ + e->cost = edge_cost(e, s->best_cost); + assert(__edge_is_good(e)); + assert(is_layer_group_active[e->rb->group]); + if (e->cost < s->best_cost) + rnd_heap_insert(s->workheap, e->cost, e); + else + DestroyEdge(&e); +} + +static void best_path_candidate(routeone_state_t *s, edge_t * e, routebox_t * best_target) +{ + e->cost = edge_cost(e, EXPENSIVE); + if (s->best_path == NULL || e->cost < s->best_cost) { +#if defined(ROUTE_DEBUG) && defined (ROUTE_VERBOSE) + fprintf(stderr, INFO "New best path seen! cost = %f\n", e->cost); +#endif + /* new best path! */ + if (s->best_path && s->best_path->flags.homeless) + RB_down_count(s->best_path); + s->best_path = e->rb; + s->best_target = best_target; + s->best_cost = e->cost; + assert(s->best_cost >= 0); + /* don't free this when we destroy edge! */ + if (s->best_path->flags.homeless) + RB_up_count(s->best_path); + } +} + + +/* vectors for via site candidates (see mtspace.h) */ +struct routeone_via_site_state { + vector_t *free_space_vec; + vector_t *lo_conflict_space_vec; + vector_t *hi_conflict_space_vec; +}; + +void +add_via_sites(routeone_state_t *s, + struct routeone_via_site_state *vss, + mtspace_t * mtspace, routebox_t * within, + conflict_t within_conflict_level, edge_t * parent_edge, rtrnd_rtree_t * targets, double shrink, rtrnd_bool_t in_plane) +{ + double radius, clearance; + vetting_t *work; + rtrnd_rtree_box_t region = shrink_routebox(within); + rnd_shrink_box(®ion, shrink); + + radius = HALF_THICK(AutoRouteParameters.style->Diameter); + clearance = AutoRouteParameters.style->Clearance; + assert(AutoRouteParameters.use_vias); + /* XXX: need to clip 'within' to shrunk_pcb_bounds, because when + XXX: routing with conflicts may poke over edge. */ + + /* ask for a via box near our cost_point first */ + work = mtspace_query_rect(mtspace, ®ion, radius, clearance, + NULL, vss->free_space_vec, + vss->lo_conflict_space_vec, + vss->hi_conflict_space_vec, + AutoRouteParameters.is_odd, AutoRouteParameters.with_conflicts, &parent_edge->cost_point); + if (!work) + return; + CreateSearchEdge(s, work, parent_edge, within, within_conflict_level, targets, in_plane); +} + +void +do_via_search(edge_t * search, routeone_state_t *s, + struct routeone_via_site_state *vss, mtspace_t * mtspace, rtrnd_rtree_t * targets) +{ + int i, j, count = 0; + double radius, clearance; + vetting_t *work; + routebox_t *within; + conflict_t within_conflict_level; + + radius = HALF_THICK(AutoRouteParameters.style->Diameter); + clearance = AutoRouteParameters.style->Clearance; + work = mtspace_query_rect(mtspace, NULL, 0, 0, + search->work, vss->free_space_vec, + vss->lo_conflict_space_vec, + vss->hi_conflict_space_vec, AutoRouteParameters.is_odd, AutoRouteParameters.with_conflicts, NULL); + within = search->rb; + within_conflict_level = search->flags.via_conflict_level; + for (i = 0; i < 3; i++) { + vector_t *v = + (i == NO_CONFLICT ? vss->free_space_vec : + i == LO_CONFLICT ? vss->lo_conflict_space_vec : i == HI_CONFLICT ? vss->hi_conflict_space_vec : NULL); + assert(v); + while (!vector_is_empty(v)) { + rtrnd_rtree_box_t cliparea; + rtrnd_rtree_box_t *area = (rtrnd_rtree_box_t *) vector_remove_last(v); + if (!(i == NO_CONFLICT || AutoRouteParameters.with_conflicts)) { + free(area); + continue; + } + /* answers are bloated by radius + clearance */ + cliparea = rnd_shrink_box(area, radius + clearance); + free(area); + assert(rnd_box_is_good(&cliparea)); + count++; + for (j = 0; j < pcb_max_group(PCB); j++) { + edge_t *ne; + if (j == within->group || !is_layer_group_active[j]) + continue; + ne = CreateViaEdge(&cliparea, j, within, search, within_conflict_level, (conflict_t) i, targets); + add_or_destroy_edge(s, ne); + } + } + } + /* prevent freeing of work when this edge is destroyed */ + search->flags.via_search = 0; + if (!work) + return; + CreateSearchEdge(s, work, search, within, within_conflict_level, targets, search->flags.in_plane); + assert(vector_is_empty(vss->free_space_vec)); + assert(vector_is_empty(vss->lo_conflict_space_vec)); + assert(vector_is_empty(vss->hi_conflict_space_vec)); +} + +/* vector of expansion areas to be eventually removed from r-tree + * this is a global for troubleshooting + */ +vector_t *area_vec; + +/* some routines for use in gdb while debugging */ +#if defined(ROUTE_DEBUG) +static void list_conflicts(routebox_t * rb) +{ + int i, n; + if (!rb->conflicts_with) + return; + n = vector_size(rb->conflicts_with); + for (i = 0; i < n; i++) + fprintf(stderr, "%p, ", (void *)vector_element(rb->conflicts_with, i)); +} + +static void show_area_vec(int lay) +{ + int n, save; + + if (!area_vec) + return; + save = showboxen; + showboxen = lay; + for (n = 0; n < vector_size(area_vec); n++) { + routebox_t *rb = (routebox_t *) vector_element(area_vec, n); + showroutebox(rb); + } + showboxen = save; +} + +static rtrnd_bool_t net_id(routebox_t * rb, long int id) +{ + routebox_t *p; + LIST_LOOP(rb, same_net, p); + if (p->flags.source && p->parent.pad->ID == id) + return rtrnd_true; + PCB_END_LOOP; + return rtrnd_false; +} + +static void trace_parents(routebox_t * rb) +{ + while (rb && rb->type == EXPANSION_AREA) { + fprintf(stderr, " %p ->", (void *)rb); + rb = rb->parent.expansion_area; + } + if (rb) + fprintf(stderr, " %p is source\n", (void *)rb); + else + fprintf(stderr, "NULL!\n"); +} + +static void show_one(routebox_t * rb) +{ + int save = showboxen; + showboxen = -1; + showroutebox(rb); + showboxen = save; +} + +static void show_path(routebox_t * rb) +{ + while (rb && rb->type == EXPANSION_AREA) { + show_one(rb); + rb = rb->parent.expansion_area; + } + show_one(rb); +} + +static void show_sources(routebox_t * rb) +{ + routebox_t *p; + if (!rb->flags.source && !rb->flags.target) { + fprintf(stderr, ERROR "start with a source or target please\n"); + return; + } + LIST_LOOP(rb, same_net, p); + if (p->flags.source) + show_one(p); + PCB_END_LOOP; +} + +#endif + +static rnd_r_dir_t __conflict_source(const rtrnd_rtree_box_t * box, void *cl) +{ + routebox_t *rb = (routebox_t *) box; + if (rb->flags.touched || rb->flags.fixed) + return RND_R_DIR_NOT_FOUND; + else { + routebox_t *dis = (routebox_t *) cl; + path_conflicts(dis, rb, rtrnd_false); + touch_conflicts(dis->conflicts_with, 1); + } + return RND_R_DIR_FOUND_CONTINUE; +} + +static void source_conflicts(rtrnd_rtree_t * tree, routebox_t * rb) +{ + if (!AutoRouteParameters.with_conflicts) + return; + rnd_r_search(tree, &rb->sbox, NULL, __conflict_source, rb, NULL); + touch_conflicts(NULL, 1); +} + +typedef struct routeone_status_s { + rtrnd_bool_t found_route; + int route_had_conflicts; + rnd_heap_cost_t best_route_cost; + rtrnd_bool_t net_completely_routed; +} routeone_status_t; + + +static routeone_status_t RouteOne(routedata_t * rd, routebox_t * from, routebox_t * to, int max_edges) +{ + routeone_status_t result; + routebox_t *p; + int seen, i; + const rtrnd_rtree_box_t **target_list; + int num_targets; + rtrnd_rtree_t *targets; + /* vector of source edges for filtering */ + vector_t *source_vec; + /* working vector */ + vector_t *edge_vec; + + routeone_state_t s; + struct routeone_via_site_state vss; + + assert(rd && from); + result.route_had_conflicts = 0; + /* no targets on to/from net need clearance areas */ + LIST_LOOP(from, same_net, p); + p->flags.nobloat = 1; + PCB_END_LOOP; + /* set 'source' flags */ + LIST_LOOP(from, same_subnet, p); + if (!p->flags.nonstraight) + p->flags.source = 1; + PCB_END_LOOP; + + /* count up the targets */ + num_targets = 0; + seen = 0; + /* remove source/target flags from non-straight obstacles, because they + * don't fill their bounding boxes and so connecting to them + * after we've routed is problematic. Better solution? */ + if (to) { /* if we're routing to a specific target */ + if (!to->flags.source) { /* not already connected */ + /* check that 'to' and 'from' are on the same net */ + seen = 0; +#ifndef NDEBUG + LIST_LOOP(from, same_net, p); + if (p == to) + seen = 1; + PCB_END_LOOP; +#endif + assert(seen); /* otherwise from and to are on different nets! */ + /* set target flags only on 'to's subnet */ + LIST_LOOP(to, same_subnet, p); + if (!p->flags.nonstraight && is_layer_group_active[p->group]) { + p->flags.target = 1; + num_targets++; + } + PCB_END_LOOP; + } + } + else { + /* all nodes on the net but not connected to from are targets */ + LIST_LOOP(from, same_net, p); + if (!p->flags.source && is_layer_group_active[p->group] + && !p->flags.nonstraight) { + p->flags.target = 1; + num_targets++; + } + PCB_END_LOOP; + } + + /* if no targets, then net is done! reset flags and return. */ + if (num_targets == 0) { + LIST_LOOP(from, same_net, p); + p->flags.source = p->flags.target = p->flags.nobloat = 0; + PCB_END_LOOP; + result.found_route = rtrnd_false; + result.net_completely_routed = rtrnd_true; + result.best_route_cost = 0; + result.route_had_conflicts = 0; + + return result; + } + result.net_completely_routed = rtrnd_false; + + /* okay, there's stuff to route */ + assert(!from->flags.target); + assert(num_targets > 0); + /* create list of target pointers and from that a r-tree of targets */ + target_list = (const rtrnd_rtree_box_t **) malloc(num_targets * sizeof(*target_list)); + i = 0; + LIST_LOOP(from, same_net, p); + if (p->flags.target) { + target_list[i++] = &p->box; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_TARGETS) + showroutebox(p); +#endif + } + PCB_END_LOOP; + targets = rnd_r_create_tree(); + rnd_r_insert_array(targets, (const rtrnd_rtree_box_t **)target_list, i); + assert(i <= num_targets); + free(target_list); + + source_vec = vector_create(); + /* touch the source subnet to prepare check for conflictors */ + LIST_LOOP(from, same_subnet, p); + p->flags.touched = 1; + PCB_END_LOOP; + LIST_LOOP(from, same_subnet, p); + { + /* we need the test for 'source' because this box may be nonstraight */ + if (p->flags.source && is_layer_group_active[p->group]) { + rnd_cheap_point_t cp; + edge_t *e; + rtrnd_rtree_box_t b = shrink_routebox(p); + +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_SOURCES) + showroutebox(p); +#endif + /* may expand in all directions from source; center edge cost point. */ + /* note that planes shouldn't really expand, but we need an edge */ + + cp.X = RND_BOX_CENTER_X(b); + cp.Y = RND_BOX_CENTER_Y(b); + e = CreateEdge(p, cp.X, cp.Y, 0, NULL, RND_ANY_DIR, targets); + cp = rnd_closest_cheap_point_in_box(&cp, &e->minpcb_cost_target->sbox); + cp = rnd_closest_cheap_point_in_box(&cp, &b); + e->cost_point = cp; + p->cost_point = cp; + source_conflicts(rd->layergrouptree[p->group], p); + vector_append(source_vec, e); + } + } + PCB_END_LOOP; + LIST_LOOP(from, same_subnet, p); + p->flags.touched = 0; + PCB_END_LOOP; + /* break source edges; some edges may be too near obstacles to be able + * to exit from. */ + + /* okay, main expansion-search routing loop. */ + /* set up the initial activity heap */ + s.workheap = rnd_heap_create(); + assert(s.workheap); + while (!vector_is_empty(source_vec)) { + edge_t *e = (edge_t *) vector_remove_last(source_vec); + assert(is_layer_group_active[e->rb->group]); + e->cost = edge_cost(e, EXPENSIVE); + rnd_heap_insert(s.workheap, e->cost, e); + } + vector_destroy(&source_vec); + /* okay, process items from heap until it is empty! */ + s.best_path = NULL; + s.best_cost = EXPENSIVE; + area_vec = vector_create(); + edge_vec = vector_create(); + vss.free_space_vec = vector_create(); + vss.lo_conflict_space_vec = vector_create(); + vss.hi_conflict_space_vec = vector_create(); + while (!rnd_heap_is_empty(s.workheap)) { + edge_t *e = (edge_t *) rnd_heap_remove_smallest(s.workheap); +#ifdef ROUTE_DEBUG + if (aabort) + goto dontexpand; +#endif + /* don't bother expanding this edge if the minimum possible edge cost + * is already larger than the best edge cost we've found. */ + if (s.best_path && e->cost >= s.best_cost) { + rnd_heap_free(s.workheap, KillEdge); + goto dontexpand; /* skip this edge */ + } + /* surprisingly it helps to give up and not try too hard to find + * a route! This is not only faster, but results in better routing. + * who would have guessed? + */ + if (seen++ > max_edges) + goto dontexpand; + assert(__edge_is_good(e)); + /* mark or unmark conflictors as needed */ + touch_conflicts(e->rb->conflicts_with, 1); + if (e->flags.via_search) { + do_via_search(e, &s, &vss, rd->mtspace, targets); + goto dontexpand; + } + /* we should never add edges on inactive layer groups to the heap. */ + assert(is_layer_group_active[e->rb->group]); +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EXPANSION_BOXES) + /*showedge (e); */ +#endif + if (e->rb->flags.is_thermal) { + best_path_candidate(&s, e, e->minpcb_cost_target); + goto dontexpand; + } + /* for a plane, look for quick connections with thermals or vias */ + if (e->rb->type == PLANE) { + routebox_t *pin = FindThermable(targets, e->rb); + if (pin) { + rtrnd_rtree_box_t b = shrink_routebox(pin); + edge_t *ne; + routebox_t *nrb; + assert(pin->flags.target); + nrb = CreateExpansionArea(&b, e->rb->group, e->rb, rtrnd_true, e); + nrb->flags.is_thermal = 1; + /* moving through the plane is free */ + e->cost_point.X = b.x1; + e->cost_point.Y = b.y1; + ne = CreateEdge2(nrb, e->expand_dir, e, NULL, pin); + best_path_candidate(&s, ne, pin); + DestroyEdge(&ne); + } + else { + /* add in possible via sites in plane */ + if (AutoRouteParameters.use_vias && e->cost + AutoRouteParameters.ViaCost < s.best_cost) { + /* we need a giant thermal */ + routebox_t *nrb = CreateExpansionArea(&e->rb->sbox, e->rb->group, e->rb, + rtrnd_true, e); + edge_t *ne = CreateEdge2(nrb, e->expand_dir, e, NULL, + e->minpcb_cost_target); + nrb->flags.is_thermal = 1; + add_via_sites(&s, &vss, rd->mtspace, nrb, NO_CONFLICT, ne, targets, e->rb->style->Diameter, rtrnd_true); + } + } + goto dontexpand; /* planes only connect via thermals */ + } + if (e->flags.is_via) { /* special case via */ + routebox_t *intersecting; + assert(AutoRouteParameters.use_vias); + assert(e->expand_dir == RND_ANY_DIR); + assert(vector_is_empty(edge_vec)); + /* if there is already something here on this layer (like an + * EXPANSION_AREA), then we don't want to expand from here + * at least not inside the expansion area. A PLANE on the + * other hand may be a target, or not. + */ + intersecting = FindOneInBox(rd->layergrouptree[e->rb->group], e->rb); + + if (intersecting && intersecting->flags.target && intersecting->type == PLANE) { + /* we have hit a plane */ + edge_t *ne; + routebox_t *nrb; + rtrnd_rtree_box_t b = shrink_routebox(e->rb); + /* limit via region to that inside the plane */ + rnd_clip_box(&b, &intersecting->sbox); + nrb = CreateExpansionArea(&b, e->rb->group, e->rb, rtrnd_true, e); + nrb->flags.is_thermal = 1; + ne = CreateEdge2(nrb, e->expand_dir, e, NULL, intersecting); + best_path_candidate(&s, ne, intersecting); + DestroyEdge(&ne); + goto dontexpand; + } + else if (intersecting == NULL) { + /* this via candidate is in an open area; add it to r-tree as + * an expansion area */ + assert(e->rb->type == EXPANSION_AREA && e->rb->flags.is_via); + /*assert (!rnd_r_search(rd->layergrouptree[e->rb->group], + &e->rb->box, NULL, no_planes,0)); + */ + rnd_r_insert_entry(rd->layergrouptree[e->rb->group], &e->rb->box); + e->rb->flags.homeless = 0; /* not homeless any more */ + /* add to vector of all expansion areas in r-tree */ + vector_append(area_vec, e->rb); + /* mark reset refcount to 0, since this is not homeless any more. */ + e->rb->refcount = 0; + /* go ahead and expand this edge! */ + } + else if (1) + goto dontexpand; + else if (0) { /* XXX: disabling this causes no via + collisions. */ + rtrnd_rtree_box_t a = bloat_routebox(intersecting), b; + edge_t *ne; + int i, j; + /* something intersects this via candidate. split via candidate + * into pieces and add these pieces to the workheap. */ + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + b = shrink_routebox(e->rb); + switch (i) { + case 0: + b.x2 = RND_MIN(b.x2, a.x1); + break; /* left */ + case 1: + b.x1 = RND_MAX(b.x1, a.x1); + b.x2 = RND_MIN(b.x2, a.x2); + break; /*c */ + case 2: + b.x1 = RND_MAX(b.x1, a.x2); + break; /* right */ + default: + assert(0); + } + switch (j) { + case 0: + b.y2 = RND_MIN(b.y2, a.y1); + break; /* top */ + case 1: + b.y1 = RND_MAX(b.y1, a.y1); + b.y2 = RND_MIN(b.y2, a.y2); + break; /*c */ + case 2: + b.y1 = RND_MAX(b.y1, a.y2); + break; /* bottom */ + default: + assert(0); + } + /* skip if this box is not valid */ + if (!(b.x1 < b.x2 && b.y1 < b.y2)) + continue; + if (i == 1 && j == 1) { + /* this bit of the via space is obstructed. */ + if (intersecting->type == EXPANSION_AREA || intersecting->flags.fixed) + continue; /* skip this bit, it's already been done. */ + /* create an edge with conflicts, if enabled */ + if (!AutoRouteParameters.with_conflicts) + continue; + ne = CreateEdgeWithConflicts(&b, intersecting, e, 1 + /*cost penalty to box */ + , targets); + add_or_destroy_edge(&s, ne); + } + else { + /* if this is not the intersecting piece, create a new + * (hopefully unobstructed) via edge and add it back to the + * workheap. */ + ne = CreateViaEdge(&b, e->rb->group, e->rb->parent.expansion_area, e, e->flags.via_conflict_level, NO_CONFLICT + /* value here doesn't matter */ + , targets); + add_or_destroy_edge(&s, ne); + } + } + } + goto dontexpand; + } + /* between the time these edges are inserted and the + * time they are processed, new expansion boxes (which + * conflict with these edges) may be added to the graph! + * w.o vias this isn't a problem because the broken box + * is not homeless. */ + } + if (1) { + routebox_t *nrb; + struct E_result *ans; + rtrnd_rtree_box_t b; + vector_t *broken; + if (e->flags.is_interior) { + assert(AutoRouteParameters.with_conflicts); /* no interior edges unless + routing with conflicts! */ + assert(e->rb->conflicts_with); + b = e->rb->sbox; + switch (e->rb->came_from) { + case RND_NORTH: + b.y2 = b.y1 + DELTA; + b.x1 = RND_BOX_CENTER_X(b); + b.x2 = b.x1 + DELTA; + break; + case RND_EAST: + b.x1 = b.x2 - DELTA; + b.y1 = RND_BOX_CENTER_Y(b); + b.y2 = b.y1 + DELTA; + break; + case RND_SOUTH: + b.y1 = b.y2 - DELTA; + b.x1 = RND_BOX_CENTER_X(b); + b.x2 = b.x1 + DELTA; + break; + case RND_WEST: + b.x2 = b.x1 + DELTA; + b.y1 = RND_BOX_CENTER_Y(b); + b.y2 = b.y1 + DELTA; + break; + default: + assert(0); + } + } + /* sources may not expand to their own edges because of + * adjacent blockers. + */ + else if (e->rb->flags.source) + b = rnd_box_center(&e->rb->sbox); + else + b = e->rb->sbox; + ans = Expand(rd->layergrouptree[e->rb->group], e, &b); + if (!rnd_box_intersect(&ans->inflated, &ans->orig)) + goto dontexpand; +#if 0 + /* skip if it didn't actually expand */ + if (ans->inflated.x1 >= e->rb->sbox.x1 && + ans->inflated.x2 <= e->rb->sbox.x2 && ans->inflated.y1 >= e->rb->sbox.y1 && ans->inflated.y2 <= e->rb->sbox.y2) + goto dontexpand; +#endif + + if (!rnd_box_is_good(&ans->inflated)) + goto dontexpand; + nrb = CreateExpansionArea(&ans->inflated, e->rb->group, e->rb, rtrnd_true, e); + rnd_r_insert_entry(rd->layergrouptree[nrb->group], &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + broken = BreakManyEdges(&s, targets, rd->layergrouptree[nrb->group], area_vec, ans, nrb, e); + while (!vector_is_empty(broken)) { + edge_t *ne = (edge_t *) vector_remove_last(broken); + add_or_destroy_edge(&s, ne); + } + vector_destroy(&broken); + + /* add in possible via sites in nrb */ + if (AutoRouteParameters.use_vias && !e->rb->flags.is_via && e->cost + AutoRouteParameters.ViaCost < s.best_cost) + add_via_sites(&s, &vss, rd->mtspace, nrb, NO_CONFLICT, e, targets, 0, rtrnd_false); + goto dontexpand; + } + dontexpand: + DestroyEdge(&e); + } + touch_conflicts(NULL, 1); + rnd_heap_destroy(&s.workheap); + rnd_r_destroy_tree(&targets); + assert(vector_is_empty(edge_vec)); + vector_destroy(&edge_vec); + + /* we should have a path in best_path now */ + if (s.best_path) { + routebox_t *rb; +#ifdef ROUTE_VERBOSE + fprintf(stderr, INFO "%d:%d RC %.0f", ro++, seen, s.best_cost); +#endif + result.found_route = rtrnd_true; + result.best_route_cost = s.best_cost; + /* determine if the best path had conflicts */ + result.route_had_conflicts = 0; + if (AutoRouteParameters.with_conflicts && s.best_path->conflicts_with) { + while (!vector_is_empty(s.best_path->conflicts_with)) { + rb = (routebox_t *) vector_remove_last(s.best_path->conflicts_with); + rb->flags.is_bad = 1; + result.route_had_conflicts++; + } + } +#ifdef ROUTE_VERBOSE + if (result.route_had_conflicts) + fprintf(stderr, " (%d conflicts)", result.route_had_conflicts); +#endif + if (result.route_had_conflicts < AutoRouteParameters.hi_conflict) { + /* back-trace the path and add lines/vias to r-tree */ + TracePath(rd, s.best_path, s.best_target, from, result.route_had_conflicts); + MergeNets(from, s.best_target, SUBNET); + } + else { +#ifdef ROUTE_VERBOSE + fprintf(stderr, " (too many in fact)"); +#endif + result.found_route = rtrnd_false; + } +#ifdef ROUTE_VERBOSE + fprintf(stderr, "\n"); +#endif + } + else { +#ifdef ROUTE_VERBOSE + fprintf(stderr, INFO "%d:%d NO PATH FOUND.\n", ro++, seen); +#endif + result.best_route_cost = s.best_cost; + result.found_route = rtrnd_false; + } + /* now remove all expansion areas from the r-tree. */ + while (!vector_is_empty(area_vec)) { + routebox_t *rb = (routebox_t *) vector_remove_last(area_vec); + assert(!rb->flags.homeless); + if (rb->conflicts_with && rb->parent.expansion_area->conflicts_with != rb->conflicts_with) + vector_destroy(&rb->conflicts_with); + rnd_r_delete_entry_free_data(rd->layergrouptree[rb->group], &rb->box, free); + } + vector_destroy(&area_vec); + /* clean up; remove all 'source', 'target', and 'nobloat' flags */ + LIST_LOOP(from, same_net, p); + if (p->flags.source && p->conflicts_with) + vector_destroy(&p->conflicts_with); + p->flags.touched = p->flags.source = p->flags.target = p->flags.nobloat = 0; + PCB_END_LOOP; + + vector_destroy(&vss.free_space_vec); + vector_destroy(&vss.lo_conflict_space_vec); + vector_destroy(&vss.hi_conflict_space_vec); + + return result; +} + +static void InitAutoRouteParameters(int pass, pcb_route_style_t * style, rtrnd_bool_t with_conflicts, rtrnd_bool_t is_smoothing, rtrnd_bool_t lastpass) +{ + int i; + /* routing style */ + AutoRouteParameters.style = style; + AutoRouteParameters.bloat = style->Clearance + HALF_THICK(style->Thickness); + /* costs */ + AutoRouteParameters.ViaCost = 88.9 + style->Diameter * (is_smoothing ? 80 : 30); + AutoRouteParameters.LastConflictPenalty = ((400 * pass / passes + 2) / (pass + 1)) / 1000000.0; + AutoRouteParameters.ConflictPenalty = (4 * AutoRouteParameters.LastConflictPenalty) / 1000000.0; + AutoRouteParameters.JogPenalty = (1000 * (is_smoothing ? 20 : 4)) / 1000000.0; + AutoRouteParameters.CongestionPenalty = 1e6 / 1000000.0; + AutoRouteParameters.MinPenalty = EXPENSIVE; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (is_layer_group_active[i]) { + AutoRouteParameters.MinPenalty = RND_MIN(x_cost[i], AutoRouteParameters.MinPenalty); + AutoRouteParameters.MinPenalty = RND_MIN(y_cost[i], AutoRouteParameters.MinPenalty); + } + } + AutoRouteParameters.NewLayerPenalty = is_smoothing ? 0.5 * EXPENSIVE : 10 * AutoRouteParameters.ViaCost; + /* other */ + AutoRouteParameters.hi_conflict = RND_MAX(8 * (passes - pass + 1), 6); + AutoRouteParameters.is_odd = (pass & 1); + AutoRouteParameters.with_conflicts = with_conflicts; + AutoRouteParameters.is_smoothing = is_smoothing; + AutoRouteParameters.rip_always = is_smoothing; + AutoRouteParameters.last_smooth = 0; /*lastpass; */ + AutoRouteParameters.pass = pass + 1; +} + +#ifndef NDEBUG +rnd_r_dir_t bad_boy(const rtrnd_rtree_box_t * b, void *cl) +{ + routebox_t *box = (routebox_t *) b; + if (box->type == EXPANSION_AREA) + return RND_R_DIR_FOUND_CONTINUE; + return RND_R_DIR_NOT_FOUND; +} + +rtrnd_bool_t no_expansion_boxes(routedata_t * rd) +{ + int i; + rtrnd_rtree_box_t big; + big.x1 = 0; + big.x2 = RND_MAX_COORD; + big.y1 = 0; + big.y2 = RND_MAX_COORD; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (rnd_r_search(rd->layergrouptree[i], &big, NULL, bad_boy, NULL, NULL)) + return rtrnd_false; + } + return rtrnd_true; +} +#endif + + +struct routeall_status { + /* --- for completion rate statistics ---- */ + int total_subnets; + /* total subnets routed without conflicts */ + int routed_subnets; + /* total subnets routed with conflicts */ + int conflict_subnets; + /* net failted entirely */ + int failed; + /* net was ripped */ + int ripped; + int total_nets_routed; +}; + +static double calculate_progress(double this_heap_item, double this_heap_size, struct routeall_status *ras) +{ + double total_passes = passes + smoothes + 1; /* + 1 is the refinement pass */ + double this_pass = AutoRouteParameters.pass - 1; /* Number passes from zero */ + double heap_fraction = (double) (ras->routed_subnets + ras->conflict_subnets + ras->failed) / (double) ras->total_subnets; + double pass_fraction = (this_heap_item + heap_fraction) / this_heap_size; + double process_fraction = (this_pass + pass_fraction) / total_passes; + + return process_fraction; +} + +struct routeall_status RouteAll(routedata_t * rd) +{ + struct routeall_status ras; + routeone_status_t ros; + rtrnd_bool_t rip; + int request_cancel; +#ifdef NET_HEAP + rnd_heap_t *net_heap; +#endif + rnd_heap_t *this_pass, *next_pass, *tmp; + routebox_t *net, *p, *pp; + rnd_heap_cost_t total_net_cost, last_cost = 0, this_cost = 0; + int i; + int this_heap_size; + int this_heap_item; + + /* initialize heap for first pass; + * do smallest area first; that makes + * the subsequent costs more representative */ + this_pass = rnd_heap_create(); + next_pass = rnd_heap_create(); +#ifdef NET_HEAP + net_heap = rnd_heap_create(); +#endif + LIST_LOOP(rd->first_net, different_net, net); + { + double area; + rtrnd_rtree_box_t bb = shrink_routebox(net); + LIST_LOOP(net, same_net, p); + { + RND_MAKE_MIN(bb.x1, p->sbox.x1); + RND_MAKE_MIN(bb.y1, p->sbox.y1); + RND_MAKE_MAX(bb.x2, p->sbox.x2); + RND_MAKE_MAX(bb.y2, p->sbox.y2); + } + PCB_END_LOOP; + area = (double) (bb.x2 - bb.x1) * (bb.y2 - bb.y1); + rnd_heap_insert(this_pass, area, net); + } + PCB_END_LOOP; + + ras.total_nets_routed = 0; + /* refinement/finishing passes */ + for (i = 0; i <= passes + smoothes; i++) { +#ifdef ROUTE_VERBOSE + if (i > 0 && i <= passes) + fprintf(stderr, INFO "--------- STARTING REFINEMENT PASS %d ------------\n", i); + else if (i > passes) + fprintf(stderr, INFO "--------- STARTING SMOOTHING PASS %d -------------\n", i - passes); +#endif + ras.total_subnets = ras.routed_subnets = ras.conflict_subnets = ras.failed = ras.ripped = 0; + assert(rnd_heap_is_empty(next_pass)); + + this_heap_size = rnd_heap_size(this_pass); + for (this_heap_item = 0; !rnd_heap_is_empty(this_pass); this_heap_item++) { +#ifdef ROUTE_DEBUG + if (aabort) + break; +#endif + net = (routebox_t *) rnd_heap_remove_smallest(this_pass); + InitAutoRouteParameters(i, net->style, i < passes, i > passes, i == passes + smoothes); + if (i > 0) { + /* rip up all unfixed traces in this net ? */ + if (AutoRouteParameters.rip_always) + rip = rtrnd_true; + else { + rip = rtrnd_false; + LIST_LOOP(net, same_net, p); + if (p->flags.is_bad) { + rip = rtrnd_true; + break; + } + PCB_END_LOOP; + } + + LIST_LOOP(net, same_net, p); + p->flags.is_bad = 0; + if (!p->flags.fixed) { +#ifndef NDEBUG + rtrnd_bool_t del; +#endif + assert(!p->flags.homeless); + if (rip) { + RemoveFromNet(p, NET); + RemoveFromNet(p, SUBNET); + } + if (AutoRouteParameters.use_vias && p->type != VIA_SHADOW && p->type != PLANE) { + mtspace_remove(rd->mtspace, &p->box, p->flags.is_odd ? ODD : EVEN, p->style->Clearance); + if (!rip) + mtspace_add(rd->mtspace, &p->box, p->flags.is_odd ? EVEN : ODD, p->style->Clearance); + } + if (rip) { +#ifndef NDEBUG + del = +#endif + rnd_r_delete_entry_free_data(rd->layergrouptree[p->group], &p->box, free); +#ifndef NDEBUG + assert(del); +#endif + } + else { + p->flags.is_odd = AutoRouteParameters.is_odd; + } + } + PCB_END_LOOP; + /* reset to original connectivity */ + if (rip) { + ras.ripped++; + ResetSubnet(net); + } + else { + rnd_heap_insert(next_pass, 0, net); + continue; + } + } + /* count number of subnets */ + FOREACH_SUBNET(net, p); + ras.total_subnets++; + END_FOREACH(net, p); + /* the first subnet doesn't require routing. */ + ras.total_subnets--; + /* and re-route! */ + total_net_cost = 0; + /* only route that which isn't fully routed */ +#ifdef ROUTE_DEBUG + if (ras.total_subnets == 0 || aabort) +#else + if (ras.total_subnets == 0) +#endif + { + rnd_heap_insert(next_pass, 0, net); + continue; + } + + /* the loop here ensures that we get to all subnets even if + * some of them are unreachable from the first subnet. */ + LIST_LOOP(net, same_net, p); + { +#ifdef NET_HEAP + rtrnd_rtree_box_t b = shrink_routebox(p); + /* using a heap allows us to start from smaller objects and + * end at bigger ones. also prefer to start at planes, then pads */ + rnd_heap_insert(net_heap, (float) (b.x2 - b.x1) * +#if defined(ROUTE_RANDOMIZED) + (0.3 + rnd_rand() / (RAND_MAX + 1.0)) * +#endif + (b.y2 - b.y1) * (p->type == PLANE ? -1 : ((p->type == TERM) ? 1 : 10)), p); + } + PCB_END_LOOP; + ros.net_completely_routed = 0; + while (!rnd_heap_is_empty(net_heap)) { + p = (routebox_t *) rnd_heap_remove_smallest(net_heap); +#endif + if (!p->flags.fixed || p->flags.subnet_processed || p->type == OTHER) + continue; + + while (!ros.net_completely_routed) { + double percent; + + assert(no_expansion_boxes(rd)); + /* FIX ME: the number of edges to examine should be in autoroute parameters + * i.e. the 2000 and 800 hard-coded below should be controllable by the user + */ + ros = RouteOne(rd, p, NULL, ((AutoRouteParameters.is_smoothing ? 2000 : 800) * (i + 1)) * routing_layers); + total_net_cost += ros.best_route_cost; + if (ros.found_route) { + if (ros.route_had_conflicts) + ras.conflict_subnets++; + else { + ras.routed_subnets++; + ras.total_nets_routed++; + } + } + else { + if (!ros.net_completely_routed) + ras.failed++; + /* don't bother trying any other source in this subnet */ + LIST_LOOP(p, same_subnet, pp); + pp->flags.subnet_processed = 1; + PCB_END_LOOP; + break; + } + /* note that we can infer nothing about ras.total_subnets based + * on the number of calls to RouteOne, because we may be unable + * to route a net from a particular starting point, but perfectly + * able to route it from some other. */ + percent = calculate_progress(this_heap_item, this_heap_size, &ras); + request_cancel = rtrnd_progress(rd->ctx, percent); + if (request_cancel) { + ras.total_nets_routed = 0; + ras.conflict_subnets = 0; + goto out; + } + } + } +#ifndef NET_HEAP + PCB_END_LOOP; +#endif + if (!ros.net_completely_routed) + net->flags.is_bad = 1; /* don't skip this the next round */ + + /* Route easiest nets from this pass first on next pass. + * This works best because it's likely that the hardest + * is the last one routed (since it has the most obstacles) + * but it will do no good to rip it up and try it again + * without first changing any of the other routes + */ + rnd_heap_insert(next_pass, total_net_cost, net); + if (total_net_cost < EXPENSIVE) + this_cost += total_net_cost; + /* reset subnet_processed flags */ + LIST_LOOP(net, same_net, p); + { + p->flags.subnet_processed = 0; + } + PCB_END_LOOP; + } + /* swap this_pass and next_pass and do it all over again! */ + ro = 0; + assert(rnd_heap_is_empty(this_pass)); + tmp = this_pass; + this_pass = next_pass; + next_pass = tmp; +#if defined(ROUTE_DEBUG) || defined (ROUTE_VERBOSE) + fprintf(stderr, INFO "END OF PASS %d: %d/%d subnets routed without conflicts at cost %.0f, %d conflicts, %d failed %d ripped\n", + i, ras.routed_subnets, ras.total_subnets, this_cost, ras.conflict_subnets, ras.failed, ras.ripped); +#endif +#ifdef ROUTE_DEBUG + if (aabort) + break; +#endif + /* if no conflicts found, skip directly to smoothing pass! */ + if (ras.conflict_subnets == 0 && ras.routed_subnets == ras.total_subnets && i <= passes) + i = passes - (smoothes ? 0 : 1); + /* if no changes in a smoothing round, then we're done */ + if (this_cost == last_cost && i > passes && i < passes + smoothes) + i = passes + smoothes - 1; + last_cost = this_cost; + this_cost = 0; + } + +#warning TODO: pass this back +/* rnd_message(RND_MSG_INFO, "%d of %d nets successfully routed.\n", ras.routed_subnets, ras.total_subnets);*/ + +out: + rnd_heap_destroy(&this_pass); + rnd_heap_destroy(&next_pass); +#ifdef NET_HEAP + rnd_heap_destroy(&net_heap); +#endif + + /* no conflicts should be left at the end of the process. */ + assert(ras.conflict_subnets == 0); + + return ras; +} + +struct fpin_info { + rtrnd_via_t *ps; + double x, y; + jmp_buf env; +}; + +static rnd_r_dir_t fpstk_rect(const rtrnd_rtree_box_t * b, void *cl) +{ + rtrnd_via_t *ps = (rtrnd_via_t *)b; + struct fpin_info *info = (struct fpin_info *) cl; + if (ps->x == info->x && ps->y == info->y) { + info->ps = ps; + longjmp(info->env, 1); + } + return RND_R_DIR_NOT_FOUND; +} + +static int FindPin(const rtrnd_rtree_box_t *box, rtrnd_via_t **ps_out) +{ + struct fpin_info info; + + info.ps = NULL; + info.x = box->x1; + info.y = box->y1; + if (setjmp(info.env) == 0) { + rnd_r_search(&PCB->vias, box, NULL, fpstk_rect, &info, NULL); + } + else { + *ps_out = info.ps; + return RTRND_VIA; + } + + *ps_out = NULL; + return RTRND_VOID; +} + + +/* paths go on first 'on' layer in group */ +/* returns 'rtrnd_true' if any paths were added. */ +rtrnd_bool_t IronDownAllUnfixedPaths(routedata_t * rd) +{ + rtrnd_bool_t changed = rtrnd_false; + routebox_t *net, *p; + int i; + LIST_LOOP(rd->first_net, different_net, net); + { + LIST_LOOP(net, same_net, p); + { + if (!p->flags.fixed) { + rtrnd_net_t *rnet = NULL; + if (net->ns != NULL) + rnet = net->ns->net; + + /* find first on layer in this group */ + assert(is_layer_group_active[p->group]); + assert(p->type != EXPANSION_AREA); + if (p->type == LINE) { + double halfwidth = HALF_THICK(p->style->Thickness); + double th = halfwidth * 2 + DELTA; + rtrnd_rtree_box_t b; + assert(p->parent.line == NULL); + /* orthogonal; thickness is 2*halfwidth */ + /* flip coordinates, if bl_to_ur */ + b = p->sbox; + total_wire_length += sqrt((b.x2 - b.x1 - th) * (b.x2 - b.x1 - th) + (b.y2 - b.y1 - th) * (b.y2 - b.y1 - th)); + b = rnd_shrink_box(&b, halfwidth); + if (b.x2 == b.x1 + DELTA) + b.x2 = b.x1; + if (b.y2 == b.y1 + DELTA) + b.y2 = b.y1; + if (p->flags.bl_to_ur) { + double t; + t = b.x1; + b.x1 = b.x2; + b.x2 = t; + } + + /* using CreateDrawn instead of CreateNew concatenates sequential lines */ + rtrnd_draw_res_line(rd->ctx, PCB->layers.array[p->group], rd->annot[p->group], rnet, + p->line.x1, p->line.y1, p->line.x2, p->line.y2, p->style->Thickness, p->style->Clearance, + p->style->Thickness, p->style->Clearance); + changed = rtrnd_true; + } + else if (p->type == VIA || p->type == VIA_SHADOW) { + routebox_t *pp = (p->type == VIA_SHADOW) ? p->parent.via_shadow : p; + double radius = HALF_THICK(pp->style->Diameter); + rtrnd_rtree_box_t b = shrink_routebox(p); + total_via_count++; + assert(pp->type == VIA); + if (pp->parent.via == NULL) { + assert(labs((b.x1 + radius) - (b.x2 - radius)) < 2); + assert(labs((b.y1 + radius) - (b.y2 - radius)) < 2); + pp->parent.via = 1; + rtrnd_draw_res_via(rd->ctx, rd->annot_via, rnet, + b.x1 + radius, b.y1 + radius, + pp->style->Diameter, pp->style->Clearance, pp->style->Diameter, pp->style->Clearance); + changed = rtrnd_true; + } + assert(pp->parent.via); + if (p->type == VIA_SHADOW) { + p->type = VIA; + p->parent.via = pp->parent.via; + } + } + else if (p->type == THERMAL) + /* nothing to do because, the via might not be there yet */ ; + else + assert(0); + } + } + PCB_END_LOOP; + /* loop again to place all the thermals now that the vias are down */ + LIST_LOOP(net, same_net, p); + { + if (p->type == THERMAL) { + rtrnd_via_t *pin = NULL; + /* thermals are alread a single point search, no need to shrink */ + int type = FindPin(&p->box, &pin); + if (pin) { +#warning TODO: add thermal +#if 0 + pcb_undo_add_obj_to_clear_poly(type, pin->parent.data, pin, pin, rtrnd_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_PSTK, pcb_get_layer(PCB->Data, p->layer), pin); + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_THERM_ASSIGN(p->layer, autoroute_therm_style, pin); + pcb_undo_add_obj_to_clear_poly(type, pin->parent.data, pin, pin, rtrnd_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_PSTK, pcb_get_layer(PCB->Data, p->layer), pin); +#endif + changed = rtrnd_true; + } + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + return changed; +} + +RTRND_INLINE int group_of_obj(rtrnd_any_obj_t *o) +{ + switch(o->hdr.type) { + case RTRND_LINE: + case RTRND_ARC: + case RTRND_POLY: + return layer_id(&o->hdr.parent->layer); + default:; + } + return 0; +} + +static rtrnd_bool_t route_hace(rtrnd_t *ctx, rtrnd_bool_t selected) +{ + rtrnd_bool_t changed = rtrnd_false; + routedata_t *rd; + rtrnd_rat_t *rat; + int i; + + PCB = ctx->board; + total_wire_length = 0; + total_via_count = 0; + +#ifdef ROUTE_DEBUG + ddraw = rnd_gui->request_debug_draw(); + if (ddraw != NULL) { + ar_gc = ddraw->make_gc(); + ddraw->set_line_cap(ar_gc, rnd_cap_round); + } +#endif + + rd = CreateRouteData(ctx); + if (rd == NULL) { + fprintf(stderr, ERROR "Failed to initialize data; might be missing\n" "top or bottom copper layer.\n"); + return rtrnd_false; + } + + rtrnd_ratsnest_map(&rd->nest, ctx->board, 0); + rd->annot_rats = rtrnd_annot_new(ctx, "rat"); + strcpy(rd->annot_rats->color, "#cb9800"); + rtrnd_ratsnest_draw(&rd->nest, rd->annot_rats); + + if (1) { + routebox_t *net, *rb, *last; + int i = rd->nest.lst.length; + +#ifdef ROUTE_VERBOSE + fprintf(stderr, INFO "%d nets!\n", i); +#endif + if (i == 0) + goto donerouting; /* nothing to do here */ + /* if only one rat selected, do things the quick way. =) */ + if (i == 1) { + /* look up the end points of this rat line */ + routebox_t *a; + routebox_t *b; + + rat = gdl_first(&rd->nest.lst); + + a = FindRouteBoxOnLayerGroup(rd, rat->x[0], rat->y[0], group_of_obj(rat->o[0])); + b = FindRouteBoxOnLayerGroup(rd, rat->x[1], rat->y[1], group_of_obj(rat->o[1])); + assert(a != NULL && b != NULL); + assert(a->style == b->style); +/* + if (a->type != PAD && b->type == PAD) + { + routebox_t *t = a; + a = b; + b = t; + } +*/ + /* route exactly one net, without allowing conflicts */ + InitAutoRouteParameters(0, a->style, rtrnd_false, rtrnd_true, rtrnd_true); + /* hace planes work better as sources than targets */ + changed = RouteOne(rd, a, b, 150000).found_route || changed; + goto donerouting; + } + + /* otherwise, munge the netlists so that only the selected rats + * get connected. */ + /* first, separate all sub nets into separate nets */ + /* note that this code works because LIST_LOOP is clever enough not to + * be fooled when the list is changing out from under it. */ + last = NULL; + LIST_LOOP(rd->first_net, different_net, net); + { + FOREACH_SUBNET(net, rb); + { + if (last) { + last->different_net.next = rb; + rb->different_net.prev = last; + } + last = rb; + } + END_FOREACH(net, rb); + LIST_LOOP(net, same_net, rb); + { + rb->same_net = rb->same_subnet; + } + PCB_END_LOOP; + /* at this point all nets are equal to their subnets */ + } + PCB_END_LOOP; + if (last) { + last->different_net.next = rd->first_net; + rd->first_net->different_net.prev = last; + } + + /* now merge only those subnets connected by a rat line */ + for(rat = gdl_first(&rd->nest.lst); rat != NULL; rat = gdl_next(&rd->nest.lst, rat)) { + /* look up the end points of this rat line */ + routebox_t *a = FindRouteBoxOnLayerGroup(rd, rat->x[0], rat->y[0], group_of_obj(rat->o[0])); + routebox_t *b = FindRouteBoxOnLayerGroup(rd, rat->x[1], rat->y[1], group_of_obj(rat->o[1])); + + if (!a || !b) { + fprintf(stderr, ERROR "The rats nest is stale! Aborting...\n"); + assert(!"stale rats"); + goto donerouting; + } + /* merge subnets into a net! */ + MergeNets(a, b, NET); + } + + /* now 'different_net' may point to too many different nets. Reset. */ + LIST_LOOP(rd->first_net, different_net, net); + { + if (!net->flags.touched) { + LIST_LOOP(net, same_net, rb); + rb->flags.touched = 1; + PCB_END_LOOP; + } + else /* this is not a "different net"! */ + RemoveFromNet(net, DIFFERENT_NET); + } + PCB_END_LOOP; + /* reset "touched" flag */ + LIST_LOOP(rd->first_net, different_net, net); + { + LIST_LOOP(net, same_net, rb); + { + assert(rb->flags.touched); + rb->flags.touched = 0; + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + rtrnd_ratsnest_uninit(&rd->nest); + + /* okay, rd's idea of netlist now corresponds to what we want routed */ + /* auto-route all nets */ + changed = (RouteAll(rd).total_nets_routed > 0) || changed; +donerouting: + rtrnd_progress(ctx, 1); + +#ifdef ROUTE_DEBUG + if (ddraw != NULL) + ddraw->finish_debug_draw(); +#endif + + if (changed) + changed = IronDownAllUnfixedPaths(rd); +#warning TODO: pass this back: +/* rnd_message(RND_MSG_INFO, "Total added wire length = %$mS, %d vias added\n", (double) total_wire_length, total_via_count);*/ + DestroyRouteData(&rd); + +#if defined (ROUTE_DEBUG) + aabort = 0; +#endif + return !changed; +} + +static const rtrnd_router_t rt_hace = { + "hace", "gridless rectangle-expansion router", + hace_cfg_desc, + route_hace +}; + +void rt_hace_init(void) +{ + vtp0_append(&rtrnd_all_router, (void *)&rt_hace); +} Index: tags/0.9.0/src/plugins/rt_hace/heap.c =================================================================== --- tags/0.9.0/src/plugins/rt_hace/heap.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/heap.c (revision 1402) @@ -0,0 +1,233 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, heap.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* operations on heaps. */ + +#include +#include +#include "config.h" +#include "heap.h" + +/* define this for more thorough self-checking of data structures */ +#undef SLOW_ASSERTIONS + +struct heap_element { + rnd_heap_cost_t cost; + void *data; +}; +struct rnd_heap_s { + struct heap_element *element; + int size, max; +}; + +static rnd_heap_cost_t MIN_COST = 0; + +/* --------------------------------------------------------------------------- + * functions. + */ +/* helper functions for assertions */ +#ifndef NDEBUG +#ifdef SLOW_ASSERTIONS +static int __heap_is_good_slow(rnd_heap_t * heap) +{ + int i; + /* heap condition: key in each node should be smaller than in its children */ + /* alternatively (and this is what we check): key in each node should be + * larger than (or equal to) key of its parent. */ + /* note that array element[0] is not used (except as a sentinel) */ + for (i = 2; i < heap->size; i++) + if (heap->element[i].cost < heap->element[i / 2].cost) + return 0; + return 1; +} +#endif /* SLOW_ASSERTIONS */ +static int __heap_is_good(rnd_heap_t * heap) +{ + return heap && (heap->max == 0 || heap->element) && + (heap->max >= 0) && (heap->size >= 0) && (heap->max == 0 || heap->size < heap->max) && +#ifdef SLOW_ASSERTIONS + __heap_is_good_slow(heap) && +#endif + 1; +} +#endif /* ! NDEBUG */ + +/* create an empty heap */ +rnd_heap_t *rnd_heap_create() +{ + rnd_heap_t *heap; + /* initialize MIN_COST if necessary */ + if (MIN_COST == 0) + MIN_COST = -1e23; + assert(MIN_COST < 0); + /* okay, create empty heap */ + heap = (rnd_heap_t *) calloc(1, sizeof(*heap)); + assert(heap); + assert(__heap_is_good(heap)); + return heap; +} + +/* destroy a heap */ +void rnd_heap_destroy(rnd_heap_t ** heap) +{ + assert(heap && *heap); + assert(__heap_is_good(*heap)); + if ((*heap)->element) + free((*heap)->element); + free(*heap); + *heap = NULL; +} + +/* free all elements in the heap */ +void rnd_heap_free(rnd_heap_t * heap, void (*freefunc) (void *)) +{ + assert(heap); + assert(__heap_is_good(heap)); + for (; heap->size; heap->size--) { + if (heap->element[heap->size].data) + freefunc(heap->element[heap->size].data); + } +} + +/* -- mutation -- */ +static void __upheap(rnd_heap_t * heap, int k) +{ + struct heap_element v; + + assert(heap && heap->size < heap->max); + assert(k <= heap->size); + + v = heap->element[k]; + heap->element[0].cost = MIN_COST; + for (v = heap->element[k]; heap->element[k / 2].cost > v.cost; k = k / 2) + heap->element[k] = heap->element[k / 2]; + heap->element[k] = v; +} + +void rnd_heap_insert(rnd_heap_t * heap, rnd_heap_cost_t cost, void *data) +{ + assert(heap && __heap_is_good(heap)); + assert(cost >= MIN_COST); + + /* determine whether we need to grow the heap */ + if (heap->size + 1 >= heap->max) { + heap->max *= 2; + if (heap->max == 0) + heap->max = 256; /* default initial heap size */ + heap->element = (struct heap_element *) realloc(heap->element, heap->max * sizeof(*heap->element)); + } + heap->size++; + assert(heap->size < heap->max); + heap->element[heap->size].cost = cost; + heap->element[heap->size].data = data; + __upheap(heap, heap->size); /* fix heap condition violation */ + assert(__heap_is_good(heap)); + return; +} + +/* this procedure moves down the heap, exchanging the node at position + * k with the smaller of its two children as necessary and stopping when + * the node at k is smaller than both children or the bottom is reached. + */ +static void __downheap(rnd_heap_t * heap, int k) +{ + struct heap_element v; + + assert(heap && heap->size < heap->max); + assert(k <= heap->size); + + v = heap->element[k]; + while (k <= heap->size / 2) { + int j = k + k; + if (j < heap->size && heap->element[j].cost > heap->element[j + 1].cost) + j++; + if (v.cost < heap->element[j].cost) + break; + heap->element[k] = heap->element[j]; + k = j; + } + heap->element[k] = v; +} + +void *rnd_heap_remove_smallest(rnd_heap_t * heap) +{ + struct heap_element v; + assert(heap && __heap_is_good(heap)); + assert(heap->size > 0); + assert(heap->max > 1); + + v = heap->element[1]; + heap->element[1] = heap->element[heap->size--]; + if (heap->size > 0) + __downheap(heap, 1); + + assert(__heap_is_good(heap)); + return v.data; +} + +void *rnd_heap_replace(rnd_heap_t * heap, rnd_heap_cost_t cost, void *data) +{ + assert(heap && __heap_is_good(heap)); + + if (rnd_heap_is_empty(heap)) + return data; + + assert(heap->size > 0); + assert(heap->max > 1); + + heap->element[0].cost = cost; + heap->element[0].data = data; + __downheap(heap, 0); /* ooh, tricky! */ + + assert(__heap_is_good(heap)); + return heap->element[0].data; +} + +/* -- interrogation -- */ +int rnd_heap_is_empty(rnd_heap_t * heap) +{ + assert(__heap_is_good(heap)); + return heap->size == 0; +} + +/* -- size -- */ +int rnd_heap_size(rnd_heap_t * heap) +{ + assert(__heap_is_good(heap)); + return heap->size; +} Index: tags/0.9.0/src/plugins/rt_hace/heap.h =================================================================== --- tags/0.9.0/src/plugins/rt_hace/heap.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/heap.h (revision 1402) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, heap.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* Heap used by the polygon code and autoroute */ + +#ifndef RND_HEAP_H +#define RND_HEAP_H + +#include "config.h" + +/* type of heap costs */ +typedef double rnd_heap_cost_t; +/* what a heap looks like */ +typedef struct rnd_heap_s rnd_heap_t; + +/* create an empty heap */ +rnd_heap_t *rnd_heap_create(); +/* destroy a heap */ +void rnd_heap_destroy(rnd_heap_t ** heap); +/* free all elements in a heap */ +void rnd_heap_free(rnd_heap_t * heap, void (*funcfree) (void *)); + +/* -- mutation -- */ +void rnd_heap_insert(rnd_heap_t * heap, rnd_heap_cost_t cost, void *data); +void *rnd_heap_remove_smallest(rnd_heap_t * heap); +/* replace the smallest item with a new item and return the smallest item. + * (if the new item is the smallest, than return it, instead.) */ +void *rnd_heap_replace(rnd_heap_t * heap, rnd_heap_cost_t cost, void *data); + +/* -- interrogation -- */ +int rnd_heap_is_empty(rnd_heap_t * heap); +int rnd_heap_size(rnd_heap_t * heap); + +#endif /* RND_HEAP_H */ Index: tags/0.9.0/src/plugins/rt_hace/mtspace.c =================================================================== --- tags/0.9.0/src/plugins/rt_hace/mtspace.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/mtspace.c (revision 1402) @@ -0,0 +1,524 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, mtspace.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * Copyright (c) 2006 harry eaton. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* implementation for "empty space" routines (needed for via-space tracking + * in the auto-router. + */ + +#include "config.h" + +#include +#include +#include + +#include "heap.h" +#include "rnd_rtree.h" +#include "mtspace.h" +#include "vector.h" + +/* mtspace data structures are built on r-trees. */ + +typedef struct mtspacebox { + const rtrnd_rtree_box_t box; + double clearance; /* the smallest clearance around this box */ +} mtspacebox_t; + +/* this is an mtspace_t */ +struct mtspace { + /* rtrees keeping track of regions expanded by their required clearance. */ + /* one for fixed, even, and odd */ + rtrnd_rtree_t *ftree, *etree, *otree; +}; + +typedef union { + vector_t *v; + rnd_heap_t *h; +} heap_or_vector; + +/* this is a vetting_t */ +struct vetting { + heap_or_vector untested; + heap_or_vector no_fix; + heap_or_vector no_hi; + heap_or_vector hi_candidate; + double radius; + double clearance; + rnd_cheap_point_t desired; +}; + +#define SPECIAL 823157 + +mtspacebox_t *mtspace_create_box(const rtrnd_rtree_box_t * box, double clearance) +{ + mtspacebox_t *mtsb; + assert(rnd_box_is_good(box)); + mtsb = (mtspacebox_t *) malloc(sizeof(*mtsb)); + /* the box was sent to us pre-bloated by the clearance amount */ + *((rtrnd_rtree_box_t *) & mtsb->box) = *box; + mtsb->clearance = clearance; + assert(rnd_box_is_good(&mtsb->box)); + return mtsb; +} + +/* create an "empty space" representation */ +mtspace_t *mtspace_create(void) +{ + mtspace_t *mtspace; + + /* create mtspace data structure */ + mtspace = (mtspace_t *) malloc(sizeof(*mtspace)); + mtspace->ftree = rnd_r_create_tree(); + mtspace->etree = rnd_r_create_tree(); + mtspace->otree = rnd_r_create_tree(); + /* done! */ + return mtspace; +} + +/* destroy an "empty space" representation. */ +void mtspace_destroy(mtspace_t ** mtspacep) +{ + assert(mtspacep); + rnd_r_free_tree_data((*mtspacep)->ftree, free); + rnd_r_free_tree_data((*mtspacep)->etree, free); + rnd_r_free_tree_data((*mtspacep)->otree, free); + rnd_r_destroy_tree(&(*mtspacep)->ftree); + rnd_r_destroy_tree(&(*mtspacep)->etree); + rnd_r_destroy_tree(&(*mtspacep)->otree); + free(*mtspacep); + *mtspacep = NULL; +} + +struct mts_info { + double clearance; + rtrnd_rtree_box_t box; + rtrnd_rtree_t *tree; + jmp_buf env; +}; + +static rnd_r_dir_t mts_remove_one(const rtrnd_rtree_box_t * b, void *cl) +{ + struct mts_info *info = (struct mts_info *) cl; + mtspacebox_t *box = (mtspacebox_t *) b; + + /* there can be duplicate boxes, we just remove one */ + /* the info box is pre-bloated, so just check equality */ + if (b->x1 == info->box.x1 && b->x2 == info->box.x2 && + b->y1 == info->box.y1 && b->y2 == info->box.y2 && box->clearance == info->clearance) { + rnd_r_delete_entry_free_data(info->tree, (rtrnd_rtree_box_t *)b, free); + longjmp(info->env, 1); + } + return RND_R_DIR_NOT_FOUND; +} + +rtrnd_rtree_t *which_tree(mtspace_t * mtspace, mtspace_type_t which) +{ + switch (which) { + case FIXED: + return mtspace->ftree; + case EVEN: + return mtspace->etree; + default: + return mtspace->otree; + } +} + +/* add a space-filler to the empty space representation. */ +void mtspace_add(mtspace_t * mtspace, const rtrnd_rtree_box_t * box, mtspace_type_t which, double clearance) +{ + mtspacebox_t *filler = mtspace_create_box(box, clearance); + rnd_r_insert_entry(which_tree(mtspace, which), (const rtrnd_rtree_box_t *) filler); +} + +/* remove a space-filler from the empty space representation. */ +void mtspace_remove(mtspace_t * mtspace, const rtrnd_rtree_box_t * box, mtspace_type_t which, double clearance) +{ + struct mts_info cl; + rtrnd_rtree_box_t small_search; + + cl.clearance = clearance; + cl.box = *box; + cl.tree = which_tree(mtspace, which); + small_search = rnd_box_center(box); + if (setjmp(cl.env) == 0) { + rnd_r_search(cl.tree, &small_search, NULL, mts_remove_one, &cl, NULL); + assert(0); /* didn't find it?? */ + } +} + +struct query_closure { + rtrnd_rtree_box_t *cbox; + heap_or_vector checking; + heap_or_vector touching; + rnd_cheap_point_t *desired; + double radius, clearance; + jmp_buf env; + rtrnd_bool_t touch_is_vec; +}; + +static inline void heap_append(rnd_heap_t * heap, rnd_cheap_point_t * desired, rtrnd_rtree_box_t * newone) +{ + rnd_cheap_point_t p = *desired; + assert(desired); + rnd_closest_cheap_point_in_box(&p, newone); + rnd_heap_insert(heap, fabs(p.X - desired->X) + (p.Y - desired->Y), newone); +} + +static inline void append(struct query_closure *qc, rtrnd_rtree_box_t * newone) +{ + if (qc->desired) + heap_append(qc->checking.h, qc->desired, newone); + else + vector_append(qc->checking.v, newone); +} + +/* we found some space filler that may intersect this query. + * First check if it does intersect, then break it into + * overlaping regions that don't intersect this box. + */ +static rnd_r_dir_t query_one(const rtrnd_rtree_box_t * box, void *cl) +{ + struct query_closure *qc = (struct query_closure *) cl; + mtspacebox_t *mtsb = (mtspacebox_t *) box; + double shrink; + +#ifndef NDEBUG + { + /* work around rounding errors: grow both boxes by 2 nm */ + rtrnd_rtree_box_t b1 = *qc->cbox, b2 = mtsb->box; + b1.x1--;b1.y1--;b1.x2++;b1.y2++; + b2.x1--;b2.y1--;b2.x2++;b2.y2++; + assert(rnd_box_intersect(&b1, &b2)); + } +#endif + + /* we need to satisfy the larger of the two clearances */ + if (qc->clearance > mtsb->clearance) + shrink = mtsb->clearance; + else + shrink = qc->clearance; + /* if we shrink qc->box by this amount and it doesn't intersect + * then we didn't actually touch this box */ + if (qc->cbox->x1 + shrink >= mtsb->box.x2 || + qc->cbox->x2 - shrink <= mtsb->box.x1 || qc->cbox->y1 + shrink >= mtsb->box.y2 || qc->cbox->y2 - shrink <= mtsb->box.y1) + return RND_R_DIR_NOT_FOUND; + /* ok, we do touch this box, now create up to 4 boxes that don't */ + if (mtsb->box.y1 > qc->cbox->y1 + shrink) { /* top region exists */ + double Y1 = qc->cbox->y1; + double Y2 = mtsb->box.y1 + shrink; + if (Y2 - Y1 >= 2 * (qc->radius + qc->clearance)) { + rtrnd_rtree_box_t *newone = (rtrnd_rtree_box_t *) malloc(sizeof(rtrnd_rtree_box_t)); + newone->x1 = qc->cbox->x1; + newone->x2 = qc->cbox->x2; + newone->y1 = Y1; + newone->y2 = Y2; + assert(newone->y2 < qc->cbox->y2); + append(qc, newone); + } + } + if (mtsb->box.y2 < qc->cbox->y2 - shrink) { /* bottom region exists */ + double Y1 = mtsb->box.y2 - shrink; + double Y2 = qc->cbox->y2; + if (Y2 - Y1 >= 2 * (qc->radius + qc->clearance)) { + rtrnd_rtree_box_t *newone = (rtrnd_rtree_box_t *) malloc(sizeof(rtrnd_rtree_box_t)); + newone->x1 = qc->cbox->x1; + newone->x2 = qc->cbox->x2; + newone->y2 = qc->cbox->y2; + newone->y1 = Y1; + assert(newone->y1 > qc->cbox->y1); + append(qc, newone); + } + } + if (mtsb->box.x1 > qc->cbox->x1 + shrink) { /* left region exists */ + double X1 = qc->cbox->x1; + double X2 = mtsb->box.x1 + shrink; + if (X2 - X1 >= 2 * (qc->radius + qc->clearance)) { + rtrnd_rtree_box_t *newone; + newone = (rtrnd_rtree_box_t *) malloc(sizeof(rtrnd_rtree_box_t)); + newone->y1 = qc->cbox->y1; + newone->y2 = qc->cbox->y2; + newone->x1 = qc->cbox->x1; + newone->x2 = X2; + assert(newone->x2 < qc->cbox->x2); + append(qc, newone); + } + } + if (mtsb->box.x2 < qc->cbox->x2 - shrink) { /* right region exists */ + double X1 = mtsb->box.x2 - shrink; + double X2 = qc->cbox->x2; + if (X2 - X1 >= 2 * (qc->radius + qc->clearance)) { + rtrnd_rtree_box_t *newone = (rtrnd_rtree_box_t *) malloc(sizeof(rtrnd_rtree_box_t)); + newone->y1 = qc->cbox->y1; + newone->y2 = qc->cbox->y2; + newone->x2 = qc->cbox->x2; + newone->x1 = X1; + assert(newone->x1 > qc->cbox->x1); + append(qc, newone); + } + } + if (qc->touching.v) { + if (qc->touch_is_vec || !qc->desired) + vector_append(qc->touching.v, qc->cbox); + else + heap_append(qc->touching.h, qc->desired, qc->cbox); + } + else + free(qc->cbox); /* done with this one */ + longjmp(qc->env, 1); + return RND_R_DIR_FOUND_CONTINUE; /* never reached */ +} + +/* qloop takes a vector (or heap) of regions to check (checking) if they don't intersect + * anything. If a region does intersect something, it is broken into + * pieces that don't intersect that thing (if possible) which are + * put back into the vector/heap of regions to check. + * qloop returns rtrnd_false when it finds the first empty region + * it returns rtrnd_true if it has exhausted the region vector/heap and never + * found an empty area. + */ +static void qloop(struct query_closure *qc, rtrnd_rtree_t * tree, heap_or_vector res, rtrnd_bool_t is_vec) +{ + rtrnd_rtree_box_t *cbox; + int n; + + while (!(qc->desired ? rnd_heap_is_empty(qc->checking.h) : vector_is_empty(qc->checking.v))) { + cbox = qc->desired ? (rtrnd_rtree_box_t *) rnd_heap_remove_smallest(qc->checking.h) : (rtrnd_rtree_box_t *) vector_remove_last(qc->checking.v); + if (setjmp(qc->env) == 0) { + assert(rnd_box_is_good(cbox)); + qc->cbox = cbox; + rnd_r_search(tree, cbox, NULL, query_one, qc, &n); + assert(n == 0); + /* nothing intersected with this tree, put it in the result vector */ + if (is_vec) + vector_append(res.v, cbox); + else { + if (qc->desired) + heap_append(res.h, qc->desired, cbox); + else + vector_append(res.v, cbox); + } + return; /* found one - perhaps one answer is good enough */ + } + } +} + +/* free the memory used by the vetting structure */ +void mtsFreeWork(vetting_t ** w) +{ + vetting_t *work = (*w); + if (work->desired.X != -SPECIAL || work->desired.Y != -SPECIAL) { + rnd_heap_free(work->untested.h, free); + rnd_heap_destroy(&work->untested.h); + rnd_heap_free(work->no_fix.h, free); + rnd_heap_destroy(&work->no_fix.h); + rnd_heap_free(work->no_hi.h, free); + rnd_heap_destroy(&work->no_hi.h); + rnd_heap_free(work->hi_candidate.h, free); + rnd_heap_destroy(&work->hi_candidate.h); + } + else { + while (!vector_is_empty(work->untested.v)) + free(vector_remove_last(work->untested.v)); + vector_destroy(&work->untested.v); + while (!vector_is_empty(work->no_fix.v)) + free(vector_remove_last(work->no_fix.v)); + vector_destroy(&work->no_fix.v); + while (!vector_is_empty(work->no_hi.v)) + free(vector_remove_last(work->no_hi.v)); + vector_destroy(&work->no_hi.v); + while (!vector_is_empty(work->hi_candidate.v)) + free(vector_remove_last(work->hi_candidate.v)); + vector_destroy(&work->hi_candidate.v); + } + free(work); + (*w) = NULL; +} + + +/* returns some empty spaces in 'region' (or former narrowed regions) + * that may hold a feature with the specified radius and clearance + * It tries first to find Completely empty regions (which are appended + * to the free_space_vec vector). If that fails, it looks for regions + * filled only by objects generated by the previous pass (which are + * appended to the lo_conflict_space_vec vector). Then it looks for + * regions that are filled by objects generated during *this* pass + * (which are appended to the hi_conflict_space_vec vector). The + * current pass identity is given by 'is_odd'. As soon as one completely + * free region is found, it returns with that answer. It saves partially + * searched regions in vectors "untested", "no_fix", "no_hi", and + * "hi_candidate" which can be passed to future calls of this function + * to search harder for such regions if the computation becomes + * necessary. + */ +vetting_t *mtspace_query_rect(mtspace_t * mtspace, const rtrnd_rtree_box_t * region, + double radius, double clearance, + vetting_t * work, + vector_t * free_space_vec, + vector_t * lo_conflict_space_vec, + vector_t * hi_conflict_space_vec, rtrnd_bool_t is_odd, rtrnd_bool_t with_conflicts, rnd_cheap_point_t * desired) +{ + struct query_closure qc; + + /* pre-assertions */ + assert(free_space_vec); + assert(lo_conflict_space_vec); + assert(hi_conflict_space_vec); + /* search out to anything that might matter */ + if (region) { + rtrnd_rtree_box_t *cbox; + assert(work == NULL); + assert(rnd_box_is_good(region)); + assert(vector_is_empty(free_space_vec)); + assert(vector_is_empty(lo_conflict_space_vec)); + assert(vector_is_empty(hi_conflict_space_vec)); + work = (vetting_t *) malloc(sizeof(vetting_t)); + work->clearance = clearance; + work->radius = radius; + cbox = (rtrnd_rtree_box_t *) malloc(sizeof(rtrnd_rtree_box_t)); + *cbox = rnd_bloat_box(region, clearance + radius); + if (desired) { + work->untested.h = rnd_heap_create(); + work->no_fix.h = rnd_heap_create(); + work->hi_candidate.h = rnd_heap_create(); + work->no_hi.h = rnd_heap_create(); + assert(work->untested.h && work->no_fix.h && work->no_hi.h && work->hi_candidate.h); + rnd_heap_insert(work->untested.h, 0, cbox); + work->desired = *desired; + } + else { + work->untested.v = vector_create(); + work->no_fix.v = vector_create(); + work->hi_candidate.v = vector_create(); + work->no_hi.v = vector_create(); + assert(work->untested.v && work->no_fix.v && work->no_hi.v && work->hi_candidate.v); + vector_append(work->untested.v, cbox); + work->desired.X = work->desired.Y = -SPECIAL; + } + return work; + } + qc.clearance = work->clearance; + qc.radius = work->radius; + if (work->desired.X == -SPECIAL && work->desired.Y == -SPECIAL) + qc.desired = NULL; + else + qc.desired = &work->desired; + /* do the query */ + do { + heap_or_vector temporary; + temporary.v = free_space_vec; + + /* search the fixed object tree discarding any intersections + * and placing empty regions in the no_fix vector. + */ + qc.checking = work->untested; + qc.touching.v = NULL; + qloop(&qc, mtspace->ftree, work->no_fix, rtrnd_false); + /* search the hi-conflict tree placing intersectors in the + * hi_candidate vector (if conflicts are allowed) and + * placing empty regions in the no_hi vector. + */ + qc.checking.v = work->no_fix.v; + qc.touching.v = with_conflicts ? work->hi_candidate.v : NULL; + qc.touch_is_vec = rtrnd_false; + qloop(&qc, is_odd ? mtspace->otree : mtspace->etree, work->no_hi, rtrnd_false); + /* search the lo-conflict tree placing intersectors in the + * lo-conflict answer vector (if conflicts allowed) and + * placing emptry regions in the free-space answer vector. + */ + qc.checking = work->no_hi; +/* XXX lo_conflict_space_vec will be treated like a heap! */ + qc.touching.v = (with_conflicts ? lo_conflict_space_vec : NULL); + qc.touch_is_vec = rtrnd_true; + qloop(&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, rtrnd_true); + + /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, (heap_or_vector)free_space_vec, rtrnd_true); */ + if (!vector_is_empty(free_space_vec)) { + if (qc.desired) { + if (rnd_heap_is_empty(work->untested.h)) + break; + } + else { + if (vector_is_empty(work->untested.v)) + break; + } + return work; + } + /* finally check the hi-conflict intersectors against the + * lo-conflict tree discarding intersectors (two types of conflict is real bad) + * and placing empty regions in the hi-conflict answer vector. + */ + if (with_conflicts) { + heap_or_vector temporary; + temporary.v = hi_conflict_space_vec; + + qc.checking = work->hi_candidate; + qc.touching.v = NULL; + qloop(&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, rtrnd_true); + + /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, */ + /* (heap_or_vector)hi_conflict_space_vec, rtrnd_true); */ + } + } + while (!(qc.desired ? rnd_heap_is_empty(work->untested.h) : vector_is_empty(work->untested.v))); + if (qc.desired) { + if (rnd_heap_is_empty(work->no_fix.h) && rnd_heap_is_empty(work->no_hi.h) && rnd_heap_is_empty(work->hi_candidate.h)) { + mtsFreeWork(&work); + return NULL; + } + } + else { + if (vector_is_empty(work->no_fix.v) && vector_is_empty(work->no_hi.v) && vector_is_empty(work->hi_candidate.v)) { + mtsFreeWork(&work); + return NULL; + } + } + return work; +} + +int mtsBoxCount(vetting_t * w) +{ +#if 0 + int ans; + ans = 3 * vector_size(w->untested); + ans += 2 * vector_size(w->no_fix); + ans += vector_size(w->no_hi); + ans += vector_size(w->hi_candidate); + return ans; +#endif + return 100; +} Index: tags/0.9.0/src/plugins/rt_hace/mtspace.h =================================================================== --- tags/0.9.0/src/plugins/rt_hace/mtspace.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/mtspace.h (revision 1402) @@ -0,0 +1,208 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, mtspace.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* "empty space" routines (needed for via-space tracking in the auto-router. */ + +#ifndef PCB_MTSPACE_H +#define PCB_MTSPACE_H + +/* mtspace data structures are built on r-trees. */ + +#include "config.h" +#include "data.h" +#include "vector.h" /* for vector_t in mtspace_query_rect prototype */ + +/* 1 nm to match pcb-rnd's original behavior */ +#define DELTA 0.0000001 + +typedef struct rnd_cheap_point_s { + double X, Y; +} rnd_cheap_point_t; + +RTRND_INLINE rtrnd_bool_t rnd_box_is_good(const rtrnd_rtree_box_t *b) +{ + return (b->x1 < b->x2) && (b->y1 < b->y2); +} + +RTRND_INLINE rtrnd_bool_t rnd_box_intersect(const rtrnd_rtree_box_t * a, const rtrnd_rtree_box_t * b) +{ + return (a->x1 < b->x2) && (b->x1 < a->x2) && (a->y1 < b->y2) && (b->y1 < a->y2); +} + +RTRND_INLINE rtrnd_bool_t rnd_point_in_box(const rtrnd_rtree_box_t * box, double X, double Y) +{ + return (X >= box->x1) && (Y >= box->y1) && (X <= box->x2) && (Y <= box->y2); +} + +#define RND_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define RND_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define RND_MAKE_MIN(a,b) if ((b) < (a)) (a) = (b) +#define RND_MAKE_MAX(a,b) if ((b) > (a)) (a) = (b) + +RTRND_INLINE rtrnd_bool_t rnd_box_in_box(const rtrnd_rtree_box_t *outer, const rtrnd_rtree_box_t *inner) +{ + return (outer->x1 <= inner->x1) && (inner->x2 <= outer->x2) && (outer->y1 <= inner->y1) && (inner->y2 <= outer->y2); +} + +RTRND_INLINE rtrnd_rtree_box_t rnd_clip_box(const rtrnd_rtree_box_t *box, const rtrnd_rtree_box_t *clipbox) +{ + rtrnd_rtree_box_t r; + assert(rnd_box_intersect(box, clipbox)); + r.x1 = RND_MAX(box->x1, clipbox->x1); + r.x2 = RND_MIN(box->x2, clipbox->x2); + r.y1 = RND_MAX(box->y1, clipbox->y1); + r.y2 = RND_MIN(box->y2, clipbox->y2); + return r; +} + +RTRND_INLINE rtrnd_rtree_box_t rnd_shrink_box(const rtrnd_rtree_box_t * box, double amount) +{ + rtrnd_rtree_box_t r = *box; + r.x1 += amount; + r.y1 += amount; + r.x2 -= amount; + r.y2 -= amount; +assert(r.x1 < r.x2); +assert(r.y1 < r.y2); + return r; +} + +RTRND_INLINE rtrnd_rtree_box_t rnd_bloat_box(const rtrnd_rtree_box_t * box, double amount) +{ + return rnd_shrink_box(box, -amount); +} + +RTRND_INLINE rnd_cheap_point_t rnd_closest_cheap_point_in_box(const rnd_cheap_point_t * from, const rtrnd_rtree_box_t * box) +{ + rnd_cheap_point_t r; + assert(box->x1 < box->x2 && box->y1 < box->y2); + r.X = (from->X < box->x1) ? box->x1 : (from->X > box->x2) ? box->x2 : from->X; + r.Y = (from->Y < box->y1) ? box->y1 : (from->Y > box->y2) ? box->y2 : from->Y; + assert(rnd_point_in_box(box, r.X, r.Y)); + return r; +} + +/* construct a box that holds a single point */ +RTRND_INLINE rtrnd_rtree_box_t rnd_point_box(double X, double Y) +{ + rtrnd_rtree_box_t r; + r.x1 = X; + r.x2 = X + 0.000001; + r.y1 = Y; + r.y2 = Y + 0.000001; + return r; +} + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#define RND_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define RND_ABS(a) (((a) < 0) ? -(a) : (a)) +#define RND_BOX_CENTER_X(b) ((b).x1 + ((b).x2 - (b).x1)/2) +#define RND_BOX_CENTER_Y(b) ((b).y1 + ((b).y2 - (b).y1)/2) + +#define RND_BOX_ROTATE_TO_NORTH(box, dir) \ +do { double t;\ + switch(dir) {\ + case RND_EAST: \ + t = (box).x1; (box).x1 = (box).y1; (box).y1 = -(box).x2;\ + (box).x2 = (box).y2; (box).y2 = -t; break;\ + case RND_SOUTH: \ + t = (box).x1; (box).x1 = -(box).x2; (box).x2 = -t;\ + t = (box).y1; (box).y1 = -(box).y2; (box).y2 = -t; break;\ + case RND_WEST: \ + t = (box).x1; (box).x1 = -(box).y2; (box).y2 = (box).x2;\ + (box).x2 = -(box).y1; (box).y1 = t; break;\ + case RND_NORTH: break;\ + default: assert(0);\ + }\ +} while (0) + +#define RND_BOX_ROTATE_FROM_NORTH(box, dir) \ +do { double t;\ + switch(dir) {\ + case RND_WEST: \ + t = (box).x1; (box).x1 = (box).y1; (box).y1 = -(box).x2;\ + (box).x2 = (box).y2; (box).y2 = -t; break;\ + case RND_SOUTH: \ + t = (box).x1; (box).x1 = -(box).x2; (box).x2 = -t;\ + t = (box).y1; (box).y1 = -(box).y2; (box).y2 = -t; break;\ + case RND_EAST: \ + t = (box).x1; (box).x1 = -(box).y2; (box).y2 = (box).x2;\ + (box).x2 = -(box).y1; (box).y1 = t; break;\ + case RND_NORTH: break;\ + default: assert(0);\ + }\ +} while (0) + + +typedef struct mtspace mtspace_t; +typedef enum { FIXED, ODD, EVEN } mtspace_type_t; +typedef struct vetting vetting_t; + +/* create an "empty space" representation with a shrunken boundary */ +mtspace_t *mtspace_create(void); +/* destroy an "empty space" representation. */ +void mtspace_destroy(mtspace_t ** mtspacep); + +/* -- mutation -- */ + +/* add a space-filler to the empty space representation. The given box + * should *not* be bloated; it should be "true". The feature will fill + * *at least* a radius of clearance around it; + */ +void mtspace_add(mtspace_t * mtspace, const rtrnd_rtree_box_t * box, mtspace_type_t which, double clearance); +/* remove a space-filler from the empty space representation. The given box + * should *not* be bloated; it should be "true". The feature will fill + * *at least* a radius of clearance around it; + */ +void mtspace_remove(mtspace_t * mtspace, const rtrnd_rtree_box_t * box, mtspace_type_t which, double clearance); + + +vetting_t *mtspace_query_rect(mtspace_t * mtspace, const rtrnd_rtree_box_t * region, + double radius, double clearance, + vetting_t * work, + vector_t * free_space_vec, + vector_t * lo_conflict_space_vec, + vector_t * hi_conflict_space_vec, rtrnd_bool_t is_odd, rtrnd_bool_t with_conflicts, rnd_cheap_point_t * desired); + +void mtsFreeWork(vetting_t **); +int mtsBoxCount(vetting_t *); + +#endif /* ! PCB_MTSPACE_H */ Index: tags/0.9.0/src/plugins/rt_hace/rnd_rtree.c =================================================================== --- tags/0.9.0/src/plugins/rt_hace/rnd_rtree.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/rnd_rtree.c (revision 1402) @@ -0,0 +1,156 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017,2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include + +#include +#include +#include + +#include "rtree.h" +#include "rnd_rtree.h" + +/* Temporary compatibility layer for the transition */ +rtrnd_rtree_t *rnd_r_create_tree(void) +{ + rtrnd_rtree_t *root = malloc(sizeof(rtrnd_rtree_t)); + rtrnd_rtree_init(root); + return root; +} + +void rnd_r_destroy_tree(rtrnd_rtree_t **tree) +{ + rtrnd_rtree_uninit(*tree); + free(*tree); + *tree = NULL; +} + +void rnd_r_insert_entry(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *which) +{ + assert(which != NULL); + rtrnd_rtree_insert(rtree, (void *)which, (rtrnd_rtree_box_t *)which); /* assumes first field is the bounding box */ +} + +void rnd_r_insert_array(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *boxlist[], long len) +{ + long n; + + if (len == 0) + return; + + assert(boxlist != 0); + + for(n = 0; n < len; n++) + rnd_r_insert_entry(rtree, boxlist[n]); +} + +rtrnd_bool_t rnd_r_delete_entry(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *which) +{ + assert(which != NULL); + return rtrnd_rtree_delete(rtree, (void *)which, (rtrnd_rtree_box_t *)which) == 0; /* assumes first field is the bounding box */ +} + +rtrnd_bool_t rnd_r_delete_entry_free_data(rtrnd_rtree_t *rtree, rtrnd_rtree_box_t *box, void (*free_data)(void *d)) +{ + void *obj = box; /* assumes first field is the bounding box */ + assert(obj != NULL); + if (rtrnd_rtree_delete(rtree, obj, (rtrnd_rtree_box_t *)box) != 0) + return rtrnd_false; + free_data(obj); + return rtrnd_true; +} + +typedef struct { + rnd_r_dir_t (*region_in_search)(const rtrnd_rtree_box_t *region, void *closure); + rnd_r_dir_t (*rectangle_in_region)(const rtrnd_rtree_box_t *box, void *closure); + void *clo; +} r_cb_t; + +static rtrnd_rtree_dir_t r_cb_node(void *ctx_, void *obj, const rtrnd_rtree_box_t *box) +{ + r_cb_t *ctx = (r_cb_t *)ctx_; + return ctx->region_in_search((const rtrnd_rtree_box_t *)box, ctx->clo); +} + +static rtrnd_rtree_dir_t r_cb_obj(void *ctx_, void *obj, const rtrnd_rtree_box_t *box) +{ + r_cb_t *ctx = (r_cb_t *)ctx_; + return ctx->rectangle_in_region((const rtrnd_rtree_box_t *)obj, ctx->clo); +} + + +rnd_r_dir_t rnd_r_search(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *query, + rnd_r_dir_t (*region_in_search)(const rtrnd_rtree_box_t *region, void *closure), + rnd_r_dir_t (*rectangle_in_region)(const rtrnd_rtree_box_t *box, void *closure), + void *closure, int *num_found) +{ + rnd_r_dir_t res; + rtrnd_rtree_cardinal_t out_cnt; + r_cb_t ctx; + ctx.region_in_search = region_in_search; + ctx.rectangle_in_region = rectangle_in_region; + ctx.clo = closure; + + res = rtrnd_rtree_search_any(rtree, (const rtrnd_rtree_box_t *)query, + (ctx.region_in_search != NULL) ? r_cb_node : NULL, + (ctx.rectangle_in_region != NULL) ? r_cb_obj : NULL, + &ctx, &out_cnt); + + if (num_found != NULL) + *num_found = out_cnt; + + return res; +} + +int rnd_r_region_is_empty(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *region) +{ + return rtrnd_rtree_is_box_empty(rtree, (const rtrnd_rtree_box_t *)region); +} + +void rnd_r_free_tree_data(rtrnd_rtree_t *rtree, void (*free)(void *ptr)) +{ + rtrnd_rtree_it_t it; + void *o; + + for(o = rtrnd_rtree_all_first(&it, rtree); o != NULL; o = rtrnd_rtree_all_next(&it)) + free(o); +} + +rtrnd_rtree_box_t *rnd_r_first(rtrnd_rtree_t *tree, rtrnd_rtree_it_t *it) +{ + if (tree == NULL) + return NULL; + return (rtrnd_rtree_box_t *)rtrnd_rtree_all_first(it, tree); +} + +rtrnd_rtree_box_t *rnd_r_next(rtrnd_rtree_it_t *it) +{ + return (rtrnd_rtree_box_t *)rtrnd_rtree_all_next(it); +} + +void rnd_r_end(rtrnd_rtree_it_t *it) +{ +} Index: tags/0.9.0/src/plugins/rt_hace/rnd_rtree.h =================================================================== --- tags/0.9.0/src/plugins/rt_hace/rnd_rtree.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/rnd_rtree.h (revision 1402) @@ -0,0 +1,108 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, rtree.h, was written and is + * Copyright (c) 2004 harry eaton, it's based on C. Scott's kdtree.h template + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* Compatibility layer between the new rtree and the old rtree for the + period of transition */ + +#ifndef RND_RTREE2_COMPAT_H +#define RND_RTREE2_COMPAT_H + +#include "data.h" +#include "rtree.h" + +/* callback direction to the search engine */ +typedef enum rnd_r_dir_e { + RND_R_DIR_NOT_FOUND = 0, /* object not found or not accepted */ + RND_R_DIR_FOUND_CONTINUE = 1, /* object found or accepted, go on searching */ + RND_R_DIR_CANCEL = 2 /* cancel the search and return immediately */ +} rnd_r_dir_t; + +rtrnd_rtree_t *rnd_r_create_tree(void); +void rnd_r_destroy_tree(rtrnd_rtree_t **tree); +void rnd_r_free_tree_data(rtrnd_rtree_t *rtree, void (*free)(void *ptr)); + +void rnd_r_insert_entry(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *which); +void rnd_r_insert_array(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *boxlist[], long len); + +rtrnd_bool_t rnd_r_delete_entry(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *which); +rtrnd_bool_t rnd_r_delete_entry_free_data(rtrnd_rtree_t *rtree, rtrnd_rtree_box_t *box, void (*free_data)(void *d)); + +/* generic search routine */ +/* region_in_search should return rnd_true if "what you're looking for" is + * within the specified region; + * rectangle_in_region should return rnd_true if the given rectangle is + * "what you're looking for". + * The search will find all rectangles matching the criteria given + * by region_in_search and rectangle_in_region and return a count of + * how many things rectangle_in_region returned rnd_true for. closure is + * used to abort the search if desired from within rectangle_in_region + * Look at the implementation of r_region_is_empty for how to + * abort the search if that is the desired behavior. + */ +rnd_r_dir_t rnd_r_search(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *query, + rnd_r_dir_t (*region_in_search)(const rtrnd_rtree_box_t *region, void *closure), + rnd_r_dir_t (*rectangle_in_region)(const rtrnd_rtree_box_t *box, void *closure), + void *closure, int *num_found); + +/* return 0 if there are any rectangles in the given region. */ +int rnd_r_region_is_empty(rtrnd_rtree_t *rtree, const rtrnd_rtree_box_t *region); + +#define RND_RTREE_EMPTY(rt) (((rt) == NULL) || ((rt)->size == 0)) + +/* -- Iterate through an rtree; DO NOT modify the tree while iterating -- */ + +/* Get the first item, get fields of iterator set up; return can be casted to an object; returns NULL if rtree is empty */ +rtrnd_rtree_box_t *rnd_r_first(rtrnd_rtree_t *tree, rtrnd_rtree_it_t *it); + +/* Get the next item, return can be casted to an object; returns NULL if no more items */ +rtrnd_rtree_box_t *rnd_r_next(rtrnd_rtree_it_t *it); + +/* Free fields of the iterator - not needed anymore, will be removed */ +void rnd_r_end(rtrnd_rtree_it_t *it); + +/* construct a minimum box that touches the input box at the center */ +RTRND_INLINE rtrnd_rtree_box_t rnd_box_center(const rtrnd_rtree_box_t * box) +{ + rtrnd_rtree_box_t r; + r.x1 = box->x1 + (box->x2 - box->x1) / 2; + r.x2 = r.x1 + 0.0000001; + r.y1 = box->y1 + (box->y2 - box->y1) / 2; + r.y2 = r.y1 + 0.0000001; + return r; +} + +#endif Index: tags/0.9.0/src/plugins/rt_hace/vector.c =================================================================== --- tags/0.9.0/src/plugins/rt_hace/vector.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/vector.c (revision 1402) @@ -0,0 +1,207 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, vector.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* operations on vectors. */ + +#include "config.h" + +#include +#include +#include + +#include "vector.h" + +#define RND_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define RND_MAX(a,b) ((a) > (b) ? (a) : (b)) + +struct vector_struct { + vector_element_t *element; + int size, max; +}; + +/* helper function for assertions */ +#ifndef NDEBUG +static int __vector_is_good(vector_t * vector) +{ + return vector && (vector->max == 0 || vector->element) && + (vector->max >= 0) && (vector->size >= 0) && (vector->size <= vector->max) && 1; +} +#endif /* !NDEBUG */ + +/* create an empty vector */ +vector_t *vector_create() +{ + vector_t *vector; + /* okay, create empty vector */ + vector = (vector_t *) calloc(1, sizeof(*vector)); + assert(vector); + assert(__vector_is_good(vector)); + return vector; +} + +/* destroy a vector */ +void vector_destroy(vector_t ** vector) +{ + assert(vector && *vector); + assert(__vector_is_good(*vector)); + if ((*vector)->element) + free((*vector)->element); + free(*vector); + *vector = NULL; +} + +/* -- interrogation -- */ +int vector_is_empty(vector_t * vector) +{ + assert(__vector_is_good(vector)); + return (vector->size == 0); +} + +int vector_size(vector_t * vector) +{ + assert(__vector_is_good(vector)); + return (vector->size); +} + +vector_element_t vector_element(vector_t * vector, int N) +{ + assert(__vector_is_good(vector)); + assert(N < vector->size); + return vector->element[N]; +} + +/* return the first element of the vector. */ +vector_element_t vector_element_first(vector_t * vector) +{ + assert(__vector_is_good(vector)); + assert(vector->size > 0); + return vector_element(vector, 0); +} + +/* return the last element of the vector. */ +vector_element_t vector_element_last(vector_t * vector) +{ + assert(__vector_is_good(vector)); + assert(vector->size > 0); + return vector_element(vector, vector->size - 1); +} + +/* -- mutation -- */ +/* add data to end of vector */ +void vector_append(vector_t * vector, vector_element_t data) +{ + vector_insert_many(vector, vector->size, &data, 1); +} + +void vector_append_many(vector_t * vector, vector_element_t data[], int count) +{ + vector_insert_many(vector, vector->size, data, count); +} + +void vector_append_vector(vector_t * vector, vector_t * other_vector) +{ + vector_append_many(vector, other_vector->element, other_vector->size); +} + +void vector_insert(vector_t * vector, int N, vector_element_t data) +{ + vector_insert_many(vector, N, &data, 1); +} + +/* add data at specified position of vector */ +void vector_insert_many(vector_t * vector, int N, vector_element_t data[], int count) +{ + assert(__vector_is_good(vector)); + assert(N <= vector->size); + if (count == 0) + return; + assert(data && count > 0); + if (vector->size + count > vector->max) { + vector->max = RND_MAX(32, RND_MAX(vector->size + count, vector->max * 2)); + vector->element = (void **) realloc(vector->element, vector->max * sizeof(*vector->element)); + } + memmove(vector->element + N + count, vector->element + N, (vector->size - N) * sizeof(*vector->element)); + memmove(vector->element + N, data, count * sizeof(*data)); + vector->size += count; + assert(__vector_is_good(vector)); +} + +vector_t *vector_duplicate(vector_t * orig) +{ + vector_t *newone = vector_create(); + if (!orig) + return newone; + newone->element = (void **) malloc(orig->max * sizeof(*orig->element)); + newone->max = orig->max; + newone->size = orig->size; + memcpy(newone->element, orig->element, orig->size * sizeof(vector_element_t)); + assert(__vector_is_good(newone)); + return newone; +} + +/* return and delete the *last* element of vector */ +vector_element_t vector_remove_last(vector_t * vector) +{ + assert(vector->size > 0); + return vector_remove(vector, vector->size - 1); +} + +/* return and delete data at specified position of vector */ +vector_element_t vector_remove(vector_t * vector, int N) +{ + vector_element_t old; + assert(__vector_is_good(vector)); + assert(N < vector->size); + old = vector->element[N]; + memmove(vector->element + N, vector->element + N + 1, (vector->size - (N + 1)) * sizeof(*vector->element)); + vector->size--; + assert(__vector_is_good(vector)); + return old; +} + +/* replace the data at the specified position with the given data. + * returns the old data. */ +vector_element_t vector_replace(vector_t * vector, vector_element_t data, int N) +{ + vector_element_t old; + assert(__vector_is_good(vector)); + assert(N < vector->size); + old = vector->element[N]; + vector->element[N] = data; + assert(__vector_is_good(vector)); + return old; +} Index: tags/0.9.0/src/plugins/rt_hace/vector.h =================================================================== --- tags/0.9.0/src/plugins/rt_hace/vector.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_hace/vector.h (revision 1402) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, vector.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#ifndef PCB_VECTOR_H +#define PCB_VECTOR_H + +/* what a vector looks like */ +typedef struct vector_struct vector_t; +/* what data in a vector looks like */ +typedef void *vector_element_t; + +/* create an empty vector */ +vector_t *vector_create(); +/* destroy a vector */ +void vector_destroy(vector_t ** vector); +/* copy a vector */ +vector_t *vector_duplicate(vector_t * vector); + +/* -- interrogation -- */ +int vector_is_empty(vector_t * vector); +int vector_size(vector_t * vector); +vector_element_t vector_element(vector_t * vector, int N); +vector_element_t vector_element_first(vector_t * vector); +vector_element_t vector_element_last(vector_t * vector); + +/* -- mutation -- */ +/* add data to end of vector */ +void vector_append(vector_t * vector, vector_element_t data); +/* add multiple elements to end of vector */ +void vector_append_many(vector_t * vector, vector_element_t data[], int count); +/* add a vector of elements to the end of vector */ +void vector_append_vector(vector_t * vector, vector_t * other_vector); +/* add data at specified position of vector */ +void vector_insert(vector_t * vector, int N, vector_element_t data); +/* add multiple elements at specified position of vector */ +void vector_insert_many(vector_t * vector, int N, vector_element_t data[], int count); +/* return and delete the *last* element of vector */ +vector_element_t vector_remove_last(vector_t * vector); +/* return and delete data at specified position of vector */ +vector_element_t vector_remove(vector_t * vector, int N); +/* replace the data at the specified position with the given data. + * returns the old data. */ +vector_element_t vector_replace(vector_t * vector, vector_element_t data, int N); + +#endif /* PCB_VECTOR_H */ Index: tags/0.9.0/src/plugins/rt_horver/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/rt_horver/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/Makefile.inc (revision 1402) @@ -0,0 +1,6 @@ +BUILDIN_RT_HORVER = \ + $(PLG)/rt_horver/rt_horver.o \ + $(PLG)/rt_horver/escape.o \ + $(PLG)/rt_horver/optimize.o \ + $(PLG)/rt_horver/bus.o \ + $(PLG)/rt_horver/hpkp.o Index: tags/0.9.0/src/plugins/rt_horver/bus.c =================================================================== --- tags/0.9.0/src/plugins/rt_horver/bus.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/bus.c (revision 1402) @@ -0,0 +1,87 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: bus at the edges + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "bus.h" +#include "rt_horver.h" + +void bus_init(bus_t *bus, int dirpol, double first, double spacing, int len, double minor0, double minor1) +{ + int n; + double ma; + + /* cheat: cheap way to make sure vias next to each other on adjacent bus lines won't get too close in diagonal */ + if (spacing < via_dia + via_clr) + spacing *= 1.5; + + if (dirpol < 0) + spacing = -spacing; + + bus->len = len; + bus->raline = calloc(sizeof(rtrnd_raline_t), len); + for(ma = first, n = 0; n < len; n++, ma += spacing) { + bus->raline[n].major = ma; + vtd0_append(&bus->raline[n].minor, minor0); + vtd0_append(&bus->raline[n].minor, minor1); + } +} + +void bus_uninit(bus_t *bus) +{ + int n; + for(n = 0; n < bus->len; n++) + vtd0_uninit(&bus->raline[n].minor); + free(bus->raline); +} + + +rtrnd_raline_t *bus_reserve(bus_t *bus, double from, double to) +{ + int n; + for(n = 0; n < bus->len; n++) { + if (rtrnd_raline_range_avail(&bus->raline[n], from, to)) { + rtrnd_raline_block(&bus->raline[n], from, to); + return &bus->raline[n]; + } + } + return NULL; +} + + +void bus_draw_grid(bus_t *bus, rtrnd_layer_t *ly, int is_major_x) +{ + int n; + for(n = 0; n < bus->len; n++) { + rtrnd_raline_t *rl = &bus->raline[n]; + long last = rl->minor.used - 1; + if (is_major_x) + rtrnd_line_new(ly, NULL, NULL, rl->major, rl->minor.array[0], rl->major, rl->minor.array[last], 0.1, 0); + else + rtrnd_line_new(ly, NULL, NULL, rl->minor.array[0], rl->major, rl->minor.array[last], rl->major, 0.1, 0); + } +} + Index: tags/0.9.0/src/plugins/rt_horver/bus.h =================================================================== --- tags/0.9.0/src/plugins/rt_horver/bus.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/bus.h (revision 1402) @@ -0,0 +1,18 @@ +#ifndef RTRND_RT_HORVER_BUS_H +#define RTRND_RT_HORVER_BUS_H + +#include "util_grid.h" + +/* bus lines on the edge */ +typedef struct { + int len; + rtrnd_raline_t *raline; /* array of 'len' lines */ +} bus_t; + +void bus_init(bus_t *bus, int dirpol, double first, double spacing, int len, double minor0, double minor1); +void bus_uninit(bus_t *bus); +rtrnd_raline_t *bus_reserve(bus_t *bus, double from, double to); +void bus_draw_grid(bus_t *bus, rtrnd_layer_t *ly, int is_major_x); + + +#endif Index: tags/0.9.0/src/plugins/rt_horver/escape.c =================================================================== --- tags/0.9.0/src/plugins/rt_horver/escape.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/escape.c (revision 1402) @@ -0,0 +1,471 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: escape wires for simple grid based horizontal/vertical routing + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "rt_horver.h" +#include "hpkp.h" +#include "escape.h" + +/* Add an escape raline to eseg at escape line rl, if it is available the + escape range is available in direction dirpol. An escape lane spans from + bus_minor to mid_minor then a dogleg connects rl->major;mid_minor with + obj_major;obj_minor. + Returns 1 if escape found is available. + If dry is non-zero, do not modify eseg or rl. + */ +static int escape_add(void *cbctx, rtrnd_raline_t *rl, int is_major_x, int dirpol, double mid_minor, double bus_minor, double obj_major, double obj_minor, int dry) +{ + escape_seg_t *eseg = cbctx; + escape_dir_t dir; + int n, avail; + vtp0_t *lines; + + /* check if eseg already contains an escape line for this major; if so, + look if we can optimize it (get the escape shorter) */ + if (!dry) + for(n = 0; n < eseg->len; n++) { + if (eseg->poss[n].rl->major == rl->major) { + /* choose the mid_minor that is closer to the edge - escape lines should be short */ + if (dirpol < 0) { + if (mid_minor < eseg->poss[n].mid_minor) { + eseg->poss[n].mid_minor = mid_minor; + eseg->poss[n].obj_minor = obj_minor; + eseg->poss[n].obj_major = obj_major; + if (!eseg->poss[n].avail) { + dir = ESCAPE_DIR(is_major_x, dirpol); + rl = eseg->poss[n].rl; + eseg->poss[n].avail = rtrnd_raline_range_avail(rl, bus_minor, mid_minor); + printf(" FR1M: ma=%f mi=%f..%f avail=%d rlid=%ld\n", rl->major, mid_minor, bus_minor, eseg->poss[n].avail, rl->rt_data.l[dir]); + } + } + } + else { + if (mid_minor > eseg->poss[n].mid_minor) { + eseg->poss[n].mid_minor = mid_minor; + eseg->poss[n].obj_minor = obj_minor; + eseg->poss[n].obj_major = obj_major; + if (!eseg->poss[n].avail) { + dir = ESCAPE_DIR(is_major_x, dirpol); + rl = eseg->poss[n].rl; + eseg->poss[n].avail = rtrnd_raline_range_avail(rl, mid_minor, bus_minor); + printf(" FR0M: ma=%f mi=%f..%f avail=%d rlid=%ld\n", rl->major, mid_minor, bus_minor, eseg->poss[n].avail, rl->rt_data.l[dir]); + } + } + } + return eseg->poss[n].avail; /* already added */ + } + } + + /* new major, not present in eseg yet; check if the main escape range + between bus_minor and mid_minor is avaialble */ + if (mid_minor > bus_minor) + avail = rtrnd_raline_range_avail(rl, bus_minor, mid_minor); + else + avail = rtrnd_raline_range_avail(rl, mid_minor, bus_minor); + + if (dry) return avail; + + /* allocate an rl within the target eseg for this major and remember + the current idea for escaping (we may optimize it to shorter minor + later on if we are called with the same major from another object + again) */ + eseg->poss[eseg->len].rl = rl; + eseg->poss[eseg->len].avail = avail; + eseg->poss[n].bus_minor = bus_minor; + eseg->poss[n].mid_minor = mid_minor; + eseg->poss[n].obj_major = obj_major; + eseg->poss[n].obj_minor = obj_minor; + eseg->len++; + + /* also remember the raline, by id, per escape direction */ + dir = ESCAPE_DIR(is_major_x, dirpol); + if (rl->rt_data.l[dir] == 0) { + rl->rt_data.l[dir] = hvctx->escape[dir].next_raline_id++; + lines = &hvctx->escape[dir].ralines; + vtp0_append(lines, rl); + } + + printf(" From: ma=%f mi=%f..%f avail=%d rlid=%ld\n", rl->major, mid_minor, bus_minor, avail, rl->rt_data.l[dir]); + return avail; +} + +static long escape_obj_append(escape_seg_t *eseg, rtrnd_ragrid_t *grid, rtrnd_any_obj_t *o, int is_major_x, int dirpol, int dry) +{ + return horver_map_obj(escape_add, eseg, grid, o, is_major_x, dirpol, dry); +} + + +/* return 1 if object is reacahble on the layer of the escape line in a given direction */ +static int escape_obj_on_right_layer(horver_t *hvctx, rtrnd_any_obj_t *o, int is_major_x) +{ +#warning TODO: this ignores bbvia + if (o->hdr.type == RTRND_VIA) return 1; + + return (&o->hdr.parent->layer == hvctx->ly_copper[is_major_x]); +} + +/* Calculate all escape lines for each net segment of a net + in a given direction and sotre the resulting newly allocated eseg + in each netseg; returns number of available escapes or -1 on error */ +static long escape_net(horver_t *hvctx, rtrnd_ragrid_t *grid, rtrnd_net_t *net, int is_major_x, int dirpol, int dry) +{ + rtrnd_netseg_t *ns; + long cnt = 0; + int bad = 0; + + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + escape_seg_t *eseg = NULL; + rtrnd_any_obj_t *o; + double span; + + if (!dry) { + eseg = calloc(sizeof(escape_seg_t), 1); + eseg->chosen = -1; + NSDATA_ESEG(ns) = eseg; + } + + /* worst case allocation: all lines the bbox of the segment potentially spans, + +1 before +1 after */ + span = is_major_x ? (ns->hdr.bbox.x2 - ns->hdr.bbox.x1) : (ns->hdr.bbox.y2 - ns->hdr.bbox.y1); + span = ceil(span / grid->spacing) + 2; + if (!dry) + eseg->poss = malloc(sizeof(escape_poss_t) * ((long)span)); + + if (!dry) + printf(" ns %s bbox = %f;%f .. %f;%f alloc-span=%ld\n", ns->hdr.oid, ns->hdr.bbox.x1, ns->hdr.bbox.y1, ns->hdr.bbox.x2, ns->hdr.bbox.y2, (long)span); + + /* map esegs from each object of the netseg */ + for(o = gdl_first(&ns->objs); o != NULL; o = gdl_next(&ns->objs, o)) { + long r; + if (!escape_obj_on_right_layer(hvctx, o, is_major_x)) + continue; + r = escape_obj_append(eseg, grid, o, is_major_x, dirpol, dry); + if (r < 0) + bad++; + else + cnt += r; + } + } + + return bad ? -1 : cnt; +} + +/* Init the escape system, mapping all escapes of all nets in the best + direction for the given net */ +void escape_init(rtrnd_t *ctx, horver_t *hvctx) +{ + htsp_entry_t *e; + int g; + long n; + + /* reset raline allocation */ + for(g = 0; g < 2; g++) { + for(n = 0; n < hvctx->grid[g].len; n++) { + rtrnd_raline_t *rl = &hvctx->grid[g].raline[n]; + rl->rt_data.l[0] = rl->rt_data.l[1] = rl->rt_data.l[2] = rl->rt_data.l[3] = 0; + } + } + + printf("ESC: determining net escape direction\n"); + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + printf(" net: %s segs=%ld\n", net->hdr.oid, net->segments.length); + if (net->segments.length > 1) { + escape_dir_t dir; + rtrnd_netseg_t *ns; + int n, bestn; + long best = 0, av[4] = {0}; + int ismx[4] = {0, 0, 1, 1}; + int dpol[4] = {-1, +1, -1, +1}; + + /* estimate number of escapes in all directions that have not been disabled/failed */ + for(n = 0; n < 4; n++) { + dir = ESCAPE_DIR(ismx[n], dpol[n]); + if (NETDATA_FAILDIR(net, dir) || disable_dir[dir]) + av[n] = -1; /* already failed in that dir or disabled */ + else + av[n] = escape_net(hvctx, &hvctx->grid[ismx[n]], net, ismx[n], dpol[n], 1); + } + + printf(" escapes per dir:"); + + /* for now simply pick the most promising one: + the direction that is not yet failed/disabled and has the + largest number of potential escapes */ + for(bestn = n = 0; n < 4; n++) { + printf(" %ld", av[n]); + if (av[n] > best) { + best = av[n]; + bestn = n; + } + } + + if (av[bestn] <= 0) { + printf(" picked nothing: no chance to escape %s\n", net->hdr.oid); + continue; + } + + printf(" picked: %ld/%ld\n", best, av[bestn]); + + /* assign direction to the net */ + NETDATA_IS_MAJOR_X(net) = ismx[bestn]; + NETDATA_DIR(net) = dpol[bestn]; + dir = ESCAPE_DIR(NETDATA_IS_MAJOR_X(net), NETDATA_DIR(net)); + + /* assign an unique ID to each net seg */ + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) + NSDATA_IDX(ns) = hvctx->escape[dir].num_ns++; + } + } + + /* allocates the vector for all available escape lines */ + for(n = 0; n < 4; n++) { + hvctx->escape[n].next_raline_id = hvctx->escape[n].num_ns; + vtp0_init(&hvctx->escape[n].ralines); + } + + /* map all escape lines in the direction picked for the net */ + printf("ESC: escapeing\n"); + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + if (net->segments.length > 1) { + long r; + int grididx = !!NETDATA_IS_MAJOR_X(net); + r = escape_net(hvctx, &hvctx->grid[grididx], net, NETDATA_IS_MAJOR_X(net), NETDATA_DIR(net), 0); + printf(" net esc: %s segs=%ld res=%ld\n", net->hdr.oid, net->segments.length, r); + } + } + +} + +/* free all escape lines and esegs in each netsg */ +void escape_uninit(rtrnd_t *ctx, horver_t *hvctx) +{ + int n; + htsp_entry_t *e; + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + if (net->segments.length > 1) { + rtrnd_netseg_t *ns; + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + escape_seg_t *eseg = NSDATA_ESEG(ns); + free(eseg->poss); + free(eseg); + } + } + } + + for(n = 0; n < 4; n++) + vtp0_uninit(&hvctx->escape[n].ralines); +} + +/* Draw the escape line of a netseg at a given rl->major grid line */ +void escape_draw(rtrnd_t *ctx, horver_t *hvctx, int is_major_x, int dirpol, rtrnd_netseg_t *ns, rtrnd_raline_t *rl) +{ + escape_seg_t *eseg = NSDATA_ESEG(ns); + long n; + + for(n = 0; n < eseg->len; n++) { + if (eseg->poss[n].rl->major == rl->major) { + double mid_minor = eseg->poss[n].mid_minor, obj_major = eseg->poss[n].obj_major, obj_minor = eseg->poss[n].obj_minor; + double mi_edge = eseg->poss[n].bus_minor; + if (is_major_x) { + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns->net, rl->major, mid_minor, rl->major, mi_edge, wire_thick, wire_clr, 0.1, 0); + if ((rl->major != obj_major) || (mid_minor != obj_minor)) + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns->net, rl->major, mid_minor, obj_major, obj_minor, wire_thick, wire_clr, 0.1, 0); + } + else { + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns->net, mid_minor, rl->major, mi_edge, rl->major, wire_thick, wire_clr, 0.1, 0); + if ((rl->major != obj_major) || (mid_minor != obj_minor)) + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns->net, mid_minor, rl->major, obj_minor, obj_major, wire_thick, wire_clr, 0.1, 0); + } + } + } +} + +/* when placed an escape line in one direction, available escape lines on + the opposite direction may be affected. Since they are already as short + as possible for a netseg, if they are affected, they are simply unavailable */ +static void escape_adjust_avail(rtrnd_t *ctx, horver_t *hvctx, int is_major_x, int dirpol, double major, double minor_from, double minor_to) +{ + htsp_entry_t *e; + + if (minor_from > minor_to) { + double tmp = minor_from; + minor_from = minor_to; + minor_to = tmp; + } + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + + /* skip nets not trying to use this direction */ + if ((NETDATA_IS_MAJOR_X(net) != is_major_x) || (NETDATA_DIR(net) != dirpol)) + continue; + + if (net->segments.length > 1) { + rtrnd_netseg_t *ns; + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + long n; + escape_seg_t *eseg = NSDATA_ESEG(ns); + + for(n = 0; n < eseg->len; n++) { + if (!eseg->poss[n].avail || (eseg->poss[n].rl->major != major)) + continue; + /* found a major */ + printf("Possible ADJUST at major %f\n", major); + if ((eseg->poss[n].mid_minor >= minor_from) && (eseg->poss[n].mid_minor <= minor_to)) { + printf(" had to disable\n"); + eseg->poss[n].avail = 0; + } + } + } + } + } +} + + +/* make the pairing for a direction; returns the number of net segs failed to escape */ +long escape_calc(rtrnd_t *ctx, horver_t *hvctx, int is_major_x, int dirpol, int adjust_dirpol) +{ + htsp_entry_t *e; + escape_dir_t dir = ESCAPE_DIR(is_major_x, dirpol); + hpkp_t h; + long bad = 0; + + printf("PAIRING: segs=%ld lines=%ld (%ld)\n", hvctx->escape[dir].num_ns, hvctx->escape[dir].ralines.used, hvctx->escape[dir].next_raline_id); + if (hvctx->escape[dir].num_ns == 0) { + printf(" -> unused, skipping\n"); + return 0; + } + + if (hvctx->escape[dir].ralines.used == 0) { + printf(" -> no ralines, skipping\n"); + return 0; + } + + /* u:v is ns:raline */ + hpkp_init(&h, hvctx->escape[dir].next_raline_id, hvctx->escape[dir].num_ns * hvctx->escape[dir].ralines.used); + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + + /* skip nets not trying to use this direction */ + if ((NETDATA_IS_MAJOR_X(net) != is_major_x) || (NETDATA_DIR(net) != dirpol)) + continue; + + if (net->segments.length > 1) { + rtrnd_netseg_t *ns; + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + escape_seg_t *eseg = NSDATA_ESEG(ns); + long n, found; + for(found = n = 0; n < eseg->len; n++) { + rtrnd_raline_t *rl = eseg->poss[n].rl; + if (eseg->poss[n].avail) { + hpkp_add_edge(&h, NSDATA_IDX(ns), rl->rt_data.l[dir]); + printf(" add edge: %ld %ld\n", NSDATA_IDX(ns), rl->rt_data.l[dir]); + found++; + } + } + if (found == 0) { + printf(" ERROR: failed to escape netseg %s: no available grid lines\n", ns->hdr.oid); + NETDATA_FAILED_SET(net); + NETDATA_FAILDIR_SET(net, dir); + } + } + } + } + + hpkp_solve(&h); + + printf("Matches:\n"); + { + int n; + for(n = 0; n < hvctx->escape[dir].num_ns; n++) + printf(" %d %d\n", n, h.match[n]); + } + + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + + /* care about nets with the right escape direction only */ + if (ESCAPE_DIR(NETDATA_IS_MAJOR_X(net), NETDATA_DIR(net)) != dir) + continue; + + if (net->segments.length > 1) { + rtrnd_netseg_t *ns; + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + int nsidx = NSDATA_IDX(ns); + if (h.match[nsidx] != -1) { + int i; + escape_seg_t *eseg = NSDATA_ESEG(ns); + void **rl_ = vtp0_get(&hvctx->escape[dir].ralines, h.match[nsidx] - hvctx->escape[dir].num_ns, 0); + rtrnd_raline_t *rl = NULL; + assert(rl_ != NULL); + rl = *rl_; + assert(h.match[nsidx] == rl->rt_data.l[dir]); + + assert(NSDATA_IDX(ns) == nsidx); + for(i = 0; i < eseg->len; i++) { + if (rl == eseg->poss[i].rl) { + eseg->chosen = i; + if (adjust_dirpol != 0) + escape_adjust_avail(ctx, hvctx, is_major_x, adjust_dirpol, rl->major, eseg->poss[i].bus_minor, eseg->poss[i].mid_minor); + break; + } + } + printf(" %d:%ld on major=%f chosen=%p/%d\n", nsidx, h.match[nsidx] - hvctx->escape[dir].num_ns, rl->major, eseg, eseg->chosen); + assert(eseg->chosen != -1); + } + else { + printf(" ERROR: no escape grid match for %s\n", ns->hdr.oid); + bad++; + } + } + } + } + + hpkp_uninit(&h); + return bad; +} + +long escape(rtrnd_t *ctx, horver_t *hvctx) +{ + long bad; + + escape_init(ctx, hvctx); + + bad = escape_calc(ctx, hvctx, 0, +1, -1); + bad += escape_calc(ctx, hvctx, 0, -1, 0); + bad += escape_calc(ctx, hvctx, 1, +1, -1); + bad += escape_calc(ctx, hvctx, 1, -1, 0); + + return bad; +} + Index: tags/0.9.0/src/plugins/rt_horver/escape.h =================================================================== --- tags/0.9.0/src/plugins/rt_horver/escape.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/escape.h (revision 1402) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: escape wires for simple grid based horizontal/vertical routing + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef RT_HORVER_ESCAPE_H +#define RT_HORVER_ESCAPE_H + +#define RT_HORVER_ONLY_TYPEDEF 1 +#include "rt_horver.h" +#undef RT_HORVER_ONLY_TYPEDEF + +typedef int escape_dir_t; +#define ESCAPE_DIR(is_major_x, dir) (((!!(is_major_x)) << 1) | (dir > 0)) + + +typedef struct { /* possible escape in a given direction */ + rtrnd_raline_t *rl; + double bus_minor, mid_minor, obj_minor, obj_major; + unsigned avail:1; /* whether to use this line as escape */ +} escape_poss_t; + +typedef struct { + int ex, ey; /* escape direction */ + + /* possible escapes */ + int chosen; /* index of the escape currently used */ + int len; /* length of poss (number of possible escapes) */ + escape_poss_t *poss; /*possible escapes */ + + int coll_cnt; /* collision counter: how many times we had to sacrifice another escape_seg_t to get this one escaped */ +} escape_seg_t; + +typedef struct { /* all escape states in a specific one direction: */ + vtp0_t ralines; /* a raline-id-ordered list of all grid lines used in a direction for the graph pairing */ + long next_raline_id; /* for escape_grid's id allocation */ + long num_ns; /* how many net segments we have on each direction */ +} escape_t; + +long escape(rtrnd_t *ctx, horver_t *hvctx); +void escape_draw(rtrnd_t *ctx, horver_t *hvctx, int is_major_x, int dirpol, rtrnd_netseg_t *ns, rtrnd_raline_t *rl); +void escape_uninit(rtrnd_t *ctx, horver_t *hvctx); + + +#endif Index: tags/0.9.0/src/plugins/rt_horver/hpkp.c =================================================================== --- tags/0.9.0/src/plugins/rt_horver/hpkp.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/hpkp.c (revision 1402) @@ -0,0 +1,115 @@ +#include +#include +#include +#include "hpkp.h" + +#define INVALID ((1L<<31)-2) +#define END -1 + +void hpkp_init(hpkp_t *ctx, int nodes, int max_edges) +{ + assert(nodes > 0); + assert(max_edges > 0); + + ctx->num_nodes = nodes; + ctx->num_edges = 0; + ctx->max_edges = max_edges; + + nodes++; + ctx->estart = malloc(sizeof(int) * nodes); + ctx->match = calloc(sizeof(int), nodes); + ctx->cost = malloc(sizeof(int) * nodes); + ctx->bp = malloc(sizeof(int) * nodes); + ctx->enext = malloc(sizeof(int) * ctx->max_edges); + ctx->edge_v = malloc(sizeof(int) * ctx->max_edges); + memset(ctx->estart, END, sizeof(int) * nodes); +} + +void hpkp_uninit(hpkp_t *ctx) +{ + free(ctx->estart); + free(ctx->match); + free(ctx->cost); + free(ctx->bp); + free(ctx->enext); + free(ctx->edge_v); +} + +/* Adding edge between u and v */ +void hpkp_add_edge(hpkp_t *ctx, int u, int v) +{ + assert(u < ctx->num_nodes); + assert(v < ctx->num_nodes); + u++;v++; /* internal indexing is 1-based, API is 0-based */ + ctx->enext[ctx->num_edges] = ctx->estart[u]; + ctx->estart[u] = ctx->num_edges; + ctx->edge_v[ctx->num_edges] = v; + ctx->num_edges++; +} + +static int hpkp_bfs(hpkp_t *ctx) +{ + int u, v, n, qh = 0, qt = 0; + for(n = 1; n <= ctx->num_nodes; n++) { + if (!ctx->match[n]) { + ctx->cost[n] = 0; + ctx->bp[qt] = n; + qt++; + } + else + ctx->cost[n] = INVALID; + } + ctx->cost[0] = INVALID; + while(qh < qt) { + u = ctx->bp[qh]; + qh++; + if (u != 0) { + for(n = ctx->estart[u]; n != END; n = ctx->enext[n]) { + v = ctx->edge_v[n]; + if (ctx->cost[ctx->match[v]] == INVALID) { + ctx->cost[ctx->match[v]] = ctx->cost[u] + 1; + ctx->bp[qt] = ctx->match[v]; + qt++; + } + } + } + } + return ctx->cost[0] != INVALID; +} + +static int hpkp_dfs(hpkp_t *ctx, int u) +{ + int v, n; + + if (u != 0) { + for(n = ctx->estart[u]; n != END; n = ctx->enext[n]) { + v = ctx->edge_v[n]; + if (ctx->cost[ctx->match[v]] == ctx->cost[u] + 1) { + if (hpkp_dfs(ctx, ctx->match[v])) { + ctx->match[v] = u; + ctx->match[u] = v; + assert(u <= ctx->num_nodes); + assert(v <= ctx->num_nodes); + return 1; + } + } + } + ctx->cost[u] = INVALID; + return 0; + } + return 1; +} + +int hpkp_solve(hpkp_t *ctx) +{ + int n, matching = 0; + while(hpkp_bfs(ctx)) + for(n = 1; n <= ctx->num_nodes; n++) + if (!ctx->match[n] && hpkp_dfs(ctx, n)) + matching++; + + /* internal indexing is 1-based, API is 0-based */ + for(n = 1; n <= ctx->num_nodes; n++) + ctx->match[n-1] = ctx->match[n]-1; + return matching; +} Index: tags/0.9.0/src/plugins/rt_horver/hpkp.h =================================================================== --- tags/0.9.0/src/plugins/rt_horver/hpkp.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/hpkp.h (revision 1402) @@ -0,0 +1,25 @@ +/* Calculate matching in a bipartite graph. Input: + - nodes are numbered from 0 to num_nodes + - nodes are implicitly grouped in sets u and v + (every edge connects one u and one v node) + - (typically u nodes are listed first then v nodes) + - hpkp_solve() returns the number of pairs... + - ... and loads ctx->match[] so that for every u it gives the corresponding v + - the Hopcroft-Karp algorithm is used for solving the problem +*/ + +typedef struct { + int num_nodes, num_edges, max_edges; + int *estart, *enext, *edge_v, *match, *cost, *bp; +} hpkp_t; + +/* num_nodes is num_u + num_v; max_edge is an upper estimation of how many + times hpkp_add_edge() is going to be called */ +void hpkp_init(hpkp_t *ctx, int num_nodes, int max_edges); + +/* free all memory within ctx (doesn't free ctx itself) */ +void hpkp_uninit(hpkp_t *ctx); + +void hpkp_add_edge(hpkp_t *ctx, int u, int v); + +int hpkp_solve(hpkp_t *ctx); Index: tags/0.9.0/src/plugins/rt_horver/optimize.c =================================================================== --- tags/0.9.0/src/plugins/rt_horver/optimize.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/optimize.c (revision 1402) @@ -0,0 +1,347 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: escape wires for simple grid based horizontal/vertical routing + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include "rt_horver.h" +#include "optimize.h" +#include "netseg.h" + +static int debug = 0; + +typedef struct { /* possible escape in a given direction */ + rtrnd_raline_t *rl; /* original, for major */ + rtrnd_raline_t availm; /* local, containing arm range; inverted: blocked ranges are the ones where arms reach out; based on mid points */ + rtrnd_raline_t availo; /* local, containing arm range; inverted: blocked ranges are the ones where arms reach out; based on obj points */ + double obj_major; +} arm_t; + +static int opt1_map_cb(void *cbctx, rtrnd_raline_t *rl, int is_major_x, int dirpol, double mid_minor, double bus_minor, double obj_major, double obj_minor, int dry) +{ + htpp_t *rlhash = cbctx; + arm_t *arm; + long avidx, cnt = 0; + + if (!htpp_has(rlhash, rl)) { + arm = calloc(sizeof(arm_t), 1); + arm->availo.major = rl->major; + arm->availm.major = rl->major; + arm->rl = rl; + arm->obj_major = obj_major; + htpp_set(rlhash, rl, arm); + vtd0_append(&arm->availo.minor, dirpol < 0 ? -10000 : obj_minor); + vtd0_append(&arm->availo.minor, dirpol > 0 ? +10000 : obj_minor); + vtd0_append(&arm->availm.minor, dirpol < 0 ? -10000 : obj_minor); + vtd0_append(&arm->availm.minor, dirpol > 0 ? +10000 : obj_minor); + } + arm = htpp_get(rlhash, rl); + + + avidx = rtrnd_raline_pt_range(rl, mid_minor); + if (avidx >= 0) { + double fromm, tom, fromo, too; +printf(" MAP: %f %d : mid=%f in %f;%f\n", rl->major, dirpol, mid_minor, rl->minor.array[avidx], rl->minor.array[avidx+1]); + if (dirpol < 0) { + fromm = rl->minor.array[avidx]; + tom = mid_minor; + fromo = rl->minor.array[avidx]; + too = obj_minor; + } + else { + fromm = mid_minor; + tom = rl->minor.array[avidx+1]; + fromo = obj_minor; + too = rl->minor.array[avidx+1]; + } + + rtrnd_raline_block(&arm->availm, fromm, tom); + rtrnd_raline_block(&arm->availo, fromo, too); + + /* another object might be crossing this rl, which is then a better option (no dogleg needed) */ + if (arm->rl->major == obj_major) + arm->obj_major = obj_major; + + cnt++; + if (debug) + printf(" map: %f + for %f..%f (idx=%ld)\n", rl->major, fromm, tom, avidx); + } + else if (debug) + printf(" map: %f failed for %f..%f\n", rl->major, bus_minor, mid_minor); + + + return cnt; +} + +static void free_arms(htpp_t *rlhash) +{ + genht_uninit_deep(htpp, rlhash, { + arm_t *arm = htent->value; + if (arm != NULL) { + vtd0_uninit(&arm->availm.minor); + vtd0_uninit(&arm->availo.minor); + free(arm); + } + }); + + free(rlhash); +} + +typedef struct { + rtrnd_raline_t *rl[2]; + double major[2]; + double minor[3]; + double score; +} match_t; + +static void dump_ra(rtrnd_raline_t *ra) +{ + long n; + for(n = 0; n < ra->minor.used; n+=2) + printf(" [%f %f]", ra->minor.array[n], ra->minor.array[n+1]); + printf("\n"); +} + +static void find_overlap(rtrnd_ragrid_t *grid, arm_t *arm1, arm_t *arm2, match_t *best) +{ + long n, m, o, penalty; + match_t ma; + + printf(" find_overlap:\n"); + printf(" arm1 %f:", arm1->rl->major); dump_ra(&arm1->availo); + printf(" arm2 %f:", arm2->rl->major); dump_ra(&arm2->availo); + + for(n = 1; n < arm1->availm.minor.used-2; n+=2) { + m = rtrnd_raline_pt_neg_range(&arm2->availm, arm1->availm.minor.array[n]); + o = rtrnd_raline_pt_neg_range(&arm2->availo, arm1->availo.minor.array[n]); + if (m >= 0) { + printf(" match: %ld %ld at %f!\n", n, m, arm1->availm.minor.array[n]); + ma.rl[0] = arm2->rl; + ma.rl[1] = arm1->rl; + ma.major[0] = arm2->obj_major; + ma.major[1] = arm1->obj_major; + ma.minor[0] = arm2->availm.minor.array[m]; + ma.minor[2] = arm1->availm.minor.array[n+1]; + + /* mid-point */ + ma.minor[1] = (arm2->availm.minor.array[m] + arm1->availm.minor.array[n+1])/2; + + /* make sure the above path is still available - other opt1 paths may have blocked it */ + if (!rtrnd_raline_range_avail(ma.rl[0], ma.minor[0], ma.minor[1])) continue; + if (!rtrnd_raline_range_avail(ma.rl[1], ma.minor[1], ma.minor[2])) continue; + + /* adjust end to reach the object */ + { + long n2; + ma.minor[0] = arm2->availo.minor.array[o]; + + /* nothing guarantees 'n' found for avaim means the same for availo; search the same range in availo here, assuming it's wider */ + n2 = rtrnd_raline_pt_neg_range(&arm1->availo, arm1->availm.minor.array[n+1]); + ma.minor[2] = arm1->availo.minor.array[n2+1]; + } + + penalty = rtrnd_raline_dist(grid, arm1->rl, arm2->rl); + if (penalty < 0) + penalty = -penalty; + ma.score = fabs(ma.minor[2] - ma.minor[0]) + penalty; + if (ma.score < best->score) { + *best = ma; + printf(" better match! score=%f\n", ma.score); + } + else { + printf(" worst match! score=%f\n", ma.score); + } + } + } +} + + +static void find_best_match(rtrnd_t *ctx, horver_t *hvctx, int is_major_x, rtrnd_netseg_t *ns1, rtrnd_netseg_t *ns2) +{ + rtrnd_ragrid_t *grid = &hvctx->grid[is_major_x]; + htpp_entry_t *e; + htpp_t *left = NSDATA_O1LEFT(ns1), *right = NSDATA_O1RIGHT(ns2); + match_t best; + + if ((NSDATA_O1MERGE(ns1) == ns2) || (NSDATA_O1MERGE(ns2) == ns1)) + return; + + best.score = HUGE_VAL; + + printf(" bestmatch %s vs. %s:\n", ns1->hdr.oid, ns2->hdr.oid); + + for(e = htpp_first(left); e != NULL; e = htpp_next(left, e)) { + arm_t *arm1 = e->value, *arm2, *arm2m = NULL, *arm2p = NULL; + rtrnd_raline_t *r; + +#warning TODO: consider +-1 majors on arm2 +/* printf(" major %f:\n", arm1->rl->major);*/ + + /* from arm1 to the same major on arm2 */ + arm2 = htpp_get(right, arm1->rl); + + /* figure previous and next arm2 possibilities (step one up or down in major direction) */ + r = rtrnd_raline_step(grid, arm1->rl, -1); + if (r != NULL) + arm2m = htpp_get(right, r); + r = rtrnd_raline_step(grid, arm1->rl, +1); + if (r != NULL) + arm2p = htpp_get(right, r); + +#warning TODO: straight connection is disabled for now for debugging + if (arm2 != NULL) + find_overlap(grid, arm1, arm2, &best); + if (arm2m != NULL) + find_overlap(grid, arm1, arm2m, &best); + if (arm2p != NULL) + find_overlap(grid, arm1, arm2p, &best); + + } + + if (best.score < HUGE_VAL) { + NSDATA_O1MERGE(ns2) = ns1; + printf(" best: %f: %f;%f %f;%f %f;%f %f;%f\n", best.score, + best.minor[0], best.rl[0]->major, + best.minor[1], best.rl[0]->major, + best.minor[1], best.rl[1]->major, + best.minor[2], best.rl[1]->major + ); + + if (is_major_x) { + /* dogleg */ + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.major[0], best.minor[0], best.rl[0]->major, best.minor[0], wire_thick, wire_clr, 0.1, 0); + + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.rl[0]->major, best.minor[0], best.rl[0]->major, best.minor[1], wire_thick, wire_clr, 0.1, 0); + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.rl[0]->major, best.minor[1], best.rl[1]->major, best.minor[1], wire_thick, wire_clr, 0.1, 0); + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.rl[1]->major, best.minor[1], best.rl[1]->major, best.minor[2], wire_thick, wire_clr, 0.1, 0); + + /* dogleg */ + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.rl[1]->major, best.minor[1], best.major[1], best.minor[2], wire_thick, wire_clr, 0.1, 0); + + rtrnd_raline_block(best.rl[0], best.minor[0], best.minor[1]); + rtrnd_raline_block(best.rl[1], best.minor[1], best.minor[2]); + } + else { + /* dogleg */ + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.minor[0], best.rl[0]->major, best.minor[0], best.major[0], wire_thick, wire_clr, 0.1, 0); + + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.minor[0], best.rl[0]->major, best.minor[1], best.rl[0]->major, wire_thick, wire_clr, 0.1, 0); + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.minor[1], best.rl[0]->major, best.minor[1], best.rl[1]->major, wire_thick, wire_clr, 0.1, 0); + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.minor[1], best.rl[1]->major, best.minor[2], best.rl[1]->major, wire_thick, wire_clr, 0.1, 0); + + /* dogleg */ + rtrnd_draw_res_line(ctx, hvctx->ly_copper[is_major_x], hvctx->ly_escape[is_major_x], ns1->net, + best.minor[2], best.rl[1]->major, best.minor[2], best.major[1], wire_thick, wire_clr, 0.1, 0); + + rtrnd_raline_block(best.rl[0], best.minor[0], best.minor[1]); + rtrnd_raline_block(best.rl[1], best.minor[1], best.minor[2]); + } + } +} + +long opt1_noescape_dir(rtrnd_t *ctx, horver_t *hvctx, int is_major_x) +{ + rtrnd_ragrid_t *grid = &hvctx->grid[is_major_x]; + htsp_entry_t *e; + long cnt = 0; + + printf("optimize step 1 in dir is_major_x=%d\n", is_major_x); + /* build the has for arms facing left (dirpol=-1) */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rtrnd_netseg_t *ns; + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + rtrnd_any_obj_t *o; + htpp_t *left, *right; + + NSDATA_O1LEFT(ns) = left = htpp_alloc(ptrhash, ptrkeyeq); + NSDATA_O1RIGHT(ns) = right = htpp_alloc(ptrhash, ptrkeyeq); + + for(o = gdl_first(&ns->objs); o != NULL; o = gdl_next(&ns->objs, o)) { + horver_map_obj(opt1_map_cb, left, grid, o, is_major_x, -1, 0); + horver_map_obj(opt1_map_cb, right, grid, o, is_major_x, +1, 0); + } + } + } + + /* do a search on arms facing right (dirpol=+1) to see if any of them meet + any of the hashed left facing arms */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rtrnd_netseg_t *ns1, *ns2; + for(ns1 = gdl_first(&net->segments); ns1 != NULL; ns1 = gdl_next(&net->segments, ns1)) { + for(ns2 = gdl_first(&net->segments); ns2 != NULL; ns2 = gdl_next(&net->segments, ns2)) { + if (ns1 == ns2) + continue; + find_best_match(ctx, hvctx, is_major_x, ns1, ns2); + } + } + } + + + /* free hashes */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rtrnd_netseg_t *ns, *target; + + /* free arms data */ + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + free_arms(NSDATA_O1LEFT(ns)); + free_arms(NSDATA_O1RIGHT(ns)); + NSDATA_O1LEFT(ns) = NSDATA_O1RIGHT(ns) = NULL; + } + + /* merge net segs that got connected */ + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + target = NSDATA_O1MERGE(ns); + if (target != NULL) { + printf("Merge req: %s with %s\n", ns->hdr.oid, target->hdr.oid); + rtrnd_netseg_merge(target, ns); + } + NSDATA_O1MERGE(ns) = NULL; + } + } + + return cnt; +} + + +long opt1_noescape(rtrnd_t *ctx, horver_t *hvctx) +{ + return opt1_noescape_dir(ctx, hvctx, 0) + opt1_noescape_dir(ctx, hvctx, 1); +} + Index: tags/0.9.0/src/plugins/rt_horver/optimize.h =================================================================== --- tags/0.9.0/src/plugins/rt_horver/optimize.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/optimize.h (revision 1402) @@ -0,0 +1,7 @@ +typedef struct { /* possible escape in a given direction */ + rtrnd_raline_t *rl; + rtrnd_raline_t arms; /* the range is available where any object of the netseg can reach */ +} o1_poss_t; + +long opt1_noescape(rtrnd_t *ctx, horver_t *hvctx); + Index: tags/0.9.0/src/plugins/rt_horver/rt_horver.c =================================================================== --- tags/0.9.0/src/plugins/rt_horver/rt_horver.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/rt_horver.c (revision 1402) @@ -0,0 +1,426 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: simple grid based horizontal/vertical routing for 2 layer boards + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include +#include "data.h" +#include "util_grid.h" +#include "rt_horver.h" +#include "escape.h" +#include "optimize.h" +#include "bus.h" +#include "route_res.h" +#include "conf.h" + + +#define ERROR "route-rnd rt-horver error: " + +/* settings */ +double wire_thick, wire_clr, via_dia, via_clr; +int disable_dir[4]; +static g2d_box_t brdbox; + +static rtrnd_conf_t horver_cfg_desc[] = { + RTRND_CONF_COORD("wire_thick", 0.25, 0.01, 10, "signal wire thickness", &wire_thick) + RTRND_CONF_COORD("wire_clr", 0.25, 0.01, 10, "clearance around signal wire", &wire_clr) + RTRND_CONF_COORD("via_dia", 1.6, 0.01, 10, "via copper ring outer diameter", &via_dia) + RTRND_CONF_COORD("via_clr", 0.25, 0.01, 10, "clearance around via copper", &via_clr) + RTRND_CONF_BOOLEAN("disable_left", 0, "do not use the left side for buses", &disable_dir[0]) + RTRND_CONF_BOOLEAN("disable_right", 0, "do not use the right side for buses", &disable_dir[1]) + RTRND_CONF_BOOLEAN("disable_top", 0, "do not use the top side for buses", &disable_dir[2]) + RTRND_CONF_BOOLEAN("disable_bottom", 0, "do not use the bottom side for buses", &disable_dir[3]) + RTRND_CONF_TERMINATE +}; + +/* states */ +horver_t hvctx_ = {0}, *hvctx = &hvctx_; + +double wirebox_minor_end(int is_major_x, int dirpol) +{ + if (is_major_x) { + assert(dirpol != 0); + if (dirpol > 0) + return hvctx->wirebox.p2.y; + return hvctx->wirebox.p1.y; + } + if (dirpol > 0) + return hvctx->wirebox.p2.x; + return hvctx->wirebox.p1.x; +} + +/* figure best wire grid so wires can pass between pins, but don't let vias overlap */ +static double adjust_grid_to_wire(double term_spacing, double via_spacing_max) +{ + double gap, num_wires, wspc; + + if (term_spacing < 0.01) + return wire_thick+wire_clr; + + if (via_clr > wire_clr) + gap = term_spacing - via_dia - via_clr*2; + else + gap = term_spacing - via_dia - wire_clr*2; + + num_wires = (gap + wire_clr) / (wire_thick + wire_clr) + 1; + if (num_wires < 1) { + rtrnd_error("horver wire grid: can't pass a wire between two terminals; make sure your terminals are aligned to a grid!"); + return wire_thick + wire_clr; + } + + wspc = term_spacing / floor(num_wires); +/*printf("GAP: %f %f nw=%f -> %f\n", term_spacing, gap, num_wires, wspc);*/ + + if (wspc < via_spacing_max) { /* but don't let wire-via get too close because they need to pass at buses */ + num_wires = floor(term_spacing / via_spacing_max); + if (num_wires < 1) + num_wires = 1; + wspc = term_spacing / num_wires; + } + return wspc; +} + +static void create_bus_(rtrnd_t *ctx, horver_t *hvctx, int grididx, int is_major_x, int dirpol, double spacing, int len) +{ + escape_dir_t dir = ESCAPE_DIR(is_major_x, dirpol); + double first; + long ridx; + rtrnd_raline_t *rl; + + if (dirpol < 0) + ridx = 0; + else + ridx = hvctx->grid[grididx].len - 1; + + rl = &hvctx->grid[grididx].raline[ridx]; + if (dirpol < 0) + first = rl->major - spacing; + else + first = rl->major + spacing; + + bus_init(&hvctx->bus[dir], dirpol, first, spacing, len, rl->minor.array[0] - spacing, rl->minor.array[1] + spacing); + bus_draw_grid(&hvctx->bus[dir], hvctx->ly_busgrid, !is_major_x); +} + +static void do_bus(rtrnd_t *ctx, horver_t *hvctx, rtrnd_layer_t *ly) +{ + htsp_entry_t *e; + + printf("do_bus:\n"); + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + escape_dir_t dir = ESCAPE_DIR(NETDATA_IS_MAJOR_X(net), NETDATA_DIR(net)); + rtrnd_netseg_t *ns; + rtrnd_raline_t *busline; + double ma_from, ma_to, ma, tune_via; + int esced = 0; + + if (net->segments.length < 2) continue; + + /* calculate bus line span */ + printf(" net=%s\n", net->hdr.oid); + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + escape_seg_t *eseg = NSDATA_ESEG(ns); + if (eseg->chosen == -1) continue; /* did not find an escape */ + ma = eseg->poss[eseg->chosen].rl->major; +printf(" seg: %s %f\n", ns->hdr.oid, ma); + if (esced) { + if (ma < ma_from) ma_from = ma; + if (ma > ma_to) ma_to = ma; + } + else + ma_from = ma_to = ma; + esced++; + } + if (esced < 2) continue; /* 0 or 1 segment escaped, no point in a bus */ + tune_via = via_dia/2 + via_clr; + busline = bus_reserve(&hvctx->bus[dir], ma_from - tune_via, ma_to + tune_via); + printf(" span=%f..%f on %f net is_major_x=%d net dir=%d\n", ma_from, ma_to, busline->major, (int)NETDATA_IS_MAJOR_X(net), (int)NETDATA_DIR(net)); + + /* place the bus line */ + if (!NETDATA_IS_MAJOR_X(net)) + rtrnd_draw_res_line(ctx, hvctx->ly_copper[!NETDATA_IS_MAJOR_X(net)], ly, net, busline->major, ma_from, busline->major, ma_to, wire_thick, wire_clr, 0.2, 0); + else + rtrnd_draw_res_line(ctx, hvctx->ly_copper[!NETDATA_IS_MAJOR_X(net)], ly, net, ma_from, busline->major, ma_to, busline->major, wire_thick, wire_clr, 0.2, 0); + + /* adjust escape lines */ + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_next(&net->segments, ns)) { + double vx, vy; + escape_seg_t *eseg = NSDATA_ESEG(ns); + if (eseg->chosen == -1) continue; /* did not find an escape */ + eseg->poss[eseg->chosen].bus_minor = busline->major; + escape_draw(ctx, hvctx, NETDATA_IS_MAJOR_X(net), NETDATA_DIR(net), ns, eseg->poss[eseg->chosen].rl); + + /* place the vias */ + if (NETDATA_IS_MAJOR_X(net)) { + vy = eseg->poss[eseg->chosen].bus_minor; + vx = eseg->poss[eseg->chosen].rl->major; + } + else { + vx = eseg->poss[eseg->chosen].bus_minor; + vy = eseg->poss[eseg->chosen].rl->major; + } + + rtrnd_draw_res_via(ctx, hvctx->ly_copper[!NETDATA_IS_MAJOR_X(net)], net, vx, vy, via_dia, via_clr, 0.5, 0); + } + + } +} + +static void create_bus(rtrnd_t *ctx, horver_t *hvctx) +{ + double spacing = (wire_thick + via_dia)/2 + (via_clr > wire_clr ? via_clr : wire_clr); +#warning TODO: number of netsegs/2 oslt + int len = 10; + create_bus_(ctx, hvctx, 1, 0, -1, spacing, len); + create_bus_(ctx, hvctx, 1, 0, +1, spacing, len); + create_bus_(ctx, hvctx, 0, 1, -1, spacing, len); + create_bus_(ctx, hvctx, 0, 1, +1, spacing, len); +} + +static void destroy_bus(rtrnd_t *ctx, horver_t *hvctx) +{ + int n; + for(n = 0; n < 4; n++) + bus_uninit(&hvctx->bus[n]); +} + +static int shuffle_collision(rtrnd_t *ctx, horver_t *hvctx) +{ + htsp_entry_t *e; + long todo = 0; + unsigned disable_bits = 0; + int n; + + for(n = 0; n < 4; n++) + if (disable_dir[n]) + disable_bits |= 1 << n; + + printf("Shuffle:\n"); + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + + if ((net->segments.length < 2) || (!NETDATA_FAILED(net))) + continue; /* deal with routable, filed nets */ + + if ((NETDATA_FAILDIRS(net) | disable_bits) != 0x0F) { + NETDATA_FAILED_CLR(net); + todo++; + printf(" shuffling %s: %x %x\n", net->hdr.oid, (unsigned)NETDATA_FAILDIRS(net), disable_bits); + } + } + + if (todo == 0) { + printf("shuffled all nets in all possible ways - there's no chance for any progress\n"); + return -1; + } + + escape_uninit(ctx, hvctx); + return 0; +} + +static rtrnd_layer_t *find_layer(rtrnd_t *ctx, rtrnd_layer_loc_t loc) +{ + int n; + for(n = 0; n < ctx->board->layers.used; n++) { + rtrnd_layer_t *ly = ctx->board->layers.array[n]; + if (ly->loc == loc) + return ly; + } + return NULL; +} + +/* return the relevant box edge closer to the target bus in 1d, depending on + direction polarity */ +static double box_edge_by_pol(double small, double big, int dirpol) +{ + return (dirpol < 0) ? small : big; +} + +long horver_map_obj(horver_map_cb_t cb, void *cbctx, rtrnd_ragrid_t *grid, rtrnd_any_obj_t *o, int is_major_x, int dirpol, int dry) +{ + double ma_from, ma_to, mi, mi2; + rtrnd_raline_t *rl, *rlmax; + int first; + long cnt = 0, r; + + /* figure the (ascending) range of majors that spans the bbox of the + object, +1 major on each side */ + ma_from = is_major_x ? o->hdr.bbox.x1 : o->hdr.bbox.y1 ; + ma_to = is_major_x ? o->hdr.bbox.x2 : o->hdr.bbox.y2; + mi = is_major_x ? box_edge_by_pol(o->hdr.bbox.y1, o->hdr.bbox.y2, dirpol) : box_edge_by_pol(o->hdr.bbox.x1, o->hdr.bbox.x2, dirpol); + + rl = rtrnd_grid_find_major_before(grid, ma_from); + if (rl == NULL) + return -1; + + mi2 = wirebox_minor_end(is_major_x, dirpol); + if (!dry) + printf(" obj: ma:%f..%f\n", ma_from, ma_to); + + /* check each major within the range of majors for possible escape in + the specified direction */ + for(rlmax = &grid->raline[grid->len], first = 1; rl < rlmax; rl++, first = 0) { + int within, ma_obj_found; + double o_from, o_to, ma_obj, mi1; + + /* ignore the cutout on the raline if it was made by this specific object */ + within = (rtrnd_raline_obj_mask_size_at(rl, is_major_x, wire_thick, wire_clr, o, &o_from, &o_to) == 0); + if (within) + mi1 = (dirpol < 0) ? o_from : o_to; + else + mi1 = mi; + + /* determine the object-side end of the dog-leg */ + ma_obj_found = 0; + if (first) { /* one grid before the object starts; dogleg steps one up */ + if (rl+1 < rlmax) { + rtrnd_raline_obj_mask_size_at(rl+1, is_major_x, 0, 0, o, &o_from, &o_to); + ma_obj = rl[1].major; + ma_obj_found = 1; + } + } + else if (rl->major >= ma_to) { /* one grid after the object ends; dogleg steps one down */ + if (rl-1 >= grid->raline) { + rtrnd_raline_obj_mask_size_at(rl-1, is_major_x, 0, 0, o, &o_from, &o_to); + ma_obj = rl[-1].major; + ma_obj_found = 1; + } + } + if (!ma_obj_found) { /* dogleg is on a mid point or was unable to step up/down */ + rtrnd_raline_obj_mask_size_at(rl, is_major_x, 0, 0, o, &o_from, &o_to); + ma_obj = rl->major; + } + + /* now we have the mid_point, the object anchor point at the end of the + dogleg; store it */ +/* printf(" at ma=%f: obj_ma=%f obj_mi=%f mi1=%f mi2=%f\n", rl->major, ma_obj, (o_from+o_to)/2, mi1, mi2);*/ + r = cb(cbctx, rl, is_major_x, dirpol, mi1, mi2, ma_obj, (o_from+o_to)/2, dry); + if (r > 0) cnt += r; + if (!first && !within) break; /* this was a line effectively beyond the object's major */ + if (rl->major > ma_to) break; + } + + return cnt; +} + + +static int route_horver(rtrnd_t *ctx) +{ + double x_orig, x_spacing, y_orig, y_spacing, via_spacing; + long bad; + + if (rtrnd_grid_detect_terms(ctx->board, &x_orig, &x_spacing, &y_orig, &y_spacing) != 0) { + fprintf(stderr, ERROR "failed to determine terminal grid\n"); + return -1; + } + +/* printf("terminal grid 1: %f:%f %f:%f\n", x_spacing, x_orig, y_spacing, y_orig);*/ + + via_spacing = via_dia/2 + wire_thick/2 + (via_clr > wire_clr ? via_clr : wire_clr); + x_spacing = adjust_grid_to_wire(x_spacing, via_spacing); + y_spacing = adjust_grid_to_wire(y_spacing, via_spacing); + +/* printf("terminal grid 2: %f:%f %f:%f\n", x_spacing, x_orig, y_spacing, y_orig);*/ + + hvctx->ly_wiregrid = rtrnd_annot_new(ctx, "wiregrid"); + strcpy(hvctx->ly_wiregrid->color, "#333333"); + hvctx->ly_busgrid = rtrnd_annot_new(ctx, "busgrid"); + strcpy(hvctx->ly_busgrid->color, "#111199"); + hvctx->ly_escape[0] = rtrnd_annot_new(ctx, "escape"); + strcpy(hvctx->ly_escape[0]->color, "#AAAA00"); + hvctx->ly_escape[1] = rtrnd_annot_new(ctx, "escape"); + strcpy(hvctx->ly_escape[1]->color, "#AA00AA"); + + rtrnd_board_bbox(&brdbox, ctx->board); + hvctx->wirebox = brdbox; + + /* origin will shift it at most 1 grid up, make sure there are enough grids on the top */ + hvctx->wirebox.p1.x -= x_spacing; + hvctx->wirebox.p1.y -= x_spacing; + hvctx->wirebox.p2.x += x_spacing; + hvctx->wirebox.p2.y += y_spacing; + + rtrnd_ragrid_init(&hvctx->grid[0], hvctx->wirebox.p1.y, hvctx->wirebox.p2.y, y_orig, y_spacing, hvctx->wirebox.p1.x, hvctx->wirebox.p2.x); + rtrnd_grid_mask_objs(&hvctx->grid[0], 0, ctx->board, ctx->board->layers.array[0], wire_thick, wire_clr); + rtrnd_ragrid_draw(&hvctx->grid[0], hvctx->ly_wiregrid, 0); + hvctx->ly_copper[0] = find_layer(ctx, RTRND_LLOC_TOP); + if (hvctx->ly_copper[0] == NULL) { + fprintf(stderr, ERROR "No top copper layer available, can not route\n"); + return -1; + } + + + rtrnd_ragrid_init(&hvctx->grid[1], hvctx->wirebox.p1.x, hvctx->wirebox.p2.x, x_orig, x_spacing, hvctx->wirebox.p1.y, hvctx->wirebox.p2.y); + rtrnd_grid_mask_objs(&hvctx->grid[1], 1, ctx->board, ctx->board->layers.array[1], wire_thick, wire_clr); + rtrnd_ragrid_draw(&hvctx->grid[1], hvctx->ly_wiregrid, 1); + hvctx->ly_copper[1] = find_layer(ctx, RTRND_LLOC_BOTTOM); + if (hvctx->ly_copper[1] == NULL) { + fprintf(stderr, ERROR "No bottom copper layer available, can not route\n"); + return -1; + } + + + create_bus(ctx, hvctx); + + opt1_noescape(ctx, hvctx); + + + for(;;) { + bad = escape(ctx, hvctx); + if (bad == 0) + break; + + printf("*** Net segs failed to escape: %ld\n", bad); + if (shuffle_collision(ctx, hvctx) != 0) { + printf("*** Failed to shuffle collisions, unrouted net segs remain\n"); + break; + } + } + + do_bus(ctx, hvctx, hvctx->ly_busgrid); + escape_uninit(ctx, hvctx); + destroy_bus(ctx, hvctx); + + rtrnd_ragrid_uninit(&hvctx->grid[0]); + rtrnd_ragrid_uninit(&hvctx->grid[1]); + return 0; +} + +static const rtrnd_router_t rt_horver = { + "horver", "2 layer, grid based, horizontal/vertical escape to orthogonal buses on the sides", + horver_cfg_desc, + route_horver +}; + +void rt_horver_init(void) +{ + vtp0_append(&rtrnd_all_router, (void *)&rt_horver); +} Index: tags/0.9.0/src/plugins/rt_horver/rt_horver.h =================================================================== --- tags/0.9.0/src/plugins/rt_horver/rt_horver.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_horver/rt_horver.h (revision 1402) @@ -0,0 +1,53 @@ +#ifndef RT_HORVER_H +#define RT_HORVER_H + +typedef struct horver_s horver_t; + +#include "data.h" +#include "util_grid.h" +#include "escape.h" +#include "bus.h" + +extern horver_t *hvctx; /* temporary */ +extern double wire_thick, wire_clr, via_dia, via_clr; /* temporary */ +extern int disable_dir[4]; + +#define NETDATA_IS_MAJOR_X(net) ((net)->hdr.rt_data.l[0]) +#define NETDATA_DIR(net) ((net)->hdr.rt_data.l[1]) + +#define NETDATA_FAILDIR(net, dir) ((net)->hdr.rt_data.l[2] & (1 << dir)) +#define NETDATA_FAILDIR_SET(net, dir) ((net)->hdr.rt_data.l[2] |= (1 << dir)) +#define NETDATA_FAILDIRS(net) ((net)->hdr.rt_data.l[2] & 0xF) +#define NETDATA_FAILED(net) ((net)->hdr.rt_data.l[2] & 0x80000) +#define NETDATA_FAILED_SET(net) ((net)->hdr.rt_data.l[2] |= 0x80000) +#define NETDATA_FAILED_CLR(net) ((net)->hdr.rt_data.l[2] &= ~0x80000) + + +#define NSDATA_IDX(ns) ((ns)->hdr.rt_data.l[0]) +#define NSDATA_ESEG(ns) ((ns)->hdr.rt_data.p[1]) +#define NSDATA_O1LEFT(ns) ((ns)->hdr.rt_data.p[1]) +#define NSDATA_O1RIGHT(ns) ((ns)->hdr.rt_data.p[2]) +#define NSDATA_O1MERGE(ns) ((ns)->hdr.rt_data.p[3]) + + + +#ifndef RT_HORVER_ONLY_TYPEDEF + +struct horver_s { + rtrnd_layer_t *ly_wiregrid, *ly_escape[2], *ly_busgrid, *ly_copper[2]; + rtrnd_ragrid_t grid[2]; + g2d_box_t wirebox; + escape_t escape[4]; /* indexed with escape_dir_t */ + bus_t bus[4]; /* indexed with escape_dir_t */ +}; + +double wirebox_minor_end(int is_major_x, int dirpol); + + +/* Append all possible escape lines of an object to eseg. + Return the number of newly added ralines available for escape */ +typedef int (*horver_map_cb_t)(void *cbctx, rtrnd_raline_t *rl, int is_major_x, int dirpol, double mid_minor, double bus_minor, double obj_major, double obj_minor, int dry); +long horver_map_obj(horver_map_cb_t cb, void *cbctx, rtrnd_ragrid_t *grid, rtrnd_any_obj_t *o, int is_major_x, int dirpol, int dry); + +#endif +#endif Index: tags/0.9.0/src/plugins/rt_topo/Makefile.inc =================================================================== --- tags/0.9.0/src/plugins/rt_topo/Makefile.inc (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/Makefile.inc (revision 1402) @@ -0,0 +1,12 @@ +BUILDIN_RT_TOPO = \ + $(PLG)/rt_topo/rt_topo.o \ + $(PLG)/rt_topo/vt2br.o \ + $(PLG)/rt_topo/vtcr.o \ + $(PLG)/rt_topo/vtve0.o \ + $(PLG)/rt_topo/laa.o \ + $(PLG)/rt_topo/trbs.o \ + $(PLG)/rt_topo/crbs.o \ + $(THIRD)/libgrbs/grbs.o \ + $(THIRD)/libgrbs/addr_hash.o \ + $(THIRD)/libgrbs/rtree.o \ + $(THIRD)/libgrbs/debug.o Index: tags/0.9.0/src/plugins/rt_topo/README =================================================================== --- tags/0.9.0/src/plugins/rt_topo/README (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/README (revision 1402) @@ -0,0 +1,25 @@ + +Differences compared to the thesis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. LAA, step II + +Instead of placing 1..5 vias "randomly" on 2nets, an rtree is build of +all 2nets and crossings are mapped, then possible via sites are determined so +that: + - there's a via between any two possible 2net crossings on each 2net + - if a terminal is not a via accessing all layers, there would be a + a possible via site placed between the terminal and the first crossing + (to give the 2net a chance to leave the terminal's initial layer) + - special case: if a 2net has only a single branch between two non-via + terminals, a possible via site is inserted in the middle so that + swithcing layers is possible (typical example: 2 SMD pads on opposite layers) + +2. LAA, step III + +Instead of doing anything clever in the initial branch assignment, every +brnach is assigned to layer 0. This means there is no 'free branch' concept. +The steepest descent algorithm should still find the same solution. Net result: +simpler code. + +TODO: cached crossings and detours. Index: tags/0.9.0/src/plugins/rt_topo/crbs.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/crbs.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/crbs.c (revision 1402) @@ -0,0 +1,261 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2021 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "data.h" +#include "io.h" +#include "route_res.h" + +#include +#include + +#include "crbs.h" + +grbs_2net_t tn_unknown; + +static void crbs_coll_report_cb(grbs_t *grbs, grbs_2net_t *tn, grbs_2net_t *coll_tn, grbs_arc_t *coll_arc) +{ + crbs_t *crbs = grbs->user_data; + crbs_2net_t *coll_ctn = coll_tn->user_data; +/* crbs_2net_t *ctn = tn->user_data;*/ + + if (coll_tn != &tn_unknown) + coll_ctn->coll = 1; +} + + +static int crbs_coll_ingore_tn_line_cb(grbs_t *grbs, grbs_2net_t *tn, grbs_line_t *l) +{ + crbs_2net_t *lctn = l->user_data; + crbs_2net_t *tctn = tn->user_data; + + assert(tctn != NULL); + + if (lctn == NULL) + return 0; + + return lctn->net == tctn->net; +} + +static int crbs_coll_ingore_tn_point_cb(grbs_t *grbs, grbs_2net_t *tn, grbs_point_t *pt) +{ + crbs_point_t *p = pt->user_data; + crbs_2net_t *tctn = tn->user_data; + + assert(tctn != NULL); + + if (p == NULL) + return 0; + + return p->net == tctn->net; +} + + +crbs_point_t *crbs_point_new(crbs_t *crbs) +{ + crbs_point_t *p = calloc(sizeof(crbs_point_t), 1); +#warning TODO: do this allocation using ualloc stacks + return p; +} + +#include +GRBS_ADDR_HASH(htad_hash); + +point_t *crbs_make_point(crbs_t *crbs, double x, double y, double cop, double clr, rtrnd_via_t *via, rtrnd_net_t *net) +{ + grbs_point_t *gpt; + point_t *cpt; + crbs_point_t *p; + + cpt = cdt_insert_point(&crbs->cdt, x, y); + if (cpt->data != NULL) { /* already initialized */ + p = cpt->data; + if (cop > p->gpt->copper) + p->gpt->copper = cop; + if (clr > p->gpt->clearance) + p->gpt->clearance = clr; + return cpt; + } + + p = crbs_point_new(crbs); + cpt->data = p; + gpt = grbs_point_new(&crbs->grbs, x, y, cop, clr); + gpt->user_data = p; + + printf("GT point_new P%ld %f %f %f %f\n", gpt->uid, x, y, cop, clr); + + p->cpt = cpt; + p->gpt = gpt; + p->obj = via; + p->net = net; + + return cpt; +} + +/* Return an existing point with the same net near x;y (max distance + is dist) or create a new point and return that if there was no match near */ +point_t *crbs_make_point_near(crbs_t *crbs, double x, double y, double cop, double clr, rtrnd_via_t *via, rtrnd_net_t *net, double dist) +{ + grbs_rtree_box_t bbox; + grbs_point_t *pt; + grbs_rtree_it_t it; + double dp2 = dist/2, dist2 = dist*dist, dx, dy; + + bbox.x1 = x - dp2; + bbox.y1 = y - dp2; + bbox.x2 = x + dp2; + bbox.y2 = y + dp2; + + for(pt = grbs_rtree_first(&it, &crbs->grbs.point_tree, &bbox); pt != NULL; pt = grbs_rtree_next(&it)) { + crbs_point_t *cpt = pt->user_data; + if (cpt->net != net) continue; + dx = pt->x - x; + dy = pt->y - y; + if ((dx*dx+dy*dy) > dist2) continue; + return cpt->cpt; + } + + /* nothing found near */ + return crbs_make_point(crbs, x, y, cop, clr, via, net); +} + +static void crbs_init(crbs_t *crbs, rtrnd_t *ctx) +{ + + grbs_init(&crbs->grbs); + crbs->ctx = ctx; + crbs->grbs.coll_report_cb = crbs_coll_report_cb; + crbs->grbs.coll_ingore_tn_line= crbs_coll_ingore_tn_line_cb; + crbs->grbs.coll_ingore_tn_point = crbs_coll_ingore_tn_point_cb; + + crbs->grbs.user_data = crbs; + htad_init(&crbs->addrs, htad_hash, grbs_addr_hash_keyeq); + +} + +static void crbs_clean(crbs_t *crbs) +{ +} + +static void crbs_uninit(crbs_t *crbs) +{ +} + + +static long crbs_dist_heur(double x1, double y1, double x2, double y2) +{ + double dx = x2 - x1, dy = y2 - y1, d = dx*dx+dy*dy; + + return d == 0 ? 0 : floor(sqrt(d * DIST_HEUR_MULT)); +} + + + +#include "crbs_cdt.c" +#include "crbs_route.c" + + +int rt_topo_crbs(rtrnd_t *ctx, rt_topo_laa2rbs_t *src) +{ + int n, res = 0; + + /* route each layer */ + for(n = 0; n < ctx->board->layers.used; n++) + res |= rt_topo_crbs_layer(ctx, ctx->board->layers.array[n], src->ly2nets.array[n]); + + return res; +} + + +static int crbs_grbs_draw(crbs_t *crbs, char *fn) +{ + FILE *f = fopen(fn, "w"); + + if (f == NULL) + return -1; + + grbs_draw_begin(&crbs->grbs, f); + fprintf(f, "\n"); + grbs_draw_points(&crbs->grbs, f); + grbs_draw_wires(&crbs->grbs, f); + grbs_draw_end(&crbs->grbs, f); + + fclose(f); + + return 0; +} + +static int crbs_grbs_dump(crbs_t *crbs, char *fn) +{ + FILE *f = fopen(fn, "w"); + + if (f == NULL) + return -1; + + grbs_dump_points(&crbs->grbs, f); + grbs_dump_wires(&crbs->grbs, f); + + fclose(f); + + return 0; +} + +void crbs_draw_routes(crbs_t *crbs, rtrnd_layer_t *ly_out, rtrnd_layer_t *ly_drw) +{ + grbs_line_t *l; + grbs_arc_t *a; + rtrnd_any_obj_t *o; + crbs_2net_t *ctn; + + for(l = gdl_first(&crbs->grbs.all_lines); l != NULL; l = gdl_next(&crbs->grbs.all_lines, l)) { + ctn = l->user_data; + if ((ctn != NULL) && ctn->old) continue; + rtrnd_line_new(ly_drw, NULL, NULL, l->x1, l->y1, l->x2, l->y2, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_line_new(ly_out, NULL, NULL, l->x1, l->y1, l->x2, l->y2, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(crbs->ctx, o); + } + } + + for(a = gdl_first(&crbs->grbs.all_arcs); a != NULL; a = gdl_next(&crbs->grbs.all_arcs, a)) { + if (!a->in_use) continue; + if ((a->r == 0) || (a->da == 0)) continue; + rtrnd_arc_new(ly_drw, NULL, NULL, a->parent_pt->x, a->parent_pt->y, a->r, a->sa, a->da, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_arc_new(ly_out, NULL, NULL, a->parent_pt->x, a->parent_pt->y, a->r, a->sa, a->da, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(crbs->ctx, o); + } + } +} + Index: tags/0.9.0/src/plugins/rt_topo/crbs.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/crbs.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/crbs.h (revision 1402) @@ -0,0 +1,77 @@ +#ifndef RT_TOPO_CRBS_H +#define RT_TOPO_CRBS_H + +#include "data.h" +#include "rt_topo.h" +#include +#include +#include +#include + +#include + + +typedef grbs_addr_key_t htad_key_t; +typedef struct htad_value_s { + unsigned valid:1; + grbs_detached_addr_t *det; + void *mark; +} htad_value_t; +#define HT_INVALID_VALUE (htad_value_t){0} +#define HT(x) htad_ ## x +#include +#undef HT + +typedef struct { + point_t *cstart, *cend; + rt_topo_2net_t *tn; /* for nets we are routing; NULL for fixed objects */ + rtrnd_net_t *net; + grbs_2net_t *gtn; + unsigned int ripped_up; /* how many times this net got ripped up */ + unsigned coll:1; /* collided with current routing effort */ + unsigned old:1; /* virtual 2-net for an old object that already existed on load */ + gdl_elem_t link; +} crbs_2net_t; + +typedef struct crbs_point_s { + rtrnd_any_obj_t *obj; + point_t *cpt; + grbs_point_t *gpt; + rtrnd_net_t *net; +} crbs_point_t; + +typedef struct crbs_edge_s { + long nets; /* nets parallel with this edge */ + double ang[2]; /* outgoing edge angle, indexed by endp[] */ + edge_t *edge; +} crbs_edge_t; + +typedef struct { + rtrnd_t *ctx; + cdt_t cdt; + grbs_t grbs; + gdl_list_t twonets; /* of crbs_2net_t */ + htad_t addrs; + + unsigned disable_concave:1; /* when set to 1, do an all-convex routing */ + unsigned enable_mid_virt:1; /* when set to 1, insert a virtual point in between any two real points in the original cdt; this allows convex-only routing to emulate concave in corridors */ + + /* routing */ + grbs_detached_addr_t *first; /* the address the twonet is starting from */ + grbs_detached_addr_t *target; /* the address we are trying to reach */ + void *first_mark, *target_mark; + grbs_2net_t *routing_tn; + int max_ripup; /* how many times are we willing to rip up a 2net (total within a layer routing) */ +} crbs_t; + +int rt_topo_crbs(rtrnd_t *ctx, rt_topo_laa2rbs_t *src); + +/* When a collision happens but the 2net is not known */ +extern grbs_2net_t tn_unknown; + +/* create a new point (e.g. for a via) in the triangulation and in grbs */ +point_t *crbs_make_point(crbs_t *crbs, double x, double y, double cop, double clr, rtrnd_via_t *via, rtrnd_net_t *net); + +#define DIST_HEUR_MULT 1000.0 + +#endif Index: tags/0.9.0/src/plugins/rt_topo/crbs_cdt.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/crbs_cdt.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/crbs_cdt.c (revision 1402) @@ -0,0 +1,291 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020,2021 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include + +#include "geo.h" +#include "gengeo2d/cline.h" + +#warning TODO: use libualloc for ctn +static int add_c_edge_cnt; +#define ADD_C_EDGE(p1, p2) \ +do { \ + e = cdt_insert_constrained_edge(cdt, p1, p2); \ + e->data = obj; \ + if (add_grbs) { \ + crbs_point_t *cp1 = p1->data, *cp2 = p2->data; \ + grbs_line_t *gl; \ + grbs_2net_t *tn = grbs_2net_new(&crbs->grbs, cop, clr); \ + crbs_2net_t *ctn = calloc(sizeof(crbs_2net_t), 1); \ + tn->user_data = ctn; \ + ctn->tn = NULL; \ + ctn->net = obj->hdr.net; \ + ctn->old = 1; \ + gl = grbs_line_realize(&crbs->grbs, tn, cp1->gpt, cp2->gpt); \ + gl->user_data = ctn; \ + printf("GT 2net_new _c_edge_%d %f %f from P%ld to P%ld\n", add_c_edge_cnt++, cop, clr, cp1->gpt->uid, cp2->gpt->uid); \ + } \ +} while(0) \ + + +static void long_constrained_edge(crbs_t *crbs, point_t *p1, point_t *p2, double maxlen2, double maxlen, double cop, double clr, int add_grbs, rtrnd_any_obj_t *obj, rtrnd_net_t *net) +{ + edge_t *e; + double dx = p2->pos.x - p1->pos.x, dy = p2->pos.y - p1->pos.y; + double len2 = dx*dx + dy*dy; + cdt_t *cdt = &crbs->cdt; + + if (len2 > maxlen2) { + double d, len, x, y; + long spn, n; + point_t *lp, *p; + + len = sqrt(len2); + spn = ceil(len/maxlen); + dx /= ((double)spn+1); + dy /= ((double)spn+1); + x = p1->pos.x; + y = p1->pos.y; + lp = p1; + + /* start and internal points */ + for(n = 0; n < spn; n++) { + x += dx; + y += dy; + p = crbs_make_point(crbs, x, y, cop, clr, NULL, net); + if (p == NULL) + continue; + ADD_C_EDGE(lp, p); + lp = p; + } + + /* end */ + ADD_C_EDGE(lp, p2); + } + else + ADD_C_EDGE(p1, p2); +} + +void rt_topo_crbs_cdt_init(rtrnd_t *ctx, crbs_t *crbs) +{ + cdt_t *cdt = &crbs->cdt; + cdt_init(cdt, ctx->board->hdr.bbox.x1, ctx->board->hdr.bbox.y1, ctx->board->hdr.bbox.x2, ctx->board->hdr.bbox.y2); +} + +void rt_topo_crbs_cdt_create_points(rtrnd_t *ctx, rtrnd_layer_t *ly, crbs_t *crbs) +{ + rtrnd_any_obj_t *obj; + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + point_t *p1, *p2; + cdt_t *cdt = &crbs->cdt; + rtp_vertex_t *v; + edge_t *e; + long n; + double maxl2, maxlen = (rt_topo_cfg.wire_thick + rt_topo_cfg.wire_clr/2) * 50; /* split long constrained edges so that no segment is longer than this value */ + double cop, clr; + + maxl2 = maxlen*maxlen; + + for(via = rtrnd_rtree_all_first(&it, &ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) + crbs_make_point(crbs, via->x, via->y, via->dia/2, via->clearance, via, via->hdr.net); + + for(obj = rtrnd_rtree_all_first(&it, &ly->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) { + switch(obj->hdr.type) { + case RTRND_LINE: + cop = obj->line.thickness/2; + clr = obj->line.clearance; + if (clr < 0) clr = 0; + p1 = crbs_make_point(crbs, obj->line.cline.p1.x, obj->line.cline.p1.y, cop, clr, NULL, obj->hdr.net); + if ((obj->line.cline.p1.x != obj->line.cline.p2.x) || (obj->line.cline.p1.y != obj->line.cline.p2.y)) { + p2 = crbs_make_point(crbs, obj->line.cline.p2.x, obj->line.cline.p2.y, cop, clr, NULL, obj->hdr.net); + long_constrained_edge(crbs, p1, p2, maxl2, maxlen, cop, clr, 1, obj, obj->hdr.net); + } + break; + case RTRND_POLY: + clr = 0/*obj->poly.clearance*/; + v = gdl_last(&obj->poly.rtpoly.lst); + p2 = crbs_make_point(crbs, v->x, v->y, 0, clr, NULL, obj->hdr.net); + for(v = gdl_first(&obj->poly.rtpoly.lst); v != NULL; v = gdl_next(&obj->poly.rtpoly.lst, v)) { + p1 = crbs_make_point(crbs, v->x, v->y, 0, clr, NULL, obj->hdr.net); + long_constrained_edge(crbs, p1, p2, maxl2, maxlen, 0, clr, 1, obj, obj->hdr.net); + p2 = p1; + } + break; + default: +#warning handle all other types + ; + } + } + + if (crbs->enable_mid_virt) { + vtd0_t np = {0}; + double minlen2, minlen = (rt_topo_cfg.wire_thick + rt_topo_cfg.wire_clr/2) * 16; /* minimum length of an edge to split */ + + minlen2 = minlen * minlen; + + for(n = 0; n < cdt->edges.used; n++) { + double len; + edge_t *e = cdt->edges.array[n]; + double dx, dy, len2; + + if (e->is_constrained) + continue; + + dx = e->endp[0]->pos.x - e->endp[1]->pos.x; + dy = e->endp[0]->pos.y - e->endp[1]->pos.y; + len2 = dx*dx + dy*dy; + if (len2 > minlen2) { + long i; + int bad = 0; + double x = (e->endp[0]->pos.x + e->endp[1]->pos.x)/2, y = (e->endp[0]->pos.y + e->endp[1]->pos.y)/2; + + /* avoid multiple splits too close */ + for(i = 0; i < np.used; i++) { + if ((fabs(x - np.array[i]) < minlen) && (fabs(y - np.array[i+1]) < minlen)) { + bad = 1; + break; + } + } + if (!bad) { + vtd0_append(&np, x); + vtd0_append(&np, y); + } + } + } +#warning TODO: this should be 0,0 for copper and clearance once grbs supports convex implicit attachments + for(n = 0; n < np.used; n+=2) + crbs_make_point(crbs, np.array[n], np.array[n+1], rt_topo_cfg.wire_thick/2, rt_topo_cfg.wire_clr, NULL, NULL); + vtd0_uninit(&np); + } + +} + +void rt_topo_crbs_cdt_create_edges(rtrnd_t *ctx, rtrnd_layer_t *ly, crbs_t *crbs) +{ + cdt_t *cdt = &crbs->cdt; + long n; + + for(n = 0; n < cdt->edges.used; n++) { + edge_t *e = cdt->edges.array[n]; +#warning TODO: use libualloc here + crbs_edge_t *ce = malloc(sizeof(crbs_edge_t)); + e->data = ce; + memset(ce, 0, sizeof(crbs_edge_t)); + ce->ang[0] = atan2(e->endp[1]->pos.y - e->endp[0]->pos.y, e->endp[1]->pos.x - e->endp[0]->pos.x); + ce->ang[1] = atan2(e->endp[0]->pos.y - e->endp[1]->pos.y, e->endp[0]->pos.x - e->endp[1]->pos.x); + ce->edge = e; + } +} + +void rt_topo_crbs_cdt_draw(rtrnd_t *ctx, rtrnd_layer_t *ly_out, cdt_t *cdt) +{ + VTEDGE_FOREACH(edge, &cdt->edges) + rtrnd_line_new(ly_out, NULL, NULL, + edge->endp[0]->pos.x, edge->endp[0]->pos.y, edge->endp[1]->pos.x, edge->endp[1]->pos.y, \ + edge->is_constrained ? 0.1 : 0.01, 0); + VTEDGE_FOREACH_END(); + +/* labels:*/ + VTPOINT_FOREACH(pt, &cdt->points) + if (pt->data != NULL) { + char tmp[64]; + sprintf(tmp, "P%ld", ((crbs_point_t *)pt->data)->gpt->uid); + rtrnd_text_new(ly_out, pt->pos.x, pt->pos.y, tmp, 0.5); + } + VTPOINT_FOREACH_END(); + + VTEDGE_FOREACH(edge, &cdt->edges) { + if ((edge->data != NULL) && (((crbs_edge_t *)edge->data)->nets > 0)) { + char tmp[64]; + double x = (edge->endp[0]->pos.x + edge->endp[1]->pos.x)/2, y = (edge->endp[0]->pos.y + edge->endp[1]->pos.y)/2; + + sprintf(tmp, "(%ld)", ((crbs_edge_t *)edge->data)->nets); + rtrnd_text_new(ly_out, x, y, tmp, 0.5); + } + } + VTEDGE_FOREACH_END(); +} + +static edge_t *crbs_cdt_get_edge(point_t *pt1, point_t *pt2) +{ + EDGELIST_FOREACH(e, (pt1->adj_edges)) { + if ((e->endp[0] == pt2) || (e->endp[1] == pt2)) + return e; + } + EDGELIST_FOREACH_END(); + + return NULL; +} + +void rt_topo_crbs_cdt_inc_edge(crbs_t *crbs, grbs_addr_t *a1, grbs_addr_t *a2) +{ + crbs_point_t *pt1, *pt2; + edge_t *cdt_e; + crbs_edge_t *edge; + + if ((a1->type & 0x0F) == ADDR_POINT) + pt1 = a1->obj.pt->user_data; + else + pt1 = a1->obj.arc->parent_pt->user_data; + + if ((a2->type & 0x0F) == ADDR_POINT) + pt2 = a2->obj.pt->user_data; + else + pt2 = a2->obj.arc->parent_pt->user_data; + + cdt_e = crbs_cdt_get_edge(pt1->cpt, pt2->cpt); + + assert(cdt_e != NULL); + edge = cdt_e->data; + edge->nets++; + assert(edge->nets > 0); /* unlikely: overflow */ +} + +void rt_topo_crbs_cdt_dec_edge(crbs_t *crbs, grbs_arc_t *arc1, grbs_arc_t *arc2) +{ + crbs_point_t *pt1 = arc1->parent_pt->user_data, *pt2 = arc2->parent_pt->user_data; + edge_t *cdt_e = crbs_cdt_get_edge(pt1->cpt, pt2->cpt); + crbs_edge_t *edge; + + assert(cdt_e != NULL); + edge = cdt_e->data; + assert(edge->nets > 0); + edge->nets--; +} + + +void rt_topo_crbs_cdt_unref_tn(crbs_t *crbs, grbs_2net_t *tn) +{ + grbs_arc_t *prev = NULL, *a; + for(a = gdl_first(&tn->arcs); a != NULL; prev = a, a = gdl_next(&tn->arcs, a)) { + if (prev != NULL) + rt_topo_crbs_cdt_dec_edge(crbs, prev, a); + } +} Index: tags/0.9.0/src/plugins/rt_topo/crbs_route.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/crbs_route.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/crbs_route.c (revision 1402) @@ -0,0 +1,694 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020,2021 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "crbs.h" +#define HT(x) htad_ ## x +#include +#undef HT + +#include +#include + +static int crbs_grbs_draw(crbs_t *crbs, char *fn); + +static int crbs_trace_ast = 1; +static int hop_svg = 0; /* whether to write 3..4 svgs per next_hop call */ + +static int cnt_grbs = 0; + +static long crbs_ast_heuristic(usrch_a_star_t *ctx, void *node) +{ + crbs_t *crbs = ctx->user_data; + grbs_detached_addr_t *from = node; + double tx, ty; + long dist; + + tx = from->pt->x + cos(from->new_sa) * from->new_r; + ty = from->pt->y + sin(from->new_sa) * from->new_r; + + dist = crbs_dist_heur(crbs->target->pt->x, crbs->target->pt->y, tx, ty); + + /* prefer concave over convex assuming the puller will get it shorter */ + if ((from->type & 0x0F) == ADDR_ARC_CONCAVE) + dist = dist * 2 / 3; + + return dist; +} + +static long crbs_ast_cost(usrch_a_star_t *ctx, void *from_, void *to_) +{ +/* crbs_t *crbs = ctx->user_data;*/ + grbs_detached_addr_t *from = from_, *to = to_; + double ex, ey, tx, ty, tune = 1; + long cost; + int from_dir = 0, to_dir = 0; + + switch(from->type & 0x0F) { + case ADDR_ARC_CONCAVE: + tune = 2.0/3.0; /* prefer concave over convex assuming the puller will get it shorter */ + case ADDR_ARC_CONVEX: + ex = from->pt->x + cos(from->new_sa + from->new_da) * from->new_r; + ey = from->pt->y + sin(from->new_sa + from->new_da) * from->new_r; + cost = floor(from->new_r * from->new_da * DIST_HEUR_MULT * tune); + from_dir = from->new_adir; + break; + + case ADDR_POINT: + ex = from->pt->x; + ey = from->pt->y; + cost = 0; + break; + } + + switch(to->type & 0x0F) { + case ADDR_ARC_CONCAVE: + tune = tune * (2.0/3.0); + case ADDR_ARC_CONVEX: + to_dir = to->new_adir; + case ADDR_POINT: + break; + } + + tx = to->pt->x + cos(to->new_sa) * to->new_r; + ty = to->pt->y + sin(to->new_sa) * to->new_r; + cost += crbs_dist_heur(ex, ey, tx, ty); + + /* in an arc-arc path prefer not switching between cw and ccw by increasing + the path cost by 1% on a switch - trying to keep the situation convex; + this is supposed to help in situations when there are two equally cheap + paths without blocking switches where they are reasonable */ + if ((from_dir != 0) && (to_dir != 0) && (from_dir != to_dir)) + cost *= 1.01; + + return cost; +} + +typedef struct { + vtp0_t pts; /* of (crbs_point_t *) */ + int pt_idx; /* current idx on pts */ + int grbs_idx; /* how we try to go around that point */ +} crbs_ast_t; + +static void *crbs_ast_neighbor_pre(usrch_a_star_t *ctx, void *curr) +{ + crbs_t *crbs = ctx->user_data; + static crbs_ast_t a; + int target_idx = -1; + grbs_detached_addr_t *from_addr = curr; + crbs_point_t *from = from_addr->pt->user_data; + + a.pt_idx = 0; + a.grbs_idx = 0; + a.pts.used = 0; + + /* collect next hops on a list */ + EDGELIST_FOREACH(e, (from->cpt->adj_edges)) { + point_t *to_pt; + crbs_point_t *pt; + + if (e->endp[0] == from->cpt) to_pt = e->endp[1]; + else if (e->endp[1] == from->cpt) to_pt = e->endp[0]; + else continue; /* shouldn't happen: neither end of the edge is 'from' */ + + pt = to_pt->data; + + if (pt != NULL) { + vtp0_append(&a.pts, pt); + if (pt->gpt == crbs->target->pt) + target_idx = a.pts.used - 1; + } + } + EDGELIST_FOREACH_END(); + + /* optimization: move target to the front of the list so that we evaluate + a finishing path before anything else */ + if (target_idx > 0) { + void *tmp; + + tmp = a.pts.array[target_idx]; + a.pts.array[target_idx] = a.pts.array[0]; + a.pts.array[0] = tmp; + } + + return &a; +} + +/* +static void print_det(grbs_detached_addr_t *det) +{ + printf("type=%d ", det->type); + if (det->arc != NULL) printf("arc=%ld ", det->arc->uid); + if (det->pt != NULL) printf("P%ld ", det->pt->uid); + printf("u=%ld new=(r%f %f %f|%d)", det->user_long, det->new_r, det->new_sa, det->new_da, det->new_adir); +} + + +static void print_detkey(grbs_addr_key_t key) +{ + printf("ang=%d o%d conc=%d %s P%d", key.ang, key.orbit, key.is_concave, key.is_ccw ? "ccw" : "cw", key.pt_uid); +} +*/ + +static int hop_cnt = 0; + +/* Attempt to create a grbs path segment from curr to pt:adir. If fails, return + NULL. If succeeds, remove the path segment from the grbs context, add a + detached address of it to the hash and return it. */ +static grbs_detached_addr_t *crbs_next_hop(crbs_t *crbs, grbs_detached_addr_t *curr, crbs_point_t *pt, grbs_arc_dir_t adir) +{ + grbs_addr_t *froma, *toa; + grbs_2net_t *gtn = crbs->routing_tn; + grbs_detached_addr_t *res = NULL, dtmp; + char tmp[128]; + + hop_cnt++; + printf(" {%d} ", hop_cnt); + + if (hop_svg) { + sprintf(tmp, "3_GRBS_routed_%d_h%d_a.svg", cnt_grbs, hop_cnt); + crbs_grbs_draw(crbs, tmp); + } + + froma = grbs_reattach_addr(&crbs->grbs, curr); + if (froma == NULL) { + printf(" Neigh: can't reattach curr\n"); + return NULL; + } + + if (hop_svg) { + sprintf(tmp, "3_GRBS_routed_%d_h%d_b.svg", cnt_grbs, hop_cnt); + crbs_grbs_draw(crbs, tmp); + } + + if ((froma->type != ADDR_POINT) && (froma->obj.arc != NULL)) { assert(froma->obj.arc->link_point.parent != NULL); } + + toa = grbs_path_next(&crbs->grbs, gtn, froma, pt->gpt, adir); + if (toa != NULL) { + grbs_addr_key_t key; + htad_entry_t *e; + + if (hop_svg) { + sprintf(tmp, "3_GRBS_routed_%d_h%d_c.svg", cnt_grbs, hop_cnt); + crbs_grbs_draw(crbs, tmp); + } + + if (((froma->type & 0x0f) == ADDR_ARC_CONVEX) || ((froma->type & 0x0f) == ADDR_ARC_CONCAVE)) { + if (fabs(froma->obj.arc->new_da) > M_PI) { +/* printf(" INVALID arc (too long): %f at P%ld\n", froma->obj.arc->new_da, froma->obj.arc->parent_pt == NULL ? -1 : froma->obj.arc->parent_pt->uid);*/ + grbs_path_cleanup_addr(&crbs->grbs, toa); + grbs_path_cleanup_addr(&crbs->grbs, froma); + return NULL; + } + } + + if ((froma->type & 0x0f) == ADDR_ARC_CONCAVE) { + if (fabs(froma->obj.arc->new_da) < 0.01) { +/* printf(" INVALID arc (too short): %f at P%ld\n", froma->obj.arc->new_da, froma->obj.arc->parent_pt == NULL ? -1 : froma->obj.arc->parent_pt->uid);*/ + grbs_path_cleanup_addr(&crbs->grbs, toa); + grbs_path_cleanup_addr(&crbs->grbs, froma); + return NULL; + } + } + + grbs_detach_addr(&crbs->grbs, &dtmp, toa); + key = grbs_det_addr_to_key(&dtmp); + e = htad_getentry(&crbs->addrs, key); + if (e == NULL) { + htad_value_t val = {0}; + + val.valid = 1; +#warning TODO: allocate this with ualloc stacks + val.det = res = calloc(sizeof(grbs_detached_addr_t), 1); + memcpy(val.det, &dtmp, sizeof(dtmp)); + val.det->user_long = adir; +/* printf("\nDET SET: key: "); print_detkey(key); printf(" | det: ");print_det(res); printf("\n");*/ + htad_set(&crbs->addrs, key, val); + } + else { + res = e->value.det; +/* printf("\nDET S2T: key: "); print_detkey(grbs_det_addr_to_key(res)); printf(" | det: ");print_det(res); printf("\n");*/ + } + + grbs_path_cleanup_addr(&crbs->grbs, toa); + } + + if (hop_svg) { + sprintf(tmp, "3_GRBS_routed_%d_h%d_d.svg", cnt_grbs, hop_cnt); + crbs_grbs_draw(crbs, tmp); + } + + grbs_path_cleanup_addr(&crbs->grbs, froma); + return res; +} + +static void *crbs_ast_neighbor(usrch_a_star_t *ctx, void *curr_, void *nctx) +{ + crbs_t *crbs = ctx->user_data; + crbs_ast_t *a = nctx; + grbs_detached_addr_t *next, *curr = curr_; + const char *from_type; + + + + for(;;) { + crbs_point_t *pt; + + if (a->grbs_idx >= 4) { + a->grbs_idx = 0; + a->pt_idx++; + } + + if (a->pt_idx >= a->pts.used) + break; + + pt = a->pts.array[a->pt_idx]; + + switch(curr->type & 0x0F) { + case ADDR_ARC_CONVEX: from_type = (curr->new_adir > 0) ? "convex cw" : "convex ccw"; break; + case ADDR_ARC_CONCAVE: from_type = (curr->new_adir > 0) ? "concave cw" : "concave ccw"; break; + case ADDR_POINT: from_type = "incident"; break; + default: from_type = "UNKNOWN"; break; + } + +/*printf("Neigh: %d / %d (dir: %d)\n", a->pt_idx, a->pts.used, a->grbs_idx);*/ + + if (pt == crbs->target->pt->user_data) { /* quick lane for reaching the target */ + printf(" try from %s P%ld to TARGET P%ld", from_type, curr->pt->uid, pt->gpt->uid); + next = crbs_next_hop(crbs, curr, pt, GRBS_ADIR_INC); + if (next != NULL) { + a->pt_idx = a->pts.used; /* don't consider detours from the current node if target node can be reached directly */ + printf(" -> ok\n"); + return crbs->target; + } + printf(" -> failed\n"); + a->pt_idx++; + continue; + } + + + while(a->grbs_idx < 4) { + printf(" try from %s P%ld to P%ld", from_type, curr->pt->uid, pt->gpt->uid); + + if (crbs->disable_concave) { + if (a->grbs_idx < 2) + a->grbs_idx = 2; + } + + /* prefer concave over convex; order matters when reaching target: first + valid solution will stop the search */ + switch(a->grbs_idx) { + case 0: printf(" concave ccw"); next = crbs_next_hop(crbs, curr, pt, GRBS_ADIR_CONCAVE_CCW); break; + case 1: printf(" concave cw"); next = crbs_next_hop(crbs, curr, pt, GRBS_ADIR_CONCAVE_CW); break; + case 2: printf(" convex ccw"); next = crbs_next_hop(crbs, curr, pt, GRBS_ADIR_CONVEX_CCW); break; + case 3: printf(" convex cw"); next = crbs_next_hop(crbs, curr, pt, GRBS_ADIR_CONVEX_CW); break; + } + + a->grbs_idx++; + if (next != NULL) { + printf(" -> ok\n"); + return next; + } + printf(" -> failed\n"); + } + } + + return NULL; +} + +static void crbs_ast_set_mark(usrch_a_star_t *ctx, void *node, usrch_a_star_node_t *mark) +{ + crbs_t *crbs = ctx->user_data; + grbs_detached_addr_t *det = node; + htad_entry_t *e; + + if (det->pt == crbs->first->pt) { + crbs->first_mark = mark; + return; + } + + if (det->pt == crbs->target->pt) { + crbs->target_mark = mark; + return; + } + +/* { + static dcnt=0; + dcnt++; + printf("DET get: key: "); print_detkey(grbs_det_addr_to_key(det)); printf(" | det: ");print_det(det); printf(" {%d}\n", dcnt); + }*/ + e = htad_getentry(&crbs->addrs, grbs_det_addr_to_key(det)); + if (e == NULL) { /* this may happen if we land on a different orbit since the last try (e.g. in legit spiral case) */ + htad_value_t val = {0}; + + val.valid = 1; +#warning TODO: allocate this with ualloc stacks + val.det = calloc(sizeof(grbs_detached_addr_t), 1); + memcpy(val.det, det, sizeof(grbs_detached_addr_t)); +/* printf("\nDET SET: key: "); print_detkey(key); printf(" | det: ");print_det(res); printf("\n");*/ + htad_set(&crbs->addrs, grbs_det_addr_to_key(val.det), val); + e = htad_getentry(&crbs->addrs, grbs_det_addr_to_key(det)); + } +/* printf("DET res: e=%p\n", e);*/ + fflush(stdout); + assert(e != NULL); + e->value.mark = mark; +} + +static usrch_a_star_node_t *crbs_ast_get_mark(usrch_a_star_t *ctx, void *node) +{ + crbs_t *crbs = ctx->user_data; + grbs_detached_addr_t *det = node; + htad_entry_t *e; + + if (det->pt == crbs->first->pt) + return crbs->first_mark; + if (det->pt == crbs->target->pt) + return crbs->target_mark; + + e = htad_getentry(&crbs->addrs, grbs_det_addr_to_key(det)); + if (e == NULL) + return NULL; + return e->value.mark; +} + +static grbs_detached_addr_t *addr_new_point(crbs_t *crbs, point_t *pt, grbs_detached_addr_t *addr) +{ + crbs_point_t *cp = pt->data; + + memset(addr, 0, sizeof(grbs_detached_addr_t)); + addr->type = ADDR_POINT; + addr->pt = cp->gpt; + addr->user_long = GRBS_ADIR_INC; + + /* this address is unique to every two-net, but will look the same when + started from the same point so do not save it in the hash */ + return addr; +} + +static int rt_topo_crbs_route_net(crbs_t *crbs, crbs_2net_t *ctn) +{ + usrch_res_t sres; + usrch_a_star_t ast = {0}; + usrch_a_star_node_t *it; + grbs_detached_addr_t addr_tmp[2]; + grbs_detached_addr_t *first, *da, *prev; + grbs_addr_t *na, *pa, *firsta, *lasta; + crbs_2net_t *tn; + int res = -1; + + + /* reset net collisions */ + for(tn = gdl_first(&crbs->twonets); tn != NULL; tn = gdl_next(&crbs->twonets, tn)) + tn->coll = 0; + + /* reset address hash */ + { + htad_entry_t *e; + +/* printf("DET: --- reset ---\n");*/ +#warning TODO: when det allocation is libualloc staks based, these two lines can be replaced with a stack reset: + for(e = htad_first(&crbs->addrs); e != NULL; e = htad_next(&crbs->addrs, e)) + free(e->value.det); + htad_clear(&crbs->addrs); + } + + ast.heuristic = crbs_ast_heuristic; + ast.cost = crbs_ast_cost; + ast.neighbor_pre = crbs_ast_neighbor_pre; + ast.neighbor = crbs_ast_neighbor; + ast.set_mark = crbs_ast_set_mark; + ast.get_mark = crbs_ast_get_mark; + ast.user_data = crbs; + + cnt_grbs++; + + crbs->first = first = addr_new_point(crbs, ctn->cstart, &addr_tmp[0]); + crbs->target = ast.target = addr_new_point(crbs, ctn->cend, &addr_tmp[1]); + +#warning TODO: per net wire thickness + if (ctn->gtn == NULL) { + crbs->routing_tn = ctn->gtn = grbs_2net_new(&crbs->grbs, rt_topo_cfg.wire_thick, rt_topo_cfg.wire_clr); + crbs->routing_tn->user_data = ctn; + } + else + crbs->routing_tn = ctn->gtn; + + printf(" route_net: from P%ld to P%ld (step 3_GRBS_routed_%d)\n", + ((crbs_point_t *)(ctn->cstart->data))->gpt->uid, + ((crbs_point_t *)(ctn->cend->data))->gpt->uid, + cnt_grbs); + + sres = usrch_a_star_start(&ast, first); + if (sres != USRCH_RES_SUCCESS) { + printf(" a* start fail 1\n"); + goto err; + } + + while((sres = usrch_a_star_iter(&ast)) == USRCH_RES_CONTINUE) ; + + if (sres != USRCH_RES_FOUND) { + printf(" a* search fail 2\n"); + goto err; + } + + /*** reconstruct the path ***/ + + /* abuse da->user_data for building a linked list for reversing */ + first = NULL; + for(da = usrch_a_star_path_first(&ast, &it); da != NULL; da = usrch_a_star_path_next(&ast, &it)) { + da->user_data = first; + first = da; + } + + /* build from start to end, in the original order */ + prev = first; + firsta = NULL; + lasta = pa = grbs_addr_new(&crbs->grbs, ADDR_POINT, first->pt); + lasta->user_data = NULL; + printf("GT 2net_new %s %f %f from P%ld", ctn->tn->net->hdr.oid, rt_topo_cfg.wire_thick, rt_topo_cfg.wire_clr, first->pt->uid); + for(da = first->user_data; da != NULL; prev = da, da = da->user_data) { + hop_cnt++; + switch(da->user_long) { + case GRBS_ADIR_INC: printf(" to P%ld", da->pt->uid); break; + case GRBS_ADIR_CONVEX_CCW: printf(" ccw P%ld", da->pt->uid); break; + case GRBS_ADIR_CONVEX_CW: printf(" cw P%ld", da->pt->uid); break; + case GRBS_ADIR_CONCAVE_CCW: printf(" concave ccw P%ld", da->pt->uid); break; + case GRBS_ADIR_CONCAVE_CW: printf(" concave cw P%ld", da->pt->uid); break; + } + na = grbs_path_next(&crbs->grbs, crbs->routing_tn, pa, da->pt, da->user_long); + if (na != NULL) { + na->user_data = pa; /* ->user_data is next; build the list again in reverse order for realize */ + pa = na; + firsta = na; + } + else { + if (hop_svg) { + char tmp[256]; + sprintf(tmp, "3_GRBS_routfail_%d_h%d_b.svg", cnt_grbs, hop_cnt); + crbs_grbs_draw(crbs, tmp); + } + printf("Internal ERROR, TODO: failed to pre-realize the path (%s at P%ld) {%d}\n", ctn->tn->net->hdr.oid, da->pt->uid, hop_cnt); + } + } + + printf("\n"); + fflush(stdout); + + pa = NULL; + for(na = firsta; na != NULL; pa = na, na = na->user_data) { + if (grbs_path_validate(&crbs->grbs, crbs->routing_tn, pa, na, na->user_data) != 0) { + abort(); + } + if (pa != NULL) + rt_topo_crbs_cdt_inc_edge(crbs, pa, na); + } + + for(na = firsta; na != NULL; na = na->user_data) { + grbs_arc_t *arc = grbs_path_realize(&crbs->grbs, crbs->routing_tn, na, 0); + if (arc != NULL) + arc->user_data = ctn; + else + abort(); /* we have validated the path so this can not fail */ + } + + { + char tmp[128]; + + sprintf(tmp, "3_GRBS_routed_%d.svg", cnt_grbs); + crbs_grbs_draw(crbs, tmp); + } + + res = 0; +err: + + usrch_a_star_uninit(&ast); + crbs->routing_tn = NULL; + return res; +} + +/* Returns 1 if ripped up something */ +static int on_fail_ripup(crbs_t *crbs, crbs_2net_t *tn) +{ + int best_r = crbs->max_ripup; + crbs_2net_t *ctn, *best = NULL; + char tmp[128]; + + printf(" Failed to route; checking what to rip up:\n"); + + for(ctn = gdl_first(&crbs->twonets); ctn != NULL; ctn = gdl_next(&crbs->twonets, ctn)) { + if (ctn->coll) { + printf(" %s (%d)\n", ctn->tn->net->hdr.oid, ctn->ripped_up); + if (ctn->ripped_up < best_r) { + best_r = ctn->ripped_up; + best = ctn; + } + } + } + + if (best == NULL) + return 0; /* nothing to rip up */ + + printf(" ripping up %s\n", best->tn->net->hdr.oid); + printf("GT 2net_del %s\n", best->tn->net->hdr.oid); + + sprintf(tmp, "3_GRBS_routed_%d_rip1.svg", cnt_grbs); + crbs_grbs_draw(crbs, tmp); + + + /* remove the offending 2net */ + best->ripped_up++; + rt_topo_crbs_cdt_unref_tn(crbs, best->gtn); + grbs_path_remove_2net(&crbs->grbs, best->gtn); + best->gtn = NULL; + + /* re-schedule it as last (to avoid cycling through the same 2..3 nets) */ + gdl_remove(&crbs->twonets, best, link); + gdl_append(&crbs->twonets, best, link); + + sprintf(tmp, "3_GRBS_routed_%d_rip2.svg", cnt_grbs); + crbs_grbs_draw(crbs, tmp); + + return 1; +} + +static int rt_topo_crbs_layer_(rtrnd_t *ctx, crbs_t *crbs, rtrnd_layer_t *ly, long attempt, rtrnd_layer_t *ly_cdt, rtrnd_layer_t *ly_bnk) +{ + rtrnd_layer_t ly_neighb = {0}, ly_route = {0}, ly_cdt2 = {0}; + vtp0_t annot = {0}; + char fn[1024]; + crbs_2net_t *ttn; + int res = 0; + + + vtp0_append(&annot, ly_cdt); + vtp0_append(&annot, ly_bnk); + snprintf(fn, sizeof(fn), "3_%s_%ld_1_cdt", ly->name, attempt); + rtrnd_export(ctx, "svg", fn, NULL, &annot); + + /* route all nets */ + for(ttn = gdl_first(&crbs->twonets); ttn != NULL; ) { + printf("CRBS route net %s:\n", ttn->tn->net->hdr.oid); + if (rt_topo_crbs_route_net(crbs, ttn) != 0) { + if (on_fail_ripup(crbs, ttn)) + continue; /* ripped up another net, retry with ttn */ + /* else: coudln't find anything to rip up or ripup count is too high + already: give up routing this net */ + printf(" => Giving up routing %s\n", ttn->tn->net->hdr.oid); + } + ttn = gdl_next(&crbs->twonets, ttn); + } + + rtrnd_layer_init(&ly_cdt2, "cdt"); + strcpy(ly_cdt2.color, "#555555"); + vtp0_append(&annot, &ly_cdt2); + + rtrnd_layer_init(&ly_neighb, "neighb"); + strcpy(ly_neighb.color, "#ff0000"); + vtp0_append(&annot, &ly_neighb); +/* crbs_draw_neigh(crbs, &ly_neighb);*/ + + rtrnd_layer_init(&ly_route, "route"); + strcpy(ly_route.color, "#00ff00"); + vtp0_append(&annot, &ly_route); + +/* TODO */ + crbs_draw_routes(crbs, (res == 0) ? ly : NULL, &ly_route); + + rt_topo_crbs_cdt_draw(ctx, &ly_cdt2, &crbs->cdt); + + snprintf(fn, sizeof(fn), "3_%s_%ld_2_route", ly->name, attempt); + rtrnd_export(ctx, "svg", fn, NULL, &annot); + + vtp0_uninit(&annot); + return res; +} + +static int rt_topo_crbs_layer(rtrnd_t *ctx, rtrnd_layer_t *ly, gdl_list_t *tnl) +{ + crbs_t crbs; + rt_topo_2net_t *t; + rtrnd_layer_t ly_cdt = {0}, ly_bnk = {0}; + int res, tries; + + memset(&crbs, 0, sizeof(crbs_t)); + crbs.disable_concave = 1; + crbs.enable_mid_virt = rt_topo_cfg.mid_virt; + crbs_init(&crbs, ctx); + + rt_topo_crbs_cdt_init(ctx, &crbs); + rt_topo_crbs_cdt_create_points(ctx, ly, &crbs); + + rtrnd_layer_init(&ly_cdt, "laa"); + strcpy(ly_cdt.color, "#888888"); + rtrnd_layer_init(&ly_bnk, "laa"); + strcpy(ly_bnk.color, "#6666aa"); + + /* convert input twonets to crbs twonets, making sure they have endpoints in the cdt */ + crbs.max_ripup = 0; + for(t = gdl_first(tnl); t != NULL; t = t->link.next) { +#warning TODO: use libualloc + crbs_2net_t *ct = calloc(sizeof(crbs_2net_t), 1); + rtrnd_net_t *net = ct->net; + + ct->cstart = crbs_make_point_near(&crbs, t->x[0], t->y[0], 0.001, 0.001, NULL, net, 0.5); + ct->cend = crbs_make_point_near(&crbs, t->x[1], t->y[1], 0.001, 0.001, NULL, net, 0.5); + ct->tn = t; + ct->net = t->net; + gdl_append(&crbs.twonets, ct, link); + crbs.max_ripup++; + } + + rt_topo_crbs_cdt_create_edges(ctx, ly, &crbs); + + rt_topo_crbs_cdt_draw(ctx, &ly_cdt, &crbs.cdt); + + res = rt_topo_crbs_layer_(ctx, &crbs, ly, 0, &ly_cdt, &ly_bnk); + + crbs_uninit(&crbs); + return res; +} Index: tags/0.9.0/src/plugins/rt_topo/laa.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa.c (revision 1402) @@ -0,0 +1,136 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include "geo.h" +#include +#include +#include +#include +#include + +#include "data.h" +#include "vt2br.h" +#include "vtcr.h" +#include "vtve0.h" +#include "rtree.h" +#include "find.h" +#include "io.h" + +#include "rt_topo.h" +#include "laa.h" + + +#define LAA_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define LAA_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/* return a bitmask with all 1's for all possible layers */ +static long layer_bits_all(rtrnd_t *ctx) +{ + return (1 << ctx->board->layers.used) - 1; +} + +/* return a bitmask corresponding to the object; for layer objects this means + 1 only on the layer the object is on; for vias it's a block of 1s the via + spans */ +static long layer_bits(rtrnd_t *ctx, rtrnd_any_obj_t *obj) +{ + long lid; + + switch(obj->hdr.type) { + case RTRND_LINE: + case RTRND_ARC: + case RTRND_POLY: + for(lid = 0; lid < ctx->board->layers.used; lid++) + if (&obj->hdr.parent->layer == ctx->board->layers.array[lid]) + return 1 << lid; + assert(!"invalid layer"); + return 0; + + case RTRND_VIA: +#warning TODO: this ignores bbvia + return layer_bits_all(ctx); + + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + assert(!"invalid object for layer_bits"); + break; + } + return 0; +} + +#include "laa1.c" +#include "laa2.c" +#include "laa3.c" + +laa_test_hook_t laa_test_hook[5]; + +int rt_topo_laa(rtrnd_t *ctx, rt_topo_laa2rbs_t *dst) +{ + rtrnd_layer_t ly_mst = {0}; + rtrnd_rtree_t r2net; + vtp0_t annot = {0}; + int n, res = 0; + + rtrnd_layer_init(&ly_mst, "laa"); + strcpy(ly_mst.color, "#777700"); + + rtrnd_rtree_init(&r2net); + + if (laa_test_hook[0] != NULL) laa_test_hook[0](ctx, &annot, &r2net); + laa_2nets(ctx, &ly_mst, &r2net); /* step I */ + + if (laa_test_hook[1] != NULL) laa_test_hook[1](ctx, &annot, &r2net); + laa_2vias(ctx, &ly_mst, &r2net); /* step II */ + + vtp0_append(&annot, &ly_mst); + rtrnd_export(ctx, "svg", "2_1_laa", NULL, &annot); + annot.used = 0; + rtrnd_layer_uninit(&ly_mst); + + if (laa_test_hook[2] != NULL) laa_test_hook[2](ctx, &annot, &r2net); + + res = laa_solve(ctx, &annot, &r2net, dst); /* step III */ + + if (laa_test_hook[4] != NULL) laa_test_hook[4](ctx, &annot, &r2net); + + rtrnd_export(ctx, "svg", "2_2_laa", NULL, &annot); + + for(n = 0; n < annot.used; n++) { + rtrnd_layer_uninit(annot.array[n]); + free(annot.array[n]); + } + + rtrnd_rtree_uninit(&r2net); + vtp0_uninit(&annot); + return res; +} Index: tags/0.9.0/src/plugins/rt_topo/laa.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa.h (revision 1402) @@ -0,0 +1,44 @@ +#ifndef RT_TOPO_LAA_H +#define RT_TOPO_LAA_H +#include "data.h" +#include "rtree.h" +#include "vt2br.h" +#include "vtcr.h" +#include "rt_topo.h" + +typedef struct rt_topo_laa_2net_s rt_topo_laa_2net_t; + +struct rt_topo_laa_2net_s { + rtrnd_rtree_box_t bbox; + vt2br_t br; /* via site allocation, branches for the assignment graph */ + char *asg; /* current layer assignment over br */ + rtrnd_net_t *net; + rt_topo_laa_2net_t *next; + vtcr_t cross; /* crossings with other 2nets */ + + /* cached costs */ + double cost_detour; + double cost_vialayer; /* total via and layer usage cost */ + + /* temporary fields for building the rtree */ + double x1, y1, x2, y2; /* endpoint coords */ + long p1ly, p2ly, ely; /* endpoint and edge layers */ + unsigned p1fx:1, p2fx:1, efx:1; /* whether endpoints and edge is fixed */ +}; + +/* Layer assignment for a net, stored in NETDATA_LAA */ +typedef struct rt_topo_2nets_s { + rtrnd_net_t *net; + rt_topo_laa_2net_t *head; /* singly linked list of 2nets */ +} rt_topo_2nets_t; + +/* Calculat the laa-2nets (steiner tree) and potential vias and final + layer assigment of nets */ +int rt_topo_laa(rtrnd_t *ctx, rt_topo_laa2rbs_t *dst); + + +typedef void (*laa_test_hook_t)(rtrnd_t *ctx, vtp0_t *annot, rtrnd_rtree_t *r2net); + +extern laa_test_hook_t laa_test_hook[5]; + +#endif Index: tags/0.9.0/src/plugins/rt_topo/laa1.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa1.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa1.c (revision 1402) @@ -0,0 +1,171 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step I: build the 2net branch graph for each net (no vias); builds the + minimal steiner tree per net. Included from laa.c */ + +/* Create a new node in the steiner tree input for a point */ +static ustn_node_t *laa_mst_add_point(ustn_tree_t *tree, ustn_coord_t x, ustn_coord_t y, int fixed) +{ + ustn_node_t *nd = ustn_find_node(tree, x, y, fixed); + if (nd == NULL) { + nd = ustn_add_node(tree, x, y); + if (fixed > 0) + nd->fixed = 1; + } + return nd; +} + +/* Add an object to the steiner tree input */ +static void laa_mst_add(rtrnd_t *ctx, ustn_tree_t *mst, rtrnd_any_obj_t *obj) +{ + ustn_node_t *p1, *p2; + ustn_edge_t *e; + + switch(obj->hdr.type) { + case RTRND_LINE: + if (obj->hdr.terminal) { /* place one point, in the center */ + laa_mst_add_point(mst, (obj->line.cline.p1.x + obj->line.cline.p2.x)/2, (obj->line.cline.p1.y + obj->line.cline.p2.y)/2, -1); + break; + } + + if (g2d__distance2(g2d_cvect_t_convfrom_g2d_vect_t(obj->line.cline.p1), g2d_cvect_t_convfrom_g2d_vect_t(obj->line.cline.p2)) < 2) { + laa_mst_add_point(mst, obj->line.cline.p1.x, obj->line.cline.p1.y, -1); + break; + } + + /* create unmovable points and connect with an edge */ + p1 = laa_mst_add_point(mst, obj->line.cline.p1.x, obj->line.cline.p1.y, 1); + p2 = laa_mst_add_point(mst, obj->line.cline.p2.x, obj->line.cline.p2.y, 1); + e = ustn_add_edge(mst, p1, p2); + e->fixed = 1; + e->user_ptr = obj; + p1->user_long |= p2->user_long |= e->user_long |= layer_bits(ctx, obj); + break; + case RTRND_VIA: + p1 = laa_mst_add_point(mst, obj->via.x, obj->via.y, -1); + p1->user_long |= layer_bits_all(ctx); + break; + + case RTRND_ARC: + assert(!"TODO: arc"); + break; + case RTRND_POLY: + if (obj->hdr.terminal) { /* place one point, in the center */ + double cx = 0, cy = 0; + rtp_vertex_t *v; + for(v = gdl_first(&obj->poly.rtpoly.lst); v != NULL; v = v->link.next) { + cx += v->x; + cy += v->y; + } + if (gdl_length(&obj->poly.rtpoly.lst) > 1) { + cx /= (double)gdl_length(&obj->poly.rtpoly.lst); + cy /= (double)gdl_length(&obj->poly.rtpoly.lst); + } + p1 = laa_mst_add_point(mst, cx, cy, -1); + p1->user_long = layer_bits(ctx, obj); + } + else { +#warning TODO: non-terminal poly heuristics + } + break; + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + assert(!"invalid object for the steiner tree"); + break; + } +} + +/* Returns if a node is in a terminal (in which case it should be considered unmovable) */ +static int homed(ustn_node_t *nd) +{ + return (nd->x == nd->ix) && (nd->y == nd->iy); +} + +/* calculate the steiner tree of a single net */ +static void laa_2net(rtrnd_t *ctx, rtrnd_net_t *net, rtrnd_layer_t *ly, rtrnd_rtree_t *r2net) +{ + ustn_tree_t mst = {0}; + long n; + rt_topo_2nets_t *tns = calloc(sizeof(rt_topo_2nets_t), 1); + + NETDATA_LAA(net) = tns; + tns->net = net; + + rtrnd_any_obj_t *obj; + for(obj = gdl_first(&net->objs); obj != NULL; obj = gdl_next(&net->objs, obj)) + laa_mst_add(ctx, &mst, obj); + + /* calculate the minimal steiner tree */ + ustn_solve_iterate_pre(&mst); + while(mst.itc < 9000) + if (!ustn_solve_iterate(&mst)) + break; + ustn_optimize(&mst); + + + /* collect mst edges as 2-nets */ + for(n = 0; n < mst.edges.used; n++) { + ustn_edge_t *edge = mst.edges.array[n]; + rt_topo_laa_2net_t *tn = calloc(sizeof(rt_topo_laa_2net_t), 1); + + /* steiner points are vias, potentially using any layer */ + if (!edge->p1->fixed) edge->p1->user_long = layer_bits_all(ctx); + if (!edge->p2->fixed) edge->p2->user_long = layer_bits_all(ctx); + + tn->bbox.x1 = LAA_MIN(edge->p1->x, edge->p2->x); + tn->bbox.y1 = LAA_MIN(edge->p1->y, edge->p2->y); + tn->bbox.x2 = LAA_MAX(edge->p1->x, edge->p2->x); + tn->bbox.y2 = LAA_MAX(edge->p1->y, edge->p2->y); + tn->x1 = edge->p1->x; tn->y1 = edge->p1->y; + tn->x2 = edge->p2->x; tn->y2 = edge->p2->y; + tn->p1ly = edge->p1->user_long; tn->p1fx = edge->p1->fixed || homed(edge->p1); + tn->p2ly = edge->p2->user_long; tn->p2fx = edge->p2->fixed || homed(edge->p2); + tn->ely = edge->user_long; tn->efx = edge->fixed; + tn->net = net; + + rtrnd_rtree_insert(r2net, tn, &tn->bbox); + + tn->next = tns->head; + tns->head = tn; + } + + +#warning TODO: free mst fields +} + +/* Main entry point, deals with the whole board */ +static void laa_2nets(rtrnd_t *ctx, rtrnd_layer_t *ly, rtrnd_rtree_t *r2net) +{ + htsp_entry_t *e; + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) + laa_2net(ctx, e->value, ly, r2net); +} Index: tags/0.9.0/src/plugins/rt_topo/laa2.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa2.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa2.c (revision 1402) @@ -0,0 +1,260 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step II: place via sites on 2nets, building the assignment graph; adds + potential via sites between crossings. Included from laa.c */ + +RTRND_INLINE double pt2offs(rt_topo_laa_2net_t *tn, double x, double y) +{ + g2d_vect_t pt; + g2d_cline_t cl; + + pt.x = x; pt.y = y; + cl.p1.x = tn->x1; cl.p1.y = tn->y1; + cl.p2.x = tn->x2; cl.p2.y = tn->y2; + return g2d_offs_cline_pt(&cl, pt); +} + +static rtrnd_2branch_t *br_append_point(rt_topo_laa_2net_t *tn, vt2br_t *br, double x, double y, int fixed, long pt_layers, int avoid_overlap) +{ + rtrnd_2branch_t *p; + + /* do not add overlapping points (zero length branches) */ + if (avoid_overlap && (br->used > 0)) { + p = &br->array[br->used-1]; + if ((fabs(p->x-x) < 0.00001) && (fabs(p->y-y) < 0.00001)) + return p; + } + + + p = vt2br_alloc_append(br, 1); + p->parent = tn; + p->offs = pt2offs(tn, x, y); + p->x = x; p->y = y; + p->coord_fixed = fixed; + p->pt_layers = pt_layers; + p->edge_ly_fixed = -1; /* assume free-to-allocate outgoing edge */ + p->cridx = -1; + return p; +} + +static int cmp_crossing(const void *a, const void *b) +{ + const rtrnd_crossing_t *c1 = a, *c2 = b; + + if (c1->offs > c2->offs) return 1; + return -1; +} + +/* Look for 2net crossings to create potential via sites in 2nets */ +static void laa_2net_vias(rtrnd_t *ctx, rtrnd_net_t *net, rtrnd_layer_t *ly, rtrnd_rtree_t *r2net) +{ + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn, *cn; + vtcr_t cr = {0}; /* crossings */ + long n, lall = layer_bits_all(ctx); + +printf("2nets for %s:\n", net->hdr.oid); + for(tn = tns->head; tn != NULL; tn = tn->next) { + rtrnd_rtree_it_t it; + g2d_cline_t l1; + l1.p1.x = tn->x1; l1.p1.y = tn->y1; l1.p2.x = tn->x2; l1.p2.y = tn->y2; + + rtrnd_line_new(ly, NULL, NULL, tn->x1, tn->y1, tn->x2, tn->y2, tn->efx ? 0.01 : 0.1, 0); +printf(" [%d:%02lx] %.3f;%.3f %.3f;%.3f\n", tn->efx, tn->ely, tn->x1, tn->y1, tn->x2, tn->y2); +printf(" %d:%02lx %d:%02lx Crossings for %p:\n", tn->p1fx, tn->p1ly, tn->p2fx, tn->p2ly, tn); + + /* find all crossings (in random order) and build co, a list of offsets on tn/l1 */ + cr.used = 0; + for(cn = rtrnd_rtree_first(&it, r2net, &tn->bbox); cn != NULL; cn = rtrnd_rtree_next(&it)) { + g2d_cline_t l2; + g2d_vect_t ip[2]; + g2d_offs_t offs[2]; + int iscs; + rtrnd_crossing_t *cp; + + if (cn->net == tn->net) + continue; + l2.p1.x = cn->x1; l2.p1.y = cn->y1; l2.p2.x = cn->x2; l2.p2.y = cn->y2; + + iscs = g2d_iscp_cline_cline(&l1, &l2, ip, offs); + switch(iscs) { + case 0: break; /* no crossing, just bboxes got close */ + case 1: /* 2net crossing in a single point (common case) */ + printf(" %p at %.02f;%.02f (single): %.03f\n", cn, ip[0].x, ip[0].y, offs[0]); + cp = vtcr_alloc_append(&cr, 1); + cp->offs = offs[0]; + cp->x = ip[0].x; cp->y = ip[0].y; + cp->cn = cn; + cp->bridx = -1; + break; + case 2: /* 2net crossing in an overlap (rare case); place a single via in the middle */ + printf(" %p at %.02f;%.02f (overlap): %03f\n", cn, (ip[0].x+ip[1].x)/2.0, (ip[0].y+ip[1].y)/2.0, (offs[0]+offs[1])/2.0); + cp = vtcr_alloc_append(&cr, 1); + cp->offs = (offs[0]+offs[1])/2.0; + cp->x = (ip[0].x+ip[1].x)/2.0; cp->y = (ip[0].y+ip[1].y)/2.0; + cp->cn = cn; + cp->bridx = -1; + break; + } + } + + /* sort offsets so it's easier to calculate midpoints for via sites */ + qsort(cr.array, cr.used, sizeof(rtrnd_crossing_t), cmp_crossing); + + /* calculate potential via sites */ + br_append_point(tn, &tn->br, tn->x1, tn->y1, tn->p1fx, tn->p1ly, 0); /* append start */ + if (tn->efx) { + tn->br.array[0].edge_ly_fixed = tn->ely; /* for fixed/static 2net edges, the outgoing edge of the branch is also fixed and is the same */ + for(n = 0; n < cr.used; n++) + cr.array[n].bridx = tn->br.used; + } + + /* build a list of potential via sites, if possible */ + if ((cr.used > 0) && !tn->efx) { + g2d_cvect_t last, curr; + /* if starting point does not reach every layer, need to add a via site, just in case */ + if (tn->p1ly != lall) { + g2d_cvect_t cross = g2d__cline_offs(&l1, cr.array[0].offs); + last.x = (tn->x1 + cross.x)/2; + last.y = (tn->y1 + cross.y)/2; + br_append_point(tn, &tn->br, last.x, last.y, 0, lall, 0); + } + + /* cross-index the crossing on the outgoing of the first segment */ + n = 0; + cr.array[n].bridx = tn->br.used-1; + tn->br.array[tn->br.used-1].cridx = n; + + /* sites in between 2 crossings */ + for(n = 0; n < cr.used; n++) { + curr = g2d__cline_offs(&l1, cr.array[n].offs); + if (n > 0) { + br_append_point(tn, &tn->br, (last.x + curr.x)/2, (last.y + curr.y)/2, 0, lall, 0); + /* cross-index the crossing on the outgoing of theis segment */ + cr.array[n].bridx = tn->br.used-1; + tn->br.array[tn->br.used-1].cridx = n; + } + last = curr; + } + /* if ending point does not reach every layer, need to add a via site, just in case */ + if (tn->p2ly != lall) + br_append_point(tn, &tn->br, (tn->x2 + last.x)/2, (tn->y2 + last.y)/2, 0, lall, 1); + } + else if ((cr.used == 0) && !tn->efx) { + /* special case: there are only a starting and an ending terminal and no + crossings; if neither terminals are 100% free to choose their layer, + better add a via so jumping layer is possible. Typical example: + a 2net ending in 2 SMD pads on opposit sides. */ + if ((tn->p1ly != lall) && (tn->p2ly != lall)) + br_append_point(tn, &tn->br, (tn->x1 + tn->x2)/2, (tn->y1 + tn->y2)/2, 0, lall, 1); + } + br_append_point(tn, &tn->br, tn->x2, tn->y2, tn->p2fx, tn->p2ly, 1); /* append end */ + + printf(" via sites:"); + for(n = 0; n < tn->br.used; n++) { + double x = tn->br.array[n].x, y = tn->br.array[n].y, size = 0.2; + printf(" %.3f %.3f", x, y); + if (tn->br.array[n].pt_layers == lall) size = 0.4; + if (tn->br.array[n].coord_fixed) { + rtrnd_line_new(ly, NULL, NULL, x-size, y, x+size, y, 0.07, 0); + rtrnd_line_new(ly, NULL, NULL, x, y-size, x, y+size, 0.07, 0); + } + else { + rtrnd_line_new(ly, NULL, NULL, x-size, y-size, x+size, y+size, 0.07, 0); + rtrnd_line_new(ly, NULL, NULL, x-size, y+size, x+size, y-size, 0.07, 0); + } + } + printf("\n"); + + memcpy(&tn->cross, &cr, sizeof(cr)); + memset(&cr, 0, sizeof(cr)); + } + vtcr_uninit(&cr); +} + +/* assuming all branches are created, fill in br->cn_bridx */ +static void laa_2net_cn_bridx(rtrnd_t *ctx, rtrnd_net_t *net) +{ + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn; + + printf("cn_bridx %s:\n", net->hdr.oid); + for(tn = tns->head; tn != NULL; tn = tn->next) { + long n, i; + for(n = 0; n < tn->cross.used; n++) { + double offs = pt2offs(tn->cross.array[n].cn, tn->cross.array[n].x, tn->cross.array[n].y); + + if (tn->cross.array[n].cn->br.used <= 1) + continue; + + if (offs < 1.0) { + tn->cross.array[n].cn_bridx = -1; + for(i = 1; i < tn->cross.array[n].cn->br.used; i++) { + if (offs < tn->cross.array[n].cn->br.array[i].offs) { + tn->cross.array[n].cn_bridx = i-1; + break; + } + } + } + else + tn->cross.array[n].cn_bridx = tn->cross.array[n].cn->br.used - 2; + printf(" offs2=%f -> %d (self: %f)\n", offs, tn->cross.array[n].cn_bridx, tn->cross.array[n].offs); + assert(tn->cross.array[n].cn_bridx < (tn->cross.array[n].cn->br.used-1)); + assert(tn->cross.array[n].cn_bridx != -1); + assert(tn->cross.array[n].bridx >= 0); + { /* look up the pair of this crossing */ + tn->cross.array[n].cn_cr = NULL; + for(i = 0; i < tn->cross.array[n].cn->cross.used; i++) { + rtrnd_crossing_t *cr2 = &tn->cross.array[n].cn->cross.array[i]; + if (cr2->bridx == tn->cross.array[n].cn_bridx) { + tn->cross.array[n].cn_cr = cr2; + tn->cross.array[n].cn_cridx = i; + break; + } + } + assert(tn->cross.array[n].cn_cr != NULL); + } + } + } +} + +/* Main entry point, deals with the whole board */ +static void laa_2vias(rtrnd_t *ctx, rtrnd_layer_t *ly, rtrnd_rtree_t *r2net) +{ + htsp_entry_t *e; + + /* create via sites on each 2net */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) + laa_2net_vias(ctx, e->value, ly, r2net); + + /* fill in cn_bridx */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) + laa_2net_cn_bridx(ctx, e->value); + +} Index: tags/0.9.0/src/plugins/rt_topo/laa3.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa3.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa3.c (revision 1402) @@ -0,0 +1,309 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step III: optimize the assignment graphs; result is a layer assignment. + Included from laa.c */ + +typedef struct { + rtrnd_t *ctx; + rtrnd_rtree_t *r2net; + + /* cache */ + vtp0_t hull; + vtve0_t all_pts; +} laa3_t; + +static void laa_br_init_2net(rtrnd_t *ctx, rt_topo_laa_2net_t *tn) +{ + int n, lid, start = -1, end = -1; + + /* allocate current assignment */ + tn->asg = malloc(tn->br.used); + memset(tn->asg, -1, tn->br.used); + + /* simple case: there's a common layer in first and last node, use that + layer all the way long */ + for(lid = 0; lid < ctx->board->layers.used; lid++) { + long lb = (1 << lid); + if ((tn->br.array[0].pt_layers & lb) && (tn->br.array[tn->br.used-1].pt_layers & lb)) { + memset(tn->asg, lid, tn->br.used); + return; + } + } + + /* no common layer - figure start and end layer */ + for(lid = 0; (lid < ctx->board->layers.used) && ((start < 0) || (end < 0)); lid++) { + long lb = (1 << lid); + if ((start < 0) && (tn->br.array[0].pt_layers & lb)) + start = lid; + if ((end < 0) && (tn->br.array[tn->br.used-1].pt_layers & lb)) + end = lid; + } + + assert(start >= 0); + assert(end >= 0); + + /* go on start layer until the first via then on dest layer */ + tn->asg[0] = start; + for(n = 1; n < tn->br.used; n++) + tn->asg[n] = end; +} + +static void laa_br_init_net(rtrnd_t *ctx, rtrnd_net_t *net) +{ + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn; + + for(tn = tns->head; tn != NULL; tn = tn->next) + laa_br_init_2net(ctx, tn); +} + +static void laa_br_get_ends_on(const rt_topo_laa_2net_t *tn, int bridx, g2d_cline_t *dst, int indices[2], int lid) +{ + int start, end; + + if (lid < 0) + lid = tn->asg[bridx]; /* default lid is the assigned lid */ + + /* find the first branch that has an outgoing line on a different layer, backward */ + for(start = bridx; start >= 0; start--) + if (tn->asg[start] != lid) + break; + start++; /* and then return to the one that first used our layer */ + + /* find the first branch that has an outgoing line on a different layer, forward */ + for(end = bridx; end < tn->br.used; end++) + if (tn->asg[end] != lid) + break; + if (end == tn->br.used) + end--; + + dst->p1.x = tn->br.array[start].x; dst->p1.y = tn->br.array[start].y; + dst->p2.x = tn->br.array[end].x; dst->p2.y = tn->br.array[end].y; + indices[0] = start; + indices[1] = end; +} + +#include "laa3_detour.c" + +typedef struct { + vtve0_t pts; /* of rtrnd_2branch_t * */ + unsigned make_pts:1; /* whether to fill in pts */ + const struct rt_topo_laa_2net_s *tn_detouring; /* the 2net hat is making the detour (shorter detour) */ +} detour_t; + +static double laa_cross_cost(laa3_t *laa3, const rt_topo_laa_2net_t *tn, const rtrnd_crossing_t *cr, detour_t *det) +{ + const rt_topo_laa_2net_t *tn1 = tn, *tn2 = cr->cn; + int bridx1 = cr->bridx, bridx2 = cr->cn_bridx; + double res; + vtve0_t *pts; + + assert(tn1 != NULL); + assert(tn2 != NULL); + assert(bridx1 >= 0); + assert(bridx2 >= 0); + + /* if they are not on the same layer, there is no crossing so the cost is 0 */ + if (tn1->asg[bridx1] != tn2->asg[bridx2]) + return 0; + + if (det == NULL) + return 1; + + pts = det->make_pts ? &det->pts : &laa3->all_pts; + pts->used = 0; + det->tn_detouring = NULL; + + res = HUGE_VAL; + if (laa_detour_len(laa3, tn1, bridx1, tn2, bridx2, pts, &res, det->make_pts)) + det->tn_detouring = tn1; + if (laa_detour_len(laa3, tn2, bridx2, tn1, bridx1, pts, &res, det->make_pts)) + det->tn_detouring = tn2; + + /* corner case: since vias size is 0, a detour can end up being 0 long: + + B + | + A----B----A + + In this case net A will go around the bottom B pin, but that will still be + 0 detour because that pin is in-line with A pins. In this case we need to + return a non-zero value so that the crossing has a cost */ + if (res == 0) + res = 0.0001; + + return res; +} + +static void laa_br_print_net(laa3_t *laa3, rtrnd_net_t *net) +{ + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn; + printf(" net %s\n", net->hdr.oid); + for(tn = tns->head; tn != NULL; tn = tn->next) { + int lid, n; + printf(" 2net between %.2f;%2f and %.2f;%2f\n", tn->x1, tn->y1, tn->x2, tn->y2); + for(lid = 0; lid < laa3->ctx->board->layers.used; lid++) { + long lb = 1 << lid; + printf(" "); + for(n = 0; n < tn->br.used; n++) { + int ahere = (tn->br.array[n].pt_layers & lb); + int athere = (n < tn->br.used-1) ? (tn->br.array[n+1].pt_layers & lb) : 0; + const char *conn; + if (n >= tn->br.used-1) + conn = ""; + else if ((tn->asg != NULL) && (tn->asg[n] == lid)) { + if (tn->br.array[n].cridx >= 0) { + int cridx = tn->br.array[n].cridx; + if (laa_cross_cost(laa3, tn, &tn->cross.array[cridx], NULL) == 0) + conn = "=x="; /* no real crossing */ + else + conn = "=X="; /* they are both on the same layer -> real crossing */ + } + else + conn = "==="; + } + else if (ahere && athere) + conn = "---"; + else + conn = "..."; + printf("%c%s", + ahere ? '+' : '.', + conn + ); + } + printf("\n"); + } + } +} + +static void laa_br_draw_net(laa3_t *laa3, rtrnd_net_t *net, vtp0_t *annot) +{ + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn; + detour_t det = {0}; + + det.make_pts = 1; + + + for(tn = tns->head; tn != NULL; tn = tn->next) { + int n, lid, ci; + + for(n = 0; n < tn->br.used-1; n++) { + double x1, y1, x2, y2; + lid = tn->asg[n]; + if (lid < 0) continue; + x1 = tn->br.array[n].x; y1 = tn->br.array[n].y; + x2 = tn->br.array[n+1].x; y2 = tn->br.array[n+1].y; + + rtrnd_line_new(annot->array[lid], NULL, NULL, x1, y1, x2, y2, 0.2, 0); + } + /* draw detours in thin */ + for(ci = 0; ci < tn->cross.used; ci++) { + double cc = laa_cross_cost(laa3, tn, &tn->cross.array[ci], &det); + if (cc > 0) { + long l; + printf("CROSSING at %.2f;%.2f: detour len=%ld %.2f\n", + tn->cross.array[ci].x, tn->cross.array[ci].y, + det.pts.used, cc); + for(l = 1; l < det.pts.used; l++) + rtrnd_line_new(annot->array[lid], NULL, NULL, + det.pts.array[l-1].x, det.pts.array[l-1].y, + det.pts.array[l].x, det.pts.array[l].y, + 0.05, 0); + + rtrnd_line_new(annot->array[lid], NULL, NULL, + det.pts.array[l-1].x, det.pts.array[l-1].y, + det.pts.array[0].x, det.pts.array[0].y, + 0.05, 0); + } + } + } +} + +#include "laa3_solve.c" +#include "laa3_render.c" + +/* Main entry point, deals with the whole board */ +static int laa_solve(rtrnd_t *ctx, vtp0_t *annot, rtrnd_rtree_t *r2net, rt_topo_laa2rbs_t *dst) +{ + htsp_entry_t *e; + int n, i, q, res = 0; + laa3_t laa3 = {0}; + + laa3.ctx = ctx; + laa3.r2net = r2net; + + /* set up annotation layers */ + for(n = 0; n < ctx->board->layers.used; n++) { + rtrnd_layer_t *src = ctx->board->layers.array[n]; + rtrnd_layer_t *dst = calloc(sizeof(rtrnd_layer_t), 1); + + rtrnd_layer_init(dst, src->name); + strcpy(dst->color, src->color); + vtp0_append(annot, dst); + /* modify the color */ + for(i = 0; i < 3; i++) { + char *c = &dst->color[1+i*2]; + if ((*c >= '0') && (*c <= '9')) + q = *c - '0'; + else if ((*c >= 'a') && (*c <= 'f')) + q = *c - 'a' + 10; + else if ((*c >= 'A') && (*c <= 'F')) + q = *c - 'A' + 10; + q += 3; + if (q > 15) + q = 15; + if (q < 10) + *c = q + '0'; + else + *c = q - 10 + 'a'; + } + } + + /* create the initial allocation */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) + laa_br_init_net(ctx, e->value); + + if (laa_test_hook[3] != NULL) laa_test_hook[3](ctx, annot, r2net); + + res |= laa3_solve(&laa3); + + if (res == 0) + laa3_render(&laa3, dst); + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + laa_br_print_net(&laa3, e->value); + laa_br_draw_net(&laa3, e->value, annot); + } + + vtp0_uninit(&laa3.hull); + vtve0_uninit(&laa3.all_pts); + return res; +} Index: tags/0.9.0/src/plugins/rt_topo/laa3_detour.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa3_detour.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa3_detour.c (revision 1402) @@ -0,0 +1,226 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step III: calculate minimum detour of a branch component around a + connected component of a net. + Included from laa3.c */ + +/* append the branch point br to pts if it is on the requested side of tncl */ +static void laa_detour_append_sidept(vtve0_t *pts, g2d_cline_t *tncl, rtrnd_2branch_t *br, int req_side) +{ + g2d_vect_t pt; + g2d_calc_t d; + g2d_vect_t ve; + + pt.x = br->x; pt.y = br->y; + d = g2d_side_cline_pt(tncl, pt); + + /* don't append if we are on the wrong side */ + if (req_side && (d > 0)) return; + if (!req_side && (d < 0)) return; + + /* NOTE: d == 0: it is on the line; append it for a corner case: + we may have exacty 3 points lined up */ + + ve.x = br->x; ve.y = br->y; + vtve0_append(pts, ve); +} + +static void laa_detour_append_open(rtrnd_2branch_t **open, rtrnd_2branch_t *br) +{ + if (br->found) + return; + + br->found_next = *open; + *open = br->found_next; + br->found = 1; +} + +/* find any outgoing 2net from br and: + - add the terminating point (on the same layer) to pts + - if it uses the current layer (lid) all the way to the other endpoint, + add the other endpoint to the open list as well */ +static void laa_detour_find_tns(laa3_t *laa3, vtve0_t *pts, rtrnd_2branch_t **open, g2d_cline_t *tncl, int lid, rtrnd_net_t *net, rtrnd_2branch_t *br, int side_req) +{ + const rt_topo_laa_2net_t *tn; + rtrnd_rtree_it_t it; + rtrnd_rtree_box_t bbox; + + bbox.x1 = br->x - 0.001; bbox.y1 = br->y - 0.001; + bbox.x2 = br->x + 0.001; bbox.y2 = br->y + 0.001; + for(tn = rtrnd_rtree_first(&it, laa3->r2net, &bbox); tn != NULL; tn = rtrnd_rtree_next(&it)) { + int lasti = tn->br.used - 1; + rtrnd_2branch_t *br1 = &tn->br.array[0], *br2 = &tn->br.array[lasti]; + if ((br1->x == br->x) && (br1->y == br->y)) { + /* first point match, let's find our way toward the second point */ + g2d_cline_t cl; + int idx[2]; + laa_br_get_ends_on(tn, 0, &cl, idx, lid); + br1->found = 1; + laa_detour_append_sidept(pts, tncl, &tn->br.array[idx[1]], side_req); + if (idx[1] == lasti) /* all the 2net is used, may continue from the second point */ + laa_detour_append_open(open, br2); + } + else if ((br2->x == br->x) && (br2->y == br->y)) { + /* first point match, let's find our way toward the second point */ + g2d_cline_t cl; + int idx[2]; + laa_br_get_ends_on(tn, lasti, &cl, idx, lid); + br2->found = 1; + laa_detour_append_sidept(pts, tncl, &tn->br.array[idx[0]], side_req); + if (idx[0] == 0) /* all the 2net is used, may continue from the first point */ + laa_detour_append_open(open, br1); + } + } +} + +static int laa_detour_len_half(laa3_t *laa3, const rt_topo_laa_2net_t *tn, int bridx, g2d_cline_t *tncl, double tncl_len, const rt_topo_laa_2net_t *ttn, int tbridx, vtve0_t *pts, double *len, long start, int which, int make_pts) +{ + long n, hull_used; + int lid = tn->asg[bridx], hres, res = 0; + double dlen; + g2d_cline_t tcl; + rtrnd_2branch_t *open = NULL; /* branches to check from */ + rtrnd_2branch_t *closed = NULL; /* branches to clear ->found on */ + int idx[2]; + + /* append the ends of the section-on-this-layer of the crossing branch */ + laa_br_get_ends_on(ttn, tbridx, &tcl, idx, lid); + laa_detour_append_sidept(pts, tncl, &ttn->br.array[idx[0]], which); + laa_detour_append_sidept(pts, tncl, &ttn->br.array[idx[1]], which); + ttn->br.array[idx[0]].found = 1; + ttn->br.array[idx[0]].found_next = open; + open = &ttn->br.array[idx[0]]; + ttn->br.array[idx[1]].found = 1; + ttn->br.array[idx[1]].found_next = open; + open = &ttn->br.array[idx[1]]; + + /* set up open: if our crossing ends in an endpoint, append new branches ending there */ + if (idx[0] == 0) + laa_detour_append_open(&open, &ttn->br.array[idx[0]]); + if (idx[1] == (ttn->br.used-1)) + laa_detour_append_open(&open, &ttn->br.array[idx[1]]); + + while(open != NULL) { + rtrnd_2branch_t *br = open; + open = open->found_next; + br->found_next = closed; + closed = br; + + laa_detour_find_tns(laa3, pts, &open, tncl, lid, ttn->net, br, which); + } + + /* clear found flags */ + { + rtrnd_2branch_t *br, *next; + for(br = closed; br != NULL; br = next) { + next = br->found_next; + br->found = 0; + br->found_next = NULL; + } + } + + /* now all points are in pts, from 'start' - calculate the hull */ + vtp0_enlarge(&laa3->hull, pts->used - start + 4); + hull_used = laa3->hull.alloced; + hres = g2d_chull((g2d_vect_t **)laa3->hull.array, &hull_used, pts->array+start, pts->used - start); + assert(hres == 0); + laa3->hull.used = hull_used; + + /* calculate detour len (depends on [used+1] being the first point */ + dlen = -2 * tncl_len; /* the original line is replaced by the detour; subtract it once more because the penalty is not the total length of the detour but how much longer it is than the original straight line solution */ + for(n = 0; n < laa3->hull.used; n++) { /* this depends on the hull algo really setting one extra point beyond the end which matches the first point */ + g2d_vect_t *a = laa3->hull.array[n], *b = laa3->hull.array[n+1]; + dlen += sqrt(g2d__distance2(g2d_cvect_t_convfrom_g2d_vect_t(*a), g2d_cvect_t_convfrom_g2d_vect_t(*b))); + } + + if (dlen < *len) { + if (make_pts) { /* save points for drawing the detour, when requested */ + g2d_vect_t *v = malloc(sizeof(g2d_vect_t) * (laa3->hull.used+1)); + + /* copy over the points in the right order */ + for(n = 0; n < laa3->hull.used; n++) { + g2d_vect_t *a = laa3->hull.array[n]; + v[n] = *a; + } + + v[n].x = 0; v[n].y = 0; /* terminator (unused really) */ + + /* replace the array in pts */ + free(pts->array); + pts->array = v; + pts->used = pts->alloced = laa3->hull.used; + } + else + pts->used = start; + + *len = dlen; + res = 1; + } + else /* we are not better, forget it! */ + pts->used = start; + + return res; +} + +/* calculate a detour tn:bridx needs to do around ttn at ttn:tbridx; use + pts for temporary storage. Currently known shortest detour is in len. + If the new detour is + - shorter: change *len and pts to hold the new detour + - not shorter: leave pts and len as is. + Return 1 if this detour is shorter than the previous +*/ +static int laa_detour_len(laa3_t *laa3, const rt_topo_laa_2net_t *tn, int bridx, const rt_topo_laa_2net_t *ttn, int tbridx, vtve0_t *pts, double *len, int make_pts) +{ + g2d_cline_t tncl; + long start; + int idx[2], ret = 0; + g2d_vect_t ve; + double tncl_len; + + laa_br_get_ends_on(tn, bridx, &tncl, idx, -1); + tncl_len = sqrt(g2d__distance2(g2d_cvect_t_convfrom_g2d_vect_t(tncl.p1), g2d_cvect_t_convfrom_g2d_vect_t(tncl.p2))); + + /* insert the line segment from the original, for first half */ + start = pts->used; + ve.x = tn->br.array[idx[0]].x; ve.y = tn->br.array[idx[0]].y; + vtve0_append(pts, ve); + ve.x = tn->br.array[idx[1]].x; ve.y = tn->br.array[idx[1]].y; + vtve0_append(pts, ve); + ret |= laa_detour_len_half(laa3, tn, bridx, &tncl, tncl_len, ttn, tbridx, pts, len, start, 0, make_pts); + + /* insert the line segment from the original, for second half */ + start = pts->used; + ve.x = tn->br.array[idx[0]].x; ve.y = tn->br.array[idx[0]].y; + vtve0_append(pts, ve); + ve.x = tn->br.array[idx[1]].x; ve.y = tn->br.array[idx[1]].y; + vtve0_append(pts, ve); + ret |= laa_detour_len_half(laa3, tn, bridx, &tncl, tncl_len, ttn, tbridx, pts, len, start, 1, make_pts); + + return ret; +} Index: tags/0.9.0/src/plugins/rt_topo/laa3_render.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa3_render.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa3_render.c (revision 1402) @@ -0,0 +1,215 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step III: convert the solution to a per layer 2net format needed + by the RBS code */ + +typedef struct { /* temp storage for ordering 2nets before creating them for the rbs */ + rt_topo_laa_2net_t *tn; + int bi1, bi2; /* [bi1..bi2) is the section of the laa 2net that is becoming the rbs 2net */ + vtp0_t before; + int is_before; + gdl_elem_t link; + unsigned inserted:1; +} laa2rbs_t; + +static void print_coord(rtrnd_2branch_t *br) +{ + if (br->via != NULL) + printf(" [%f %f]", br->via->x, br->via->y); + else + printf(" (%f %f)", br->x, br->y); +} + +static void laa3_render_order(laa2rbs_t *l2r) +{ + rt_topo_laa_2net_t *tn = l2r->tn; + int bi; + + for(bi = l2r->bi1; bi < l2r->bi2; bi++) { + rtrnd_2branch_t *br = &tn->br.array[bi], *br2; + rtrnd_crossing_t *cr; + + if (br->cridx < 0) continue; + cr = &tn->cross.array[br->cridx]; + if ((cr->tn_detouring == tn) && (cr->cn_bridx >= 0) && (cr->cn != NULL)) { + laa2rbs_t *o = br->ordinfo, *o2; + br2 = &cr->cn->br.array[cr->cn_bridx]; + o2 = br2->ordinfo; + printf(" ord: %p after %p!\n", o, o2); + if (o2 != NULL) { + vtp0_append(&o2->before, o); + o->is_before++; + } + } + } +} + +static laa2rbs_t *l2r_alloc(uall_stacks_t *ordstk, rt_topo_laa_2net_t *tn, int bi1, int bi2) +{ + laa2rbs_t *l2r = uall_stacks_alloc(ordstk); + int n; + + memset(l2r, 0, sizeof(laa2rbs_t)); + l2r->tn = tn; + l2r->bi1 = bi1; + l2r->bi2 = bi2; + + for(n = bi1; n < bi2; n++) + tn->br.array[n].ordinfo = l2r; + + return l2r; +} + +void laa3_render(laa3_t *laa3, rt_topo_laa2rbs_t *dst) +{ + rtrnd_t *ctx = laa3->ctx; + htsp_entry_t *e; + rt_topo_laa_2net_t *tn; + laa2rbs_t *l2r, *ch; + int bi, tni; + long n, added; + vtp0_t ord = {0}; + uall_stacks_t ordstk = {0}; + uall_sysalloc_t sys = {0}; + gdl_list_t S = {0}; + + sys.alloc = uall_stdlib_alloc; + sys.free = uall_stdlib_free; + sys.page_size = 4096; + ordstk.sys = &sys; + ordstk.elem_size = sizeof(laa2rbs_t); + + /* create a list of 2nets for each layer */ + for(n = 0; n < ctx->board->layers.used; n++) + vtp0_append(&dst->ly2nets, calloc(sizeof(gdl_list_t), 1)); + +printf("** RENDER **\n"); + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn = tns->head, tni=0; tn != NULL; tn = tn->next, tni++) { + int currly = tn->asg[0], start = 0; + for(bi = 1; bi < tn->br.used; bi++) { + if (tn->asg[bi] != currly) { +printf(" net: %s:%d %d..%d bily: %d currly: %d", net->hdr.oid, tni, start, bi, tn->asg[bi], currly); +print_coord(&tn->br.array[start]); +print_coord(&tn->br.array[bi]); + l2r = l2r_alloc(&ordstk, tn, start, bi); + vtp0_append(&ord, l2r); +printf(" -> %p\n", l2r); + currly = tn->asg[bi]; + start = bi; + } + } + if (start != bi-1) { +printf(" net: %s:%d %d..%d", net->hdr.oid, tni, start, bi-1); +print_coord(&tn->br.array[start]); +print_coord(&tn->br.array[bi-1]); + l2r = l2r_alloc(&ordstk, tn, start, bi-1); + vtp0_append(&ord, l2r); +printf(" -> %p\n", l2r); + } + } + } + + /* build the ordering graph */ + for(n = 0; n < ord.used; n++) + laa3_render_order(ord.array[n]); + + +printf("Final order on %ld nets:\n", ord.used); + + /* Kahn's algorithm for topological sorting */ + for(n = 0; n < ord.used; n++) { + l2r = ord.array[n]; + if (l2r->is_before == 0) + gdl_insert(&S, l2r, link); + } + + add_more:; + while((l2r = gdl_first(&S)) != NULL) { + rtrnd_2branch_t *br1 = &l2r->tn->br.array[l2r->bi1], *br2 = &l2r->tn->br.array[l2r->bi2]; + long ly = l2r->tn->asg[l2r->bi1]; + gdl_list_t *lst = dst->ly2nets.array[ly]; + rt_topo_2net_t *res2net; + + gdl_remove(&S, l2r, link); + +printf(" %p ly=%d: %s %f;%f %f;%f\n", l2r, ly, br1->parent->net->hdr.oid, br1->x, br1->y, br2->x, br2->y); + if (!l2r->inserted) { + res2net = calloc(sizeof(rt_topo_2net_t), 1); + res2net->x[0] = br1->x; res2net->y[0] = br1->y; + res2net->x[1] = br2->x; res2net->y[1] = br2->y; + res2net->net = br1->parent->net; + gdl_append(lst, res2net, link); + l2r->inserted = 1; +printf("Insert: %p\n", l2r); + } + + for(n = l2r->before.used - 1; n >= 0; n--) { + ch = l2r->before.array[n]; + assert(ch->is_before > 0); + ch->is_before--; + if (ch->is_before == 0) { + if (ch->link.parent == NULL) + gdl_insert(&S, ch, link); + } + } + l2r->before.used = 0; + } + + + added = 0; + for(n = 0; n < ord.used; n++) { /* append remainings at the end */ + l2r = ord.array[n]; + if (!l2r->inserted) { + gdl_append(&S, l2r, link); +printf("Append: %p\n", l2r); + added++; + } + } + if (added) + goto add_more; + + + /* free temporary data */ + for(n = 0; n < ord.used; n++) { + l2r = ord.array[n]; + vtp0_uninit(&l2r->before); + } + vtp0_uninit(&ord); + uall_stacks_clean(&ordstk); + + printf(" Resulting ordered nets: (%ld); per layer:\n", gdl_length(&S)); + for(n = 0; n < 2; n++) { + gdl_list_t *lst = dst->ly2nets.array[n]; + printf(" [%ld] %ld\n", n, lst == NULL ? 0 : gdl_length(lst)); + } +} + Index: tags/0.9.0/src/plugins/rt_topo/laa3_solve.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/laa3_solve.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/laa3_solve.c (revision 1402) @@ -0,0 +1,396 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA step III: find the optimal resolution of crossings by activating + vias and detorus */ + +static double laa_cost_2net_update(rt_topo_laa_2net_t *tn) +{ + double cost = 0; + int ci; + + for(ci = 0; ci < tn->cross.used; ci++) { + rtrnd_crossing_t *cr = &tn->cross.array[ci]; + cost += cr->detcost; + } + + tn->cost_detour = cost; + return cost; +} + + +/* Wire length (detour) cost, already multipled by 1-alpha */ +static detour_t laa_cost_det = {0}; +static double laa_cost_2net_calc_cross(laa3_t *laa3, rt_topo_laa_2net_t *tn, int ci, int update) +{ + rtrnd_crossing_t *cr = &tn->cross.array[ci]; + double c = laa_cross_cost(laa3, tn, cr, &laa_cost_det) * rt_topo_cfg.alpha2; + if (update) { + cr->detcost = c; + cr->tn_detouring = laa_cost_det.tn_detouring; + } + return c; +} + +/* Total via cost, already multiplied by alpha */ +static double laa_cost_2net_calc_via_layer(laa3_t *laa3, rt_topo_laa_2net_t *tn, int update) +{ + int n; + double cost = 0; + for(n = 1; n < tn->br.used; n++) { + if (tn->asg[n-1] != tn->asg[n]) + cost += rt_topo_cfg.alpha; + } + if (update) + tn->cost_vialayer = cost; + return cost; +} + +static void laa3_solve_init(laa3_t *laa3) +{ + double cost = 0; + htsp_entry_t *e; + rtrnd_t *ctx = laa3->ctx; + + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + rt_topo_laa_2net_t *tn; + + for(tn = tns->head; tn != NULL; tn = tn->next) { + int ci; + for(ci = 0; ci < tn->cross.used; ci++) + laa_cost_2net_calc_cross(laa3, tn, ci, 1); + cost += laa_cost_2net_update(tn); + } + } + + printf("initial board cost: %f\n", cost); +} + +static double laa3_solve_best(laa3_t *laa3) +{ + htsp_entry_t *e; + rtrnd_t *ctx = laa3->ctx; + double best_gain = 0, gain, best_detcost, detcost, best_vialayercost, vialayercost; + rt_topo_laa_2net_t *tn, *best_tn = NULL; + int lid, ci, best_ci = -1, best_lid = -1, orig_lid; + + /* take each crossing... */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn = tns->head; tn != NULL; tn = tn->next) { + for(ci = 0; ci < tn->cross.used; ci++) { + rtrnd_crossing_t *cr = &tn->cross.array[ci]; + rtrnd_2branch_t *br = &tn->br.array[cr->bridx]; + long lbit = 1; + + if (cr->detcost/2 > best_gain) { + /* ... and try relocating the segment to different layers and see the cost */ + orig_lid = tn->asg[cr->bridx]; /* remember original assignment */ + for(lid = 0; (lid < ctx->board->layers.used); lid++, lbit <<= 1) { + if (lid == orig_lid) continue; + if (!(br->pt_layers & lbit)) continue; + tn->asg[cr->bridx] = lid; /* temporarily change the assingment so costs can be recalculated */ + detcost = laa_cost_2net_calc_cross(laa3, tn, ci, 0); + vialayercost = laa_cost_2net_calc_via_layer(laa3, tn, 0); + gain = (cr->detcost + tn->cost_vialayer) - (detcost + vialayercost); + if (gain > best_gain) { + best_gain = gain; + best_tn = tn; + best_ci = ci; + best_lid = lid; + best_detcost = detcost; + best_vialayercost = vialayercost; + } + } + tn->asg[cr->bridx] = orig_lid; /* restore original settings for now */ + } + } + } + } + + printf("laa3 solver gain: %f", best_gain); + if (best_gain > 0) { + rtrnd_crossing_t *cr = &best_tn->cross.array[best_ci], *cr2; + int cridx2; + + printf(" by moving tn %p seg %d from layer %d to %d\n", best_tn, best_ci, best_tn->asg[cr->bridx], best_lid); + best_tn->asg[cr->bridx] = best_lid; + cr->detcost = best_detcost; + best_tn->cost_vialayer = best_vialayercost; + + /* need to update the other side of the crossing; via/layer cost doesn't need update as it didn't change */ + laa_cost_2net_calc_cross(laa3, cr->cn, cr->cn_cridx, 1); + +/* can not do this check: it may be that some crossing happens to be on the + same coord as an unrelated pin; common when the board uses grid and well + aligned pins */ +#ifdef DOUBLE_CHECK_CROSSING + for(cridx2 = 0; cridx2 < cr->cn->cross.used; cridx2++) { + cr2 = &cr->cn->cross.array[cridx2]; + if ((fabs(cr2->x-cr->x) < 0.0001) && (fabs(cr2->y-cr->y) < 0.0001)) { + if (cr->cn_cr != cr2) + printf(" update2 mismatch %d %d at {%f %f} vs {%f %f} (%p == %p)\n", cr->cn_bridx, cr2->bridx, cr->x, cr->y, cr2->x, cr2->y, cr->cn_cr, cr2); + assert(cr->cn_cr == cr2); + } + } +#endif + + } + printf("\n"); + return best_gain; +} + +static int found_stop_cb(rtrnd_find_t *ctx, rtrnd_any_obj_t *new_obj, rtrnd_any_obj_t *arrived_from) +{ + if (arrived_from == NULL) + return 0; +printf("found %s %p\n", new_obj->hdr.oid, arrived_from); + return 1; +} + +static rtrnd_via_t *laa3_find_via(laa3_t *laa3, vtp0_t *vias, double x, double y, rtrnd_net_t *net) +{ + long n; + for(n = 0; n < vias->used; n++) { + rtrnd_via_t *via = vias->array[n]; + if ((via->x == x) && (via->y == y) && (via->hdr.net == net)) + return via; + } + return NULL; +} + +static int laa3_board_has_via(rtrnd_t *ctx, double x, double y, rtrnd_net_t *net) +{ + rtrnd_rtree_it_t it; + rtrnd_rtree_box_t bbox; + + bbox.x1 = x - 0.001; bbox.y1 = y - 0.001; + bbox.x2 = x + 0.001; bbox.y2 = y + 0.001; + + return (rtrnd_rtree_first(&it, &ctx->board->vias, &bbox) != NULL); +} + +static void laa3_check_stenier_via(laa3_t *laa3, vtp0_t *vias, rt_topo_laa_2net_t *tn1, int i1, rt_topo_laa_2net_t *tn2, int i2, double x, double y) +{ + int fx1, fx2; + int ly1, ly2; + rtrnd_via_t *via; + + fx1 = (i1 == 1) ? tn1->p1fx : tn1->p2fx; + fx2 = (i2 == 1) ? tn2->p1fx : tn2->p2fx; + + /* don't do anything if this endpoint is fixed (terminal) */ + if (fx1 || fx2) + return; + + ly1 = (i1 == 1) ? tn1->asg[0] : tn1->asg[LAA_MAX(tn1->br.used-1, 0)]; + ly2 = (i2 == 1) ? tn2->asg[0] : tn2->asg[LAA_MAX(tn2->br.used-1, 0)]; + + /* don't add via if there's no layer switch */ + if (ly1 == ly2) + return; + + /* add via if there's no via there already */ + via = laa3_find_via(laa3, vias, x, y, tn1->net); + if (via == NULL) { + char oid[128]; + printf("STEINER VIA: %f %f fx %d %d ly %d %d\n", x, y, fx1, fx2, ly1, ly2); + + sprintf(oid, "rt_topo_sv_%ld", vias->used); + via = rtrnd_via_alloc(oid, x, y, rt_topo_cfg.via_dia, rt_topo_cfg.via_clr); + via->hdr.net = tn1->net; + vtp0_append(vias, via); + } + + /* update two-net branch via bindings */ + if (i1 == 1) + tn1->br.array[0].via = via; + else + tn1->br.array[LAA_MAX(tn1->br.used-1, 0)].via = via; + if (i2 == 1) + tn2->br.array[0].via = via; + else + tn2->br.array[LAA_MAX(tn2->br.used-1, 0)].via = via; +} + +int laa3_try_place_vias(laa3_t *laa3, vtp0_t *vias) +{ + rtrnd_t *ctx = laa3->ctx; + rtrnd_via_t *via; + htsp_entry_t *e; + rt_topo_laa_2net_t *tn, *tn1, *tn2; + int bi, limit; + + /* create vias on steiner points if there's a layer switch */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn1 = tns->head; tn1 != NULL; tn1 = tn1->next) { + for(tn2 = tn1->next; tn2 != NULL; tn2 = tn2->next) { + if ((tn1->x1 == tn2->x1) && (tn1->y1 == tn2->y1)) + laa3_check_stenier_via(laa3, vias, tn1, 1, tn2, 1, tn1->x1, tn1->y1); + else if ((tn1->x1 == tn2->x2) && (tn1->y1 == tn2->y2)) + laa3_check_stenier_via(laa3, vias, tn1, 1, tn2, 2, tn1->x1, tn1->y1); + else if ((tn1->x2 == tn2->x2) && (tn1->y2 == tn2->y2)) + laa3_check_stenier_via(laa3, vias, tn1, 2, tn2, 2, tn1->x2, tn1->y2); + else if ((tn1->x2 == tn2->x1) && (tn1->y2 == tn2->y1)) + laa3_check_stenier_via(laa3, vias, tn1, 2, tn2, 1, tn1->x2, tn1->y2); + } + } + } + + + /* create vias where a branch switched layer */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn = tns->head; tn != NULL; tn = tn->next) { + for(bi = 1; bi < tn->br.used; bi++) { + if (tn->asg[bi] != tn->asg[bi-1]) { + char oid[128]; + sprintf(oid, "rt_topo_v_%ld", vias->used); + if (laa3_board_has_via(ctx, tn->br.array[bi].x, tn->br.array[bi].y, net)) + continue; + via = laa3_find_via(laa3, vias, tn->br.array[bi].x, tn->br.array[bi].y, net); + printf(" VIA at %f;%f: %p\n", tn->br.array[bi].x, tn->br.array[bi].y, via); + if (via == NULL) { + via = rtrnd_via_alloc(oid, tn->br.array[bi].x, tn->br.array[bi].y, rt_topo_cfg.via_dia, rt_topo_cfg.via_clr); + via->hdr.net = net; + vtp0_append(vias, via); + } + tn->br.array[bi].via = via; + } + } + } + } + + /* look at all two-net start and end point and see if it falls on a via + (and then bind it) */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn = tns->head; tn != NULL; tn = tn->next) { + if (tn->br.array[0].via == NULL) { + via = laa3_find_via(laa3, vias, tn->br.array[0].x, tn->br.array[0].y, net); + if (via != NULL) + tn->br.array[0].via = via; + } + bi = tn->br.used-1; + if (tn->br.array[bi].via == NULL) { + via = laa3_find_via(laa3, vias, tn->br.array[bi].x, tn->br.array[bi].y, net); + if (via != NULL) + tn->br.array[bi].via = via; + } + } + } + + /* resolve via geo collisions by randomly tuning via positions */ + for(limit = 1024; limit > 0; limit--) { + int collided = 0; + long n; + + for(n = 0; n < vias->used; n++) { + rtrnd_via_t *via = vias->array[n]; + rtrnd_find_t fctx = {0}; + + fctx.found_cb = found_stop_cb; + fctx.bloat = rt_topo_cfg.via_clr; + rtrnd_find_from_obj(&fctx, ctx->board, via); + if (fctx.nfound > 1) { + static int mtw_inited; + static psr_mtw_t mtw; +/*printf("via coll at %f;%f\n", via->x, via->y);*/ + if (!mtw_inited) { + psr_mtw_init(&mtw, 37); + mtw_inited = 1; + } + via->x += psr_mtw_rand01(&mtw) * 0.2 - 0.1; + via->y += psr_mtw_rand01(&mtw) * 0.2 - 0.1; + collided = 1; + } + rtrnd_find_free(&fctx); + } + if (!collided) + goto done; /* no collision => done */ + } +printf("Failed to resolve via sites\n"); + return -1; + + done: + + /* when ends are tied to vias make sure their coords are updated to via moves */ + for(e = htsp_first(&ctx->board->nets); e != NULL; e = htsp_next(&ctx->board->nets, e)) { + rtrnd_net_t *net = e->value; + rt_topo_2nets_t *tns = NETDATA_LAA(net); + for(tn = tns->head; tn != NULL; tn = tn->next) { + long idx; + via = tn->br.array[0].via; + if (via != NULL) { +printf("via end adjust1: %f;%f -> %f;%f\n", tn->x1, tn->y1, via->x, via->y); + tn->x1 = tn->br.array[0].x = via->x; + tn->y1 = tn->br.array[0].y = via->y; + } + idx = tn->br.used-1; + assert(idx >= 0); + via = tn->br.array[idx].via; + if (via != NULL) { +printf("via end adjust2: %f;%f -> %f;%f\n", tn->x2, tn->y2, via->x, via->y); + tn->x2 = tn->br.array[idx].x = via->x; + tn->y2 = tn->br.array[idx].y = via->y; + } + } + } + return 0; +} + +void laa3_realize_vias(laa3_t *laa3, vtp0_t *vias) +{ + rtrnd_t *ctx = laa3->ctx; + long n; + for(n = 0; n < vias->used; n++) { + rtrnd_via_t *via = vias->array[n]; + rtrnd_net_t *net = via->hdr.net; + via->hdr.net = NULL; + rtrnd_via_reg(ctx->board, net, via); + } +} + +static int laa3_solve(laa3_t *laa3) +{ + vtp0_t vias = {0}; + + laa3_solve_init(laa3); + while(laa3_solve_best(laa3) > 0) ; + if (laa3_try_place_vias(laa3, &vias) != 0) + return -1; + laa3_realize_vias(laa3, &vias); + return 0; +} Index: tags/0.9.0/src/plugins/rt_topo/regression/D2.tdx =================================================================== --- tags/0.9.0/src/plugins/rt_topo/regression/D2.tdx (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/regression/D2.tdx (revision 1402) @@ -0,0 +1,125 @@ +tEDAx v1 + +begin stackup v1 board_stackup + layer 3.top_copper top copper + lprop 3.top_copper display-color #8b2323 + layer 8.bottom_copper bottom copper + lprop 8.bottom_copper display-color #3a5fcd +end stackup + +begin polyline v1 pstk_0x56241c257460_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c25f580_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c267250_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c26f420_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c2773c0_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c27f360_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c287430_0x56241c0cc0d0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin layernet v1 3.top_copper + poly pcb/167/196 neta tmd pstk_0x56241c257460_0x56241c0cc0d0 12.7 35.56 + poly pcb/331/360 neta tmd pstk_0x56241c25f580_0x56241c0cc0d0 114.3 35.56 + poly pcb/396/425 netb tmd pstk_0x56241c267250_0x56241c0cc0d0 60.96 2.54 + poly pcb/458/487 netb tmd pstk_0x56241c26f420_0x56241c0cc0d0 55.88 48.26 + poly pcb/489/518 netb tmd pstk_0x56241c2773c0_0x56241c0cc0d0 66.04 48.26 + poly pcb/665/694 netc tmd pstk_0x56241c27f360_0x56241c0cc0d0 55.88 44.45 + poly pcb/696/725 netc tmd pstk_0x56241c287430_0x56241c0cc0d0 66.04 44.45 +end layernet + +begin polyline v1 pstk_0x56241c257460_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c25f580_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c267250_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c26f420_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c2773c0_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c27f360_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin polyline v1 pstk_0x56241c287430_0x56241c0cc2c0 + v -1.016 -1.016 + v 1.016 -1.016 + v 1.016 1.016 + v -1.016 1.016 +end polyline +begin layernet v1 8.bottom_copper + poly pcb/167/196 neta tmd pstk_0x56241c257460_0x56241c0cc2c0 12.7 35.56 + poly pcb/331/360 neta tmd pstk_0x56241c25f580_0x56241c0cc2c0 114.3 35.56 + poly pcb/396/425 netb tmd pstk_0x56241c267250_0x56241c0cc2c0 60.96 2.54 + poly pcb/458/487 netb tmd pstk_0x56241c26f420_0x56241c0cc2c0 55.88 48.26 + poly pcb/489/518 netb tmd pstk_0x56241c2773c0_0x56241c0cc2c0 66.04 48.26 + poly pcb/665/694 netc tmd pstk_0x56241c27f360_0x56241c0cc2c0 55.88 44.45 + poly pcb/696/725 netc tmd pstk_0x56241c287430_0x56241c0cc2c0 66.04 44.45 +end layernet + + +begin route_req v1 - + stackup board_stackup + via pcb/167/196 neta tmd 12.7 35.56 1.000001 0 + via pcb/331/360 neta tmd 114.3 35.56 1.000001 0 + via pcb/396/425 netb tmd 60.96 2.54 1.000001 0 + via pcb/458/487 netb tmd 55.88 48.26 1.000001 0 + via pcb/489/518 netb tmd 66.04 48.26 1.000001 0 + via pcb/665/694 netc tmd 55.88 44.45 1.000001 0 + via pcb/696/725 netc tmd 66.04 44.45 1.000001 0 + route_all +end route_req Index: tags/0.9.0/src/plugins/rt_topo/regression/D2.test =================================================================== --- tags/0.9.0/src/plugins/rt_topo/regression/D2.test (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/regression/D2.test (revision 1402) @@ -0,0 +1,2 @@ +hook laa3 + brlayer 60.96 41 1 Index: tags/0.9.0/src/plugins/rt_topo/regression/Makefile =================================================================== --- tags/0.9.0/src/plugins/rt_topo/regression/Makefile (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/regression/Makefile (revision 1402) @@ -0,0 +1,12 @@ +ROOT=../../../.. +include $(ROOT)/Makefile.conf +include $(ROOT)/src/route-rnd/Makefile.conf + +CFLAGS = $(CFLAGS_RTRND) -I$(ROOT)/src/route-rnd +LOCLIBS = $(LOCLIBS_RTRND) +LDLIBS = $(LOCLIBS) +LDFLAGS = $(LDFLAGS_RTRND) +RTLIB=$(ROOT)/src/route-rnd/libroute-rnd.a + +tester: tester.o + $(CC) $(LDFLAGS) -o tester tester.o $(RTLIB) $(LOCLIBS) \ No newline at end of file Index: tags/0.9.0/src/plugins/rt_topo/regression/tester.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/regression/tester.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/regression/tester.c (revision 1402) @@ -0,0 +1,171 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* LAA manual tester */ + +#include +#include +#include +#include +#include "geo.h" +#include +#include "route-rnd.h" +#include "compat_misc.h" +#include "../laa.h" + +FILE *testf; +htsi_t test_hooks; + +static void test_load(const char *testfn) +{ + char line[128], *s, *end; + + if (testfn == NULL) { + fprintf(stderr, "Error: missing argument -t testfn\n"); + exit(1); + } + + testf = fopen(testfn, "r"); + if (testf == NULL) { + fprintf(stderr, "Error: can't open %s for read\n", testfn); + exit(1); + } + + htsi_init(&test_hooks, strhash, strkeyeq); + while((s = fgets(line, sizeof(line), testf)) != NULL) { + while(isspace(*s)) s++; + if ((strncmp(s, "hook", 4) == 0) && isspace(s[4])) { + char *hook = s+5; + while(isspace(*hook)) hook++; + end = strpbrk(hook, "\r\n"); + if (end != NULL) *end = '\0'; + htsi_insert(&test_hooks, rnd_strdup(hook), ftell(testf)); + } + } +} + +#define test_run(hookname, stmt) \ +do { \ + long __l__ = htsi_get(&test_hooks, hookname); \ + char line[128], *s, *cmd, *arg; \ + if (__l__ <= 0) break; \ + fseek(testf, __l__, SEEK_SET); \ + while((s = fgets(line, sizeof(line), testf)) != NULL) { \ + while(isspace(*s)) s++; \ + if ((strncmp(s, "hook", 4) == 0) && isspace(s[4])) break; \ + cmd = s; \ + arg = strpbrk(cmd, " \t\r\n"); \ + if (arg != NULL) { \ + char *end; \ + *arg = '\0'; \ + arg++; \ + while(isspace(*arg)) arg++; \ + end = strpbrk(arg, "\r\n"); \ + if (end != NULL) *end = '\0'; \ + } \ + stmt; \ + } \ +} while(0) + +static void cmd_brlayer(rtrnd_t *ctx, rtrnd_rtree_t *r2net, double x, double y, int ly) +{ + rt_topo_laa_2net_t *tn; + rtrnd_rtree_it_t it; + g2d_vect_t pt; + rtrnd_rtree_box_t bbox; + + bbox.x1 = x - 0.001; bbox.y1 = y - 0.001; + bbox.x2 = x + 0.001; bbox.y2 = y + 0.001; + pt.x = x; pt.y = y; + +printf("size=%ld\n", r2net->size); + + for(tn = rtrnd_rtree_first(&it, r2net, &bbox); tn != NULL; tn = rtrnd_rtree_next(&it)) { + g2d_cline_t cl; + g2d_offs_t offs; +printf("tn\n"); + cl.p1.x = tn->x1; cl.p1.y = tn->y1; + cl.p2.x = tn->x2; cl.p2.y = tn->y2; + offs = g2d_offs_cline_pt(&cl, pt); + if ((offs >= 0) && (offs <= 1)) { + int n; + for(n = 0; n < tn->br.used-1; n++) { + rtrnd_2branch_t *br = &tn->br.array[n], *brn = &tn->br.array[n+1]; + if ((offs >= br->offs) && (offs < brn->offs)) { + br->edge_ly_fixed = ly; + tn->asg[n] = ly; + return; + } + } + } + } + fprintf(stderr, "Test error: can't find a two-net at %f;%f\n", x, y); + exit(1); +} + +static void manual_asg(rtrnd_t *ctx, vtp0_t *annot, rtrnd_rtree_t *r2net) +{ + printf("----------------MANUAL ASG\n"); + + test_run("laa3", { + if (strcmp(cmd, "brlayer") == 0) { + double x; + double y; + int ly; + if (sscanf(arg, "%lf %lf %d\n", &x, &y, &ly) != 3) { + fprintf(stderr, "Error: invalid brlayer args '%s'\n", arg); + exit(1); + } + cmd_brlayer(ctx, r2net, x, y, ly); + } + }); +} + + +int main(int argc, char *argv[]) +{ + int n; + const char *testfn = NULL; + + for(n = 1; n < argc; n++) { + char *cmd = argv[n], *arg = argv[n+1]; + if (*cmd == '\0') continue; /* ignore empty args, useful for the tester */ + if (*cmd == '-') { + while(*cmd == '-') cmd++; + switch(*cmd) { + case 't': testfn = arg; argv[n] = argv[n+1] = ""; n++; break; + } + } + } + + test_load(testfn); + + printf("Tester!\n"); + laa_test_hook[3] = manual_asg; + return route_rnd_main(argc, argv); +} Index: tags/0.9.0/src/plugins/rt_topo/rt_topo.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/rt_topo.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/rt_topo.c (revision 1402) @@ -0,0 +1,118 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "data.h" + +#include "laa.h" +#include "trbs.h" +#include "crbs.h" +#include "rt_topo.h" + +rt_topo_cfg_t rt_topo_cfg; + +static rtrnd_conf_t topo_cfg_desc_crbs[] = { + RTRND_CONF_COORD("wire_thick", 0.20, 0.01, 10, "signal wire thickness", &rt_topo_cfg.wire_thick) + RTRND_CONF_COORD("wire_clr", 0.20, 0.01, 10, "clearance around signal wire", &rt_topo_cfg.wire_clr) + RTRND_CONF_COORD("via_dia", 1.2, 0.01, 10, "via copper ring outer diameter", &rt_topo_cfg.via_dia) + RTRND_CONF_COORD("via_clr", 0.20, 0.01, 10, "clearance around via copper", &rt_topo_cfg.via_clr) + RTRND_CONF_DOUBLE("beta", 50, 0, 100, "via vs. wire length preference; high value = short wires, low value = less vias", &rt_topo_cfg.beta) + RTRND_CONF_BOOLEAN("mid_virt", 0, "split long triangulation edges in half by inserting 0 sized virtual points; makes more routes possible but also makes tracks longer with unnecessary curves and detours", &rt_topo_cfg.beta) +/* RTRND_CONF_BOOLEAN("octilinear", 0, "draw 90 and 45 degree lines", &rt_topo_cfg.octilin)*/ + RTRND_CONF_TERMINATE +}; + +static rtrnd_conf_t topo_cfg_desc_trbs[] = { + RTRND_CONF_COORD("wire_thick", 0.20, 0.01, 10, "signal wire thickness", &rt_topo_cfg.wire_thick) + RTRND_CONF_COORD("wire_clr", 0.20, 0.01, 10, "clearance around signal wire", &rt_topo_cfg.wire_clr) + RTRND_CONF_COORD("via_dia", 1.2, 0.01, 10, "via copper ring outer diameter", &rt_topo_cfg.via_dia) + RTRND_CONF_COORD("via_clr", 0.20, 0.01, 10, "clearance around via copper", &rt_topo_cfg.via_clr) + RTRND_CONF_DOUBLE("beta", 50, 0, 100, "via vs. wire length preference; high value = short wires, low value = less vias", &rt_topo_cfg.beta) +/* RTRND_CONF_BOOLEAN("octilinear", 0, "draw 90 and 45 degree lines", &rt_topo_cfg.octilin)*/ + RTRND_CONF_TERMINATE +}; + +static int route_topo(rtrnd_t *ctx, int (*rbs)(rtrnd_t *, rt_topo_laa2rbs_t *)) +{ + double dx = ctx->board->hdr.bbox.x2 - ctx->board->hdr.bbox.x1, dy = ctx->board->hdr.bbox.y2 - ctx->board->hdr.bbox.y1; + double diag = sqrt(dx*dx+dy*dy), alpha1; + int res = 0, n; + rt_topo_laa2rbs_t laa2rbs = {0}; + + alpha1 = 0.12 * diag * rt_topo_cfg.beta / 100.0; + rt_topo_cfg.alpha = alpha1/(1+alpha1); + rt_topo_cfg.alpha2 = 1.0 - rt_topo_cfg.alpha; + if (rt_topo_laa(ctx, &laa2rbs) != 0) { + printf("Failed to solve the layer assignment\n"); + return -1; + } + + res |= rbs(ctx, &laa2rbs); + + for(n = 0; n < ctx->board->layers.used; n++) { + gdl_list_t *tnl = laa2rbs.ly2nets.array[n]; + rt_topo_2net_t *tn; + while((tn = gdl_first(tnl)) != NULL) { + gdl_remove(tnl, tn, link); + free(tn); + } + free(tnl); + } + + return res; +} + +static int route_topo_trbs(rtrnd_t *ctx) +{ + return route_topo(ctx, rt_topo_trbs); +} + +static int route_topo_crbs(rtrnd_t *ctx) +{ + return route_topo(ctx, rt_topo_crbs); +} + + +static const rtrnd_router_t rtr_topo_trbs = { + "topo_trbs", "topological: LAA + triangulated rubber band sketch", + topo_cfg_desc_trbs, + route_topo_trbs +}; + +static const rtrnd_router_t rtr_topo_crbs = { + "topo_crbs", "topological: LAA + geometric rubber band sketch", + topo_cfg_desc_crbs, + route_topo_crbs +}; + +void rt_topo_init(void) +{ + vtp0_append(&rtrnd_all_router, (void *)&rtr_topo_trbs); + vtp0_append(&rtrnd_all_router, (void *)&rtr_topo_crbs); +} Index: tags/0.9.0/src/plugins/rt_topo/rt_topo.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/rt_topo.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/rt_topo.h (revision 1402) @@ -0,0 +1,29 @@ +#ifndef ROUTE_RND_TOPO_H +#define ROUTE_RND_TOPO_H + +#define NETDATA_LAA(net) ((net)->hdr.rt_data.p[0]) + +typedef struct { + double x[2], y[2]; /* endpoint coords */ + rtrnd_net_t *net; /* the net this 2net is part of */ + gdl_elem_t link; /* part of an ordered list of 2nets on the same layer */ +} rt_topo_2net_t; + +/* Used to communicate per layer 2nets between laa and rbs */ +typedef struct { + vtp0_t ly2nets; /* each element is a gdl_list of rt_topo_2net_t elements; index is layer ID */ +} rt_topo_laa2rbs_t; + +typedef struct { + /* configured */ + double wire_thick, wire_clr, via_dia, via_clr, beta; + int octilin, algo, mid_virt; + + /* calculated */ + double alpha, alpha2; + +} rt_topo_cfg_t; + +extern rt_topo_cfg_t rt_topo_cfg; + +#endif Index: tags/0.9.0/src/plugins/rt_topo/trbs.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs.c (revision 1402) @@ -0,0 +1,287 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "data.h" +#include "io.h" +#include "route_res.h" + +#include "trbs.h" + +/*#include */ + +#include "trbs_util.c" +#include "trbs_cdt.c" +#include "trbs_vis.c" +#include "trbs_route.c" +#include "trbs_pull.c" + +static void trbs_init(trbs_t *trbs, rtrnd_t *ctx) +{ + trbs->ctx = ctx; + + /* initialize the low level allocator: use libc's malloc/free */ + trbs->sys.alloc = uall_stdlib_alloc; + trbs->sys.free = uall_stdlib_free; + trbs->sys.page_size = 4096; /* how much memory to allocate to grow the stack */ + + /* initialize the stack allocators */ + trbs->crosses.sys = &trbs->sys; trbs->crosses.elem_size = sizeof(trbs_cross_t); + trbs->tedges.sys = &trbs->sys; trbs->tedges.elem_size = sizeof(trbs_edge_t); + +} + +static void trbs_clean(trbs_t *trbs, int routed_flag) +{ + long n; + trbs_2net_t *ttn; + + /* remove non-sentinel edge crosses */ + for(n = 0; n < trbs->cdt.edges.used; n++) { + edge_t *e = trbs->cdt.edges.array[n]; + trbs_edge_t *te = e->data; + trbs_cross_t *cr = gdl_first(&te->crosses), *next; + + for(cr = cr->link_edge.next; cr->link_edge.next != NULL; cr = next) { + next = cr->link_edge.next; + gdl_remove(&te->crosses, cr, link_edge); + } + + if (te->pp_blk) { + te->pp_blk = 0; + te->blocked = 0; + } + + te->cap = te->cap_orig; + } + + /* remove route crosses */ + for(ttn = gdl_first(&trbs->twonets); ttn != NULL; ttn = gdl_next(&trbs->twonets, ttn)) { + trbs_cross_t *cr; + while((cr = gdl_first(&ttn->route)) != NULL) + gdl_remove(&ttn->route, cr, link_route); + if (routed_flag) + ttn->routed = 0; + } + +} + +static void trbs_uninit(trbs_t *trbs) +{ + uall_stacks_clean(&trbs->crosses); + uall_stacks_clean(&trbs->tedges); +} + +static long cross_uids = 0; +trbs_cross_t *trbs_cross_new(trbs_t *trbs, trbs_2net_t *tnet, edge_t *edge, trbs_cross_t *aft) +{ + trbs_cross_t *cr = uall_stacks_alloc(&trbs->crosses); + trbs_edge_t *tedge = edge->data; + + memset(cr, 0, sizeof(trbs_cross_t)); + + cr->twonet = tnet; + cr->edge = edge; + if (aft != NULL) + gdl_insert_after(&tedge->crosses, aft, cr, link_edge); + + + cr->uid = cross_uids++; + return cr; +} + +static void trbs_draw_cross_uids(trbs_t *trbs, rtrnd_layer_t *ly_out) +{ + VTEDGE_FOREACH(edge, &trbs->cdt.edges) + trbs_edge_t *tedge = edge->data; + int n, len = gdl_length(&tedge->crosses); + trbs_cross_t *cr; + + for(n = 0, cr = tedge->crosses.first; n < len; n++, cr = cr->link_edge.next) { + char tmp[64]; + sprintf(tmp, "%ld", cr->uid); + rtrnd_text_new(ly_out, cr->x, cr->y, tmp, 0.25); + } + VTEDGE_FOREACH_END(); +} + +static void trbs_draw_routes(trbs_t *trbs, rtrnd_layer_t *ly_out, rtrnd_layer_t *ly_drw) +{ + rtrnd_any_obj_t *o; + trbs_2net_t *ttn; + for(ttn = gdl_first(&trbs->twonets); ttn != NULL; ttn = gdl_next(&trbs->twonets, ttn)) { + trbs_cross_t *last, *cr = gdl_first(&ttn->route); + + if (cr == NULL) { + /* special case: route direct point-to-point on an edge - if it is really routed */ + if (ttn->routed) { + rtrnd_line_new(ly_drw, NULL, NULL, ttn->start->pos.x, ttn->start->pos.y, ttn->end->pos.x, ttn->end->pos.y, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_line_new(ly_out, NULL, NULL, ttn->start->pos.x, ttn->start->pos.y, ttn->end->pos.x, ttn->end->pos.y, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(trbs->ctx, o); + } + } + continue; + } + + rtrnd_line_new(ly_drw, NULL, NULL, ttn->start->pos.x, ttn->start->pos.y, cr->x, cr->y, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_line_new(ly_out, NULL, NULL, ttn->start->pos.x, ttn->start->pos.y, cr->x, cr->y, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(trbs->ctx, o); + } + + for(last = cr; cr != NULL; last = cr, cr = gdl_next(&ttn->route, cr)) { + rtrnd_line_new(ly_drw, NULL, NULL, last->x, last->y, cr->x, cr->y, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_line_new(ly_out, NULL, NULL, last->x, last->y, cr->x, cr->y, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(trbs->ctx, o); + } + } + + rtrnd_line_new(ly_drw, NULL, NULL, ttn->end->pos.x, ttn->end->pos.y, last->x, last->y, 0.2, 0); + if (ly_out != NULL) { + o = rtrnd_line_new(ly_out, NULL, NULL, ttn->end->pos.x, ttn->end->pos.y, last->x, last->y, rt_topo_cfg.wire_thick, 0); + rtrnd_res_add(trbs->ctx, o); + } + } +} + +static void reorder(trbs_t *trbs, trbs_2net_t *ttn, trbs_2net_t *before) +{ + gdl_remove(&trbs->twonets, ttn, link); + gdl_insert_before(&trbs->twonets, before, ttn, link); +} + +static int rt_topo_trbs_layer_(rtrnd_t *ctx, trbs_t *trbs, rtrnd_layer_t *ly, long attempt, rtrnd_layer_t *ly_cdt, rtrnd_layer_t *ly_bnk, int force_draw) +{ + rtrnd_layer_t ly_crossuid = {0}, ly_route = {0}; + vtp0_t annot = {0}; + char fn[1024]; + trbs_2net_t *ttn; + int res = 0; + + + vtp0_append(&annot, ly_cdt); + vtp0_append(&annot, ly_bnk); + snprintf(fn, sizeof(fn), "3_%s_%ld_1_cdt", ly->name, attempt); + rtrnd_export(ctx, "svg", fn, NULL, &annot); + + /* route all nets */ + for(ttn = gdl_first(&trbs->twonets); ttn != NULL; ttn = gdl_next(&trbs->twonets, ttn)) { + printf("TRBS route net %s:\n", ttn->net->hdr.oid); + if (rt_topo_trbs_route_net(trbs, ttn) != 0) { + reorder(trbs, ttn, trbs->collision); + res = 1; + break; + } + } + + rt_topo_trbs_pull_init(trbs); + if (res == 0) { + long n, p; + for(n = 0; n < 1000; n++) { + p = rt_topo_trbs_pull(trbs); + printf(" pullres=%ld\n", p); + if (p == 0) + break; + } + } + + rtrnd_layer_init(&ly_crossuid, "crossings"); + strcpy(ly_crossuid.color, "#ff0000"); + vtp0_append(&annot, &ly_crossuid); + trbs_draw_cross_uids(trbs, &ly_crossuid); + + rtrnd_layer_init(&ly_route, "route"); + strcpy(ly_route.color, "#00ff00"); + vtp0_append(&annot, &ly_route); + trbs_draw_routes(trbs, ((res == 0) || force_draw) ? ly : NULL, &ly_route); + + snprintf(fn, sizeof(fn), "3_%s_%ld_2_route", ly->name, attempt); + rtrnd_export(ctx, "svg", fn, NULL, &annot); + + vtp0_uninit(&annot); + return res; +} + +static int rt_topo_trbs_layer(rtrnd_t *ctx, rtrnd_layer_t *ly, gdl_list_t *tnl) +{ + trbs_t trbs; + rt_topo_2net_t *t; + rtrnd_layer_t ly_cdt = {0}, ly_bnk = {0}; + int res, tries; + + rt_topo_trbs_cdt_init(ctx, ly, &trbs); + trbs_init(&trbs, ctx); + + rtrnd_layer_init(&ly_cdt, "laa"); + strcpy(ly_cdt.color, "#888888"); + rtrnd_layer_init(&ly_bnk, "laa"); + strcpy(ly_bnk.color, "#6666aa"); + + /* convert input twonets to trbs twonets, making sure they have endpoints in the cdt */ + for(t = gdl_first(tnl); t != NULL; t = t->link.next) { + trbs_2net_t *tt = calloc(sizeof(trbs_2net_t), 1); + tt->start = trbs_insert_point(&trbs, t->x[0], t->y[0], NULL, t->net); + tt->end = trbs_insert_point(&trbs, t->x[1], t->y[1], NULL, t->net); + tt->net = t->net; + gdl_append(&trbs.twonets, tt, link); + } + + /* init sentinels on edges (have to be after adding all points) */ + trbs_init_cdt_edges(&trbs, &ly_bnk); + + rt_topo_trbs_cdt_draw(ctx, &ly_cdt, &trbs.cdt); + + for(tries = gdl_length(&trbs.twonets); tries > 0; tries--) { + int is_last = (tries == 1); + res = rt_topo_trbs_layer_(ctx, &trbs, ly, 0, &ly_cdt, &ly_bnk, is_last); + trbs_clean(&trbs, ((res != 0) && !is_last)); + if (res == 0) + break; + } + + trbs_uninit(&trbs); + return res; +} + + +int rt_topo_trbs(rtrnd_t *ctx, rt_topo_laa2rbs_t *src) +{ + int n, res = 0; + + /* route each layer */ + for(n = 0; n < ctx->board->layers.used; n++) + res |= rt_topo_trbs_layer(ctx, ctx->board->layers.array[n], src->ly2nets.array[n]); + + return res; +} + Index: tags/0.9.0/src/plugins/rt_topo/trbs.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs.h (revision 1402) @@ -0,0 +1,93 @@ +#ifndef RT_TOPO_RBS_H +#define RT_TOPO_RBS_H +#include "data.h" +#include +#include +#include + +#include "rt_topo.h" + +typedef struct trbs_2net_s trbs_2net_t; +typedef struct trbs_cross_s trbs_cross_t; +typedef struct trbs_edge_s trbs_edge_t; + +struct trbs_cross_s { + edge_t *edge; + trbs_2net_t *twonet; /* NULL on edge endpoint sentinel */ + void *mark; /* for libusearch A* */ + gdl_elem_t link_edge; /* crossing within edge->crosses */ + gdl_elem_t link_route; /* crossing within twonet->route or NULL on edge endpoint sentinel */ + long uid; + double x, y; + double edge_offs; /* offset of x;y on the edge, 0..1 */ +}; + + +struct trbs_2net_s { + point_t *start, *end; + rtrnd_net_t *net; + gdl_list_t route; /* of trbs_cross_t, ordered from start to end */ + gdl_elem_t link; /* in trbs->twonets, ordered list of 2nets to route */ + unsigned routed:1; /* A* succeeded */ +}; + +struct trbs_edge_s { + gdl_list_t crosses; /* of trbs_cross_t, ordered from endp 0->1, always has at least 2 crossings: sentinel crossings for the endpoints */ + double cap; /* remaining capacity */ + double cap_orig; /* original capacity, so cap can be restored after a failed routing attempt */ + rtrnd_any_obj_t *obj; /* if not NULL, the edge is inserted for the given object */ + double vx, vy; /* cached */ + double pdia_cop[2]; /* cached endpoint copper size matching edge->endp[] */ + double pdia_clr[2]; /* cached endpoint clearance size matching edge->endp[] */ + unsigned blocked:1; /* line along this edge */ + unsigned pp_blk:1; /* 'blocked' set because of a point-to-point conn */ +} ; + +typedef struct trbs_point_s { + long uid; + rtrnd_any_obj_t *obj; + rtrnd_net_t *net; +} trbs_point_t; + +typedef struct trbs_s { + rtrnd_t *ctx; + cdt_t cdt; + gdl_list_t twonets; /* of trbs_2net_t */ + + /* caches */ + uall_sysalloc_t sys; + uall_stacks_t crosses; + uall_stacks_t tedges; + long pt_uid; + + /* temporary */ + rtrnd_net_t *routing_net; + trbs_2net_t *collision; + + point_t *target; + void *target_mark; +} trbs_t; + +/* Allocate a new crossing between tnet and edge; place it after crossing aft + on the edge */ +trbs_cross_t *trbs_cross_new(trbs_t *trbs, trbs_2net_t *tnet, edge_t *edge, trbs_cross_t *aft); + + +/*** A* path search ***/ + +/* Map possible next step edge crossings considering triangle edge visibility. + Append (to dst) crossing points on visible target edges after which the + new crossing point could be inserted. Starting from a point or an edge + (specified by the crossing point the source crossing is after) */ +void trbs_next_edge_from_point(trbs_t *trbs, vtp0_t *dst, point_t *from); +void trbs_next_edge_from_edge(trbs_t *trbs, vtp0_t *dst, triangle_t *t, trbs_cross_t *from_aft, double thickness); + +/* Create the current best topological path for a twonet, between start and + end or return NULL if there's no path */ +trbs_2net_t *rt_top_trbs_2net_path(trbs_t *trbs, point_t *start, point_t *end); + + +/*** main entry point */ +int rt_topo_trbs(rtrnd_t *ctx, rt_topo_laa2rbs_t *src); + +#endif Index: tags/0.9.0/src/plugins/rt_topo/trbs_cdt.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs_cdt.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs_cdt.c (revision 1402) @@ -0,0 +1,300 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020,2021 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include + +#include "geo.h" +#include "gengeo2d/cline.h" + +void rt_topo_trbs_cdt_init(rtrnd_t *ctx, rtrnd_layer_t *ly, trbs_t *trbs) +{ + rtrnd_any_obj_t *obj; + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + point_t *p1, *p2; + cdt_t *cdt = &trbs->cdt; + rtp_vertex_t *v; + edge_t *e; + + memset(trbs, 0, sizeof(trbs_t)); + + cdt_init(cdt, ctx->board->hdr.bbox.x1, ctx->board->hdr.bbox.y1, ctx->board->hdr.bbox.x2, ctx->board->hdr.bbox.y2); + + for(via = rtrnd_rtree_all_first(&it, &ctx->board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) { + p1 = trbs_insert_point(trbs, via->x, via->y, via->hdr.net, NULL); + } + + for(obj = rtrnd_rtree_all_first(&it, &ly->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) { + switch(obj->hdr.type) { + case RTRND_LINE: + p1 = trbs_insert_point(trbs, obj->line.cline.p1.x, obj->line.cline.p1.y, obj, NULL); + p2 = trbs_insert_point(trbs, obj->line.cline.p2.x, obj->line.cline.p2.y, obj, NULL); + if (p1 != p2) { + e = cdt_insert_constrained_edge(cdt, p1, p2); + e->data = obj; + } + break; + case RTRND_POLY: + v = gdl_last(&obj->poly.rtpoly.lst); + p2 = trbs_insert_point(trbs, v->x, v->y, obj, NULL); + for(v = gdl_first(&obj->poly.rtpoly.lst); v != NULL; v = gdl_next(&obj->poly.rtpoly.lst, v)) { + p1 = trbs_insert_point(trbs, v->x, v->y, obj, NULL); + e = cdt_insert_constrained_edge(cdt, p1, p2); + e->data = obj; + p2 = p1; + } + break; + default: +#warning handle all other types + ; + } + } +} + +void rt_topo_trbs_cdt_draw(rtrnd_t *ctx, rtrnd_layer_t *ly_out, cdt_t *cdt) +{ + VTEDGE_FOREACH(edge, &cdt->edges) + rtrnd_line_new(ly_out, NULL, NULL, + edge->endp[0]->pos.x, edge->endp[0]->pos.y, edge->endp[1]->pos.x, edge->endp[1]->pos.y, \ + edge->is_constrained ? 0.1 : 0.01, 0); + VTEDGE_FOREACH_END(); + VTPOINT_FOREACH(pt, &cdt->points) + char tmp[64]; + sprintf(tmp, "P%ld", ((trbs_point_t *)pt->data)->uid); + rtrnd_text_new(ly_out, pt->pos.x, pt->pos.y, tmp, 0.5); + VTPOINT_FOREACH_END(); +} + +static int trbs_cdt_insert_perp(trbs_t *trbs, edge_t *e, triangle_t *t, double *xo, double *yo, point_t **opp) +{ + int n; + point_t *p = NULL; + g2d_offs_t o; + g2d_vect_t pt, npt; + g2d_cline_t line; + rtrnd_any_obj_t *eo = e->data; + trbs_point_t *tp; + + if (t == NULL) + return 0; + + /* find the opposite point */ + for(n = 0; n < 3; n++) { + if ((t->p[n] != e->endp[0]) && (t->p[n] != e->endp[1])) { + p = t->p[n]; + break; + } + } + assert(p != NULL); + + *opp = p; + tp = p->data; + + /* do not insert bottleneck within a polygon (all three points of the triangle are the same obj) */ + if ((tp->net != NULL) && (tp->net == ((trbs_point_t *)e->endp[0]->data)->net) && (tp->net == ((trbs_point_t *)e->endp[1]->data)->net)) + return 0; + printf(" ins obj: %p %p %p\n", tp->net, ((trbs_point_t *)e->endp[0]->data)->net, ((trbs_point_t *)e->endp[1]->data)->net); + + /* if the edge and the point both belong to the same net, they are probably + a terminal - avoid adding a lot of internal edges */ + if ((eo != NULL) && (tp->obj != NULL) && (eo->hdr.net != NULL) && (tp->obj->hdr.net == eo->hdr.net)) + return 0; + + printf(" opposite: P%ld (%f;%f)\n", ((trbs_point_t *)p->data)->uid, p->pos.x, p->pos.y); + + pt.x = p->pos.x; pt.y = p->pos.y; + line.p1.x = e->endp[0]->pos.x; line.p1.y = e->endp[0]->pos.y; + line.p2.x = e->endp[1]->pos.x; line.p2.y = e->endp[1]->pos.y; + o = g2d_project_pt_cline(pt, &line); + if ((o < 0) || (o > 1)) + return 0; + npt = g2d_cline_offs(&line, o); + + *xo = npt.x; *yo = npt.y; + return 1; +} + +/* Return how much edge capacity gets shorter at endpoint p due to the object + and clearance there */ +static void trbs_edge_cap_endp(trbs_t *trbs, edge_t *e, point_t *p, double *copper, double *clearance) +{ + double cop = 0, clr = 0; + trbs_point_t *tp = p->data; + + + if ((tp == NULL) || (tp->obj == NULL)) { + *copper = *clearance = 0; + return; + } + +#warning TODO: iterate over a list of endoint objects, e.g. a terminal is a via+poly + switch(tp->obj->hdr.type) { + case RTRND_VIA: + cop = tp->obj->via.dia / 2.0; + clr = tp->obj->via.clearance; + break; + +#warning TODO: these for arc and line ignore mid-line non-perpendicular case where we lose more room + case RTRND_LINE: + cop = tp->obj->line.thickness / 2.0; + clr = tp->obj->line.clearance; + break; + + case RTRND_ARC: + cop = tp->obj->arc.thickness / 2.0; + clr = tp->obj->arc.clearance; + break; + + case RTRND_POLY: +#warning TODO: calculate poly vs. line crossing +printf(" poly\n"); +/* + c2.p1.x = n->x; c1.p2.y = n->y; + c2.p2.x = nn->x; c2.p2.y = nn->y; + vp = gdl_last(&obj->poly.rtpoly.lst); + for(v = gdl_first(&obj->poly.rtpoly.lst); v != NULL; v = gdl_next(&obj->poly.rtpoly.lst, v)) { + c1.p1.x = v->x; c1.p1.y = v->y; + c1.p2.x = vp->x; c1.p2.y = vp->y; + if (g2d_isc_cline_cline(&c1, &c2)) +*/ + break; + + default: + break; + } + + *copper = TRBS_MAX(cop, 0); + *clearance = TRBS_MAX(clr, 0); +} + +static void trbs_init_cdt_edges(trbs_t *trbs, rtrnd_layer_t *ly_dbg) +{ + long n, n2; + vtd0_t vc = {0}; + vtp0_t vp = {0}; + + /* name all points already exist */ + VTPOINT_FOREACH(pt, &trbs->cdt.points) + trbs_insert_point(trbs, pt->pos.x, pt->pos.y, NULL, NULL); + VTPOINT_FOREACH_END(); + +#if 1 + printf("*** NARROW:\n"); + /* insert a new edge at the narrowest point between a constrained edge + and the opposite point; having such an edge means control over how + many lines may pass through there. The first loop only collects points + to draw constrained edges to, so the scenario is not changing... */ + for(n = 0; n < trbs->cdt.edges.used; n++) { + double x, y; + point_t *opp; + edge_t *e = trbs->cdt.edges.array[n]; + + if (!e->is_constrained) + continue; + printf(" edge P%ld..P%ld\n", ((trbs_point_t *)e->endp[0]->data)->uid, ((trbs_point_t *)e->endp[1]->data)->uid); + + if (trbs_cdt_insert_perp(trbs, e, e->adj_t[0], &x, &y, &opp) > 0) { + vtp0_append(&vp, opp); + vtp0_append(&vp, e); + vtd0_append(&vc, x); + vtd0_append(&vc, y); + } + if (trbs_cdt_insert_perp(trbs, e, e->adj_t[1], &x, &y, &opp) > 0) { + vtp0_append(&vp, opp); + vtp0_append(&vp, e); + vtd0_append(&vc, x); + vtd0_append(&vc, y); + } + } + + /* ... this second loop is creating the new points and actual constrained + edges as mapped in the first loop above */ + for(n = n2 = 0; n < vp.used; n += 2, n2 += 2) { + int i; + double x = vc.array[n2], y = vc.array[n2+1]; + point_t *opp = vp.array[n], *np; + edge_t *e = vp.array[n+1]; + rtrnd_any_obj_t *p_obj; + + np = rtrnd_line_new(ly_dbg, NULL, NULL, x, y, opp->pos.x, opp->pos.y, 0.2, 0); + if (((trbs_point_t *)e->endp[0]->data)->obj == ((trbs_point_t *)e->endp[1]->data)->obj) { + trbs_point_t *ntp = np->data; + p_obj = ((trbs_point_t *)e->endp[0]->data)->obj; + } + else + p_obj = NULL; + + point_t *newp = trbs_insert_point(trbs, x, y, p_obj, NULL); + if (newp != NULL) { + printf(" insert: P%ld (%f;%f) obj=%p\n", ((trbs_point_t *)newp->data)->uid, newp->pos.x, newp->pos.y, p_obj); + { + FILE *f = fopen("insert.cdt", "w"); + cdt_fdump(f, &trbs->cdt); + fprintf(f, "ins_point p1 %.16f %.16f\n", opp->pos.x, opp->pos.y); + fprintf(f, "ins_point p2 %.16f %.16f\n", newp->pos.x, newp->pos.y); + fprintf(f, "ins_cedge p1 p2\n"); + fclose(f); + } + cdt_insert_constrained_edge(&trbs->cdt, opp, newp); + } + else + printf(" FAILED insert: (%f;%f)\n", x, y); + } +#endif + + /* set up edges and edge sentinels */ + for(n = 0; n < trbs->cdt.edges.used; n++) { + edge_t *e = trbs->cdt.edges.array[n]; + trbs_cross_t *cr0; + trbs_edge_t *tedge; + rtrnd_any_obj_t *eobj = e->data; + + e->data = uall_stacks_alloc(&trbs->tedges); + memset(e->data, 0, sizeof(trbs_edge_t)); + + cr0 = trbs_cross_new(trbs, NULL, e, NULL); + tedge = e->data; + gdl_append(&tedge->crosses, cr0, link_edge); + + tedge->obj = eobj; + if (eobj != NULL) + tedge->blocked = 1; + + + /* base capacity of an edge is its length */ + tedge->cap = trbs_dist(e->endp[0]->pos.x, e->endp[0]->pos.y, e->endp[1]->pos.x, e->endp[1]->pos.y); +printf(" EDGECAP1: %f\n", tedge->cap); + trbs_edge_cap_endp(trbs, e, e->endp[0], &tedge->pdia_cop[0], &tedge->pdia_clr[0]); + trbs_edge_cap_endp(trbs, e, e->endp[1], &tedge->pdia_cop[1], &tedge->pdia_clr[1]); + tedge->cap -= (tedge->pdia_cop[0]/2 + tedge->pdia_cop[1]/2 + tedge->pdia_clr[0] + tedge->pdia_clr[1]); + tedge->cap_orig = tedge->cap; +printf(" EDGECAP2: %f\n", tedge->cap); + + trbs_cross_new(trbs, NULL, e, cr0); + } +} Index: tags/0.9.0/src/plugins/rt_topo/trbs_pull.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs_pull.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs_pull.c (revision 1402) @@ -0,0 +1,252 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* stop pulling if distance/difference is smaller than this value in mm */ +#define STOP_PULL_DIFF 0.001 + +#define DEBUG_CR_UID 245 + +#ifdef DEBUG_CR_UID +# define crprintf if (cr->uid == DEBUG_CR_UID) printf +#else +static void crprintf(const char *fmt, ...) {} +#endif + + + +static void rt_topo_trbs_place_cr(trbs_t *trbs) +{ + VTEDGE_FOREACH(edge, &trbs->cdt.edges) + trbs_edge_t *tedge = edge->data; + double x, y, vx = edge->endp[1]->pos.x - edge->endp[0]->pos.x, vy = edge->endp[1]->pos.y - edge->endp[0]->pos.y, vlen; + int n, len = gdl_length(&tedge->crosses); + trbs_cross_t *cr; + g2d_cline_t el = g2d_cline(g2d_vect(edge->endp[0]->pos.x, edge->endp[0]->pos.y), g2d_vect(edge->endp[1]->pos.x, edge->endp[1]->pos.y)); + + + vlen = sqrt(vx*vx + vy*vy); + tedge->vx = vx / vlen; + tedge->vy = vy / vlen; + + vx /= (double)(len-1); + vy /= (double)(len-1); + vx -= 2*vx/8; + vy -= 2*vy/8; + x = edge->endp[0]->pos.x + vx/8; + y = edge->endp[0]->pos.y + vy/8; + + for(n = 0, cr = tedge->crosses.first; n < len; n++, x += vx, y += vy, cr = cr->link_edge.next) { + cr->x = x; + cr->y = y; + cr->edge_offs = g2d__offs_cline_pt(&el, g2d_cvect(x, y)); + } + VTEDGE_FOREACH_END(); +} + +static rtrnd_net_t *get_pnet(point_t *p) +{ + trbs_point_t *tp = p->data; + if ((tp == NULL) || (tp->obj == NULL)) + return NULL; + return tp->obj->hdr.net; +} + +static long rt_topo_trbs_pull_cr(trbs_t *trbs, rtrnd_net_t *net, trbs_cross_t *prev, trbs_cross_t *cr, trbs_cross_t *next) +{ + edge_t *e = cr->edge; + trbs_edge_t *te = e->data; + g2d_cline_t el = g2d_cline(g2d_vect(e->endp[0]->pos.x, e->endp[0]->pos.y), g2d_vect(e->endp[1]->pos.x, e->endp[1]->pos.y)); + g2d_cline_t tl = g2d_cline(g2d_vect(prev->x, prev->y), g2d_vect(next->x, next->y)); + g2d_cvect_t ip[2]; + g2d_offs_t offs[2]; + int iscs, can_do_best, moved, samenet; + double adj_cop, adj_clr, my_cop, my_clr, stepdir, ax, ay, step, bumpx, bumpy, bumpo, besto, dx, dy; + trbs_cross_t *adj; + rtrnd_net_t *pnet; + + /* calculate crossing point of the route-prev-next points and the edge; + that's where our crossing should be if we wanted minimum wire length */ + iscs = g2d__iscp_cline_cline_o(&el, &tl, ip, offs, 1); + + /* overlap: it does not matter where we cross, can't pull */ + if (iscs == 2) + return 0; + + besto = offs[0]; /* where we'd get the shortest line */ + + if (iscs == 0) { + /* point out of the edge range, beyond either the starting or ending point */ + if (besto <= 0.0) { + adj = gdl_prev(&te->crosses, cr); + stepdir = +1; + } + else if (besto >= 1.0) { + adj = gdl_next(&te->crosses, cr); + stepdir = -1; + } + else + goto in_range; + } + else { /* point insiged of the edge range see in which direction to the current offset */ + in_range:; + if (besto < cr->edge_offs) { + adj = gdl_prev(&te->crosses, cr); + stepdir = +1; + } + else { + adj = gdl_next(&te->crosses, cr); + stepdir = -1; + } + } + + /* check if adjacent cr we try to get close to is a sentinel */ + if (gdl_prev(&te->crosses, adj) == NULL) { + adj_cop = te->pdia_cop[0]; + adj_clr = te->pdia_clr[0]; + ax = e->endp[0]->pos.x; + ay = e->endp[0]->pos.y; + pnet = get_pnet(e->endp[0]); + } + else if (gdl_next(&te->crosses, adj) == NULL) { + adj_cop = te->pdia_cop[1]; + adj_clr = te->pdia_clr[1]; + ax = e->endp[1]->pos.x; + ay = e->endp[1]->pos.y; + pnet = get_pnet(e->endp[1]); + } + else { /* adj is another net */ + adj_cop = rt_topo_cfg.wire_thick / 2.0; + adj_clr = rt_topo_cfg.wire_clr; + ax = adj->x; + ay = adj->y; + pnet = NULL; + } + + my_cop = rt_topo_cfg.wire_thick / 2.0; + my_clr = rt_topo_cfg.wire_clr; + + + samenet = ((pnet != NULL) && (net == pnet)); + + if (!samenet) + step = adj_cop + my_cop + TRBS_MAX(adj_clr, my_clr); + else + step = 0; + + crprintf("pull cr %ld at %f;%f o=%f step=%f stepdir=%f v=%f;%f\n", cr->uid, cr->x, cr->y, cr->edge_offs, step, stepdir, te->vx, te->vy); + + bumpx = ax + step * stepdir * te->vx; + bumpy = ay + step * stepdir * te->vy; + bumpo = g2d__offs_cline_pt(&el, g2d_cvect(bumpx, bumpy)); + + can_do_best = 0; + + /* if best is between bump and current, it is safe for going the best */ + if ((besto >= 0) && (besto <= 1)) { + if (cr->edge_offs < bumpo) { + if ((besto >= cr->edge_offs) && (besto <= bumpo)) + can_do_best = 1; + } + else { /* bumpo < cr->edge_offs */ + if ((besto >= bumpo) && (besto <= cr->edge_offs)) + can_do_best = 1; + } + } + + if (can_do_best) { + dx = ip[0].x - cr->x; + dy = ip[0].y - cr->y; + cr->x = ip[0].x; + cr->y = ip[0].y; + cr->edge_offs = besto; + } + else { + dx = bumpx - cr->x; + dy = bumpy - cr->y; + cr->x = bumpx; + cr->y = bumpy; + cr->edge_offs = bumpo; + } + + moved = ((dx*dx + dy*dy) > (STOP_PULL_DIFF*STOP_PULL_DIFF)); + + crprintf(" => %f;%f o=%f can_do_best=%d moved=%d\n", cr->x, cr->y, cr->edge_offs, can_do_best, moved); + + return moved; +} + +static long rt_topo_trbs_pull_net(trbs_t *trbs, trbs_2net_t *ttn) +{ + long pulled = 0; + trbs_cross_t ctmp = {0}, *cr = gdl_first(&ttn->route), *next; + + if (cr == NULL) + return 0; + + ctmp.x = ttn->start->pos.x; + ctmp.y = ttn->start->pos.y; + + /* corner case: single cr route; fake both start and end cr */ + next = gdl_next(&ttn->route, cr); + if (next == NULL) { + trbs_cross_t ctmp2 = {0}; + ctmp2.x = ttn->end->pos.x; + ctmp2.y = ttn->end->pos.y; + return rt_topo_trbs_pull_cr(trbs, ttn->net, &ctmp, cr, &ctmp2); + } + + /* normal case; first point needs to be faked */ + pulled += rt_topo_trbs_pull_cr(trbs, ttn->net, &ctmp, cr, next); + + for(cr = gdl_next(&ttn->route, cr); gdl_next(&ttn->route, cr) != NULL; cr = gdl_next(&ttn->route, cr)) + pulled += rt_topo_trbs_pull_cr(trbs, ttn->net, gdl_prev(&ttn->route, cr), cr, gdl_next(&ttn->route, cr)); + + /* fake last point */ + ctmp.x = ttn->end->pos.x; + ctmp.y = ttn->end->pos.y; + pulled += rt_topo_trbs_pull_cr(trbs, ttn->net, gdl_prev(&ttn->route, cr), cr, &ctmp); + + return pulled; +} + +static void rt_topo_trbs_pull_init(trbs_t *trbs) +{ + rt_topo_trbs_place_cr(trbs); +} + +static long rt_topo_trbs_pull(trbs_t *trbs) +{ + trbs_2net_t *ttn; + long pulled = 0; + + for(ttn = gdl_first(&trbs->twonets); ttn != NULL; ttn = gdl_next(&trbs->twonets, ttn)) + pulled += rt_topo_trbs_pull_net(trbs, ttn); + + return pulled; +} + Index: tags/0.9.0/src/plugins/rt_topo/trbs_route.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs_route.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs_route.c (revision 1402) @@ -0,0 +1,225 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + + +#include + +static int trace_astar = 0; + +static void trbs_cr_coord(trbs_t *trbs, trbs_cross_t *cr, double *x, double *y) +{ + if (cr == trbs->target) { + *x = trbs->target->pos.x; + *y = trbs->target->pos.y; + } + else { + /* temporary: assume edge center */ + *x = (cr->edge->endp[0]->pos.x + cr->edge->endp[1]->pos.x)/2; + *y = (cr->edge->endp[0]->pos.y + cr->edge->endp[1]->pos.y)/2; + } +} + +static long trbs_ast_heuristic(usrch_a_star_t *ctx, void *node) +{ + trbs_t *trbs = ctx->user_data; + trbs_cross_t *cr = node; + double x, y; + + if (cr == trbs->target) + return 0; + + trbs_cr_coord(trbs, cr, &x, &y); + return trbs_dist_heur(x, y, trbs->target->pos.x, trbs->target->pos.y); +} + +static long trbs_ast_cost(usrch_a_star_t *ctx, void *from, void *to) +{ + trbs_t *trbs = ctx->user_data; + trbs_cross_t *cr1 = from, *cr2 = to; + double x1, y1, x2, y2; + + trbs_cr_coord(trbs, cr1, &x1, &y1); + trbs_cr_coord(trbs, cr2, &x2, &y2); + + return trbs_dist_heur(x1, y1, x2, y2); +} + +static vtp0_t trbs_ast_nv; +static void *trbs_ast_neighbor_pre(usrch_a_star_t *ctx, void *curr, rtrnd_net_t *net) +{ + double thick; + trbs_cross_t *cr = curr; + trbs_t *trbs = ctx->user_data; + +#warning TODO: per net wire thickness + thick = rt_topo_cfg.wire_thick + rt_topo_cfg.wire_clr/2; + + if (trace_astar) printf("A* from: cr%ld\n", cr->uid); + + trbs_ast_nv.used = 0; + if (cr->edge->adj_t[0] != NULL) + trbs_next_edge_from_edge(trbs, &trbs_ast_nv, cr->edge->adj_t[0], cr, thick); + if (cr->edge->adj_t[1] != NULL) + trbs_next_edge_from_edge(trbs, &trbs_ast_nv, cr->edge->adj_t[1], cr, thick); + return &trbs_ast_nv; +} + +static void *trbs_ast_neighbor(usrch_a_star_t *ctx, void *curr, void *nctx) +{ + vtp0_t *v = nctx; + + if (v->used == 0) + return NULL; + + v->used--; + if (trace_astar) printf(" a* cr%ld\n", ((trbs_cross_t *)(v->array[v->used]))->uid); + return v->array[v->used]; +} + +static void trbs_ast_set_mark(usrch_a_star_t *ctx, void *node, usrch_a_star_node_t *mark) +{ + trbs_t *trbs = ctx->user_data; + trbs_cross_t *cr = node; + + + if (cr == trbs->target) + trbs->target_mark = mark; + else + cr->mark = mark; +} + +static usrch_a_star_node_t *trbs_ast_get_mark(usrch_a_star_t *ctx, void *node) +{ + trbs_t *trbs = ctx->user_data; + trbs_cross_t *cr = node; + + if (cr == trbs->target) + return trbs->target_mark; + + return cr->mark; +} + +static int rt_topo_trbs_route_net(trbs_t *trbs, trbs_2net_t *ttn) +{ + vtp0_t next = {0}; + usrch_res_t sres; + usrch_a_star_t ast = {0}; + usrch_a_star_node_t *it; + trbs_cross_t *cr, *ncr; + long ncrs; + + trbs->collision = NULL; + + ast.heuristic = trbs_ast_heuristic; + ast.cost = trbs_ast_cost; + ast.neighbor_pre = trbs_ast_neighbor_pre; + ast.neighbor = trbs_ast_neighbor; + ast.set_mark = trbs_ast_set_mark; + ast.get_mark = trbs_ast_get_mark; + ast.user_data = trbs; + + trbs->routing_net = ttn->net; + trbs->target = ast.target = ttn->end; + + printf(" route_net: from P%ld to P%ld\n", + ((trbs_point_t *)ttn->start->data)->uid, + ((trbs_point_t *)ttn->end->data)->uid); + + trbs_next_edge_from_point(trbs, &next, ttn->start); + if (next.used == 0) { + printf(" Can't start: no visible edges from start point\n"); + usrch_a_star_uninit(&ast); + trbs->routing_net = NULL; + return -1; + } + + sres = usrch_a_star_start_arr(&ast, next.array, next.used); + if (sres != USRCH_RES_SUCCESS) { + printf(" a* start fail 1\n"); + usrch_a_star_uninit(&ast); + trbs->routing_net = NULL; + return -1; + } + + while((sres = usrch_a_star_iter(&ast)) == USRCH_RES_CONTINUE) ; + + if (sres != USRCH_RES_FOUND) { + printf(" a* search fail 2\n"); + usrch_a_star_uninit(&ast); + trbs->routing_net = NULL; + return -1; + } + + ttn->routed = 1; + + /* reconstruct the path */ + ncrs = 0; + cr = usrch_a_star_path_first(&ast, &it); /* ignore the first pointer, which is the target point */ + for(cr = usrch_a_star_path_next(&ast, &it); cr != NULL; cr = usrch_a_star_path_next(&ast, &it)) { + trbs_edge_t *te; + ncr = trbs_cross_new(trbs, ttn, cr->edge, cr); + gdl_insert(&ttn->route, ncr, link_route); + printf(" above %ld: %ld\n", cr->uid, ncr->uid); + + te = cr->edge->data; +#warning TODO: per net wire thickness + te->cap -= rt_topo_cfg.wire_thick + rt_topo_cfg.wire_clr/2; + + ncrs++; + } + + /* corner case: there's no cr because the route is connecting two points + directly on an edge; the edge needs to be marked as blocked but the + block needs to be removed on a clean */ + if (ncrs == 0) { + edge_t *edge = NULL; + long n; + for(n = 0; n < trbs->cdt.edges.used; n++) { + edge_t *e = trbs->cdt.edges.array[n]; + if ((e->endp[0] == ttn->start) && (e->endp[1] == ttn->end)) { + edge = e; + break; + } + if ((e->endp[1] == ttn->start) && (e->endp[0] == ttn->end)) { + edge = e; + break; + } + } + if (edge != NULL) { + trbs_edge_t *te = edge->data; + te->blocked = 1; + te->pp_blk = 1; + } + } + + usrch_a_star_uninit(&ast); + trbs->routing_net = NULL; + + return 0; +} + Index: tags/0.9.0/src/plugins/rt_topo/trbs_util.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs_util.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs_util.c (revision 1402) @@ -0,0 +1,76 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020,2021 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TRBS_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define TRBS_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +static long trbs_dist_heur(double x1, double y1, double x2, double y2) +{ + double dx = x2 - x1, dy = y2 - y1, d = dx*dx+dy*dy; + + return d == 0 ? d : floor(sqrt(d) * 1000); +} + +static long trbs_dist(double x1, double y1, double x2, double y2) +{ + double dx = x2 - x1, dy = y2 - y1, d = dx*dx+dy*dy; + + return d == 0 ? d : floor(sqrt(d)); +} + +point_t *trbs_insert_point(trbs_t *trbs, coord_t x, coord_t y, rtrnd_any_obj_t *obj, rtrnd_net_t *net) +{ + point_t *pt = cdt_insert_point(&trbs->cdt, x, y); + trbs_point_t *udt; + + if (pt == NULL) + return NULL; + + udt = pt->data; + if ((udt != NULL) && (udt->obj != obj) && (obj != NULL)) { +#warning TODO need a list of objects + fprintf(stderr, "trbs_insert_point(): object collision\n"); + } + + if (udt == NULL) { + udt = pt->data = calloc(sizeof(trbs_point_t), 1); + udt->uid = trbs->pt_uid++; + } + + if (obj != NULL) { + udt->obj = obj; + if (net == NULL) + net = obj->hdr.net; + } + + if (net != NULL) + udt->net = net; + + return pt; +} + Index: tags/0.9.0/src/plugins/rt_topo/trbs_vis.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/trbs_vis.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/trbs_vis.c (revision 1402) @@ -0,0 +1,608 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router: topological, extended rubber band sketch (based on Tal Dayan's thesis) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +static int trbs_vis_trace = 1; + +#if 0 +# define tprintf printf +#else + static void tprintf(const char *fmt, ...) {} +#endif + +static edge_t *trbs_pt_opposite_edge(trbs_t *trbs, triangle_t *t, point_t *src) +{ + int n; + + /* find an edge that doesn't have src as endpoint - in a triangle, that + must be the opposite */ + for(n = 0; n < 3; n++) + if ((t->e[n]->endp[0] != src) && (t->e[n]->endp[1] != src)) + return t->e[n]; + + fprintf(stderr, "trbs_pt_opposite_edge(): invalid triangle!\n"); + abort(); +} + +/* returns direction (+1=start->end or -1=end->start) that corresponds to + CCW walk in a triangle on a specific edge */ +static int trbs_edge_dir_ccw(trbs_t *trbs, triangle_t *t, edge_t *e) +{ + int n, si = -1, ei = -1; + for(n = 0; n < 3; n++) { + if (t->p[n] == e->endp[0]) si = n; + if (t->p[n] == e->endp[1]) ei = n; + } + + /* broken triangle detection */ + assert(si != -1); + assert(ei != -1); + + if (ei > si) { + if ((ei-si) > 1) + return +1; /* ei=3, si=1: overflow */ + return -1; + } + + /* ei < si */ + if ((si - ei) > 1) + return -1; /* si=3, ei=1: overflow */ + return +1; +} + +/* Convert a line's dx/dy into a fake angle value between 0 and 8; the fake + angle is suitable for determining the order of lines by angle (but not + the exact angles) */ +static double line_fake_angle(double dx, double dy) +{ + int sx, sy; + + /* special cases for axis aligned lines (quicker) */ + if (dx == 0) { + if (dy == 0) + return 0; + return dy > 0 ? 2 : 6; + } + else if (dy == 0) + return dx > 0 ? 0 : 4; + + + /* arbitrary angle cases, handled by sign of dx and dy */ + sx = (dx >= 0); + sy = (dy >= 0); + + if (sx && sy) { /* base is 0 */ + if (dx > dy) + return 0 + dy / dx; + return (0 + 2 - (dx/dy)); + } + else if (!sx && sy) { /* base is 2 */ + dx = -dx; + if (dx > dy) + return 2 + 2 - (dy/dx); + return (2 + (dx/dy)); + } + else if (!sx && !sy) { /* base is 4 */ + if (dx < dy) + return 4 + (dy/dx); + return (4 + 2 - (dx/dy)); + } + else /*if (sx && !sy)*/ { /* base is 6 */ + dy = -dy; + if (dx > dy) + return 6 + 2 - (dy/dx); + return (6 + (dx/dy)); + } +} + +/* Return the next (dir>0) or previous (dir<0) crosing from cr */ +#define CR_STEP(cr, dir) (((dir) > 0) ? (cr)->link_edge.next : (cr)->link_edge.prev) + +static void trbs_print_triangle(triangle_t *t) +{ + int n; + + for(n = 0; n < 3; n++) + tprintf(" P%ld", ((trbs_point_t *)t->p[n]->data)->uid); +} + +/* Returns the insertion point next to the sentinel cr on the edge of t + that differs from src_edge but ends in the same endpoint pt */ +static trbs_cross_t *trbs_vis_get_pt_insertion(trbs_t *trbs, triangle_t *t, point_t *pt, edge_t *src_edge, int srcdir) +{ + edge_t *edge = NULL; + trbs_edge_t *tedge; + int n; + point_t *shared; + + if (trbs_vis_trace) { + tprintf(" triangle: "); + trbs_print_triangle(t); + tprintf("\n"); + } + + /* point is not in triangle means the path is leaving the triangle + through this crossing to reach another point */ + if ((t->p[0] != pt) && (t->p[1] != pt) && (t->p[2] != pt)) { + if (trbs_vis_trace) tprintf(" null1\n"); + return NULL; + } + + /* the path line cuts the triangle in two halves; to determine in which + half to search (which is our target edge), we need to find the point + that is shared between the source edge and the target edge */ + if (srcdir > 0) + shared = src_edge->endp[0]; + else + shared = src_edge->endp[1]; + + /* find target edge */ + for(n = 0; n < 3; n++) { + if (t->e[n] == src_edge) + continue; + if ((t->e[n]->endp[0] == shared) || (t->e[n]->endp[1] == shared)) { /* in our half-triangle */ + if ((t->e[n]->endp[0] == pt) || (t->e[n]->endp[1] == pt)) { /* edge ends in path end */ + edge = t->e[n]; + break; + } + } + } + + if (edge == NULL) { + fprintf(stderr, "trbs_vis_get_pt_insertion(): broken triangle\n"); + return NULL; + } + + tedge = edge->data; + + /* pt is starting point of edge: insertion point is after the start sentinel */ + if (edge->endp[0] == pt) { + if (trbs_vis_trace) tprintf(" first\n"); + return gdl_first(&tedge->crosses); + } + + /* else pt is the ending point of edge: insertion point is the point before + the end sentinel */ + if (trbs_vis_trace) tprintf(" last\n"); + return gdl_prev(&tedge->crosses, gdl_last(&tedge->crosses)); +} + +/* Returns 1 if cr is within t, 0 otherwise */ +static int trbs_vis_cr_in_trianlge(trbs_t *trbs, triangle_t *t, trbs_cross_t *cr) +{ + return (cr->edge->adj_t[0] == t) || (cr->edge->adj_t[1] == t); +} + +/* if there is a path line from point pt within triangle t, jump along that */ +static trbs_cross_t *trbs_vis_jump_line_from_pt(trbs_t *trbs, triangle_t *t, point_t *pt, trbs_cross_t *crside) +{ + edge_t *side, *ope = trbs_pt_opposite_edge(trbs, t, pt); + trbs_edge_t *tope = ope->data; + trbs_cross_t *cr; + + if (trbs_vis_trace) { + trbs_cross_t *cr1 = gdl_first(&tope->crosses), *cr2 = gdl_last(&tope->crosses); + tprintf("trbs_vis_jump_line_from_pt crside=%ld ope: %ld..%ld pt=P%ld\n", crside->uid, cr1->uid, cr2->uid, ((trbs_point_t *)pt->data)->uid); + } + + /* check the shared point between the opposite (target) side and the + side we are coming from; iterate over crossing and return the first whose + path ends in pt */ + side = crside->edge; + if ((ope->endp[0] == side->endp[0]) || (ope->endp[0] == side->endp[1])) { + if (trbs_vis_trace) tprintf(" endp[0]\n"); + /* shared point is ope->endp[0], search from the sentinel forward */ + for(cr = gdl_first(&tope->crosses); cr != NULL; cr = gdl_next(&tope->crosses, cr)) { + if (trbs_vis_trace) tprintf(" cr=%ld\n", cr->uid); + if (cr->twonet == NULL) + continue; + if (trbs_vis_trace) tprintf(" %p %p == %p\n", cr->twonet->start, cr->twonet->end, pt); + if ((cr->twonet->start == pt) || (cr->twonet->end == pt)) { + trbs->collision = cr->twonet; + return gdl_prev(&tope->crosses, cr); + } + } + } + else if ((ope->endp[1] == side->endp[0]) || (ope->endp[1] == side->endp[1])) { + if (trbs_vis_trace) tprintf(" endp[1]\n"); + /* shared point is ope->endp[1], search from the sentinel backward */ + for(cr = gdl_last(&tope->crosses); cr != NULL; cr = gdl_prev(&tope->crosses, cr)) { + if (trbs_vis_trace) tprintf(" cr=%ld\n", cr->uid); + if (cr->twonet == NULL) + continue; + if (trbs_vis_trace) tprintf(" %p %p == %p\n", cr->twonet->start, cr->twonet->end, pt); + if ((cr->twonet->start == pt) || (cr->twonet->end == pt)) { + trbs->collision = cr->twonet; + return cr; + } + } + } + else + fprintf(stderr, "trbs_vis_jump_line_from_pt(): broken triangle\n"); + + if (trbs_vis_trace) tprintf(" (line_from_pt not found)\n"); + return NULL; +} + +/* jump from cr1 to cr2 over a path line within a triangle; whether we land + before or after cr2 depends on the shared endpoint of their edges and from + which direction cr1 is reached from */ +static trbs_cross_t *trbs_vis_jump_path_line(trbs_t *trbs, triangle_t *t, trbs_cross_t *cr1, trbs_cross_t *cr2, int cr1dir) +{ + point_t *shared; + int cr1o, cr2o, cr2dir; + trbs_edge_t *tedge2 = cr2->edge->data; + + if ((cr1->edge->endp[0] == cr2->edge->endp[0]) || (cr1->edge->endp[0] == cr2->edge->endp[1])) { + shared = cr1->edge->endp[0]; + cr1o = -1; + } + else if ((cr1->edge->endp[1] == cr2->edge->endp[0]) || (cr1->edge->endp[1] == cr2->edge->endp[1])) { + shared = cr1->edge->endp[1]; + cr1o = +1; + } + else { + fprintf(stderr, "trbs_vis_jump_path_line: broken triangle\n"); + return NULL; + } + + cr2o = (shared == cr2->edge->endp[0]) ? -1 : +1; + + /* compare edge orientations toward the shared point: */ + if (cr1o == cr2o) { + /* if they are the same, both pointing toward the shared point, + invert the direction to step in the same dir */ + cr2dir = -cr1dir; + } + else { + cr2dir = cr1dir; + } + + if (cr2dir > 0) + return cr2; /* after cr2 */ + + return gdl_prev(&tedge2->crosses, cr2); /* before cr2 */ +} + +static int is_edge_blocked(trbs_edge_t *e, rtrnd_net_t *net) +{ + if (!e->blocked) + return 0; + + /* blocked, but by the same net - we may cross; this is how we can escape + from a via-in-poly starting point through the constrained edge of the poly */ + if ((e->obj != NULL) && (net != NULL) && (e->obj->hdr.net == net)) + return 0; + + return 1; +} + +/* Jump to the next edge within a triangle in CCW: start tracing from after + src_aft and return the crossing which the tracing lands after on the next + edge */ +static trbs_cross_t *trbs_vis_jump_edge(trbs_t *trbs, triangle_t *t, trbs_cross_t *src_aft) +{ + edge_t *srce = src_aft->edge, *dste = NULL; /* src is where we started from, dst is the next edge, CCW */ + trbs_cross_t *cr, *cr2; + int dsti, srcdir, dstdir; + point_t *corner; + + + srcdir = trbs_edge_dir_ccw(trbs, t, srce); + if (srcdir > 0) + corner = srce->endp[1]; + else + corner = srce->endp[0]; + + /* determine destination edge */ + for(dsti = 0; dsti < 3; dsti++) { + if (t->e[dsti] == srce) continue; + if ((t->e[dsti]->endp[0] == corner) || (t->e[dsti]->endp[1] == corner)) { + dste = t->e[dsti]; + break; + } + } + assert(dste != NULL); + dstdir = trbs_edge_dir_ccw(trbs, t, dste); + + if (trbs_vis_trace) { + trbs_edge_t *tsrce = srce->data, *tdste = dste->data; + trbs_cross_t *s0 = gdl_first(&tsrce->crosses), *s1 = gdl_last(&tsrce->crosses); + trbs_cross_t *d0 = gdl_first(&tdste->crosses), *d1 = gdl_last(&tdste->crosses); + tprintf("jump_edge from %ld in trinagle", src_aft->uid); + trbs_print_triangle(t); + tprintf(" srcedge=P%ld..P%ld (%ld..%ld) srcdir=%d dstdege=P%ld..P%ld (%ld..%ld) dstdir=%d\n", + ((trbs_point_t *)srce->endp[0]->data)->uid, ((trbs_point_t *)srce->endp[1]->data)->uid, s0->uid, s1->uid, srcdir, + ((trbs_point_t *)dste->endp[0]->data)->uid, ((trbs_point_t *)dste->endp[1]->data)->uid, d0->uid, d1->uid, dstdir); + } + + + if ((srcdir < 0) && (src_aft->twonet != NULL)) { /* we are after a path crossing and we are required to step back */ + /* we'd be stepping across a path crossing - instead, jump along the line */ + cr = src_aft; + } + else { + /* step one on the source edge */ + cr = CR_STEP(src_aft, srcdir); + + if (cr == NULL) /* we are at the sentinel */ + cr = src_aft; + } + + if (trbs_vis_trace) tprintf(" step: %ld->%ld sentinel=%d srcdir=%d\n", src_aft->uid, cr->uid, (cr->twonet == NULL), srcdir); + + + /* if we reached the sentinel, that means we reached the shared point; + walk around this "corner" of the triangle: return the region "after" + the sentinel on dste */ + if (cr->twonet == NULL) { + trbs_edge_t *e = dste->data; + assert(e != NULL); + + /* this point may be our target point */ + if (corner == trbs->target) { + if (trbs_vis_trace) tprintf(" -> target corner! (P%ld)\n", ((trbs_point_t *)corner->data)->uid); + return trbs->target; + } + + if (dstdir > 0) { + /* landed after the first point on src edge: */ + + /* check if a path line ends in this point, through our triangle - if so + make a jump through that line */ +tprintf("endpA cr=%ld [P%ld .. P%ld corner=P%ld]: ", cr->uid, + ((trbs_point_t *)cr->edge->endp[0]->data)->uid, + ((trbs_point_t *)cr->edge->endp[1]->data)->uid, + ((trbs_point_t *)corner->data)->uid); + cr = trbs_vis_jump_line_from_pt(trbs, t, corner, cr); + if (cr != NULL) { + if (trbs_vis_trace) tprintf(" -> %ld\n", cr->uid); + return cr; + } + + /* or return the first sentinel cr (after which our landing region is) */ + cr = gdl_first(&e->crosses); + assert(cr != NULL); + if (trbs_vis_trace) tprintf(" -> %ld (first)\n", cr->uid); + return cr; + } + + /* landed before the last point on dste: */ + + /* check if a path line ends in this point, through our triangle - if so + make a jump through that line */ +tprintf("endpB cr=%ld [P%ld .. P%ld corner=P%ld]: ", + cr->uid, + ((trbs_point_t *)cr->edge->endp[0]->data)->uid, + ((trbs_point_t *)cr->edge->endp[1]->data)->uid, + ((trbs_point_t *)corner->data)->uid); + cr = trbs_vis_jump_line_from_pt(trbs, t, corner, cr); + if (cr != NULL) { + if (trbs_vis_trace) tprintf(" -> %ld\n", cr->uid); + return cr; + } + + /* or count back one crossing from the last sentinel so cr is the crossing + after which our landing region is, right before the ending sentinel */ + cr = gdl_last(&e->crosses); + assert(cr != NULL); + assert(cr->link_edge.prev != NULL); + cr = cr->link_edge.prev; + if (trbs_vis_trace) { + if (cr != NULL) + tprintf(" -> %ld (last)\n", cr->uid); + else + tprintf(" -> NULL (last)\n"); + } + return cr; + } + + + /* else we have reached an existing path line crossing srce - need to use + that to jump on the next edge, which may be diffreent from dste */ + trbs->collision = cr->twonet; + + /* check if next point is in the same triangle */ + cr2 = gdl_next(&cr->twonet->route, cr); + if (cr2 == NULL) { + /* going into a triangle point at the end */ + if (trbs_vis_trace) tprintf(" INS1 at %ld\n", cr->uid); + cr2 = trbs_vis_get_pt_insertion(trbs, t, cr->twonet->end, cr->edge, srcdir); + if (cr2 != NULL) { + if (trbs_vis_trace) tprintf(" -> %ld\n", cr2->uid); + return cr2; + } + } + else { + /* next cr - check if within the same triangle */ + if (trbs_vis_trace) tprintf(" cr2a=%ld (in triangle %d)\n", cr2->uid, trbs_vis_cr_in_trianlge(trbs, t, cr2)); + if (trbs_vis_cr_in_trianlge(trbs, t, cr2)) + return trbs_vis_jump_path_line(trbs, t, cr, cr2, srcdir); + } + + /* else check if previus point is in the same triangle */ + cr2 = gdl_prev(&cr->twonet->route, cr); + if (cr2 == NULL) { + /* going into a triangle point at the start */ + if (trbs_vis_trace) tprintf(" INS2 at %ld\n", cr->uid); + cr2 = trbs_vis_get_pt_insertion(trbs, t, cr->twonet->start, cr->edge, srcdir); + if (cr2 != NULL) { + if (trbs_vis_trace) tprintf(" -> %ld\n", cr2->uid); + return cr2; + } + } + else { + /* prev cr - check if within the same triangle */ + if (trbs_vis_trace) tprintf(" cr2b=%ld (in triangle %d)\n", cr2->uid, trbs_vis_cr_in_trianlge(trbs, t, cr2)); + if (trbs_vis_cr_in_trianlge(trbs, t, cr2)) + return trbs_vis_jump_path_line(trbs, t, cr, cr2, srcdir); + } + + /* path crosses triangle edge but does not enter the triangle: this happens + when it is moving along the edge (conencting two points directly) */ + return NULL; +} + +/* Returns insert-after-crossing on dst if dst is visible from src; + returns NULL if not visible. */ +static trbs_cross_t *trbs_is_visible_from_edge(trbs_t *trbs, triangle_t *t, edge_t *dst, trbs_cross_t *src_aft) +{ + int timeout; + trbs_cross_t *cr = src_aft; + + /* go around in CCW to find our target edge */ + for(timeout = 0; timeout < 3; timeout++) { + cr = trbs_vis_jump_edge(trbs, t, cr); + if (cr == trbs->target) + return cr; + +#if 0 + if (cr->twonet == NULL) { /* hit a sentinel, check if it reached the end point */ + int is_last = (cr->link_edge.next == NULL); + point_t *pt = is_last ? cr->edge->endp[1] : cr->edge->endp[0]; + if (pt == trbs->target) + return trbs->target; + } +#endif + + if (cr->edge == dst) + return cr; /* positive: found the next edge region */ + if (cr->edge == src_aft->edge) + return NULL; /* negative: traced back to our own edge */ + } + + /* We should never get here: a triangle has 3 edges, so in 3 jumps we + either reached our dst or reached back on src or dst is not in the + triangle or the triangle is broken. */ + fprintf(stderr, "trbs_is_visible_from_edge(): broken triangle or dst query\n"); + abort(); + return NULL; /* suppress warning */ +} + +/* Returns insert-after-crossing index on dst if dst is visible from src; + returns NULL if not visible */ +static trbs_cross_t *trbs_is_visible_from_pt(trbs_t *trbs, triangle_t *t, edge_t *dst, point_t *src) +{ + edge_t *se = NULL, *te[3]; + double dx[3], dy[3]; + int n, m; + trbs_cross_t *snt; + trbs_edge_t *ste; + +#warning TODO: according to Wojciech edges are CCW ordered so we do not need this search + /* find edge 'CCW' from the point */ + for(n = m = 0; n < 3; n++) { + if (t->e[n]->endp[0] == src) { + dx[m] = t->e[n]->endp[1]->pos.x - t->e[n]->endp[0]->pos.x; + dy[m] = t->e[n]->endp[1]->pos.y - t->e[n]->endp[0]->pos.y; + te[m++] = t->e[n]; + } + else if (t->e[n]->endp[1] == src) { + dx[m] = t->e[n]->endp[0]->pos.x - t->e[n]->endp[1]->pos.x; + dy[m] = t->e[n]->endp[0]->pos.y - t->e[n]->endp[1]->pos.y; + te[m++] = t->e[n]; + } + } + assert(m == 2); + + /* se is the one that is 'CCW' from the point */ + se = ((line_fake_angle(dx[0], dy[0]) - line_fake_angle(dx[1], dy[1])) < 0) ? te[0] : te[1]; + ste = se->data; + + snt = (se->endp[0] == src) ? gdl_first(&ste->crosses) : gdl_last(&ste->crosses); + + /* start searching from the starting sentinel of the edge */ + return trbs_is_visible_from_edge(trbs, t, dst, snt); +} + + +void trbs_next_edge_from_point(trbs_t *trbs, vtp0_t *dst, point_t *from) +{ + trianglelist_node_t *tn; + + for(tn = from->adj_triangles; tn != NULL; tn = tn->next) { + triangle_t *t = tn->item; + edge_t *e = trbs_pt_opposite_edge(trbs, t, from); + trbs_cross_t *cr; + trbs_edge_t *tedge = e->data; + + cr = gdl_first(&tedge->crosses); + if (trbs_vis_trace) tprintf("\n?vis_from_pt P%ld: edge=%ld\n", ((trbs_point_t *)from->data)->uid, cr->uid); + + if ((e != NULL) && ((cr = trbs_is_visible_from_pt(trbs, t, e, from)) != NULL)) { + /* don't allow jumping on blocked edge */ + if (!is_edge_blocked(tedge, trbs->routing_net)) { + if (trbs_vis_trace) tprintf("!vis_from_pt P%ld: %ld\n", ((trbs_point_t *)from->data)->uid, cr->uid); + vtp0_append(dst, cr); + } + } + } +} + +void trbs_next_edge_from_edge(trbs_t *trbs, vtp0_t *dst, triangle_t *t, trbs_cross_t *from_aft, double thickness) +{ + int n; + trbs_cross_t *cr = from_aft; + + for(n = 0; n < 3; n++) { + trbs_edge_t *te; + + /* determine the next crossing */ + cr = trbs_vis_jump_edge(trbs, t, cr); + + if (cr == trbs->target) { + vtp0_append(dst, cr); + break; + } + + /* if arrived back to the starting edge, we have mapped all possible + landing zones (on all visible target edges) */ + if ((cr == NULL) || (cr->edge == from_aft->edge)) + break; + + te = cr->edge->data; + + /* don't allow jumping on blocked edge */ + if (is_edge_blocked(te, trbs->routing_net)) { + tprintf(" skip: blocked\n"); + continue; + } + + if (te->cap < thickness) { + tprintf(" skip: cap %f < %f\n", te->cap, thickness); + continue; + } + + if (trbs_vis_trace) { + tprintf("edge2edge %ld=>%ld in triangle", from_aft->uid, cr->uid); + trbs_print_triangle(t); + tprintf("\n"); + } + vtp0_append(dst, cr); + } +} + Index: tags/0.9.0/src/plugins/rt_topo/vt2br.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vt2br.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vt2br.c (revision 1402) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vt2br.h" +#include Index: tags/0.9.0/src/plugins/rt_topo/vt2br.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vt2br.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vt2br.h (revision 1402) @@ -0,0 +1,96 @@ +#ifndef VT2BR_H +#define VT2BR_H + +#include +#include +#include "data.h" + +typedef struct rtrnd_2branch_s rtrnd_2branch_t; + +struct rtrnd_2branch_s { + struct rt_topo_laa_2net_s *parent; + double offs; /* offset 0..1 from the the 2net's x1;y1 */ + double x, y; /* starting point coords */ + long pt_layers; /* which layers the starting point may access */ + unsigned coord_fixed:1; /* can't be moved (terminal) */ + char edge_ly_fixed; /* if >= 0, outgoing edge is fixed to a specific layer */ + int cridx; /* if >= 0, index into the crossing vector for the crossing that happens on the outgoing edge of this branch (there can be only one crossing) */ + + /* temporary fields used for laa3 */ + rtrnd_2branch_t *found_next; + rtrnd_via_t *via; /* via placed in that point, or NULL; when via placed, real coords for RBE is x;y of the via, not the x;y of the branch! */ + void *ordinfo; /* temp for laa2rbs ordering */ + unsigned found:1; +}; + +/* An actual assingment is a char[] where each byte corresponds to one + rtrnd_2branch_t and determines which layer the next edge leaves on; + -1 means free */ + +/* Elem=rtrnd_2branch_t; init=0 + Long int vector, all newly allocated bytes are set to 0 */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vt2br_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE rtrnd_2branch_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 128 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional terminator; when present, it is always appended at the end - see + vt_term(7)*/ +/* #define GVT_TERM '\0' */ + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + +/* Enable GVT_INIT_ELEM_FUNC and an user configured function is called + for each new element allocated (even between used and alloced). + See vt_init_elem(7) */ +/*#define GVT_INIT_ELEM_FUNC*/ + +/* Enable GVT_ELEM_CONSTRUCTOR and an user configured function is called + for each element that is getting within the range of ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_CONSTRUCTOR */ + +/* Enable GVT_ELEM_DESTRUCTOR and an user configured function is called + for each element that was once constructed and now getting beyong ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_DESTRUCTOR */ + +/* Enable GVT_ELEM_COPY and an user configured function is called + for copying elements into the array. + See vt_construction(7) */ +/*#define GVT_ELEM_COPY */ + +/* Optional extra fields in the vector struct - see vt_user_fields(7) */ +/* #define GVT_USER_FIELDS int foo; char bar[12]; */ + +/* An extra no_realloc field; when it is set to non-zero by the user, no + realloc() is called (any attempt to grow the array fails) */ +/* #define GVT_OPTIONAL_NO_REALLOC */ + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/0.9.0/src/plugins/rt_topo/vtcr.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vtcr.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vtcr.c (revision 1402) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtcr.h" +#include Index: tags/0.9.0/src/plugins/rt_topo/vtcr.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vtcr.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vtcr.h (revision 1402) @@ -0,0 +1,88 @@ +#ifndef VTCR_H +#define VTCR_H + +#include +#include + +typedef struct rtrnd_crossing_s rtrnd_crossing_t; + +struct rtrnd_crossing_s { + double offs; /* offset on the first line */ + double x, y; + int bridx; /* the index of the branch the crossing is after (this means the crossing takes place on the outgoing line of the given branch) */ + struct rt_topo_laa_2net_s *cn; /* crossing 2net (second line) */ + int cn_bridx; /* the index of the branch the crossing on the second line */ + rtrnd_crossing_t *cn_cr; /* the same crossing on the second line, by pointer */ + int cn_cridx; /* the same crossing on the second line, by index */ + double detcost; /* first line's cross detour cost on the current drawing (0 if there's no on-layer crossing) */ + const struct rt_topo_laa_2net_s + *tn_detouring; /* the 2net hat is making the detour (shorter detour) */ +}; + +/* Elem=rtrnd_crossing_t; init=0 + Long int vector, all newly allocated bytes are set to 0 */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtcr_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE rtrnd_crossing_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 128 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional terminator; when present, it is always appended at the end - see + vt_term(7)*/ +/* #define GVT_TERM '\0' */ + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + +/* Enable GVT_INIT_ELEM_FUNC and an user configured function is called + for each new element allocated (even between used and alloced). + See vt_init_elem(7) */ +/*#define GVT_INIT_ELEM_FUNC*/ + +/* Enable GVT_ELEM_CONSTRUCTOR and an user configured function is called + for each element that is getting within the range of ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_CONSTRUCTOR */ + +/* Enable GVT_ELEM_DESTRUCTOR and an user configured function is called + for each element that was once constructed and now getting beyong ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_DESTRUCTOR */ + +/* Enable GVT_ELEM_COPY and an user configured function is called + for copying elements into the array. + See vt_construction(7) */ +/*#define GVT_ELEM_COPY */ + +/* Optional extra fields in the vector struct - see vt_user_fields(7) */ +/* #define GVT_USER_FIELDS int foo; char bar[12]; */ + +/* An extra no_realloc field; when it is set to non-zero by the user, no + realloc() is called (any attempt to grow the array fails) */ +/* #define GVT_OPTIONAL_NO_REALLOC */ + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/0.9.0/src/plugins/rt_topo/vtve0.c =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vtve0.c (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vtve0.c (revision 1402) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtve0.h" +#include Index: tags/0.9.0/src/plugins/rt_topo/vtve0.h =================================================================== --- tags/0.9.0/src/plugins/rt_topo/vtve0.h (nonexistent) +++ tags/0.9.0/src/plugins/rt_topo/vtve0.h (revision 1402) @@ -0,0 +1,76 @@ +#ifndef VTVE0_H +#define VTVE0_H + +#include +#include +#include +#include "geo.h" +#include + +/* Elem=g2d_vect_t; init=0 + Long int vector, all newly allocated bytes are set to 0 */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtve0_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE g2d_vect_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 128 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional terminator; when present, it is always appended at the end - see + vt_term(7)*/ +/* #define GVT_TERM '\0' */ + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + +/* Enable GVT_INIT_ELEM_FUNC and an user configured function is called + for each new element allocated (even between used and alloced). + See vt_init_elem(7) */ +/*#define GVT_INIT_ELEM_FUNC*/ + +/* Enable GVT_ELEM_CONSTRUCTOR and an user configured function is called + for each element that is getting within the range of ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_CONSTRUCTOR */ + +/* Enable GVT_ELEM_DESTRUCTOR and an user configured function is called + for each element that was once constructed and now getting beyong ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_DESTRUCTOR */ + +/* Enable GVT_ELEM_COPY and an user configured function is called + for copying elements into the array. + See vt_construction(7) */ +/*#define GVT_ELEM_COPY */ + +/* Optional extra fields in the vector struct - see vt_user_fields(7) */ +/* #define GVT_USER_FIELDS int foo; char bar[12]; */ + +/* An extra no_realloc field; when it is set to non-zero by the user, no + realloc() is called (any attempt to grow the array fails) */ +/* #define GVT_OPTIONAL_NO_REALLOC */ + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/0.9.0/src/route-rnd/Makefile =================================================================== --- tags/0.9.0/src/route-rnd/Makefile (nonexistent) +++ tags/0.9.0/src/route-rnd/Makefile (revision 1402) @@ -0,0 +1,65 @@ +ROOT=../.. + +include $(ROOT)/Makefile.conf +include Makefile.conf + +CDT_COORD=-DCDT_COORD_T=double -Dcdt_precision=1000000.0 +CFLAGS_TEMP_GRBS = -I.. +CFLAGS = $(CFLAGS_RTRND) $(CDT_COORD) $(CFLAGS_TEMP_GRBS) +LOCLIBS = $(LOCLIBS_RTRND) +LDLIBS = -lm +LDFLAGS = $(LDFLAGS_RTRND) +OBJS = route-rnd.o rtree.o compat_misc.o data.o io.o util_grid.o htdi.o \ + util_rat.o netseg.o find.o rtpoly.o route_res.o conf.o +BINDIR=$(install_root)$(DESTDIR)$(PREFIX)/bin + +all: libroute-rnd.a route-rnd$(EXE) + +include ../plugins/Makefile.inc +include Makefile.dep + +route-rnd$(EXE): main.o $(OBJS) $(BUILDIN_O) $(LOCLIBS) + $(CC) -o $@ $(LDFLAGS) main.o $(OBJS) $(BUILDIN_O) $(LOCLIBS) $(LDLIBS) + +libroute-rnd.a: main.o $(OBJS) $(BUILDIN_O) $(LOCLIBS) + ar ru $@ main.o $(OBJS) $(BUILDIN_O) $(LOCLIBS) + +$(ROOT)/src_3rd/genvector/libgenvector.a: + cd $(ROOT)/src_3rd/genvector && make libgenvector.a + +$(ROOT)/src_3rd/genht/libgenht.a: + cd $(ROOT)/src_3rd/genht && make libgenht.a + +$(ROOT)/src_3rd/libusteiner/libusteiner.a: $(ROOT)/src_3rd/libusteiner/libusteiner.o $(ROOT)/src_3rd/libusteiner/libusteiner.h + cd $(ROOT)/src_3rd/libusteiner && make libusteiner.a + +$(ROOT)/src_3rd/libcdtr/libcdtr.a: + cd $(ROOT)/src_3rd/libcdtr && make libcdtr.a CFLAGS_LIBCDTR="$(CDT_COORD)" + +$(ROOT)/src_3rd/libualloc/libualloc.a: + cd $(ROOT)/src_3rd/libualloc && make libualloc.a + +$(ROOT)/src_3rd/libusearch/libusearch.a: + cd $(ROOT)/src_3rd/libusearch && make libusearch.a + +$(ROOT)/src_3rd/genprique/genprique.a: + cd $(ROOT)/src_3rd/genprique && make genprique.a + +dep: + echo $(OBJS) $(BUILDIN_O) | ../../util/dep.sh $(CFLAGS) > Makefile.dep + +install: + mkdir -p $(BINDIR) + $(CP) route-rnd$(EXE) $(BINDIR)/route-rnd$(EXE) + +linstall: + mkdir -p $(BINDIR) + $(LN) $(PWD)/route-rnd$(EXE) $(BINDIR)/route-rnd$(EXE) + +uninstall: + $(RM) $(BINDIR)/route-rnd$(EXE) + +clean: + $(RM) $(OBJS) $(BUILDIN_O) route-rnd + +distclean: clean Index: tags/0.9.0/src/route-rnd/Makefile.conf =================================================================== --- tags/0.9.0/src/route-rnd/Makefile.conf (nonexistent) +++ tags/0.9.0/src/route-rnd/Makefile.conf (revision 1402) @@ -0,0 +1,12 @@ +CFLAGS_RTRND = $(CFLAGS_CFG) -I. -I$(ROOT)/src_3rd -I$(ROOT)/src/plugins +LDLIBS_RTRND = $(LOCLIBS) +LDFLAGS_RTRND = -lm +LOCLIBS_RTRND = \ + $(ROOT)/src_3rd/genvector/libgenvector.a \ + $(ROOT)/src_3rd/genht/libgenht.a \ + $(ROOT)/src_3rd/libusteiner/libusteiner.a \ + $(ROOT)/src_3rd/libpsrand/mtw.o \ + $(ROOT)/src_3rd/libcdtr/libcdtr.a \ + $(ROOT)/src_3rd/libualloc/libualloc.a \ + $(ROOT)/src_3rd/libusearch/libusearch.a \ + $(ROOT)/src_3rd/genprique/genprique.a Index: tags/0.9.0/src/route-rnd/Makefile.dep =================================================================== --- tags/0.9.0/src/route-rnd/Makefile.dep (nonexistent) +++ tags/0.9.0/src/route-rnd/Makefile.dep (revision 1402) @@ -0,0 +1,273 @@ +route-rnd.o: route-rnd.c config.h route-rnd.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h conf.h data.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h rtree.h ../../src_3rd/genrtree/genrtree_api.h \ + geo.h ../../src_3rd/gengeo2d/typecfg_double_double.h \ + ../../src_3rd/opc89.h ../../src_3rd/gengeo2d/common.h \ + ../../src_3rd/gengeo2d/prim.h rtpoly.h netseg.h \ + ../../src/plugins/buildin.h route_res.h io.h +rtree.o: rtree.c config.h rtree.h ../../src_3rd/genrtree/genrtree_api.h \ + ../../src_3rd/genrtree/genrtree_impl.h \ + ../../src_3rd/genrtree/genrtree_search.h \ + ../../src_3rd/genrtree/genrtree_delete.h +compat_misc.o: compat_misc.c config.h +data.o: data.c config.h data.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + compat_misc.h netseg.h ../../src_3rd/gengeo2d/cline.h \ + ../../src_3rd/gengeo2d/vect.h ../../src_3rd/gengeo2d/box.h \ + ../../src_3rd/genht/hash.h ../../src_3rd/genht/ht_utils.h +io.o: io.c config.h route-rnd.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h conf.h io.h +util_grid.o: util_grid.c config.h route-rnd.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h conf.h data.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h rtree.h ../../src_3rd/genrtree/genrtree_api.h \ + geo.h ../../src_3rd/gengeo2d/typecfg_double_double.h \ + ../../src_3rd/opc89.h ../../src_3rd/gengeo2d/common.h \ + ../../src_3rd/gengeo2d/prim.h rtpoly.h ../../src_3rd/gengeo2d/box.h \ + ../../src_3rd/gengeo2d/vect.h htdi.h ../../src_3rd/genht/ht.h \ + util_grid.h ../../src_3rd/genvector/vtd0.h +htdi.o: htdi.c htdi.h ../../src_3rd/genht/ht.h ../../src_3rd/genht/ht.c \ + ../../src_3rd/genht/ht_inlines.h ../../src_3rd/genht/hash.h +util_rat.o: util_rat.c config.h route-rnd.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h conf.h data.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h rtree.h ../../src_3rd/genrtree/genrtree_api.h \ + geo.h ../../src_3rd/gengeo2d/typecfg_double_double.h \ + ../../src_3rd/opc89.h ../../src_3rd/gengeo2d/common.h \ + ../../src_3rd/gengeo2d/prim.h rtpoly.h ../../src_3rd/gengeo2d/box.h \ + ../../src_3rd/gengeo2d/vect.h util_rat.h +netseg.o: netseg.c config.h data.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + find.h ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h netseg.h +find.o: find.c config.h data.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + find.h ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h ../../src_3rd/gengeo2d/sline.h +rtpoly.o: rtpoly.c config.h geo.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h \ + ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h rtpoly.h ../../src_3rd/genlist/gendlist.h \ + rtree.h ../../src_3rd/genrtree/genrtree_api.h +route_res.o: route_res.c config.h route_res.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h +conf.o: conf.c config.h conf.h compat_misc.h +../../src/plugins//buildin.o: ../../src/plugins//buildin.c +../../src/plugins//io_tedax/parse.o: ../../src/plugins//io_tedax/parse.c \ + config.h ../../src/plugins//io_tedax/parse.h +../../src/plugins//io_tedax/io_tedax.o: \ + ../../src/plugins//io_tedax/io_tedax.c config.h \ + ../../src_3rd/genvector/vts0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h ../../src_3rd/genvector/vtd0.h \ + ../../src_3rd/genvector/gds_char.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h ../../src_3rd/genht/htss.h \ + ../../src_3rd/genht/hash.h ../../src_3rd/genht/ht_utils.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genlist/gendlist.h \ + route-rnd.h conf.h rtree.h ../../src_3rd/genrtree/genrtree_api.h geo.h \ + config.h ../../src_3rd/gengeo2d/typecfg_double_double.h \ + ../../src_3rd/opc89.h ../../src_3rd/gengeo2d/common.h \ + ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + ../../src/plugins//io_tedax/parse.h compat_misc.h conf.h +../../src/plugins//export_animator/export_animator.o: \ + ../../src/plugins//export_animator/export_animator.c config.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h +../../src/plugins//export_svg/export_svg.o: \ + ../../src/plugins//export_svg/export_svg.c config.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h +../../src/plugins//rt_horver/rt_horver.o: \ + ../../src/plugins//rt_horver/rt_horver.c config.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + util_grid.h ../../src_3rd/genvector/vtd0.h data.h \ + ../../src/plugins//rt_horver/rt_horver.h \ + ../../src/plugins//rt_horver/escape.h ../../src/plugins//rt_horver/bus.h \ + ../../src/plugins//rt_horver/optimize.h route_res.h conf.h +../../src/plugins//rt_horver/escape.o: \ + ../../src/plugins//rt_horver/escape.c \ + ../../src/plugins//rt_horver/rt_horver.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + util_grid.h ../../src_3rd/genvector/vtd0.h data.h \ + ../../src/plugins//rt_horver/escape.h ../../src/plugins//rt_horver/bus.h \ + ../../src/plugins//rt_horver/hpkp.h +../../src/plugins//rt_horver/optimize.o: \ + ../../src/plugins//rt_horver/optimize.c ../../src_3rd/genht/htpp.h \ + ../../src_3rd/genht/ht.h ../../src_3rd/genht/hash.h \ + ../../src_3rd/genht/ht_utils.h ../../src/plugins//rt_horver/rt_horver.h \ + data.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h route-rnd.h \ + conf.h rtree.h ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + util_grid.h ../../src_3rd/genvector/vtd0.h data.h \ + ../../src/plugins//rt_horver/escape.h ../../src/plugins//rt_horver/bus.h \ + ../../src/plugins//rt_horver/optimize.h netseg.h +../../src/plugins//rt_horver/bus.o: ../../src/plugins//rt_horver/bus.c \ + ../../src/plugins//rt_horver/bus.h util_grid.h \ + ../../src_3rd/genvector/vtd0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genlist/gendlist.h \ + ../../src_3rd/genht/htsp.h ../../src_3rd/genht/ht.h route-rnd.h conf.h \ + rtree.h ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + ../../src/plugins//rt_horver/rt_horver.h data.h \ + ../../src/plugins//rt_horver/escape.h +../../src/plugins//rt_horver/hpkp.o: ../../src/plugins//rt_horver/hpkp.c \ + ../../src/plugins//rt_horver/hpkp.h +../../src/plugins//rt_topo/rt_topo.o: \ + ../../src/plugins//rt_topo/rt_topo.c config.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + ../../src/plugins//rt_topo/laa.h rtree.h \ + ../../src/plugins//rt_topo/vt2br.h ../../src/plugins//rt_topo/vtcr.h \ + ../../src/plugins//rt_topo/rt_topo.h ../../src/plugins//rt_topo/trbs.h \ + ../../src_3rd/libcdtr/cdt.h ../../src_3rd/libcdtr/typedefs.h \ + ../../src_3rd/libcdtr/point.h ../../src_3rd/libcdtr/list/list.h \ + ../../src_3rd/libcdtr/edge.h ../../src_3rd/libcdtr/triangle.h \ + ../../src_3rd/libualloc/stacks_api.h ../../src_3rd/libualloc/libualloc.h \ + ../../src/plugins//rt_topo/crbs.h +../../src/plugins//rt_topo/vt2br.o: ../../src/plugins//rt_topo/vt2br.c \ + ../../src/plugins//rt_topo/vt2br.h data.h ../../src_3rd/genvector/vtp0.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + ../../src_3rd/genvector/genvector_impl.c +../../src/plugins//rt_topo/vtcr.o: ../../src/plugins//rt_topo/vtcr.c \ + ../../src/plugins//rt_topo/vtcr.h \ + ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genvector/genvector_impl.c +../../src/plugins//rt_topo/vtve0.o: ../../src/plugins//rt_topo/vtve0.c \ + ../../src/plugins//rt_topo/vtve0.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h \ + ../../src_3rd/gengeo2d/vect.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h \ + ../../src_3rd/genvector/genvector_impl.c +../../src/plugins//rt_topo/laa.o: ../../src/plugins//rt_topo/laa.c \ + config.h ../../src_3rd/libusteiner/libusteiner.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h \ + ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h ../../src_3rd/gengeo2d/sline.h \ + ../../src_3rd/gengeo2d/chull.h ../../src_3rd/libpsrand/mtw.h \ + ../../src_3rd/libpsrand/psr.h ../../src_3rd/libualloc/stacks_api.h \ + ../../src_3rd/libualloc/libualloc.h data.h \ + ../../src_3rd/genlist/gendlist.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h rtpoly.h \ + ../../src/plugins//rt_topo/vt2br.h ../../src/plugins//rt_topo/vtcr.h \ + ../../src/plugins//rt_topo/vtve0.h rtree.h find.h io.h \ + ../../src/plugins//rt_topo/rt_topo.h ../../src/plugins//rt_topo/laa.h \ + ../../src/plugins//rt_topo/laa1.c ../../src/plugins//rt_topo/laa2.c \ + ../../src/plugins//rt_topo/laa3.c \ + ../../src/plugins//rt_topo/laa3_detour.c \ + ../../src/plugins//rt_topo/laa3_solve.c \ + ../../src/plugins//rt_topo/laa3_render.c +../../src/plugins//rt_topo/trbs.o: ../../src/plugins//rt_topo/trbs.c \ + config.h ../../src_3rd/genlist/gendlist.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + io.h route_res.h data.h ../../src/plugins//rt_topo/trbs.h \ + ../../src_3rd/libcdtr/cdt.h ../../src_3rd/libcdtr/typedefs.h \ + ../../src_3rd/libcdtr/point.h ../../src_3rd/libcdtr/list/list.h \ + ../../src_3rd/libcdtr/edge.h ../../src_3rd/libcdtr/triangle.h \ + ../../src_3rd/libualloc/stacks_api.h ../../src_3rd/libualloc/libualloc.h \ + ../../src/plugins//rt_topo/rt_topo.h \ + ../../src/plugins//rt_topo/trbs_util.c \ + ../../src/plugins//rt_topo/trbs_cdt.c ../../src_3rd/genvector/vtd0.h \ + geo.h ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h ../../src/plugins//rt_topo/trbs_vis.c \ + ../../src/plugins//rt_topo/trbs_route.c \ + ../../src_3rd/libusearch/a_star_api.h ../../src_3rd/genprique/fibheap.h \ + ../../src_3rd/libusearch/common.h ../../src/plugins//rt_topo/trbs_pull.c +../../src/plugins//rt_topo/crbs.o: ../../src/plugins//rt_topo/crbs.c \ + config.h ../../src_3rd/genlist/gendlist.h data.h \ + ../../src_3rd/genvector/vtp0.h ../../src_3rd/genvector/genvector_impl.h \ + ../../src_3rd/genvector/genvector_undef.h ../../src_3rd/genht/htsp.h \ + ../../src_3rd/genht/ht.h route-rnd.h conf.h rtree.h \ + ../../src_3rd/genrtree/genrtree_api.h geo.h config.h \ + ../../src_3rd/gengeo2d/typecfg_double_double.h ../../src_3rd/opc89.h \ + ../../src_3rd/gengeo2d/common.h ../../src_3rd/gengeo2d/prim.h rtpoly.h \ + io.h route_res.h data.h ../../src/plugins//rt_topo/crbs.h \ + ../../src/plugins//rt_topo/rt_topo.h ../../src_3rd/libcdtr/cdt.h \ + ../../src_3rd/libcdtr/typedefs.h ../../src_3rd/libcdtr/point.h \ + ../../src_3rd/libcdtr/list/list.h ../../src_3rd/libcdtr/edge.h \ + ../../src_3rd/libcdtr/triangle.h ../../src_3rd/libualloc/stacks_api.h \ + ../../src_3rd/libualloc/libualloc.h \ + ../../src/plugins//rt_topo/crbs_cdt.c ../../src_3rd/genvector/vtd0.h \ + geo.h ../../src_3rd/gengeo2d/cline.h ../../src_3rd/gengeo2d/vect.h \ + ../../src_3rd/gengeo2d/box.h \ + ../../src/plugins//rt_topo/crbs_route.c \ + ../../src_3rd/libusearch/a_star_api.h ../../src_3rd/genprique/fibheap.h \ + ../../src_3rd/libusearch/common.h Index: tags/0.9.0/src/route-rnd/compat_misc.c =================================================================== --- tags/0.9.0/src/route-rnd/compat_misc.c (nonexistent) +++ tags/0.9.0/src/route-rnd/compat_misc.c (revision 1402) @@ -0,0 +1,88 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * compatibility calls, misc (copied from pcb-rnd code by the same author) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include + +char *rnd_strndup(const char *s, int len) +{ + int a, l = strlen(s); + char *o; + + a = (len < l) ? len : l; + o = malloc(a+1); + memcpy(o, s, a); + o[a] = '\0'; + return o; +} + +char *rnd_strdup(const char *s) +{ + int l = strlen(s); + char *o; + o = malloc(l+1); + memcpy(o, s, l+1); + return o; +} + +char *rnd_strdup_safe(const char *s) +{ + if (s == NULL) + return NULL; + return rnd_strdup(s); +} + +int rnd_strcasecmp(const char *s1, const char *s2) +{ + while(tolower(*s1) == tolower(*s2)) { + if (*s1 == '\0') + return 0; + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} + +int rnd_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return 0; + + while(tolower(*s1) == tolower(*s2)) { + n--; + if (n == 0) + return 0; + if (*s1 == '\0') + return 0; + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} Index: tags/0.9.0/src/route-rnd/compat_misc.h =================================================================== --- tags/0.9.0/src/route-rnd/compat_misc.h (nonexistent) +++ tags/0.9.0/src/route-rnd/compat_misc.h (revision 1402) @@ -0,0 +1,10 @@ +#ifndef RTRND_COMPAT_MISC_H +#define RTRND_COMPAT_MISC_H + +char *rnd_strndup(const char *s, int len); +char *rnd_strdup(const char *s); +char *rnd_strdup_safe(const char *s); +int rnd_strcasecmp(const char *s1, const char *s2); +int rnd_strncasecmp(const char *s1, const char *s2, size_t n); + +#endif Index: tags/0.9.0/src/route-rnd/conf.c =================================================================== --- tags/0.9.0/src/route-rnd/conf.c (nonexistent) +++ tags/0.9.0/src/route-rnd/conf.c (revision 1402) @@ -0,0 +1,146 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * router conf settings + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf.h" +#include +#include +#include +#include "compat_misc.h" + +static const char *type_names[] = { + "", "boolean", "integer", "double", "coord", "string" +}; + +const char *rtrnd_conf_type2name(rtrnd_conf_type_t type) +{ + if ((type >= 0) && (type < sizeof(type_names)/sizeof(type_names[0]))) + return type_names[type]; + return ""; +} + +rtrnd_conf_type_t rtrnd_conf_name2type(const char *name) +{ + rtrnd_conf_type_t i; + const char **n; + for(n = type_names+1, i = 1; i < sizeof(type_names)/sizeof(type_names[0]); i++,n++) + if (strcmp(*n, name) == 0) + return i; + return RTRND_CT_INVALID; +} + +static int rtrnd_conf_setval(rtrnd_conf_t *row, const char *val) +{ + switch(row->type) { + case RTRND_CT_BOOLEAN: + if ((*val == '1') || (*val == 't') || (*val == 'T') || (*val == 'y') || (*val == 'Y')) + *row->data.i = 1; + if ((*val == '0') || (*val == 'f') || (*val == 'F') || (*val == 'n') || (*val == 'N')) + *row->data.i = 1; + else + return -1; + return 0; + case RTRND_CT_INTEGER: + { + char *end; + long l = strtol(val, &end, 10); + if (*end != '\0') return -1; + if ((row->min != RTRND_CONF_NOVAL) && (l < row->min)) return -1; + if ((row->max != RTRND_CONF_NOVAL) && (l > row->max)) return -1; + *row->data.i = l; + return 0; + } + case RTRND_CT_DOUBLE: + case RTRND_CT_COORD: + { + char *end; + double d = strtod(val, &end); + if (*end != '\0') return -1; + if ((row->min != RTRND_CONF_NOVAL) && (d < row->min)) return -1; + if ((row->max != RTRND_CONF_NOVAL) && (d > row->max)) return -1; + *row->data.d = d; + return 0; + } + case RTRND_CT_STRING: + free(row->data.s); + row->data.s = rnd_strdup(val); + return 0; + case RTRND_CT_TERMINATOR: + return -1; + } + return 0; +} + +int rtrnd_conf_set(rtrnd_conf_t *table, const char *key, const char *val) +{ + rtrnd_conf_t *c; + for(c = table; c->type != RTRND_CT_TERMINATOR; c++) { + if (strcmp(c->name, key) == 0) + return rtrnd_conf_setval(c, val); + } + return -1; +} + + +static int rtrnd_conf_setdef(rtrnd_conf_t *row) +{ + + switch(row->type) { + case RTRND_CT_BOOLEAN: + if (row->defval.dval == RTRND_CONF_NOVAL) + return -1; + *row->data.i = !!row->defval.dval; break; + case RTRND_CT_INTEGER: + if (row->defval.dval == RTRND_CONF_NOVAL) + return -1; + *row->data.i = row->defval.dval; break; + case RTRND_CT_DOUBLE: + case RTRND_CT_COORD: + if (row->defval.dval == RTRND_CONF_NOVAL) + return -1; + *row->data.d = row->defval.dval; break; + case RTRND_CT_STRING: + free(row->data.s); + if (row->defval.sval != NULL) + row->data.s = rnd_strdup(row->defval.sval); + else + row->data.s = NULL; + break; + case RTRND_CT_TERMINATOR: + return -1; + } + return 0; +} + +int rtrnd_conf_defaults(rtrnd_conf_t *table) +{ + rtrnd_conf_t *c; + for(c = table; c->type != RTRND_CT_TERMINATOR; c++) + rtrnd_conf_setdef(c); + return 0; +} Index: tags/0.9.0/src/route-rnd/conf.h =================================================================== --- tags/0.9.0/src/route-rnd/conf.h (nonexistent) +++ tags/0.9.0/src/route-rnd/conf.h (revision 1402) @@ -0,0 +1,61 @@ +#ifndef RTRND_CONF_H +#define RTRND_CONF_H + +#include + +typedef enum { + RTRND_CT_TERMINATOR, + RTRND_CT_BOOLEAN, + RTRND_CT_INTEGER, + RTRND_CT_DOUBLE, + RTRND_CT_COORD, + RTRND_CT_STRING +} rtrnd_conf_type_t; + +#define RTRND_CT_INVALID RTRND_CT_TERMINATOR +#define RTRND_CONF_NOVAL HUGE_VAL + +typedef struct { + const char *name; + rtrnd_conf_type_t type; + union { + double dval; + const char *sval; + } defval; + double min, max; + const char *desc; + union { + void *any; + int *b; + long *i; + double *d; + char *s; + } data; +} rtrnd_conf_t; + +#define RTRND_CONF_BOOLEAN(name, defval, desc, ptr) \ + {name, RTRND_CT_BOOLEAN, {defval}, RTRND_CONF_NOVAL, RTRND_CONF_NOVAL, desc, {ptr}}, + +#define RTRND_CONF_INTEGER(name, defval, min, max, desc, ptr) \ + {name, RTRND_CT_INTEGER, {defval}, min, max, desc, {ptr}}, + +#define RTRND_CONF_DOUBLE(name, defval, min, max, desc, ptr) \ + {name, RTRND_CT_DOUBLE, {defval}, min, max, desc, {ptr}}, + +#define RTRND_CONF_COORD(name, defval, min, max, desc, ptr) \ + {name, RTRND_CT_COORD, {defval}, min, max, desc, {ptr}}, + +#define RTRND_CONF_STRING(name, defval, desc, ptr) \ + {name, RTRND_CT_STRING, {0, defval}, RTRND_CONF_NOVAL, RTRND_CONF_NOVAL, desc, {ptr}}, + +#define RTRND_CONF_TERMINATE \ + {NULL, RTRND_CT_TERMINATOR, {0}, RTRND_CONF_NOVAL, RTRND_CONF_NOVAL, NULL, {NULL}} + +const char *rtrnd_conf_type2name(rtrnd_conf_type_t type); + +int rtrnd_conf_set(rtrnd_conf_t *table, const char *key, const char *val); + +/* Load the config values behind a table with the default values */ +int rtrnd_conf_defaults(rtrnd_conf_t *table); + +#endif Index: tags/0.9.0/src/route-rnd/config.h =================================================================== --- tags/0.9.0/src/route-rnd/config.h (nonexistent) +++ tags/0.9.0/src/route-rnd/config.h (revision 1402) @@ -0,0 +1,7 @@ +#ifndef ROUTE_RND_CONFIG_H +#define ROUTE_RND_CONFIG_H + +#define RTRND_INLINE static inline +#define rnd_strcasecmp strcasecmp + +#endif Index: tags/0.9.0/src/route-rnd/data.c =================================================================== --- tags/0.9.0/src/route-rnd/data.c (nonexistent) +++ tags/0.9.0/src/route-rnd/data.c (revision 1402) @@ -0,0 +1,426 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * data mode handling + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include "data.h" +#include "geo.h" +#include "compat_misc.h" +#include "netseg.h" +#include +#include +#include +#include + +static void box_geo2rtree(rtrnd_rtree_box_t *dst, const g2d_box_t *src) +{ + dst->x1 = src->p1.x; dst->y1 = src->p1.y; + dst->x2 = src->p2.x; dst->y2 = src->p2.y; +} + +static void rtrnd_obj_reg_ly(rtrnd_layer_t *layer, rtrnd_any_obj_t *obj) +{ + rtrnd_rtree_insert(&layer->objs, obj, &obj->hdr.bbox); + obj->hdr.parent = (rtrnd_any_obj_t *)layer; +} + +static void rtrnd_obj_unreg_ly(rtrnd_layer_t *layer, rtrnd_any_obj_t *obj) +{ + rtrnd_rtree_delete(&layer->objs, obj, &obj->hdr.bbox); + obj->hdr.parent = NULL; +} + +static void rtrnd_obj_reg_via(rtrnd_board_t *brd, rtrnd_via_t *via) +{ + rtrnd_rtree_insert(&brd->vias, via, &via->hdr.bbox); + via->hdr.parent = (rtrnd_any_obj_t *)brd; +} + +static void rtrnd_obj_unreg_via(rtrnd_board_t *brd, rtrnd_via_t *via) +{ + rtrnd_rtree_delete(&brd->vias, via, &via->hdr.bbox); + via->hdr.parent = NULL; +} + +static void rtrnd_obj_reg_net(rtrnd_net_t *net, rtrnd_any_obj_t *obj) +{ + assert(obj->hdr.net == NULL); + if (net != NULL) { + obj->hdr.net = net; + gdl_append(&net->objs, obj, hdr.net_link); + } +} + +static void rtrnd_obj_unreg_net(rtrnd_net_t *net, rtrnd_any_obj_t *obj) +{ + assert(obj->hdr.net == net); + if (net != NULL) { + obj->hdr.net = NULL; + gdl_remove(&net->objs, obj, hdr.net_link); + } +} + +rtrnd_line_t *rtrnd_line_new(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double x1, double y1, double x2, double y2, double thick, double clr) +{ + double t2 = thick/2; + rtrnd_line_t *line = calloc(sizeof(rtrnd_line_t), 1); + g2d_box_t b; + + line->hdr.type = RTRND_LINE; + line->hdr.oid = rnd_strdup_safe(oid); + line->cline.p1.x = x1; line->cline.p1.y = y1; + line->cline.p2.x = x2; line->cline.p2.y = y2; + line->thickness = thick; + line->clearance = clr; + b = g2d_cline_bbox(&line->cline); + b.p1.x -= t2; b.p1.y -= t2; + b.p2.x += t2; b.p2.y += t2; + box_geo2rtree(&line->hdr.bbox, &b); + + rtrnd_obj_reg_ly(layer, (rtrnd_any_obj_t *)line); + rtrnd_obj_reg_net(net, (rtrnd_any_obj_t *)line); + + return line; +} + +void rtrnd_line_free(rtrnd_line_t *line) +{ + free(line->hdr.oid); + rtrnd_obj_unreg_ly(&line->hdr.parent->layer, (rtrnd_any_obj_t *)line); + rtrnd_obj_unreg_net(line->hdr.net, (rtrnd_any_obj_t *)line); + free(line); +} + + +rtrnd_arc_t *rtrnd_arc_new(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double cx, double cy, double r, double start, double delta, double thick, double clr) +{ + double t2 = thick/2; + rtrnd_arc_t *arc = calloc(sizeof(rtrnd_arc_t), 1); + g2d_box_t b; + + arc->hdr.type = RTRND_ARC; + arc->hdr.oid = rnd_strdup_safe(oid); + arc->carc.c.x = cx; arc->carc.c.y = cy; + arc->carc.r = r; + arc->carc.start = start; + arc->carc.delta = delta; + arc->thickness = thick; + arc->clearance = clr; + b = g2d_carc_bbox(&arc->carc); + b.p1.x -= t2; b.p1.y -= t2; + b.p2.x += t2; b.p2.y += t2; + box_geo2rtree(&arc->hdr.bbox, &b); + + rtrnd_obj_reg_ly(layer, (rtrnd_any_obj_t *)arc); + rtrnd_obj_reg_net(net, (rtrnd_any_obj_t *)arc); + + return arc; +} + +void rtrnd_arc_free(rtrnd_arc_t *arc) +{ + free(arc->hdr.oid); + rtrnd_obj_unreg_ly(&arc->hdr.parent->layer, (rtrnd_any_obj_t *)arc); + rtrnd_obj_unreg_net(arc->hdr.net, (rtrnd_any_obj_t *)arc); + free(arc); +} + +rtrnd_text_t *rtrnd_text_new(rtrnd_layer_t *layer, double x, double y, const char *txt, double size) +{ + rtrnd_text_t *text = calloc(sizeof(rtrnd_text_t), 1); + g2d_box_t b; + + text->hdr.type = RTRND_TEXT; + text->hdr.oid = rnd_strdup_safe(txt); + text->x = x; text->y = y; text->size = size; + b.p1.x = x-size; b.p1.y = y-size; + b.p2.x = x+size; b.p2.y = y+size; + box_geo2rtree(&text->hdr.bbox, &b); + + rtrnd_obj_reg_ly(layer, (rtrnd_any_obj_t *)text); + + return text; +} + +void rtrnd_text_free(rtrnd_text_t *text) +{ + free(text->hdr.oid); + rtrnd_obj_unreg_ly(&text->hdr.parent->layer, (rtrnd_any_obj_t *)text); + free(text); +} + + +rtrnd_poly_t *rtrnd_poly_new_from_xys(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double *xy, long xylen, double ox, double oy) +{ + rtrnd_poly_t *poly; + long i; + + if ((xylen % 2) != 0) + return NULL; + + poly = calloc(sizeof(rtrnd_poly_t), 1); + poly->hdr.type = RTRND_POLY; + poly->hdr.oid = rnd_strdup_safe(oid); + + rtpoly_new_begin(&poly->rtpoly); + for(i = 0; i < xylen; i+=2) + rtpoly_new_append(&poly->rtpoly, xy[i+0] + ox, xy[i+1] + oy); + rtpoly_new_end(&poly->rtpoly); + + box_geo2rtree(&poly->hdr.bbox, &poly->rtpoly.bbox); + + rtrnd_obj_reg_ly(layer, (rtrnd_any_obj_t *)poly); + rtrnd_obj_reg_net(net, (rtrnd_any_obj_t *)poly); + + return poly; +} + +void rtrnd_poly_free(rtrnd_poly_t *poly) +{ + free(poly->hdr.oid); + rtpoly_free(&poly->rtpoly); + rtrnd_obj_unreg_ly(&poly->hdr.parent->layer, (rtrnd_any_obj_t *)poly); + rtrnd_obj_unreg_net(poly->hdr.net, (rtrnd_any_obj_t *)poly); + free(poly); +} + +rtrnd_via_t *rtrnd_via_alloc(const char *oid, double x, double y, double dia, double clr) +{ + rtrnd_via_t *via = calloc(sizeof(rtrnd_via_t), 1); + g2d_box_t b; + + via->hdr.type = RTRND_VIA; + via->hdr.oid = rnd_strdup_safe(oid); + via->x = x; via->y = y; + via->dia = dia; + via->clearance = clr; + b.p1.x = x - dia/2; b.p1.y = y - dia/2; + b.p2.x = x + dia/2; b.p2.y = y + dia/2; + box_geo2rtree(&via->hdr.bbox, &b); + + return via; +} + +rtrnd_via_t *rtrnd_via_reg(rtrnd_board_t *brd, rtrnd_net_t *net, rtrnd_via_t *via) +{ + rtrnd_obj_reg_via(brd, via); + rtrnd_obj_reg_net(net, (rtrnd_any_obj_t *)via); + return via; +} + +rtrnd_via_t *rtrnd_via_new(rtrnd_board_t *brd, const char *oid, rtrnd_net_t *net, double x, double y, double dia, double clr) +{ + return rtrnd_via_reg(brd, net, rtrnd_via_alloc(oid, x, y, dia, clr)); +} + + +void rtrnd_via_free(rtrnd_board_t *brd, rtrnd_via_t *via) +{ + rtrnd_obj_unreg_via(brd, via); + rtrnd_obj_unreg_net(via->hdr.net, (rtrnd_any_obj_t *)via); + free(via->hdr.oid); + free(via); +} + +void rtrnd_layer_init(rtrnd_layer_t *layer, const char *name) +{ + rtrnd_rtree_init(&layer->objs); + layer->name = rnd_strdup(name); + layer->hdr.type = RTRND_LAYER; +} + +void rtrnd_layer_uninit(rtrnd_layer_t *layer) +{ + rtrnd_rtree_it_t it; + rtrnd_any_obj_t *obj; + + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_first(&it, &layer->objs)) { + switch(obj->hdr.type) { + case RTRND_LINE: rtrnd_line_free(&obj->line); break; + case RTRND_TEXT: rtrnd_text_free(&obj->text); break; + case RTRND_POLY: rtrnd_poly_free(&obj->poly); break; + case RTRND_ARC: rtrnd_arc_free(&obj->arc); break; + default: /* can't be on layer */ + break; + } + } + + rtrnd_rtree_uninit(&layer->objs); + free(layer->name); +} + + +rtrnd_board_t *rtrnd_board_new(void) +{ + rtrnd_board_t *brd = calloc(sizeof(rtrnd_board_t), 1); + rtrnd_rtree_init(&brd->vias); + htsp_init(&brd->nets, strhash, strkeyeq); + return brd; +} + +static void rtrnd_net_uninit_segs(rtrnd_net_t *net) +{ + rtrnd_netseg_t *ns; + + for(ns = gdl_first(&net->segments); ns != NULL; ns = gdl_first(&net->segments)) + rtrnd_netseg_free(ns); +} + +void rtrnd_board_free(rtrnd_board_t *brd) +{ + htsp_entry_t *e; + rtrnd_netseg_t *ns; + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + int n; + + for(ns = gdl_first(&brd->orphaned_segments); ns != NULL; ns = gdl_first(&brd->orphaned_segments)) + rtrnd_netseg_free(ns); + + for(e = htsp_first(&brd->nets); e != NULL; e = htsp_next(&brd->nets, e)) + rtrnd_net_uninit_segs(e->value); + + + for(n = 0; n < brd->layers.used; n++) { + rtrnd_layer_uninit(brd->layers.array[n]); + free(brd->layers.array[n]); + } + vtp0_uninit(&brd->layers); + + for(via = rtrnd_rtree_all_first(&it, &brd->vias); via != NULL; via = rtrnd_rtree_all_first(&it, &brd->vias)) + rtrnd_via_free(brd, via); + + genht_uninit_deep(htsp, &brd->nets, { + free(htent->key); + free(htent->value); + }); + + free(brd); +} + + +void rtrnd_board_bbox(g2d_box_t *dst, rtrnd_board_t *board) +{ + g2d_box_t b = g2d_box_invalid(); + rtrnd_via_t *via; + rtrnd_rtree_it_t it; + long n; + + for(n = 0; n < board->layers.used; n++) { + rtrnd_layer_t *layer = board->layers.array[n]; + g2d_vect_t pt; + pt.x = layer->objs.bbox.x1; pt.y = layer->objs.bbox.y1; g2d_box_bump_pt(&b, pt); + pt.x = layer->objs.bbox.x2; pt.y = layer->objs.bbox.y2; g2d_box_bump_pt(&b, pt); + } + + /* just in case some vias are beyond layer objects */ + for(via = rtrnd_rtree_all_first(&it, &board->vias); via != NULL; via = rtrnd_rtree_all_next(&it)) { + g2d_vect_t pt; + pt.x = via->hdr.bbox.x1; pt.y = via->hdr.bbox.y1; g2d_box_bump_pt(&b, pt); + pt.x = via->hdr.bbox.x2; pt.y = via->hdr.bbox.y2; g2d_box_bump_pt(&b, pt); + } + + *dst = b; +} + + +int rtrnd_via_touches_layer(rtrnd_layer_t *layer, rtrnd_via_t *via) +{ + return 1; /*bbvia: thru-hole vias only at the moment */ +} + +int rtrnd_obj_center(rtrnd_any_obj_t *obj, double *cx, double *cy) +{ + switch(obj->hdr.type) { + case RTRND_LINE: + case RTRND_POLY: + case RTRND_VIA: + *cx = (obj->hdr.bbox.x1 + obj->hdr.bbox.x2) / 2; + *cy = (obj->hdr.bbox.y1 + obj->hdr.bbox.y2) / 2; + return 0; + case RTRND_ARC: + /* TODO */ + case RTRND_TEXT: + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + return -1; + } + + return -1; +} + +rtrnd_layer_t *rtrnd_annot_new(rtrnd_t *ctx, const char *name) +{ + rtrnd_layer_t *layer = calloc(sizeof(rtrnd_layer_t), 1); + rtrnd_layer_init(layer, name); + vtp0_append(&ctx->annots, layer); + return layer; +} + +unsigned long rtrnd_mark_alloc(rtrnd_board_t *brd, const char *name) +{ + int n; + for(n = 0; n < sizeof(brd->mask_names) / sizeof(brd->mask_names[0]); n++) { + if (brd->mask_names[n] == NULL) { + brd->mask_names[n] = name; + return 1 << n; + } + } + assert(!"ran out of mask bits"); + return 0; +} + +void rtrnd_mark_free(rtrnd_board_t *brd, unsigned long mask) +{ + int n; + for(n = 0; n < sizeof(brd->mask_names) / sizeof(brd->mask_names[0]); n++) { + if ((1 << n) == mask) { + brd->mask_names[n] = NULL; + return; + } + } +} + +void rtrnd_mark_clear(rtrnd_board_t *brd, unsigned long mask) +{ + rtrnd_any_obj_t *obj; + rtrnd_rtree_it_t it; + unsigned long clr = ~mask; + int n; + + for(n = 0; n < brd->layers.used; n++) { + rtrnd_layer_t *layer = brd->layers.array[n]; + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + obj->hdr.mark &= clr; + } + + for(obj = rtrnd_rtree_all_first(&it, &brd->vias); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + obj->hdr.mark &= clr; +} Index: tags/0.9.0/src/route-rnd/data.h =================================================================== --- tags/0.9.0/src/route-rnd/data.h (nonexistent) +++ tags/0.9.0/src/route-rnd/data.h (revision 1402) @@ -0,0 +1,206 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * data model + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef RTRND_DATA_H +#define RTRND_DATA_H + +#include +#include +#include +#include "route-rnd.h" +#include "rtree.h" +#include "geo.h" +#include "rtpoly.h" + +typedef enum { + rtrnd_false = 0, + rtrnd_true = 1 +} rtrnd_bool_t; + +typedef enum { + RTRND_LINE = 0x000001, + RTRND_ARC = 0x000002, + RTRND_POLY = 0x000004, + RTRND_VIA = 0x000008, + RTRND_TEXT = 0x000100, + RTRND_BOARD = 0x010000, + RTRND_LAYER = 0x020000, + RTRND_NET = 0x040000, + RTRND_NETSEG= 0x080000 +} rtrnd_obj_type_t; + +typedef struct rtrnd_net_s rtrnd_net_t; +typedef struct rtrnd_netseg_s rtrnd_netseg_t; + +typedef struct { + long l[4]; + void *p[4]; +} rtrnd_udata_t; /* used/caller data */ + + +typedef struct rtrnd_hdr_s rtrnd_hdr_t; +struct rtrnd_hdr_s { + rtrnd_rtree_box_t bbox; + rtrnd_obj_type_t type; + char *oid; + rtrnd_any_obj_t *parent; + + unsigned long mark; + + rtrnd_udata_t rt_data; + + /* for layer objects: */ + rtrnd_net_t *net; + rtrnd_netseg_t *netseg; + gdl_elem_t net_link; + gdl_elem_t netseg_link; + unsigned cnst_move:1; /* constraint: move */ + unsigned cnst_del:1; /* constraint: del */ + unsigned terminal:1; /* object is a terminal (pin or pad) */ +}; + +typedef struct rtrnd_line_s { + rtrnd_hdr_t hdr; + g2d_cline_t cline; + double thickness, clearance; +} rtrnd_line_t; + +typedef struct rtrnd_text_s { + rtrnd_hdr_t hdr; + /* text string is hdr.oid */ + double x, y, size; +} rtrnd_text_t; + +typedef struct rtrnd_arc_s { + rtrnd_hdr_t hdr; + g2d_carc_t carc; + double thickness, clearance; +} rtrnd_arc_t; + +typedef struct rtrnd_poly_s { + rtrnd_hdr_t hdr; + rtpoly_t rtpoly; /* transformed coords */ +} rtrnd_poly_t; + +typedef struct rtrnd_via_s { + rtrnd_hdr_t hdr; + double x, y, dia, clearance; +} rtrnd_via_t; + +struct rtrnd_board_s { + rtrnd_hdr_t hdr; + vtp0_t layers; /* ordered from top to bottom */ + htsp_t nets; + gdl_list_t orphaned_segments; + rtrnd_rtree_t vias; + const char *mask_names[32]; +}; + +typedef enum { + RTRND_LLOC_TOP, + RTRND_LLOC_INTERN, + RTRND_LLOC_BOTTOM +} rtrnd_layer_loc_t; + +struct rtrnd_layer_s { + rtrnd_hdr_t hdr; + char *name; + char color[8]; + rtrnd_rtree_t objs; + rtrnd_layer_loc_t loc; +}; + +struct rtrnd_net_s { + rtrnd_hdr_t hdr; + gdl_list_t objs; /* point to each object that is in the net */ + gdl_list_t segments; +}; + +struct rtrnd_netseg_s { + rtrnd_hdr_t hdr; /* parent is unused */ + rtrnd_board_t *brd; + rtrnd_net_t *net; /* only if there is a single net in the segment */ + gdl_list_t objs; /* point to each object that is in the net segment */ + gdl_elem_t link; /* link within the an rtrnd_net_t or in brd's orphaned net segments list */ + unsigned shorted:1; /* 1 if there are objects of multiple nets connected in this segment */ +}; + +union rtrnd_any_obj_s { + rtrnd_hdr_t hdr; + rtrnd_line_t line; + rtrnd_text_t text; + rtrnd_arc_t arc; + rtrnd_poly_t poly; + rtrnd_via_t via; + rtrnd_board_t board; + rtrnd_layer_t layer; +}; + +rtrnd_line_t *rtrnd_line_new(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double x1, double y1, double x2, double y2, double thick, double clr); +rtrnd_arc_t *rtrnd_arc_new(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double cx, double cy, double r, double start, double delta, double thick, double clr); +rtrnd_via_t *rtrnd_via_new(rtrnd_board_t *brd, const char *oid, rtrnd_net_t *net, double x, double y, double dia, double clr); +rtrnd_poly_t *rtrnd_poly_new_from_xys(rtrnd_layer_t *layer, const char *oid, rtrnd_net_t *net, double *xy, long xylen, double ox, double oy); + +/* only for debug annotations: */ +rtrnd_text_t *rtrnd_text_new(rtrnd_layer_t *layer, double x, double y, const char *txt, double size); + + +rtrnd_via_t *rtrnd_via_alloc(const char *oid, double x, double y, double dia, double clr); +rtrnd_via_t *rtrnd_via_reg(rtrnd_board_t *brd, rtrnd_net_t *net, rtrnd_via_t *via); + + +void rtrnd_layer_init(rtrnd_layer_t *layer, const char *name); +void rtrnd_layer_uninit(rtrnd_layer_t *layer); +rtrnd_board_t *rtrnd_board_new(void); +void rtrnd_board_free(rtrnd_board_t *brd); +void rtrnd_board_bbox(g2d_box_t *dst, rtrnd_board_t *board); + +int rtrnd_obj_center(rtrnd_any_obj_t *obj, double *cx, double *cy); + +/* returns whether a via touches (crosses or ends on) a layer; thru-hole + vias will always return 1, bbvias depend on span */ +int rtrnd_via_touches_layer(rtrnd_layer_t *layer, rtrnd_via_t *via); + +/* Create a new annotation layer at the end (on top in rendering) */ +rtrnd_layer_t *rtrnd_annot_new(rtrnd_t *ctx, const char *name); + +unsigned long rtrnd_mark_alloc(rtrnd_board_t *brd, const char *name); +void rtrnd_mark_free(rtrnd_board_t *brd, unsigned long mask); +void rtrnd_mark_clear(rtrnd_board_t *brd, unsigned long mask); + +#define RTRND_DEG2RAD(a) ((double)(a) / 180.0 * M_PI) +#define RTRND_RAD2DEG(a) ((double)(a) / M_PI * 180.0) + +/* Return the x;y coordinates on an arc's circle for a given angle */ +RTRND_INLINE void rtrnd_arc_xy(rtrnd_arc_t *arc, double ang, double *x, double *y) +{ + *x = arc->carc.c.x + (arc->carc.r * cos(ang)); + *y = arc->carc.c.y + (arc->carc.r * sin(ang)); +} + +#endif Index: tags/0.9.0/src/route-rnd/find.c =================================================================== --- tags/0.9.0/src/route-rnd/find.c (nonexistent) +++ tags/0.9.0/src/route-rnd/find.c (revision 1402) @@ -0,0 +1,315 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * find galvanic connections + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include "data.h" +#include "rtpoly.h" +#include "geo.h" +#include "find.h" +#include +#include + +#define LOAD_SLINE(sline, rline) \ +do { \ + sline.c = rline->cline; \ + sline.s.cap = G2D_CAP_ROUND; \ + sline.s.width = rline->thickness; \ +} while(0) + +static int isc_line_line(rtrnd_find_t *ctx, rtrnd_line_t *l1, rtrnd_line_t *l2) +{ + g2d_sline_t sl1, sl2; + LOAD_SLINE(sl1, l1); + LOAD_SLINE(sl2, l2); + sl1.s.width += 2 * ctx->bloat; + return g2d_isc_sline_sline(&sl1, &sl2); +} + +static int isc_line_arc(rtrnd_find_t *ctx, rtrnd_line_t *l, rtrnd_arc_t *a) +{ +/* g2d_sline_t sl; + LOAD_SLINE(sl, l);*/ + return 0; +} + +static int isc_line_poly(rtrnd_find_t *ctx, rtrnd_line_t *l, rtrnd_poly_t *p) +{ + rtpoly_t *rp = &p->rtpoly; + g2d_sline_t sl; + g2d_cline_t side1, side2; + LOAD_SLINE(sl, l); + + g2d_sline_sides(&sl, &side1, &side2); + sl.s.width += 2 * ctx->bloat; + + if (rtpoly_isc_cline(rp, &side1) || rtpoly_isc_cline(rp, &side2)) + return 1; + + if (rtpoly_isc_circle(rp, sl.c.p1.x, sl.c.p1.y, l->thickness/2)) + return 1; + if (rtpoly_isc_circle(rp, sl.c.p2.x, sl.c.p2.y, l->thickness/2)) + return 1; + + return 0; +} + +static int isc_line_via(rtrnd_find_t *ctx, rtrnd_line_t *l, rtrnd_via_t *v) +{ + g2d_sline_t sl; + g2d_vect_t center; + LOAD_SLINE(sl, l); + center.x = v->x; center.y = v->y; + return g2d_isc_sline_circle(&sl, center, v->dia/2 + ctx->bloat); +} + +static int isc_arc_arc(rtrnd_find_t *ctx, rtrnd_arc_t *a1, rtrnd_arc_t *a2) +{ + return 0; +} + +static int isc_arc_poly(rtrnd_find_t *ctx, rtrnd_arc_t *a, rtrnd_poly_t *p) +{ + return 0; +} + +static int isc_arc_via(rtrnd_find_t *ctx, rtrnd_arc_t *a, rtrnd_via_t *v) +{ + return 0; +} + +static int isc_poly_poly(rtrnd_find_t *ctx, rtrnd_poly_t *p1, rtrnd_poly_t *p2) +{ +#warning TODO: this ignores ctx->bloat + return rtpoly_isc_rtpoly(&p1->rtpoly, &p2->rtpoly); +} + +static int isc_poly_via(rtrnd_find_t *ctx, rtrnd_poly_t *p, rtrnd_via_t *v) +{ + return rtpoly_isc_circle(&p->rtpoly, v->x, v->y, v->dia/2 + ctx->bloat); +} + +static int isc_via_via(rtrnd_find_t *ctx, rtrnd_via_t *v1, rtrnd_via_t *v2) +{ + g2d_cvect_t c1, c2; + double max_dist2; + + c1.x = v1->x; c1.y = v1->y; + c2.x = v2->x; c2.y = v2->y; + + max_dist2 = (v1->dia + v2->dia)/2 + ctx->bloat; + max_dist2 *= max_dist2; + + return (g2d__distance2(c1, c2) <= max_dist2); +} + +/* calculate whether two objects intersect */ +int rtrnd_isc_obj_obj(rtrnd_find_t *ctx, rtrnd_any_obj_t *o1, rtrnd_any_obj_t *o2) +{ + switch(o1->hdr.type) { + case RTRND_LINE: + switch(o2->hdr.type) { + case RTRND_LINE: return isc_line_line(ctx, &o1->line, &o2->line); + case RTRND_ARC: return isc_line_arc(ctx, &o1->line, &o2->arc); + case RTRND_POLY: return isc_line_poly(ctx, &o1->line, &o2->poly); + case RTRND_VIA: return isc_line_via(ctx, &o1->line, &o2->via); + case RTRND_TEXT: + case RTRND_BOARD: case RTRND_LAYER: case RTRND_NET: case RTRND_NETSEG: + break; + } + break; + case RTRND_ARC: + switch(o2->hdr.type) { + case RTRND_LINE: return isc_line_arc(ctx, &o2->line, &o1->arc); + case RTRND_ARC: return isc_arc_arc(ctx, &o1->arc, &o2->arc); + case RTRND_POLY: return isc_arc_poly(ctx, &o1->arc, &o2->poly); + case RTRND_VIA: return isc_arc_via(ctx, &o1->arc, &o2->via); + case RTRND_TEXT: + case RTRND_BOARD: case RTRND_LAYER: case RTRND_NET: case RTRND_NETSEG: + break; + } + break; + case RTRND_POLY: + switch(o2->hdr.type) { + case RTRND_LINE: return isc_line_poly(ctx, &o2->line, &o1->poly); + case RTRND_ARC: return isc_arc_poly(ctx, &o2->arc, &o1->poly); + case RTRND_POLY: return isc_poly_poly(ctx, &o1->poly, &o2->poly); + case RTRND_VIA: return isc_poly_via(ctx, &o1->poly, &o2->via); + case RTRND_TEXT: + case RTRND_BOARD: case RTRND_LAYER: case RTRND_NET: case RTRND_NETSEG: + break; + } + break; + case RTRND_VIA: + switch(o2->hdr.type) { + case RTRND_LINE: return isc_line_via(ctx, &o2->line, &o1->via); + case RTRND_ARC: return isc_arc_via(ctx, &o2->arc, &o1->via); + case RTRND_POLY: return isc_poly_via(ctx, &o2->poly, &o1->via); + case RTRND_VIA: return isc_via_via(ctx, &o1->via, &o2->via); + case RTRND_TEXT: + case RTRND_BOARD: case RTRND_LAYER: case RTRND_NET: case RTRND_NETSEG: + break; + } + break; + case RTRND_TEXT: + case RTRND_BOARD: case RTRND_LAYER: case RTRND_NET: case RTRND_NETSEG: + break; + } + return 0; +} + + +/* Do everything that needs to be done for an object found */ +static int rtrnd_find_found(rtrnd_find_t *ctx, rtrnd_any_obj_t *obj, rtrnd_any_obj_t *arrived_from) +{ + int fr; + + if (ctx->list_found) + vtp0_append(&ctx->found, obj); + + ctx->nfound++; + + if ((ctx->found_cb != NULL) && ((fr = ctx->found_cb(ctx, obj, arrived_from)) != 0)) { + if (fr == RTRND_FIND_DROP_THREAD) + return 0; + ctx->aborted = 1; + return 1; + } + + return 0; +} + + +static int rtrnd_find_addobj(rtrnd_find_t *ctx, rtrnd_any_obj_t *obj, rtrnd_any_obj_t *arrived_from, int jump) +{ + obj->hdr.mark |= ctx->mark; + if (jump) + vtp0_append(&ctx->open, obj); + + if (rtrnd_find_found(ctx, obj, arrived_from) != 0) { + ctx->aborted = 1; + return 1; + } + return 0; +} + +#define RTRND_FIND_CHECK(ctx, curr, obj, retstmt) \ + do { \ + rtrnd_any_obj_t *__obj__ = (rtrnd_any_obj_t *)obj; \ + if (!(obj->hdr.mark & ctx->mark)) { \ + if (rtrnd_isc_obj_obj(ctx, curr, __obj__)) {\ + if (rtrnd_find_addobj(ctx, __obj__, curr, 1) != 0) { retstmt; } \ + } \ + } \ + } while(0) + + +static void rtrnd_find_exec(rtrnd_find_t *ctx) +{ + rtrnd_any_obj_t *curr; + + while((ctx->open.used > 0) && (!ctx->aborted)) { + /* pop the last object, without reallocating to smaller, mark it found */ + ctx->open.used--; + curr = ctx->open.array[ctx->open.used]; + + { /* search unmkared connections: iterative approach */ + rtrnd_any_obj_t *n; + rtrnd_rtree_it_t it; + if (curr->hdr.type == RTRND_VIA) { +#warning TODO: bbvia: consider span + int lid; + for(lid = 0; lid < ctx->brd->layers.used; lid++) { + rtrnd_layer_t *layer = ctx->brd->layers.array[lid]; + for(n = rtrnd_rtree_first(&it, &layer->objs, &curr->hdr.bbox); n != NULL; n = rtrnd_rtree_next(&it)) + RTRND_FIND_CHECK(ctx, curr, n, return); + } + } + else { + for(n = rtrnd_rtree_first(&it, &curr->hdr.parent->layer.objs, &curr->hdr.bbox); n != NULL; n = rtrnd_rtree_next(&it)) + RTRND_FIND_CHECK(ctx, curr, n, return); + } + for(n = rtrnd_rtree_first(&it, &ctx->brd->vias, &curr->hdr.bbox); n != NULL; n = rtrnd_rtree_next(&it)) { +#warning TODO: bbvia: consider span + RTRND_FIND_CHECK(ctx, curr, n, return); + } + } + } +} + +static int rtrnd_find_init_(rtrnd_find_t *fctx, rtrnd_board_t *brd) +{ + if (fctx->in_use) + return -1; + fctx->in_use = 1; + fctx->aborted = 0; + fctx->mark = rtrnd_mark_alloc(brd, "rtrnd_find_from_obj"); + fctx->nfound = 0; + fctx->brd = brd; + + if (fctx->list_found) + vtp0_init(&fctx->found); + vtp0_init(&fctx->open); + return 0; +} + +int rtrnd_find_from_obj(rtrnd_find_t *ctx, rtrnd_board_t *brd, rtrnd_any_obj_t *from) +{ + if (from == NULL) + return -1; + + if (rtrnd_find_init_(ctx, brd) < 0) + return -1; + + rtrnd_mark_clear(brd, ctx->mark); + rtrnd_find_addobj(ctx, from, NULL, 1); /* add the starting object with no 'arrived_from' */ + rtrnd_find_exec(ctx); + return 0; +} + +unsigned long rtrnd_find_from_obj_next(rtrnd_find_t *ctx, rtrnd_any_obj_t *from) +{ + if (from == NULL) + return -1; + + rtrnd_find_addobj(ctx, from, NULL, 1); /* add the starting object with no 'arrived_from' */ + rtrnd_find_exec(ctx); + return 0; +} + +void rtrnd_find_free(rtrnd_find_t *ctx) +{ + if (!ctx->in_use) + return; + if (ctx->list_found) + vtp0_uninit(&ctx->found); + vtp0_uninit(&ctx->open); + rtrnd_mark_free(ctx->brd, ctx->mark); + ctx->in_use = 0; +} + Index: tags/0.9.0/src/route-rnd/find.h =================================================================== --- tags/0.9.0/src/route-rnd/find.h (nonexistent) +++ tags/0.9.0/src/route-rnd/find.h (revision 1402) @@ -0,0 +1,71 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * find galvanic connections + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef RTRND_FIND_H +#define RTRND_FIND_H + +#define RTRND_FIND_DROP_THREAD 4242 + +typedef struct rtrnd_find_s rtrnd_find_t; +struct rtrnd_find_s { + /* public config */ + unsigned list_found:1; + double bloat; + + /* if non-NULL, call after an object is found; if returns non-zero, + set ->aborted and stop the search. When search started from an object, + it is called for the starting object as well. All object data and ctx + fields are updated for new_obj before the call. arrived_from is + the previous object (that already triggered a callback) from which + new_obj was first found; can be NULL for the starting object. + If return PCB_FIND_DROP_THREAD, stop searching this thread of objects + and continue elsewhere. + */ + int (*found_cb)(rtrnd_find_t *ctx, rtrnd_any_obj_t *new_obj, rtrnd_any_obj_t *arrived_from); + + /* public state/result */ + vtp0_t found; /* objects found, when list_found is 1 - of (rtrnd_any_obj_t *) */ + void *user_data; /* filled in by caller, not read or modified by find code */ + + /* private */ + vtp0_t open; /* objects already found but need checking for conns of (rtrnd_any_obj_t *) */ + rtrnd_board_t *brd; + unsigned long mark; + unsigned long nfound; + unsigned in_use:1; + unsigned aborted:1; +}; + +int rtrnd_find_from_obj(rtrnd_find_t *ctx, rtrnd_board_t *brd, rtrnd_any_obj_t *from); +unsigned long rtrnd_find_from_obj_next(rtrnd_find_t *ctx, rtrnd_any_obj_t *from); + +void rtrnd_find_free(rtrnd_find_t *ctx); + + +#endif + Index: tags/0.9.0/src/route-rnd/geo.h =================================================================== --- tags/0.9.0/src/route-rnd/geo.h (nonexistent) +++ tags/0.9.0/src/route-rnd/geo.h (revision 1402) @@ -0,0 +1,10 @@ +#ifndef RTRND_GEO_H +#define RTRND_GEO_H + +#include "config.h" + +#define G2D_INLINE RTRND_INLINE +#include "gengeo2d/typecfg_double_double.h" +#include + +#endif Index: tags/0.9.0/src/route-rnd/htdi.c =================================================================== --- tags/0.9.0/src/route-rnd/htdi.c (nonexistent) +++ tags/0.9.0/src/route-rnd/htdi.c (revision 1402) @@ -0,0 +1,16 @@ +#include "htdi.h" +#define HT(x) htdi_ ## x +#include +#include + +int htdi_keyeq(htdi_key_t a, htdi_key_t b) +{ + return a == b; +} + +unsigned int htdi_keyhash(htdi_const_key_t a) +{ + return jenhash(&a, sizeof(a)); +} + +#undef HT Index: tags/0.9.0/src/route-rnd/htdi.h =================================================================== --- tags/0.9.0/src/route-rnd/htdi.h (nonexistent) +++ tags/0.9.0/src/route-rnd/htdi.h (revision 1402) @@ -0,0 +1,14 @@ +#ifndef GENHT_HTDI_H +#define GENHT_HTDI_H + +typedef double htdi_key_t; +typedef long int htdi_value_t; +#define HT(x) htdi_ ## x +#include +#undef HT + +int htdi_keyeq(htdi_key_t a, htdi_key_t b); +unsigned int htdi_keyhash(htdi_const_key_t a); + + +#endif Index: tags/0.9.0/src/route-rnd/io.c =================================================================== --- tags/0.9.0/src/route-rnd/io.c (nonexistent) +++ tags/0.9.0/src/route-rnd/io.c (revision 1402) @@ -0,0 +1,104 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * load/save/export using plugins + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include "route-rnd.h" +#include "io.h" + +#define ERROR "route-rnd error: " + +int rtrnd_load(rtrnd_t *ctx, const char *ifn) +{ + int n; + + FILE *f; + + f = fopen(ifn, "r"); + if (f == NULL) { + fprintf(stderr, ERROR "failed to open '%s' for read\n", ifn); + return -1; + } + + for(n = 0; n < rtrnd_all_io.used; n++) { + rtrnd_io_t *io = rtrnd_all_io.array[n]; + + if ((io == NULL) || (io->load == NULL)) + continue; + + if (io->test_parse != NULL) { + rewind(f); + if (io->test_parse(f) == 0) + continue; + } + + rewind(f); + if (io->load(ctx, f) == 0) { + fclose(f); + ctx->fn = ifn; + ctx->io = io; + return 0; + } + } + + fprintf(stderr, ERROR "none of the format plugins could read '%s'\n", ifn); + fclose(f); + return -1; +} + +int rtrnd_io_set_by_name(rtrnd_t *ctx, const char *name) +{ + int n; + for(n = 0; n < rtrnd_all_io.used; n++) { + rtrnd_io_t *io = rtrnd_all_io.array[n]; + if (strcmp(io->name, name) == 0) { + ctx->io = io; + return 0; + } + } + return -1; +} + + +int rtrnd_export(rtrnd_t *ctx, const char *fmt, const char *basename, rtrnd_layer_t *layer, vtp0_t *annot) +{ + int n; + + for(n = 0; n < rtrnd_all_export.used; n++) { + rtrnd_export_t *io = rtrnd_all_export.array[n]; + + if ((io == NULL) || (io->export == NULL) || (strcmp(fmt, io->name) != 0)) + continue; + + return io->export(ctx, basename, layer, annot); + } + + fprintf(stderr, ERROR "export format plugin '%s' not found\n", fmt); + return -1; +} Index: tags/0.9.0/src/route-rnd/io.h =================================================================== --- tags/0.9.0/src/route-rnd/io.h (nonexistent) +++ tags/0.9.0/src/route-rnd/io.h (revision 1402) @@ -0,0 +1,12 @@ +#ifndef RTRND_IO_H +#define RTRND_IO_H + +#include "route-rnd.h" + +int rtrnd_load(rtrnd_t *ctx, const char *ifn); +int rtrnd_export(rtrnd_t *ctx, const char *fmt, const char *basename, rtrnd_layer_t *layer, vtp0_t *annot); + +int rtrnd_io_set_by_name(rtrnd_t *ctx, const char *name); + + +#endif Index: tags/0.9.0/src/route-rnd/main.c =================================================================== --- tags/0.9.0/src/route-rnd/main.c (nonexistent) +++ tags/0.9.0/src/route-rnd/main.c (revision 1402) @@ -0,0 +1,5 @@ +#include "route-rnd.h" +int main(int argc, char *argv[]) +{ + return route_rnd_main(argc, argv); +} Index: tags/0.9.0/src/route-rnd/netseg.c =================================================================== --- tags/0.9.0/src/route-rnd/netseg.c (nonexistent) +++ tags/0.9.0/src/route-rnd/netseg.c (revision 1402) @@ -0,0 +1,194 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * map network segments + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include "data.h" +#include "geo.h" +#include "find.h" +#include +#include "netseg.h" + + +static int netseg_found_cb(rtrnd_find_t *ctx, rtrnd_any_obj_t *new_obj, rtrnd_any_obj_t *arrived_from) +{ + assert(new_obj->hdr.netseg == NULL); /* or maybe merge network segments? */ +/* printf(" found: %s %p\n", new_obj->hdr.oid, ctx->user_data);*/ + rtrnd_netseg_reg_obj(ctx->user_data, new_obj); + return 0; +} + +int rtrnd_netseg_map_from_obj(rtrnd_board_t *brd, rtrnd_any_obj_t *obj) +{ + rtrnd_find_t ctx = {0}; + ctx.found_cb = netseg_found_cb; + ctx.user_data = rtrnd_netseg_new(); + +/* printf("Net seg from: %s\n", obj->hdr.oid); */ + rtrnd_find_from_obj(&ctx, brd, obj); + rtrnd_find_free(&ctx); + + rtrnd_netseg_reg_net(brd, ctx.user_data); + + return -1; +} + +int rtrnd_netseg_map_board(rtrnd_board_t *brd) +{ + long lid; + rtrnd_rtree_it_t it; + rtrnd_any_obj_t *obj; + + for(lid = 0; lid < brd->layers.used; lid++) { + rtrnd_layer_t *layer = brd->layers.array[lid]; + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + if (obj->hdr.netseg == NULL) + rtrnd_netseg_map_from_obj(brd, obj); + } + + for(obj = rtrnd_rtree_all_first(&it, &brd->vias); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + if (obj->hdr.netseg == NULL) + rtrnd_netseg_map_from_obj(brd, obj); + + return 0; +} + + +void rtrnd_netseg_unreg_obj(rtrnd_netseg_t *ns, rtrnd_any_obj_t *o) +{ + gdl_remove(&ns->objs, o, hdr.netseg_link); + o->hdr.netseg = NULL; +} + +void rtrnd_netseg_reg_obj(rtrnd_netseg_t *ns, rtrnd_any_obj_t *o) +{ + gdl_append(&ns->objs, o, hdr.netseg_link); + o->hdr.netseg = ns; + if (ns->objs.length == 1) + ns->hdr.bbox = o->hdr.bbox; + else + rtrnd_rtree_box_bump(&ns->hdr.bbox, &o->hdr.bbox); +} + +void rtrnd_netseg_free(rtrnd_netseg_t *ns) +{ + rtrnd_any_obj_t *o; + + if (ns->net != NULL) + gdl_remove(&ns->net->segments, ns, link); + else + gdl_remove(&ns->brd->orphaned_segments, ns, link); + + for(o = gdl_first(&ns->objs); o != NULL; o = gdl_first(&ns->objs)) + rtrnd_netseg_unreg_obj(ns, o); + free(ns->hdr.oid); + free(ns); +} + +void rtrnd_netseg_init(rtrnd_netseg_t *ns) +{ + memset(ns, 0, sizeof(rtrnd_netseg_t)); + ns->hdr.type = RTRND_NETSEG; +} + +rtrnd_netseg_t *rtrnd_netseg_new(void) +{ + rtrnd_netseg_t *ns = malloc(sizeof(rtrnd_netseg_t)); + rtrnd_netseg_init(ns); + return ns; +} + +static void netseg_name(rtrnd_netseg_t *ns, const char *p1, const char *p2, long cnt) +{ + long l1 = strlen(p1), l2 = strlen(p2); + free(ns->hdr.oid); + ns->hdr.oid = malloc(l1+l2+16); + if ((cnt > 1000000000L) || (cnt < -1000000000L)) + sprintf(ns->hdr.oid, "%s-%s:x", p1, p2); + else + sprintf(ns->hdr.oid, "%s-%s:%ld", p1, p2, cnt); +} + + +void rtrnd_netseg_reg_net(rtrnd_board_t *brd, rtrnd_netseg_t *ns) +{ + rtrnd_any_obj_t *o; + int has_null = 0; + + ns->brd = brd; + ns->net = NULL; + ns->shorted = 0; + for(o = gdl_first(&ns->objs); o != NULL; o = gdl_next(&ns->objs, o)) { + if (o->hdr.net == NULL) + has_null = 1; + if (o->hdr.net != NULL) + ns->net = o->hdr.net; + else if (o->hdr.net != ns->net) + ns->shorted = 1; + } + + if ((ns->net == NULL) || ns->shorted) { + ns->net = NULL; + netseg_name(ns, "board", "orphaned", brd->orphaned_segments.length); + gdl_append(&brd->orphaned_segments, ns, link); + return; + } + + netseg_name(ns, "net", ns->net->hdr.oid, ns->net->segments.length); + gdl_append(&ns->net->segments, ns, link); + if (has_null) + for(o = gdl_first(&ns->objs); o != NULL; o = gdl_next(&ns->objs, o)) + if (o->hdr.net == NULL) + o->hdr.net = ns->net; +} + + +void rtrnd_netseg_merge(rtrnd_netseg_t *dst, rtrnd_netseg_t *src) +{ + rtrnd_any_obj_t *o; + + assert(dst->hdr.net == src->hdr.net); + + for(o = gdl_first(&src->objs); o != NULL; o = gdl_next(&src->objs, o)) { + gdl_remove(&src->objs, o, hdr.netseg_link); + gdl_append(&dst->objs, o, hdr.netseg_link); + o->hdr.netseg = dst; + rtrnd_rtree_box_bump(&dst->hdr.bbox, &o->hdr.bbox); + } + + if (src->shorted) { + dst->shorted = 1; + src->shorted = 0; + } + + if (src->net != NULL) { + gdl_remove(&src->net->segments, src, link); + gdl_append(&src->brd->orphaned_segments, src, link); + src->net = NULL; + } +} Index: tags/0.9.0/src/route-rnd/netseg.h =================================================================== --- tags/0.9.0/src/route-rnd/netseg.h (nonexistent) +++ tags/0.9.0/src/route-rnd/netseg.h (revision 1402) @@ -0,0 +1,52 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * map network segments + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef RTRND_NETSEG_H +#define RTRND_NETSEG_H + +int rtrnd_netseg_map_from_obj(rtrnd_board_t *brd, rtrnd_any_obj_t *obj); +int rtrnd_netseg_map_board(rtrnd_board_t *brd); + +void rtrnd_netseg_init(rtrnd_netseg_t *ns); +rtrnd_netseg_t *rtrnd_netseg_new(void); +void rtrnd_netseg_free(rtrnd_netseg_t *ns); + +void rtrnd_netseg_unreg_obj(rtrnd_netseg_t *ns, rtrnd_any_obj_t *o); +void rtrnd_netseg_reg_obj(rtrnd_netseg_t *ns, rtrnd_any_obj_t *o); + + +/* register a net segment either in the related net's segments list or in + the board's orphaned_segments list */ +void rtrnd_netseg_reg_net(rtrnd_board_t *brd, rtrnd_netseg_t *ns); + +/* Move all objects from src to dst, moving now empty src to board's orphaned + net segs */ +void rtrnd_netseg_merge(rtrnd_netseg_t *dst, rtrnd_netseg_t *src); + +#endif + Index: tags/0.9.0/src/route-rnd/regression/Makefile =================================================================== --- tags/0.9.0/src/route-rnd/regression/Makefile (nonexistent) +++ tags/0.9.0/src/route-rnd/regression/Makefile (revision 1402) @@ -0,0 +1,15 @@ +ROOT=../../.. +CFLAGS = -Wall -g -I$(ROOT)/src_3rd -I.. +LDFLAGS = -lm + +LOCLIBS = $(ROOT)/src_3rd/genvector/libgenvector.a $(ROOT)/src_3rd/genht/libgenht.a +DATAO=../htdi.o ../data.o ../rtree.o ../compat_misc.o ../netseg.o ../find.o ../rtpoly.o +GRIDO=../util_grid.o + +all: raline grid poly + +raline: raline.o $(DATA) $(LOCLIBS) + +poly: poly.o $(DATAO) $(LOCLIBS) + +grid: grid.o $(GRIDO) $(DATAO) $(LOCLIBS) Index: tags/0.9.0/src/route-rnd/regression/grid.c =================================================================== --- tags/0.9.0/src/route-rnd/regression/grid.c (nonexistent) +++ tags/0.9.0/src/route-rnd/regression/grid.c (revision 1402) @@ -0,0 +1,16 @@ +#include +#include "../util_grid.h" + +int main() +{ + double d, origin, spacing; + int res; + + vtd0_t coords = {0}; + while(scanf("%lf\n", &d) == 1) + vtd0_append(&coords, d); + + res = rtrnd_grid_detect(&coords, &origin, &spacing); + printf("res=%d %f:%f\n", res, spacing, origin); + +} \ No newline at end of file Index: tags/0.9.0/src/route-rnd/regression/poly.c =================================================================== --- tags/0.9.0/src/route-rnd/regression/poly.c (nonexistent) +++ tags/0.9.0/src/route-rnd/regression/poly.c (revision 1402) @@ -0,0 +1,76 @@ +#include +#include +#include "../rtpoly.h" + +static inline int rtpoly_isc_cline_(const rtpoly_t *poly, double x1, double y1, double x2, double y2) +{ + g2d_cline_t cl; + cl.p1.x = x1; cl.p1.y = y1; + cl.p2.x = x2; cl.p2.y = y2; + return rtpoly_isc_cline(poly, &cl); +} + +static inline int rtpoly_isc_triangle(const rtpoly_t *poly, double cx, double cy, double r) +{ + int n, res; + double a, step = 2.0*M_PI/3.0; + rtpoly_t tri; + rtpoly_new_begin(&tri); + + for(n = 0, a = 0; n < 3; n++, a+=step) { +/* printf(" %f %f\n", cx + cos(a) * r, cy + sin(a) * r);*/ + rtpoly_new_append(&tri, cx + cos(a) * r, cy + sin(a) * r); + } + + rtpoly_new_end(&tri); + res = rtpoly_isc_rtpoly(poly, &tri); + rtpoly_free(&tri); + return res; +} + +int main(int argc, char *argv[]) +{ + int end; + rtpoly_t poly; + + rtpoly_new_begin(&poly); + + rtpoly_new_append(&poly, 1,1); + rtpoly_new_append(&poly, 5,1); + rtpoly_new_append(&poly, 5,5); + rtpoly_new_append(&poly, 1,5); + + end = rtpoly_new_end(&poly); + printf("end=%d area=%f %f;%f - %f;%f\n", end, poly.area, poly.bbox.p1.x, poly.bbox.p1.y, poly.bbox.p2.x, poly.bbox.p2.y); + + printf("point isc:\n"); + printf(" in: %d\n", rtpoly_isc_point(&poly, 3, 3)); + printf(" out left: %d\n", rtpoly_isc_point(&poly, -3, 3)); + printf(" out right: %d\n", rtpoly_isc_point(&poly, 15, 3)); + printf(" on edge1: %d\n", rtpoly_isc_point(&poly, 1, 3)); + printf(" on edge2: %d\n", rtpoly_isc_point(&poly, 3, 1)); + printf(" on corner: %d\n", rtpoly_isc_point(&poly, 1, 1)); + + printf("circ isc:\n"); + printf(" in: %d\n", rtpoly_isc_circle(&poly, 3, 3, 2)); + printf(" left1: %d\n", rtpoly_isc_circle(&poly, -1, 3, 2.2)); + printf(" left2: %d\n", rtpoly_isc_circle(&poly, -1, 3, 2)); + printf(" left3: %d\n", rtpoly_isc_circle(&poly, -1, -2, 2)); + printf(" corner: %d\n", rtpoly_isc_circle(&poly, 0, 0, 1.48)); + + printf("cline isc:\n"); + printf(" in: %d\n", rtpoly_isc_cline_(&poly, 2, 2, 3, 3)); + printf(" side-yes: %d\n", rtpoly_isc_cline_(&poly, 0, 1, 2, 1.5)); + printf(" side-nope: %d\n", rtpoly_isc_cline_(&poly, 0, 1, 2, 0.9)); + printf(" corner-yes: %d\n", rtpoly_isc_cline_(&poly, 0, 0, 1, 1)); + + + printf("rtpoly isc:\n"); + printf(" in: %d\n", rtpoly_isc_triangle(&poly, 3, 3, 1)); + printf(" left-yes: %d\n", rtpoly_isc_triangle(&poly, 0, 3, 1)); + printf(" left-yes: %d\n", rtpoly_isc_triangle(&poly, 0, 3, 2)); + printf(" left-no: %d\n", rtpoly_isc_triangle(&poly, -1, 3, 1)); + + + return 0; +} Index: tags/0.9.0/src/route-rnd/regression/raline.c =================================================================== --- tags/0.9.0/src/route-rnd/regression/raline.c (nonexistent) +++ tags/0.9.0/src/route-rnd/regression/raline.c (revision 1402) @@ -0,0 +1,124 @@ +#include +#include +#include "../util_grid.h" + + +static void draw(rtrnd_raline_t *ra) +{ + char line[71]; + long n; + + memset(line, ' ', sizeof(line)); + line[70] = '\0'; + for(n = 0; n < ra->minor.used; n+=2) { + int from = ra->minor.array[n], to = ra->minor.array[n+1]; + assert(from < to); + assert(from >= 0); + assert(to <= 70); + assert(from != to); + memset(line+from, '+', to-from+1); + } + printf("%s\n", line); +} + +static void dump(rtrnd_raline_t *ra) +{ + long n; + for(n = 0; n < ra->minor.used; n+=2) { + if (n > 0) printf(" "); + printf("%.0f+%.0f", ra->minor.array[n], ra->minor.array[n+1]); + } + printf("\n"); +} + + +void reset(rtrnd_raline_t *ra) +{ + ra->minor.used = 0; + vtd0_append(&ra->minor, 00); vtd0_append(&ra->minor, 10); + vtd0_append(&ra->minor, 20); vtd0_append(&ra->minor, 30); + vtd0_append(&ra->minor, 40); vtd0_append(&ra->minor, 50); + vtd0_append(&ra->minor, 60); vtd0_append(&ra->minor, 70); +} + +int main() +{ + rtrnd_raline_t ra = {0}; + + + printf("\n1 removing within a negative range:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 13, 16) == 0); + draw(&ra); dump(&ra); + + printf("\n2 removing within a positive range:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 23, 26) == 0); + draw(&ra); dump(&ra); + + printf("\n3 removing from within pos to within next pos:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 23, 46) == 0); + draw(&ra); dump(&ra); + + printf("\n4 removing from within pos to within far pos:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 23, 66) == 0); + draw(&ra); dump(&ra); + + printf("\n5 removing from start of pos to within far pos:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 20, 66) == 0); + draw(&ra); dump(&ra); + + printf("\n6 removing from within pos to end of far pos:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 23, 50) == 0); + draw(&ra); dump(&ra); + + printf("\n7 removing from within a hole to middle of a pos:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 13, 65) == 0); + draw(&ra); dump(&ra); + + printf("\n8 removing from within a hole to middle of a hole:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 13, 55) == 0); + draw(&ra); dump(&ra); + + + printf("\n9 removing from pos-end to middle of a hole:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 20, 55) == 0); + draw(&ra); dump(&ra); + + printf("\n10 removing from pos-end to pos-begin:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 20, 60) == 0); + draw(&ra); dump(&ra); + + printf("\n10 removing from pos-end to pos-end:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 20, 50) == 0); + draw(&ra); dump(&ra); + + + printf("\n10 removing everything:\n"); + reset(&ra); + draw(&ra); + assert(rtrnd_raline_block(&ra, 00, 70) == 0); + draw(&ra); dump(&ra); + + return 0; +} Index: tags/0.9.0/src/route-rnd/regression/raline.ref =================================================================== --- tags/0.9.0/src/route-rnd/regression/raline.ref (nonexistent) +++ tags/0.9.0/src/route-rnd/regression/raline.ref (revision 1402) @@ -0,0 +1,60 @@ + +1 removing within a negative range: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++++++++ +++++++++++ +++++++++++ +0+10 20+30 40+50 60+70 + +2 removing within a positive range: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ ++++ +++++ +++++++++++ +++++++++++ +0+10 20+23 26+30 40+50 60+70 + +3 removing from within pos to within next pos: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ ++++ +++++ +++++++++++ +0+10 20+23 46+50 60+70 + +4 removing from within pos to within far pos: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ ++++ +++++ +0+10 20+23 66+70 + +5 removing from start of pos to within far pos: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++ +0+10 66+70 + +6 removing from within pos to end of far pos: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ ++++ +++++++++++ +0+10 20+23 60+70 + +7 removing from within a hole to middle of a pos: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ ++++++ +0+10 65+70 + +8 removing from within a hole to middle of a hole: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++++++++ +0+10 60+70 + +9 removing from pos-end to middle of a hole: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++++++++ +0+10 60+70 + +10 removing from pos-end to pos-begin: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++++++++ +0+10 60+70 + +10 removing from pos-end to pos-end: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ ++++++++++++ +++++++++++ +0+10 60+70 + +10 removing everything: ++++++++++++ +++++++++++ +++++++++++ +++++++++++ + + Index: tags/0.9.0/src/route-rnd/route-rnd.c =================================================================== --- tags/0.9.0/src/route-rnd/route-rnd.c (nonexistent) +++ tags/0.9.0/src/route-rnd/route-rnd.c (revision 1402) @@ -0,0 +1,263 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * main code for the executable + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include "route-rnd.h" +#include "data.h" +#include "netseg.h" +#include "buildin.h" +#include "route_res.h" +#include "io.h" + +#define ERROR "route-rnd error: " + +void rtrnd_error(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, ERROR); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + + +void rtrnd_init(rtrnd_t *ctx, int verbose) +{ + memset(ctx, 0, sizeof(rtrnd_t)); + ctx->verbose = verbose; +} + +void rtrnd_uninit(rtrnd_t *ctx) +{ + long n; + + for(n = 0; n < ctx->annots.used; n++) { + rtrnd_layer_uninit(ctx->annots.array[n]); + free(ctx->annots.array[n]); + } + + if (ctx->board != NULL) + rtrnd_board_free(ctx->board); + vtp0_uninit(&rtrnd_all_router); + vtp0_uninit(&rtrnd_all_export); + vtp0_uninit(&rtrnd_all_io); + + vtp0_uninit(&ctx->annots); + free((char *)ctx->name); +} + +int rtrnd_find_router(rtrnd_t *ctx, const char *method) +{ + int n; + + for(n = 0; n < rtrnd_all_router.used; n++) { + rtrnd_router_t *rt = rtrnd_all_router.array[n]; + if ((rt != NULL) && (rt->route != NULL) && (strcmp(method, rt->name) == 0)) { + ctx->rt = rt; + return 0; + } + } + + fprintf(stderr, ERROR "routing method '%s' not found\n", method); + return -1; +} + +void list_methods(void) +{ + int n; + + for(n = 0; n < rtrnd_all_router.used; n++) { + rtrnd_router_t *rt = rtrnd_all_router.array[n]; + printf("%s\t%s\n", rt->name, rt->desc); + } +} + +static int setup_res(rtrnd_t *ctx, char *ofn_, const char *ifn) +{ + char *fr = NULL, *ofn = ofn_; + + if ((ofn == NULL) && (ifn == NULL)) { + /* special case: no input, no output: probably called with -l, use stdout */ + ctx->resf = stdout; + return 0; + } + + if ((ofn != NULL) && ((strcmp(ofn, "-") == 0) || (strcmp(ofn, "/dev/stdout") == 0))) { + ctx->resf = stdout; + return 0; + } + + + if (ofn == NULL) { + long len = strlen(ifn); + char *sep; + fr = ofn = malloc(len + 8); + strcpy(ofn, ifn); + sep = strrchr(ofn, '.'); + if (sep != NULL) { + memmove(sep+4, sep, strlen(sep)+1); + memcpy(sep, ".res", 4); + } + } + ctx->resf = fopen(ofn, "w"); + if (ctx->resf == NULL) { + fprintf(stderr, ERROR "failed to open result file '%s' for write\n", ofn); + return 1; + } + free(fr); + return 0; +} + +static void help_generic(const char *prg) +{ + printf("route-rnd: external PCB autorouter\n"); + printf("Usage: %s [-v] -m method [-o out_fn] inp_fn\n", prg); + printf(" %s -m method -l\n", prg); + printf(" %s -M\n", prg); + printf("\nOptions:\n"); + printf(" -M list available methods (in TSV format)\n"); + printf(" -m method set method (by name, as returned by -M, first column)\n"); + printf(" -l list config options of a method (in tEDAx route res)\n"); + printf(" -v increase verbosity (can be specified multiple times)\n"); + printf(" -o ofn output file name (for tEDAx route result)\n"); + printf(" inp_fn input file name (tEDAx route request)\n"); + printf("\n"); +} + +static void help(const char *prg, const char *topic) +{ + help_generic(prg); +} + +int route_rnd_main(int argc, char *argv[]) +{ + char *ifn = NULL, *ofn = NULL, *method = "horver"; + int n, verbose = 0, list_conf = 0, res = 0; + rtrnd_t ctx; + + rtrnd_buildin_init(); + + for(n = 1; n < argc; n++) { + char *cmd = argv[n], *arg = argv[n+1]; + if (*cmd == '\0') continue; /* ignore empty args, useful for the tester */ + if (*cmd == '-') { + while(*cmd == '-') cmd++; + switch(*cmd) { + case 'h': help(argv[0], arg); exit(0); + case 'v': verbose++; break; + case 'm': method = arg; n++; break; + case 'l': list_conf = 1; break; + case 'o': ofn = arg; n++; break; + case 'M': list_methods(); return 0; + default: + fprintf(stderr, ERROR "unknown command '%s'\n", cmd); + return 1; + } + } + else { + if (ifn != NULL) { + fprintf(stderr, ERROR "multiple request file names are not supported ('%s' and '%s')\n", ifn, cmd); + return 1; + } + ifn = cmd; + } + } + + rtrnd_init(&ctx, verbose); + + if (rtrnd_find_router(&ctx, method) != 0) + return 1; + + if (ifn != NULL) + rtrnd_conf_defaults(ctx.rt->conf); + + if ((ifn != NULL) && (rtrnd_load(&ctx, ifn) != 0)) { + fprintf(stderr, ERROR "failed to load route request '%s'\n", ifn); + rtrnd_uninit(&ctx); + return 1; + } + + if (setup_res(&ctx, ofn, ifn) != 0) { + rtrnd_uninit(&ctx); + return 1; + } + + if (ctx.io == NULL) { + /* special case fallback: called with -l, without input file, so io is not detected by file format */ + if (rtrnd_io_set_by_name(&ctx, "tEDAx") != 0) { + fprintf(stderr, ERROR "failed to find the tEDAx plugin, specify an io\n"); + rtrnd_uninit(&ctx); + return 1; + } + } + + if (!list_conf && (ifn == NULL)) { + fprintf(stderr, "route-rnd: the ringdove PCB autorouter requires arguments; see --help\n"); + return 1; + } + + rtrnd_res_init(&ctx); + + if (list_conf) + rtrnd_res_conf_all(&ctx, ctx.rt->conf); + + if ((ifn != NULL) && (ctx.verbose > 1)) { + rtrnd_export(&ctx, "animator", "1load", NULL, &ctx.annots); + rtrnd_export(&ctx, "svg", "1load", NULL, &ctx.annots); + } + + if (ifn != NULL) { + rtrnd_netseg_map_board(ctx.board); + rtrnd_board_bbox(&ctx.board->hdr.bbox, ctx.board); + + ctx.board->hdr.bbox.x1 -= 5; + ctx.board->hdr.bbox.y1 -= 5; + ctx.board->hdr.bbox.x2 += 5; + ctx.board->hdr.bbox.y2 += 5; +#warning TODO: sanity checks and error reports + } + + if ((ifn != NULL) && (ctx.rt != NULL) && (ctx.rt->route(&ctx) != 0)) { + fprintf(stderr, ERROR "failed to perform routing request '%s'\n", ifn); + res = 1; + } + + if ((ifn != NULL) && (ctx.verbose > 1)) { + rtrnd_export(&ctx, "animator", "3routed", NULL, &ctx.annots); + rtrnd_export(&ctx, "svg", "3routed", NULL, &ctx.annots); + } + + rtrnd_res_uninit(&ctx); + fclose(ctx.resf); + rtrnd_uninit(&ctx); + return res; +} Index: tags/0.9.0/src/route-rnd/route-rnd.h =================================================================== --- tags/0.9.0/src/route-rnd/route-rnd.h (nonexistent) +++ tags/0.9.0/src/route-rnd/route-rnd.h (revision 1402) @@ -0,0 +1,90 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * central, modular infrastructure API + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef ROUTE_RND_H +#define ROUTE_RND_H + +#include +#include +#include "conf.h" + +typedef struct rtrnd_board_s rtrnd_board_t; +typedef struct rtrnd_layer_s rtrnd_layer_t; +typedef union rtrnd_any_obj_s rtrnd_any_obj_t; +typedef struct rtrnd_io_s rtrnd_io_t; +typedef struct rtrnd_router_s rtrnd_router_t; + +typedef struct rtrnd_s { + const char *fn; + char *name; /* name of the rotue request or board or task, as read from the file, filled in by the IO plugin */ + int verbose; + rtrnd_board_t *board; + vtp0_t annots; /* annotation layers, in order of rendering */ + rtrnd_io_t *io; /* the IO plugin that managed to load the request */ + FILE *resf; /* output route_res file */ + rtrnd_router_t *rt; /* router selected by the user */ +} rtrnd_t; + +struct rtrnd_io_s { + const char *name; + int (*test_parse)(FILE *f); /* cheap test if a file looks like suitable for reading; returns non-zero on success */ + int (*load)(rtrnd_t *ctx, FILE *f); /* load the request; returns 0 on success */ + + /* save the result; returns 0 on success */ + int (*save_begin)(rtrnd_t *ctx, FILE *f); + int (*save_add)(rtrnd_t *ctx, FILE *f, const rtrnd_any_obj_t *obj); + int (*save_log)(rtrnd_t *ctx, FILE *f, char level, char *msg, int len); + int (*save_confkey)(rtrnd_t *ctx, FILE *f, const rtrnd_conf_t *item); + int (*save_end)(rtrnd_t *ctx, FILE *f); + +}; +vtp0_t rtrnd_all_io; + +typedef struct rtrnd_export_s { + const char *name; + /* export a layer (or all layers if layer == NULL) */ + int (*export)(rtrnd_t *ctx, const char *basename, rtrnd_layer_t *layer, vtp0_t *annot_layers); +} rtrnd_export_t; +vtp0_t rtrnd_all_export; + +struct rtrnd_router_s { + const char *name, *desc; + rtrnd_conf_t *conf; + int (*route)(rtrnd_t *ctx); +}; + +vtp0_t rtrnd_all_router; + + +int route_rnd_main(int argc, char *argv[]); + + +/* Print an error message to stderr with the standard route-rnd prefix */ +void rtrnd_error(const char *fmt, ...); + +#endif Index: tags/0.9.0/src/route-rnd/route_res.c =================================================================== --- tags/0.9.0/src/route-rnd/route_res.c (nonexistent) +++ tags/0.9.0/src/route-rnd/route_res.c (revision 1402) @@ -0,0 +1,123 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * write the route_res block + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "route_res.h" + +void rtrnd_res_init(rtrnd_t *ctx) +{ + if (ctx->io->save_end != NULL) + ctx->io->save_begin(ctx, ctx->resf); +} + +void rtrnd_res_add(rtrnd_t *ctx, const rtrnd_any_obj_t *obj) +{ + if (ctx->io->save_add != NULL) + ctx->io->save_add(ctx, ctx->resf, obj); +} + +static char logbuff[8192]; +void rtrnd_res_log(rtrnd_t *ctx, char level, const char *fmt, ...) +{ + int len; + va_list ap; + + if (ctx->io->save_log == NULL) + return; + + va_start(ap, fmt); + len = vsprintf(logbuff, fmt, ap); + va_end(ap); + + if (len >= sizeof(logbuff)) { + fprintf(stderr, "rtrnd_res_log: buffer overflow\n"); + abort(); + } + + if (len > 0) + ctx->io->save_log(ctx, ctx->resf, level, logbuff, len); +} + +void rtrnd_res_confkey(rtrnd_t *ctx, const rtrnd_conf_t *item) +{ + if (ctx->io->save_confkey != NULL) + ctx->io->save_confkey(ctx, ctx->resf, item); +} + +void rtrnd_res_uninit(rtrnd_t *ctx) +{ + if (ctx->io->save_end != NULL) + ctx->io->save_end(ctx, ctx->resf); +} + + +void rtrnd_res_conf_all(rtrnd_t *ctx, const rtrnd_conf_t *first) +{ + for(; first->type != RTRND_CT_TERMINATOR; first++) + rtrnd_res_confkey(ctx, first); +} + +void rtrnd_draw_res_line(rtrnd_t *ctx, rtrnd_layer_t *ly_copper, rtrnd_layer_t *ly_annot, rtrnd_net_t *net, double x1, double y1, double x2, double y2, double cop_thick, double cop_clr, double annot_thick, double annot_clr) +{ + rtrnd_line_t tmp = {0}; + + rtrnd_line_new(ly_annot, NULL, net, x1, y1, x2, y2, annot_thick, annot_clr); + + tmp.hdr.type = RTRND_LINE; + tmp.hdr.parent = (rtrnd_any_obj_t *)ly_copper; + tmp.hdr.net = net; + tmp.cline.p1.x = x1; tmp.cline.p1.y = y1; + tmp.cline.p2.x = x2; tmp.cline.p2.y = y2; + tmp.thickness = cop_thick; + tmp.clearance = cop_clr; + + rtrnd_res_add(ctx, (rtrnd_any_obj_t *)&tmp); +} + +void rtrnd_draw_res_via(rtrnd_t *ctx, rtrnd_layer_t *ly_annot, rtrnd_net_t *net, double x, double y, double dia, double clr, double annot_thick, double annot_clr) +{ + rtrnd_via_t tmp = {0}; + double rx = annot_thick/2, ry = annot_thick*2/3; + + rtrnd_line_new(ly_annot, NULL, net, x-rx, y-ry, x+rx, y+ry, 0.05, 0); + rtrnd_line_new(ly_annot, NULL, net, x+rx, y-ry, x-rx, y+ry, 0.05, 0); + + tmp.hdr.type = RTRND_VIA; + tmp.hdr.net = net; + tmp.x = x; tmp.y = y; + tmp.dia = dia; + tmp.clearance = clr; + + rtrnd_res_add(ctx, (rtrnd_any_obj_t *)&tmp); +} + +int rtrnd_progress(rtrnd_t *ctx, double at) +{ + fprintf(stderr, "### progress: %.02f\n", at); + return 0; +} Index: tags/0.9.0/src/route-rnd/route_res.h =================================================================== --- tags/0.9.0/src/route-rnd/route_res.h (nonexistent) +++ tags/0.9.0/src/route-rnd/route_res.h (revision 1402) @@ -0,0 +1,25 @@ +#ifndef RTRND_ROUTE_RES_H +#define RTRND_ROUTE_RES_H + +#include + +#include "data.h" +#include "conf.h" + +void rtrnd_res_init(rtrnd_t *ctx); +void rtrnd_res_add(rtrnd_t *ctx, const rtrnd_any_obj_t *obj); +void rtrnd_res_log(rtrnd_t *ctx, char level, const char *fmt, ...); +void rtrnd_res_confkey(rtrnd_t *ctx, const rtrnd_conf_t *item); +void rtrnd_res_uninit(rtrnd_t *ctx); + + +void rtrnd_res_conf_all(rtrnd_t *ctx, const rtrnd_conf_t *first); + + +void rtrnd_draw_res_line(rtrnd_t *ctx, rtrnd_layer_t *ly_copper, rtrnd_layer_t *ly_annot, rtrnd_net_t *net, double x1, double y1, double x2, double y2, double cop_thick, double cop_clr, double annot_thick, double annot_clr); +void rtrnd_draw_res_via(rtrnd_t *ctx, rtrnd_layer_t *ly_annot, rtrnd_net_t *net, double x, double y, double dia, double clr, double annot_thick, double annot_clr); + +int rtrnd_progress(rtrnd_t *ctx, double at); + + +#endif Index: tags/0.9.0/src/route-rnd/rtpoly.c =================================================================== --- tags/0.9.0/src/route-rnd/rtpoly.c (nonexistent) +++ tags/0.9.0/src/route-rnd/rtpoly.c (revision 1402) @@ -0,0 +1,315 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * rtree based, hole-free polygons + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include "geo.h" +#include +#include "rtpoly.h" + +#define RTP_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define RTP_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +void rtpoly_new_begin(rtpoly_t *poly) +{ + memset(poly, 0, sizeof(rtpoly_t)); + rtrnd_rtree_init(&poly->tree); +} + +void rtpoly_new_append(rtpoly_t *poly, double x, double y) +{ + rtp_vertex_t *v = calloc(sizeof(rtp_vertex_t), 1); + v->x = x; + v->y = y; + gdl_append(&poly->lst, v, link); +} + +static int rtpoly_is_valid_selfi(rtpoly_t *poly) +{ + rtp_vertex_t *v, *vn, *vp, *n, *nn; + + for(v = gdl_first(&poly->lst); v != NULL; v = gdl_next(&poly->lst, v)) { + rtrnd_rtree_it_t it; + + vn = gdl_next(&poly->lst, v); + if (vn == NULL) vn = gdl_first(&poly->lst); + vp = gdl_prev(&poly->lst, v); + if (vp == NULL) vp = gdl_last(&poly->lst); + + for(n = rtrnd_rtree_first(&it, &poly->tree, &v->bbox); n != NULL; n = rtrnd_rtree_next(&it)) { + g2d_cline_t c1, c2; + + if ((n == v) || (n == vp) || (n == vn)) continue; + + nn = gdl_next(&poly->lst, n); + if (nn == NULL) nn = gdl_first(&poly->lst); + c1.p1.x = v->x; c1.p1.y = v->y; + c1.p2.x = vn->x; c1.p2.y = vn->y; + c2.p1.x = n->x; c1.p2.y = n->y; + c2.p2.x = nn->x; c2.p2.y = nn->y; + if (g2d_isc_cline_cline(&c1, &c2)) + return 0; + } + } + return 1; +} + + +int rtpoly_new_end(rtpoly_t *poly) +{ + rtp_vertex_t *v, *vn; + + poly->bbox = g2d_box_invalid(); + for(v = gdl_first(&poly->lst); v != NULL; v = gdl_next(&poly->lst, v)) { + g2d_vect_t pt; + vn = gdl_next(&poly->lst, v); + if (vn == NULL) vn = gdl_first(&poly->lst); + v->bbox.x1 = RTP_MIN(v->x, vn->x); + v->bbox.y1 = RTP_MIN(v->y, vn->y); + v->bbox.x2 = RTP_MAX(v->x, vn->x); + v->bbox.y2 = RTP_MAX(v->y, vn->y); + rtrnd_rtree_insert(&poly->tree, v, &v->bbox); + poly->area += (v->x - vn->x) * (v->y + vn->y); + + pt.x = v->x; pt.y = v->y; + g2d_box_bump_pt(&poly->bbox, pt); + } + + /* make sure about the orientation */ + if (poly->area < 0) { + gdl_reverse(&poly->lst); + poly->area = -poly->area; + } + + poly->area /= 2; + poly->valid = rtpoly_is_valid_selfi(poly) && (poly->lst.length > 2); + return !poly->valid; +} + +void rtpoly_free(rtpoly_t *poly) +{ + rtp_vertex_t *v; + rtrnd_rtree_uninit(&poly->tree); + for(v = gdl_first(&poly->lst); v != NULL; v = gdl_first(&poly->lst)) { + gdl_remove(&poly->lst, v, link); + free(v); + } +} + + +int rtpoly_isc_point(const rtpoly_t *poly, double x, double y) +{ + rtrnd_rtree_box_t raybox; + rtrnd_rtree_it_t it; + g2d_vect_t pt; + g2d_calc_t cross; + rtp_vertex_t *n, *nn; + int cnt = 0; + + + /* can't intersect if outside of the bbox */ + if ((x < poly->bbox.p1.x) || (x > poly->bbox.p2.x) || (y < poly->bbox.p1.y) || (y > poly->bbox.p2.y)) + return 0; + + + /* cut the polygon with a horizontal ray from the point to right x->inf */ + raybox.x1 = x; raybox.y1 = y; + raybox.x2 = poly->bbox.p2.x+1; raybox.y2 = y+0.001; + + pt.x = x; pt.y = y; + + for(n = rtrnd_rtree_first(&it, &poly->tree, &raybox); n != NULL; n = rtrnd_rtree_next(&it)) { + g2d_cline_t edge; + nn = gdl_next(&poly->lst, n); + if (nn == NULL) nn = gdl_first(&poly->lst); + + edge.p1.x = n->x; edge.p1.y = n->y; + edge.p2.x = nn->x; edge.p2.y = nn->y; + + /* the horizontal cutting line is between vectors s->v and s->v->next, but + these two can be in any order; because poly contour is CCW, this means if + the edge is going up, we went from inside to outside, else we went + from outside to inside */ + if (edge.p1.y <= y) { + if (edge.p2.y > y) { /* this also happens to blocks horizontal poly edges because they are only == */ + g2d_vect_t v1 = g2d_vect_t_sub_g2d_vect_t(edge.p2, edge.p1); + g2d_vect_t v2 = g2d_vect_t_sub_g2d_vect_t(pt, edge.p1); + cross = g2d__crossp(g2d_cvect_t_convfrom_g2d_vect_t(v1), g2d_cvect_t_convfrom_g2d_vect_t(v2)); + if (cross == 0) + return 1; /* special case: if the point is on any edge, the point is in the poly */ + if (cross > 0) + cnt++; + } + } + else { /* since the other side was <=, when we get here we also blocked horizontal lines of the negative direction */ + if (edge.p2.y <= y) { + g2d_vect_t v1 = g2d_vect_t_sub_g2d_vect_t(edge.p2, edge.p1); + g2d_vect_t v2 = g2d_vect_t_sub_g2d_vect_t(pt, edge.p1); + cross = g2d__crossp(g2d_cvect_t_convfrom_g2d_vect_t(v1), g2d_cvect_t_convfrom_g2d_vect_t(v2)); + if (cross == 0) + return 1; /* special case: if the point is on any edge, the point is in the poly */ + if (cross < 0) + cnt--; + } + } + } + + return cnt; +} + +int rtpoly_isc_circle(const rtpoly_t *poly, double x, double y, double r) +{ + rtrnd_rtree_box_t circbox; + rtrnd_rtree_it_t it; + g2d_vect_t pt; + rtp_vertex_t *n, *nn; + double r2, dist2; + + + /* can't intersect if outside of the bbox */ + if ((x < poly->bbox.p1.x-r) || (x > poly->bbox.p2.x+r) || (y < poly->bbox.p1.y-r) || (y > poly->bbox.p2.y+r)) + return 0; + + if (rtpoly_isc_point(poly, x, y)) + return 1; + + circbox.x1 = x-r; circbox.y1 = y-r; + circbox.x2 = x+r; circbox.y2 = y+r; + pt.x = x; pt.y = y; + + r2 = r*r; + + /* take each poly edge that is close to the circle and... */ + for(n = rtrnd_rtree_first(&it, &poly->tree, &circbox); n != NULL; n = rtrnd_rtree_next(&it)) { + g2d_cline_t edge; + nn = gdl_next(&poly->lst, n); + if (nn == NULL) nn = gdl_first(&poly->lst); + + edge.p1.x = n->x; edge.p1.y = n->y; + edge.p2.x = nn->x; edge.p2.y = nn->y; + + /* check if the line is closer to circle center than r */ + dist2 = g2d_dist2_cline_pt(&edge, pt); + if (dist2 <= r2) + return 1; + } + + return 0; +} + +int rtpoly_isc_cline(const rtpoly_t *poly, const g2d_cline_t *cline) +{ + rtrnd_rtree_box_t clinebox; + g2d_box_t bx; + rtrnd_rtree_it_t it; + rtp_vertex_t *n, *nn; + + clinebox.x1 = RTP_MIN(cline->p1.x, cline->p2.x); clinebox.y1 = RTP_MIN(cline->p1.y, cline->p2.y); + clinebox.x2 = RTP_MAX(cline->p1.x, cline->p2.x); clinebox.y2 = RTP_MAX(cline->p1.y, cline->p2.y); + + bx.p1.x = clinebox.x1; bx.p1.y = clinebox.y1; + bx.p2.x = clinebox.x2; bx.p2.y = clinebox.y2; + + /* can't intersect if outside of the bbox */ + if (!g2d_isc_box_box(&poly->bbox, &bx)) + return 0; + + /* take each poly edge that is close to the circle and check for intersection */ + for(n = rtrnd_rtree_first(&it, &poly->tree, &clinebox); n != NULL; n = rtrnd_rtree_next(&it)) { + g2d_cline_t edge; + nn = gdl_next(&poly->lst, n); + if (nn == NULL) nn = gdl_first(&poly->lst); + + edge.p1.x = n->x; edge.p1.y = n->y; + edge.p2.x = nn->x; edge.p2.y = nn->y; + + if (g2d_isc_cline_cline(&edge, cline)) + return 1; + } + + /* if either end is in the poly, the whole line is in */ + return rtpoly_isc_point(poly, cline->p1.x, cline->p1.y); +} + +int rtpoly_isc_rtpoly(const rtpoly_t *p1, const rtpoly_t *p2) +{ + const rtpoly_t *big, *small; + rtp_vertex_t *n, *nn, *i, *in; + rtrnd_rtree_it_t it; + + if (!g2d_isc_box_box(&p1->bbox, &p2->bbox)) + return 0; /* polygons are not even near */ + + if (p1->lst.length > p2->lst.length) { + big = p1; + small = p2; + } + else { + big = p2; + small = p1; + } + + /* since our polygons are typically small and simple, this trivial + loop will be relatively fast: iteate over each edge of the smaller + polygon and rtree-search a collision with any edge of the bigger poly; + worst case is probably O(small * log(big)) */ + for(n = gdl_first(&small->lst); n != NULL; n = gdl_next(&small->lst, n)) { + g2d_cline_t sedge, bedge; + g2d_box_t sbox; + + sbox.p1.x = n->bbox.x1; sbox.p1.y = n->bbox.y1; + sbox.p2.x = n->bbox.x2; sbox.p2.y = n->bbox.y2; + if (!g2d_isc_box_box(&big->bbox, &sbox)) + continue; /* small edge not even near the big poly */ + + nn = gdl_next(&small->lst, n); + if (nn == NULL) nn = gdl_first(&small->lst); + + sedge.p1.x = n->x; sedge.p1.y = n->y; + sedge.p2.x = nn->x; sedge.p2.y = nn->y; + + for(i = rtrnd_rtree_first(&it, &big->tree, &n->bbox); i != NULL; i = rtrnd_rtree_next(&it)) { + in = gdl_next(&big->lst, i); + if (in == NULL) in = gdl_first(&big->lst); + bedge.p1.x = i->x; bedge.p1.y = i->y; + bedge.p2.x = in->x; bedge.p2.y = in->y; + + if (g2d_isc_cline_cline(&sedge, &bedge)) + return 1; + } + } + + /* lower probabilty: one polygon is fully within the other */ + n = gdl_first(&small->lst); + if (rtpoly_isc_point(big, n->x, n->y)) return 1; + n = gdl_first(&big->lst); + if (rtpoly_isc_point(small, n->x, n->y)) return 1; + + return 0; +} Index: tags/0.9.0/src/route-rnd/rtpoly.h =================================================================== --- tags/0.9.0/src/route-rnd/rtpoly.h (nonexistent) +++ tags/0.9.0/src/route-rnd/rtpoly.h (revision 1402) @@ -0,0 +1,69 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * rtree based, hole-free polygons + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + + +#ifndef RTPOLY_H +#define RTPOLY_H + +#include +#include "rtree.h" +#include "geo.h" + +typedef struct rtp_vertex_s { + rtrnd_rtree_box_t bbox; + double x, y; + gdl_elem_t link; +} rtp_vertex_t; + +typedef struct { + g2d_box_t bbox; + gdl_list_t lst; /* of rtp_vertex_t */ + rtrnd_rtree_t tree; /* of rtp_vertex_t */ + double area; + unsigned valid:1; +} rtpoly_t; + +void rtpoly_new_begin(rtpoly_t *poly); +void rtpoly_new_append(rtpoly_t *poly, double x, double y); +int rtpoly_new_end(rtpoly_t *poly); +void rtpoly_free(rtpoly_t *poly); + + +/* returns non-zero if x;y intersects with poly */ +int rtpoly_isc_point(const rtpoly_t *poly, double x, double y); + +/* returns non-zero if a circle of radius r at x;y intersects with poly */ +int rtpoly_isc_circle(const rtpoly_t *poly, double x, double y, double r); + +/* returns non-zero if a cline intersects with poly */ +int rtpoly_isc_cline(const rtpoly_t *poly, const g2d_cline_t *cline); + +/* returns non-zero if two rtpolys intersect */ +int rtpoly_isc_rtpoly(const rtpoly_t *p1, const rtpoly_t *p2); + +#endif Index: tags/0.9.0/src/route-rnd/rtree.c =================================================================== --- tags/0.9.0/src/route-rnd/rtree.c (nonexistent) +++ tags/0.9.0/src/route-rnd/rtree.c (revision 1402) @@ -0,0 +1,10 @@ +#include "config.h" +#include +#include + +#include "rtree.h" + +#include +#include +#include + Index: tags/0.9.0/src/route-rnd/rtree.h =================================================================== --- tags/0.9.0/src/route-rnd/rtree.h (nonexistent) +++ tags/0.9.0/src/route-rnd/rtree.h (revision 1402) @@ -0,0 +1,14 @@ +#ifndef RTRND_RTREE_H +#define RTRND_RTREE_H + +#define RTR(n) rtrnd_rtree_ ## n +#define RTRU(n) RTRND_RTREE_ ## n +typedef long int rtrnd_rtree_cardinal_t; +typedef double rtrnd_rtree_coord_t; +#define rtrnd_rtree_privfunc static +#define rtrnd_rtree_size 6 +#define rtrnd_rtree_stack_max 1024 + +#include + +#endif Index: tags/0.9.0/src/route-rnd/smd.tdx =================================================================== --- tags/0.9.0/src/route-rnd/smd.tdx (nonexistent) +++ tags/0.9.0/src/route-rnd/smd.tdx (revision 1402) @@ -0,0 +1,25 @@ +tEDAx v1 + +begin stackup v1 two_layer + layer top_copper top copper + lprop top_copper display-color #8b2323 + layer bottom_copper bottom copper + lprop bottom_copper display-color #00868b +end stackup + +begin layernet v1 top_copper + line 1001 netA mdt 1 5 1.2 5 0.2 0.0 + line 1002 netA mdt 6 5 6.2 5 0.2 0.0 + line 1003 netB mdt 3 6 3.2 6 0.2 0.0 + line 1004 netB mdt 9 6 9.2 6 0.2 0.0 + line 1005 netC mdt 4 1 4 1.2 0.2 0.0 + line 1006 netC mdt 4 9 4 9.2 0.2 0.0 +end layernet + +begin layernet v1 bottom_copper +end layernet + +begin route_req v1 smd + stackup two_layer + route_all +end route_req Index: tags/0.9.0/src/route-rnd/util_grid.c =================================================================== --- tags/0.9.0/src/route-rnd/util_grid.c (nonexistent) +++ tags/0.9.0/src/route-rnd/util_grid.c (revision 1402) @@ -0,0 +1,483 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * helper functions and data structures for grid based routing + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include "route-rnd.h" +#include "data.h" +#include +#include "htdi.h" +#include "util_grid.h" + +static int dcmp(const void *A, const void *B) +{ + double a = *(double *)A, b = *(double *)B; + return (a >= b) ? +1 : -1; +} + +int rtrnd_grid_detect(vtd0_t *samples, double *origin, double *spacing) +{ + long n, i, best_spc_score = 0; + double best_orig = 0, best_spc = 0; + htdi_t spc, offs; + + if (samples->used < 2) + return -1; + + htdi_init(&spc, htdi_keyhash, htdi_keyeq); + + qsort(samples->array, samples->used, sizeof(double), dcmp); + + for(i = 0; i < samples->used-1; i++) { + double d = samples->array[i+1] - samples->array[i], best_offs; + htdi_entry_t *e; + long best_score; + + if (d == 0) + continue; + + if (htdi_get(&spc, d) > 0) + continue; + htdi_set(&spc, d, 1); + + /* assume the next distance as grid spacing; calculate the offset for each + point and see what's the most common offset and how popular it is */ + htdi_init(&offs, htdi_keyhash, htdi_keyeq); + for(n = 0; n < samples->used; n++) { + long cnt; + double o = fmod(samples->array[n], d); + cnt = htdi_get(&offs, o); + cnt++; + htdi_set(&offs, o, cnt); + } + best_score = 0; + for(e = htdi_first(&offs); e != NULL; e = htdi_next(&offs, e)) { + if (e->value > best_score) { + best_score = e->value; + best_offs = e->key; + } + } + htdi_uninit(&offs); +/* printf(" cand: spc=%f offs=%f %ld/%ld\n", d, best_offs, best_score, samples->used);*/ + if (best_score > best_spc_score) { + best_spc_score = best_score; + best_orig = best_offs; + best_spc = d; + } + } + + best_orig = fmod(best_orig, best_spc); +/* printf(" best: spc=%f offs=%f %ld/%ld\n", best_spc, best_orig, best_spc_score, samples->used);*/ + htdi_uninit(&spc); + + *origin = best_orig; + *spacing = best_spc; + + return 0; +} + +#define APPEND_IF_TERM(term) \ +do { \ + if (term->hdr.terminal) { \ + double cx, cy; \ + if (rtrnd_obj_center(term, &cx, &cy) == 0) { \ + vtd0_append(&tx, cx); \ + vtd0_append(&ty, cy); \ + } \ + } \ +} while(0) + +int rtrnd_grid_detect_terms(const rtrnd_board_t *brd, double *x_orig, double *x_spacing, double *y_orig, double *y_spacing) +{ + vtd0_t tx, ty; + int ret, n; + rtrnd_any_obj_t *obj; + rtrnd_rtree_it_t it; + + vtd0_init(&tx); + vtd0_init(&ty); + + + for(obj = rtrnd_rtree_all_first(&it, &brd->vias); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + APPEND_IF_TERM(obj); + + for(n = 0; n < brd->layers.used; n++) { + rtrnd_layer_t *layer = brd->layers.array[n]; + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + APPEND_IF_TERM(obj); + } + + ret = rtrnd_grid_detect(&tx, x_orig, x_spacing); + ret |= rtrnd_grid_detect(&ty, y_orig, y_spacing); + vtd0_uninit(&tx); + vtd0_uninit(&ty); + return ret; +} + + +void rtrnd_ragrid_init(rtrnd_ragrid_t *grid, double min_coord, double max_coord, double origin, double spacing, double minor0, double minor1) +{ + double c, from; + long n; + + assert(max_coord > min_coord); + + grid->len = floor((max_coord - min_coord) / spacing)+3; + grid->raline = calloc(sizeof(rtrnd_raline_t), grid->len); + grid->spacing = spacing; + from = floor(min_coord / spacing) * spacing + fmod(origin, spacing); + for(c = from - spacing, n = 0; n < grid->len; c += spacing, n++) { + grid->raline[n].major = c; + vtd0_append(&grid->raline[n].minor, minor0); + vtd0_append(&grid->raline[n].minor, minor1); + } +} + +void rtrnd_ragrid_uninit(rtrnd_ragrid_t *grid) +{ + long n; + for(n = 0; n < grid->len; n++) + vtd0_uninit(&grid->raline[n].minor); + free(grid->raline); + grid->len = 0; +} + +void rtrnd_ragrid_draw(rtrnd_ragrid_t *grid, rtrnd_layer_t *layer, int is_major_x) +{ + long n, i; + double thick = 0.1; + + for(i = 0; i < grid->len; i++) { + double major = grid->raline[i].major; + rtrnd_raline_t *ra = &grid->raline[i]; + for(n = 0; n < ra->minor.used; n += 2) { + if (is_major_x) + rtrnd_line_new(layer, NULL, NULL, major, ra->minor.array[n], major, ra->minor.array[n+1], thick, 0); + else + rtrnd_line_new(layer, NULL, NULL, ra->minor.array[n], major, ra->minor.array[n+1], major, thick, 0); + } + } +} + +int rtrnd_raline_block(rtrnd_raline_t *ra, double from, double to) +{ + long i1 = -1, i2 = -1, n, hole1, hole2, dfrom, dto; + double *p; + + if (to <= from) + return -1; + + if (from <= ra->minor.array[0]) /* from is before the first range */ + i1 = 0; + + if (to >= ra->minor.array[ra->minor.used-1]) /* to is after the last range */ + i2 = ra->minor.used-1; + + for(n = 0; n < ra->minor.used-1; n++) { + if ((ra->minor.array[n] <= from) && (ra->minor.array[n+1] >= from)) + i1 = n; + if ((ra->minor.array[n] <= to) && (ra->minor.array[n+1] >= to)) { + i2 = n; + break; + } + } + + if ((i1 < 0) || (i2 < 0)) + return -1; + + hole1 = ((i1 % 2) == 1); + hole2 = ((i2 % 2) == 1); + + if (i1 == i2) { + if (hole1) /* creating a hole within a hole -> nop */ + return 0; + + /* same range: have to add a new range */ + p = vtd0_alloc_insert(&ra->minor, i1+1, 2); + p[0] = from; + p[1] = to; + return 0; + } + + /* in two different ranges - tune the ends of the start/end range and + remove any range in between */ + if (hole1) { + /* starting from a hole */ + dfrom = i1+1; + } + else if (ra->minor.array[i1] == from) { + /* from-pos-range is removed from its start - remove the whole range */ + dfrom = i1; + } + else { + ra->minor.array[i1+1] = from; + dfrom = i1+2; + } + + if (hole2) { + /* ending in a hole */ + dto = i2; + } + else if (ra->minor.array[i2+1] == to) { + /* to-pos-range is removed to its end - remove the whole range */ + dto = i2+1; + } + else { + ra->minor.array[i2] = to; + dto = i2-1; + } + vtd0_remove(&ra->minor, dfrom, (dto+1) - dfrom); + return 0; +} + +G2D_INLINE int g2d_box_clip2(g2d_box_t *dst, const g2d_box_t *box, const g2d_box_t *clipbox) +{ + if (!g2d_isc_box_box(box, clipbox)) + return 0; + dst->p1.x =( G2D_MAX ( box->p1.x , clipbox->p1.x ) ); + dst->p2.x =( G2D_MIN ( box->p2.x , clipbox->p2.x ) ); + dst->p1.y =( G2D_MAX ( box->p1.y , clipbox->p1.y ) ); + dst->p2.y =( G2D_MIN ( box->p2.y , clipbox->p2.y ) ); + return 1; +} + +int rtrnd_raline_obj_mask_size_at(rtrnd_raline_t *ra, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj, double *minor_from, double *minor_to) +{ + g2d_box_t rabox, clbox, obox; + double width, clr; + + switch(obj->hdr.type) { + case RTRND_LINE: + case RTRND_POLY: + case RTRND_VIA: +#warning TODO: lazy until gengeo2d is done +#warning TODO: if object's clearance is bigger than width, use that! + clr = lclr; + width = lthick + clr; + if (is_major_x) { + rabox.p1.y = ra->minor.array[0] - width; + rabox.p2.y = ra->minor.array[ra->minor.used-1] + width; + rabox.p1.x = ra->major - width; + rabox.p2.x = ra->major + width; + } + else { + rabox.p1.x = ra->minor.array[0] - width; + rabox.p2.x = ra->minor.array[ra->minor.used-1] + width; + rabox.p1.y = ra->major - width; + rabox.p2.y = ra->major + width; + } + + obox.p1.x = obj->hdr.bbox.x1; obox.p1.y = obj->hdr.bbox.y1; + obox.p2.x = obj->hdr.bbox.x2; obox.p2.y = obj->hdr.bbox.y2; + if (!g2d_box_clip2(&clbox, &rabox, &obox)) + break; /* no intersection */ + + if (is_major_x) { + *minor_from = clbox.p1.y-clr; + *minor_to = clbox.p2.y+clr; + } + else { + *minor_from = clbox.p1.x-clr; + *minor_to = clbox.p2.x+clr; + } + return 0; + + case RTRND_ARC: +#warning TODO + case RTRND_TEXT: + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + return -1; + } + + return -1; +} + +int rtrnd_raline_mask_obj(rtrnd_raline_t *ra, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj) +{ + int res; + double minor_from, minor_to; + + res = rtrnd_raline_obj_mask_size_at(ra, is_major_x, lthick, lclr, obj, &minor_from, &minor_to); + if (res != 0) + return res; + + return rtrnd_raline_block(ra, minor_from, minor_to); +} + +int rtrnd_grid_mask_obj(rtrnd_ragrid_t *grid, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj) +{ + double from, to; + long n; + + switch(obj->hdr.type) { + case RTRND_LINE: + case RTRND_POLY: + case RTRND_VIA: + case RTRND_ARC: + if (is_major_x) { + from = obj->hdr.bbox.x1; + to = obj->hdr.bbox.x2; + } + else { + from = obj->hdr.bbox.y1; + to = obj->hdr.bbox.y2; + } + + for(n = 0; n < grid->len; n++) { + if (grid->raline[n].major < from) + continue; + if (grid->raline[n].major > to) + break; + rtrnd_raline_mask_obj(&grid->raline[n], is_major_x, lthick, lclr, obj); + } + return 0; + case RTRND_TEXT: + case RTRND_BOARD: + case RTRND_LAYER: + case RTRND_NET: + case RTRND_NETSEG: + return -1; + } + + return 0; +} + +void rtrnd_grid_mask_objs(rtrnd_ragrid_t *grid, int is_major_x, rtrnd_board_t *brd, rtrnd_layer_t *layer, double wire_thick, double wire_clr) +{ + rtrnd_any_obj_t *obj; + rtrnd_rtree_it_t it; + + /* cut out layer objects if there's a layer */ + if (layer != NULL) + for(obj = rtrnd_rtree_all_first(&it, &layer->objs); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + rtrnd_grid_mask_obj(grid, is_major_x, wire_thick, wire_clr, obj); + + /* cut out vias if there's a board */ + if (brd != NULL) + for(obj = rtrnd_rtree_all_first(&it, &brd->vias); obj != NULL; obj = rtrnd_rtree_all_next(&it)) + rtrnd_grid_mask_obj(grid, is_major_x, wire_thick, wire_clr, obj); +} + +typedef struct { + double major; + const rtrnd_raline_t *last; +} major_bs_t; + +static int major_cmp(const void *Major, const void *B) +{ + major_bs_t *ctx = (major_bs_t *)Major; + const rtrnd_raline_t *raline = B; + + ctx->last = raline; + if (ctx->major == raline->major ) return 0; + if (ctx->major < raline->major ) return -1; + return +1; +} + +rtrnd_raline_t *rtrnd_grid_find_major_around(rtrnd_ragrid_t *grid, double major) +{ + major_bs_t ctx; + ctx.major = major; + ctx.last = NULL; + bsearch(&ctx, grid->raline, grid->len, sizeof(rtrnd_raline_t), major_cmp); + return (rtrnd_raline_t *)ctx.last; +} + +rtrnd_raline_t *rtrnd_grid_find_major_before(rtrnd_ragrid_t *grid, double major) +{ + rtrnd_raline_t *ra = rtrnd_grid_find_major_around(grid, major); + if (ra->major >= major) + ra--; + return ra; +} + +int rtrnd_raline_range_avail(rtrnd_raline_t *ra, double from, double to) +{ + long n; + + for(n = 0; n < ra->minor.used; n+=2) + if ((from >= ra->minor.array[n]) && (from <= ra->minor.array[n+1])) + return (to <= ra->minor.array[n+1]); + + return 0; +} + +long rtrnd_raline_pt_range(rtrnd_raline_t *ra, double minor_pt) +{ + long n; + + for(n = 0; n < ra->minor.used; n+=2) + if ((minor_pt >= ra->minor.array[n]) && (minor_pt <= ra->minor.array[n+1])) + return n; + + return -1; +} + +long rtrnd_raline_pt_neg_range(rtrnd_raline_t *ra, double minor_pt) +{ + long n; + + for(n = 1; n < ra->minor.used; n+=2) + if ((minor_pt >= ra->minor.array[n]) && (minor_pt <= ra->minor.array[n+1])) + return n; + + return -1; +} + + +int rtrnd_raline_in_grid(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra) +{ + return (ra >= grid->raline) && (ra < (grid->raline + grid->len)); +} + +long rtrnd_raline_dist(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra, rtrnd_raline_t *rb) +{ + assert(rtrnd_raline_in_grid(grid, ra)); + assert(rtrnd_raline_in_grid(grid, rb)); + return ra - rb; +} + + +rtrnd_raline_t *rtrnd_raline_step(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra, long delta) +{ + long idx = ra - grid->raline; + + if ((idx < 0) || (idx >= grid->len)) + return NULL; + + idx += delta; + if ((idx < 0) || (idx >= grid->len)) + return NULL; + + return grid->raline + idx; +} Index: tags/0.9.0/src/route-rnd/util_grid.h =================================================================== --- tags/0.9.0/src/route-rnd/util_grid.h (nonexistent) +++ tags/0.9.0/src/route-rnd/util_grid.h (revision 1402) @@ -0,0 +1,77 @@ +#ifndef RTRND_UTIL_GRID_H +#define RTRND_UTIL_GRID_H + +#include + +#include "data.h" + +int rtrnd_grid_detect(vtd0_t *samples, double *origin, double *spacing); +int rtrnd_grid_detect_terms(const rtrnd_board_t *brd, double *x_orig, double *x_spacing, double *y_orig, double *y_spacing); + +/* range-line at a major coord; minor holds endpoints of positive ranges in + [n*2]..[n*2+1] (ordered ascending); initially the whole line is a single + positive range between its absolute min..max, then negative ranges are + added by removing segments, splitting the positive range up into a series + of smaller positive ranges */ +typedef struct { + double major; + vtd0_t minor; + rtrnd_udata_t rt_data; /* optional custom data filled in by the router algorithm using the raline */ +} rtrnd_raline_t; + +/* remove a segment (from..to inclusive) from a raline, making it negative */ +int rtrnd_raline_block(rtrnd_raline_t *ra, double from, double to); + +/* A grid is an ordered (by major) list of ralines */ +typedef struct { + double spacing; + long len; + rtrnd_raline_t *raline; +} rtrnd_ragrid_t; + +void rtrnd_ragrid_init(rtrnd_ragrid_t *grid, double min_coord, double max_coord, double origin, double spacing, double minor0, double minor1); +void rtrnd_ragrid_uninit(rtrnd_ragrid_t *grid); + +/* render the grid onto a (typically annotation) layer with thin lines */ +void rtrnd_ragrid_draw(rtrnd_ragrid_t *grid, rtrnd_layer_t *layer, int is_major_x); + +/* Determine the size (cross section range, minor coords) of the object + sliced by a grid line */ +int rtrnd_raline_obj_mask_size_at(rtrnd_raline_t *ra, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj, double *minor_from, double *minor_to); + +/* Mask out objects from the grid, assuming the grid is created for lthick/lclr wires */ +int rtrnd_raline_mask_obj(rtrnd_raline_t *ra, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj); +int rtrnd_grid_mask_obj(rtrnd_ragrid_t *grid, int is_major_x, double lthick, double lclr, rtrnd_any_obj_t *obj); +void rtrnd_grid_mask_objs(rtrnd_ragrid_t *grid, int is_major_x, rtrnd_board_t *brd, rtrnd_layer_t *layer, double wire_thick, double wire_clr); + +/* Find the last raline whose major coord is smaller than major */ +rtrnd_raline_t *rtrnd_grid_find_major_before(rtrnd_ragrid_t *grid, double major); + +/* Returns 1 if range between from..to, inclusive, is within a single positive range */ +int rtrnd_raline_range_avail(rtrnd_raline_t *ra, double from, double to); + +/* Return the index of the positive range start minor_pt is in + located right before. Returns: + - the index of the positive range (ra->minor[ret] .. ra->minor[ret+1] is the endpoints) + - or -1 if minor_pt is in a negative range +*/ +long rtrnd_raline_pt_range(rtrnd_raline_t *ra, double minor_pt); + +/* Same as rtrnd_raline_pt_range() but is searching for a negative range */ +long rtrnd_raline_pt_neg_range(rtrnd_raline_t *ra, double minor_pt); + + +/* Returns 1 if ra is part of grid */ +int rtrnd_raline_in_grid(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra); + +/* Calculate the distance between ra and rb as ra-rb: 0 means they are + the same, +1 means ra is the next line after rb, -1 means ra is the + last line before rb */ +long rtrnd_raline_dist(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra, rtrnd_raline_t *rb); + +/* Return a neighbour raline stepping delta from ra; returns NULL if stepping + went out of range */ +rtrnd_raline_t *rtrnd_raline_step(rtrnd_ragrid_t *grid, rtrnd_raline_t *ra, long delta); + + +#endif Index: tags/0.9.0/src/route-rnd/util_rat.c =================================================================== --- tags/0.9.0/src/route-rnd/util_rat.c (nonexistent) +++ tags/0.9.0/src/route-rnd/util_rat.c (revision 1402) @@ -0,0 +1,228 @@ +/* + * COPYRIGHT + * + * route-rnd, modular printed circuit board autorouter + * + * rats nest (shortest pairwise netseg connection) + * route-rnd Copyright (C) 2020 Tibor 'Igor2' Palinkas + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include "route-rnd.h" +#include "data.h" +#include +#include "util_rat.h" + +#define SQR(a) ((a) * (a)) + +RTRND_INLINE int cfg_compatible(rtrnd_any_obj_t *o1, rtrnd_ratsnest_cfg_t cfg) +{ + if ((cfg & RTRND_RNS_NO_ARC) && (o1->hdr.type == RTRND_ARC)) + return 0; + + if ((cfg & RTRND_RNS_NO_DIAG) && (o1->hdr.type == RTRND_LINE)) { + if ((o1->line.cline.p1.x != o1->line.cline.p2.x) && (o1->line.cline.p1.y != o1->line.cline.p2.y)) + return 0; + } + + return 1; +} + +RTRND_INLINE void obj_pt_next(rtrnd_any_obj_t *obj, long *idx, double *xo, double *yo) +{ + switch(obj->hdr.type) { + case RTRND_LINE: + (*idx)++; + if (*idx == 2) + break; + if (*idx == 0) { + *xo = obj->line.cline.p1.x; + *yo = obj->line.cline.p1.y; + } + else { + *xo = obj->line.cline.p2.x; + *yo = obj->line.cline.p2.y; + } + return; + case RTRND_VIA: + (*idx)++; + if (*idx == 0) { + *xo = obj->via.x; + *yo = obj->via.y; + return; + } + break; + default: + ; + } + *idx = -1; +} + +RTRND_INLINE double find_rat(rtrnd_rat_t *dst, rtrnd_netseg_t *ns1, rtrnd_netseg_t *ns2, rtrnd_ratsnest_cfg_t cfg) +{ + rtrnd_any_obj_t *o1, *o2; + + + dst->cost = HUGE_VAL; + + for(o1 = gdl_first(&ns1->objs); o1 != NULL; o1 = gdl_next(&ns1->objs, o1)) { + if (!cfg_compatible(o1, cfg)) continue; + for(o2 = gdl_first(&ns2->objs); o2 != NULL; o2 = gdl_next(&ns2->objs, o2)) { + long i1, i2; + double x[2], y[2]; + if ((o1 == o2) || !cfg_compatible(o2, cfg)) continue; + for(i1 = -1, obj_pt_next(o1, &i1, &x[0], &y[0]); i1 >= 0; obj_pt_next(o1, &i1, &x[0], &y[0])) { + for(i2 = -1, obj_pt_next(o2, &i2, &x[1], &y[1]); i2 >= 0; obj_pt_next(o2, &i2, &x[1], &y[1])) { + double cost = SQR(x[0] - x[1]) + SQR(y[0] - y[1]); + if (cost < dst->cost) { + dst->x[0] = x[0]; dst->x[1] = x[1]; + dst->y[0] = y[0]; dst->y[1] = y[1]; + dst->o[0] = o1; dst->o[1] = o2; + dst->cost = cost; + } + } + } + } + } + return dst->cost; +} + +RTRND_INLINE void dup_append_rat(rtrnd_ratsnest_t *dst, const rtrnd_rat_t *src) +{ + rtrnd_rat_t *r = malloc(sizeof(rtrnd_rat_t)); + memcpy(r, src, sizeof(rtrnd_rat_t)); + memset(&r->link, 0, sizeof(r->link)); + gdl_append(&dst->lst, r, link); +} + + + +#define mxi(i1, i2, len) \ + (((i1) < (i2)) ? ((i1)*(len)+(i2)) : ((i2)*(len)+(i1))) + +void rtrnd_ratsnest_map(rtrnd_ratsnest_t *nest, rtrnd_board_t *board, rtrnd_ratsnest_cfg_t cfg) +{ + htsp_entry_t *e; + rtrnd_rat_t *dist = NULL; + int *comp = NULL; + long max_size = 0; + nest->cfg = cfg; + rtrnd_netseg_t **ns; + + /* allocation for the worst case (biggest net) */ + for(e = htsp_first(&board->nets); e != NULL; e = htsp_next(&board->nets, e)) { + rtrnd_net_t *net = e->value; + if (net->segments.length > max_size) + max_size = net->segments.length; + } + + if (max_size <= 1) + return; + + dist = malloc(max_size * max_size * sizeof(rtrnd_rat_t)); + comp = malloc(max_size * sizeof(int)); + ns = malloc(max_size * sizeof(rtrnd_netseg_t *)); + + /* minimal spanning tree for each net */ + for(e = htsp_first(&board->nets); e != NULL; e = htsp_next(&board->nets, e)) { + rtrnd_net_t *net = e->value; + long i1, i2, n, len, from, to; + rtrnd_netseg_t *nseg; + + if (net->segments.length < 1) /* skip nets already completed */ + continue; + + len = net->segments.length; + + /* set up the distance matrix and component tracking */ + for(n = 0, nseg = gdl_first(&net->segments); nseg != NULL; nseg = gdl_next(&net->segments, nseg), n++) { + ns[n] = nseg; + comp[n] = n; + } + for(i1 = 0; i1 < len; i1++) + for(i2 = i1+1; i2 < len; i2++) + find_rat(&dist[mxi(i1, i2, len)], ns[i1], ns[i2], cfg); + + /* greedy algorithm: realize the shortest possible connection and 'merge' + the components, until all components are gone */ +/*printf("net=%s\n", net->hdr.oid);*/ + for(;;) { + int besti1, besti2; + double best_cost = HUGE_VAL; +/*printf(" outer\n");*/ + for(i1 = 0; i1 < len; i1++) { + for(i2 = i1+1; i2 < len; i2++) { + if (comp[i1] == comp[i2]) continue; + if (dist[mxi(i1, i2, len)].cost < best_cost) { + besti1 = i1; besti2 = i2; + best_cost = dist[mxi(i1, i2, len)].cost; + } + } + } + if (best_cost == HUGE_VAL) + break; + i1 = besti1; + i2 = besti2; +/*printf(" connect #%ld(%d) #%ld(%d)\n", i1, comp[i1], i2, comp[i2]);*/ + dup_append_rat(nest, &dist[mxi(i1, i2, len)]); + dist[mxi(i1, i2, len)].cost = HUGE_VAL; + from = comp[i2]; + to = comp[i1]; + for(n = 0; n < len; n++) + if (comp[n] == from) + comp[n] = to; + } + + +#if 0 +printf(" done net:"); + for(n = 0; n < len; n++) + printf(" %d", comp[n]); +printf("\n"); +#endif + + } + free(dist); + free(comp); + free(ns); +} + +void rtrnd_ratsnest_draw(rtrnd_ratsnest_t *nest, rtrnd_layer_t *ly) +{ + rtrnd_rat_t *r; + for(r = gdl_first(&nest->lst); r != NULL; r = gdl_next(&nest->lst, r)) + rtrnd_line_new(ly, NULL, r->o[0]->hdr.net, r->x[0], r->y[0], r->x[1], r->y[1], 0.1, 0); +} + + +void rtrnd_ratsnest_uninit(rtrnd_ratsnest_t *nest) +{ + rtrnd_rat_t *r; + while((r = gdl_first(&nest->lst)) != NULL) { + gdl_remove(&nest->lst, r, link); + free(r); + } +} + Index: tags/0.9.0/src/route-rnd/util_rat.h =================================================================== --- tags/0.9.0/src/route-rnd/util_rat.h (nonexistent) +++ tags/0.9.0/src/route-rnd/util_rat.h (revision 1402) @@ -0,0 +1,32 @@ +#ifndef RTRND_UTIL_RAT_H +#define RTRND_UTIL_RAT_H + +#include +#include "data.h" + +typedef struct rtrnd_rat_s { + double cost; + double x[2], y[2]; + rtrnd_any_obj_t *o[2]; + gdl_elem_t link; /* in a rtrnd_ratsnest_t */ +} rtrnd_rat_t; + +typedef enum { /* bitfield */ + RTRND_RNS_NO_ARC = 1, + RTRND_RNS_NO_DIAG = 2 +} rtrnd_ratsnest_cfg_t; + +typedef struct rtrnd_ratsnest_s { + rtrnd_ratsnest_cfg_t cfg; + gdl_list_t lst; +} rtrnd_ratsnest_t; + + +void rtrnd_ratsnest_map(rtrnd_ratsnest_t *nest, rtrnd_board_t *board, rtrnd_ratsnest_cfg_t cfg); + +void rtrnd_ratsnest_draw(rtrnd_ratsnest_t *nest, rtrnd_layer_t *ly); + +/* free all rat lines of a ratsnest */ +void rtrnd_ratsnest_uninit(rtrnd_ratsnest_t *nest); + +#endif Index: tags/0.9.0/src_3rd/Makefile.conf =================================================================== Index: tags/0.9.0/src_3rd/opc89.h =================================================================== --- tags/0.9.0/src_3rd/opc89.h (nonexistent) +++ tags/0.9.0/src_3rd/opc89.h (revision 1402) @@ -0,0 +1,16 @@ +#ifdef __OPC89__ + +/* Being compiled with opc89: use attributes to mark types and functions */ +# define funcops __attribute__((opc89_ops)) +# define opfunc __attribute__((opc89_opfunc)) + +/* make sure asserts are kept as is */ +#define assert(a) + +#else + +/* Being compiled with a c compiler: make opc marks invisible */ +# define funcops +# define opfunc + +#endif Index: tags/0.9.0/src_3rd =================================================================== --- tags/0.9.0/src_3rd (nonexistent) +++ tags/0.9.0/src_3rd (revision 1402) Property changes on: tags/0.9.0/src_3rd ___________________________________________________________________ Added: svn:externals ## -0,0 +1,12 ## +svn://svn.repo.hu/genvector/trunk/genvector@187 genvector +svn://svn.repo.hu/gengeo2d/trunk/gengeo2d@281 gengeo2d +svn://svn.repo.hu/genht/trunk/src@119 genht +svn://svn.repo.hu/genrtree/trunk/genrtree@99 genrtree +svn://svn.repo.hu/genlist/trunk/genlist@115 genlist +svn://svn.repo.hu/libusteiner/trunk/libusteiner@78 libusteiner +svn://svn.repo.hu/libpsrand/trunk/libpsrand@50 libpsrand +svn://svn.repo.hu/pcb-rnd/trunk/src_3rd/libcdtr@35671 libcdtr +svn://svn.repo.hu/libusearch/trunk/libusearch@38 libusearch +svn://svn.repo.hu/libualloc/trunk/libualloc@174 libualloc +svn://svn.repo.hu/genprique/trunk@24 genprique +svn://svn.repo.hu/libgrbs/trunk/libgrbs@1471 libgrbs Index: tags/0.9.0/util/dep.sh =================================================================== --- tags/0.9.0/util/dep.sh (nonexistent) +++ tags/0.9.0/util/dep.sh (revision 1402) @@ -0,0 +1,8 @@ +#!/bin/sh + +cflags="$@" +tr " " "\n" | while read obj +do + c=${obj%%.o}.c + gcc -MT $obj -MM $c $cflags +done Property changes on: tags/0.9.0/util/dep.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property