Index: /applications/editors/josm/plugins/seachart/GPL-v2.0.txt
===================================================================
--- /applications/editors/josm/plugins/seachart/GPL-v2.0.txt	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/GPL-v2.0.txt	(revision 30894)
@@ -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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.
+
+  <signature of Ty Coon>, 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: /applications/editors/josm/plugins/seachart/GPL-v3.0.txt
===================================================================
--- /applications/editors/josm/plugins/seachart/GPL-v3.0.txt	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/GPL-v3.0.txt	(revision 30894)
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  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.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  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.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU 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.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: /applications/editors/josm/plugins/seachart/README
===================================================================
--- /applications/editors/josm/plugins/seachart/README	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/README	(revision 30894)
@@ -0,0 +1,7 @@
+README 
+======
+
+Author: Malcolm Herring, malcolm.herring@btinternet.com
+
+License: GPL v2 or later
+
Index: /applications/editors/josm/plugins/seachart/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/build.xml	(revision 30894)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project name="SeaChart" default="dist" basedir=".">
+    <!-- enter the SVN commit message -->
+    <property name="commit.message" value="New release"/>
+    <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
+    <property name="plugin.main.version" value="7001"/>
+
+    <property name="plugin.author" value="Malcolm Herring"/>
+    <property name="plugin.class" value="seachart.Seachart"/>
+    <property name="plugin.description" value="Imagery Layer for Sea Charts"/>
+    <property name="plugin.icon" value="images/SC.png"/>
+    <property name="plugin.link" value="http://openseamap.org/"/>
+
+    <property name="josm" location="../../core/dist/josm-custom.jar"/>
+    <property name="plugin.dist.dir" value="../../dist"/>
+    
+    <!-- ** include targets that all plugins have in common ** -->
+    <import file="../build-common.xml"/>                
+
+</project>
+
Index: /applications/editors/josm/plugins/seachart/jharbour/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jharbour/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jharbour/build.xml	(revision 30894)
@@ -0,0 +1,27 @@
+<project name="jharbour" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jharbour.jar"/>
+
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}"/>
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jharbour.Jharbour"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jharbour/src/jharbour/Jharbour.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jharbour/src/jharbour/Jharbour.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jharbour/src/jharbour/Jharbour.java	(revision 30894)
@@ -0,0 +1,258 @@
+/* Copyright 2013 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jharbour;
+
+import java.io.*;
+import java.util.*;
+
+public class Jharbour {
+
+	static class Node {
+		public double lat;
+		public double lon;
+		
+		public Node() {
+			lat = 0.0;
+			lon = 0.0;
+		}
+		public Node(double iLat, double iLon) {
+			lat = iLat;
+			lon = iLon;
+		}
+	}
+
+	static HashMap<Long, Node> nodes = new HashMap<Long, Node>();
+	static HashMap<Long, ArrayList<Long>> ways = new HashMap<Long, ArrayList<Long>>();
+
+	public static void main(String[] args) throws IOException {
+
+		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+		PrintStream out = System.out;
+
+		ArrayList<String> tags = null;
+		ArrayList<Long> refs = null;
+		ArrayList<Long> outers = null;
+
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+		boolean inRel = false;
+		boolean isHarbour = false;
+		long id = 0;
+
+		String ln;
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (ln.contains("</osm")) {
+					inOsm = false;
+					out.println("</harbours>");
+				} else if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+						if (isHarbour) {
+							out.println(String.format("  <harbour node=\"%d\" lat=\"%f\" lon=\"%f\">", id, nodes.get(id).lat, nodes.get(id).lon));
+							for (String tag : tags) {
+								out.println(tag);
+							}
+							out.println("  </harbour>");
+						}
+					} else if (ln.contains("<tag")) {
+						tags.add(ln);
+						if (ln.contains("seamark:type") && (ln.contains("harbour") || ln.contains("anchorage"))) {
+							isHarbour = true;
+						}
+					}
+				} else if (inWay) {
+					if (ln.contains("</way")) {
+						inWay = false;
+						ways.put(id, refs);
+						if (isHarbour) {
+							Node node = findCentroid(refs);
+							out.println(String.format("  <harbour way=\"%d\" lat=\"%f\" lon=\"%f\">", id, node.lat, node.lon));
+							for (String tag : tags) {
+								out.println(tag);
+							}
+							out.println("  </harbour>");
+						}
+					} else if (ln.contains("<nd")) {
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								refs.add(Long.parseLong(token.split("[\"\']")[1]));
+							}
+						}
+					} else if (ln.contains("<tag")) {
+						tags.add(ln);
+						if (ln.contains("seamark:type") && (ln.contains("harbour") || ln.contains("anchorage"))) {
+							isHarbour = true;
+						}
+					}
+				} else if (inRel) {
+					if (ln.contains("</relation")) {
+						inRel = false;
+						if (isHarbour) {
+							refs = new ArrayList<Long>();
+							long first = 0;
+							long last = 0;
+							int sweep = outers.size();
+							while (!outers.isEmpty() && (sweep > 0)) {
+								long way = outers.remove(0);
+								if (refs.isEmpty()) {
+									refs.addAll(ways.get(way));
+									first = refs.get(0);
+									last = refs.get(refs.size()-1);
+								} else {
+									ArrayList<Long> nway = ways.get(way);
+									if (nway.get(0) == last) {
+										refs.addAll(nway);
+										last = refs.get(refs.size()-1);
+										sweep = outers.size();
+									} else if (nway.get(nway.size()-1) == last) {
+										Collections.reverse(nway);
+										refs.addAll(nway);
+										last = refs.get(refs.size()-1);
+										sweep = outers.size();
+									} else {
+										outers.add(way);
+										sweep--;
+									}
+								}
+								if (first == last) {
+									Node node = findCentroid(refs);
+									out.println(String.format("  <harbour rel=\"%d\" lat=\"%f\" lon=\"%f\">", id, node.lat, node.lon));
+									for (String tag : tags) {
+										out.println(tag);
+									}
+									out.println("  </harbour>");
+									refs = new ArrayList<Long>();
+									sweep = outers.size();
+								}
+							}
+						}
+					} else if (ln.contains("<member") && ln.contains("way") && ln.contains("outer")) {
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								outers.add(Long.parseLong(token.split("[\"\']")[1]));
+							}
+						}
+					} else if (ln.contains("<tag")) {
+						tags.add(ln);
+						if (ln.contains("seamark:type") && (ln.contains("harbour") || ln.contains("anchorage"))) {
+							isHarbour = true;
+						}
+					}
+				} else if (ln.contains("<node")) {
+					inNode = true;
+					isHarbour = false;
+					tags = new ArrayList<String>();
+					Node node = new Node();
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+							nodes.put(id, node);
+						} else if (token.matches("^lat=.+")) {
+							node.lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							node.lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					if (ln.contains("/>")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<way")) {
+					inWay = true;
+					isHarbour = false;
+					tags = new ArrayList<String>();
+					refs = new ArrayList<Long>();
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (ln.contains("/>")) {
+						inWay = false;
+					}
+				} else if (ln.contains("<relation")) {
+					inRel = true;
+					isHarbour = false;
+					tags = new ArrayList<String>();
+					outers = new ArrayList<Long>();
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (ln.contains("/>")) {
+						inRel = false;
+					}
+				}
+			} else {
+				if (ln.contains("<osm")) {
+					inOsm = true;
+					out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+					out.println("<harbours>");
+				}
+			}
+		}
+	}
+
+	static Node findCentroid(ArrayList<Long> refs) {
+		double lat, lon, slat, slon, llat, llon, sarc;
+		boolean first = true;
+		slat = slon = sarc = lat = lon = llat = llon = 0.0;
+		if (refs.get(0).equals(refs.get(refs.size() - 1))) {
+			for (Long ref : refs) {
+				lat = nodes.get(ref).lat;
+				lon = nodes.get(ref).lon;
+				if (first) {
+					first = false;
+				} else {
+					double arc = (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+					slat += (lat * arc);
+					slon += (lon * arc);
+					sarc += arc;
+				}
+				llon = lon;
+				llat = lat;
+			}
+			return new Node((sarc > 0.0 ? slat / sarc : 0.0), (sarc > 0.0 ? slon / sarc : 0.0));
+		} else {
+			for (Long ref : refs) {
+				lat = nodes.get(ref).lat;
+				lon = nodes.get(ref).lon;
+				if (first) {
+					first = false;
+				} else {
+					sarc += (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+				}
+				llat = lat;
+				llon = lon;
+			}
+			double harc = sarc / 2;
+			sarc = 0.0;
+			first = true;
+			for (Long ref : refs) {
+				lat = nodes.get(ref).lat;
+				lon = nodes.get(ref).lon;
+				if (first) {
+					first = false;
+				} else {
+					sarc = (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+					if (sarc > harc)
+						break;
+				}
+				harc -= sarc;
+				llat = lat;
+				llon = lon;
+			}
+			return new Node(llat + ((lat - llat) * harc / sarc), llon + ((lon - llon) * harc / sarc));
+		}
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/jicons/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jicons/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jicons/build.xml	(revision 30894)
@@ -0,0 +1,39 @@
+<project name="jicons" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jicons.jar"/>
+  <property name="ant.build.javac.target" value="1.7"/>
+  <property name="ant.build.javac.source" value="1.7"/>
+  <property name="batik.dir" value="/usr/local/bin/batik-1.7/"/>
+  <path id="classpath">
+    <fileset dir="${batik.dir}" includes="**/batik*.jar"/>
+  </path>
+            
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}" classpathref="classpath" encoding="UTF-8" />
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jicons.Jicons"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-svggen.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-dom.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-util.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-awt-util.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-ext.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-xml.jar" />
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jicons/src/jicons/Jicons.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jicons/src/jicons/Jicons.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jicons/src/jicons/Jicons.java	(revision 30894)
@@ -0,0 +1,202 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jicons;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+
+import javax.imageio.ImageIO;
+
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMImplementation;
+
+import s57.S57map;
+import s57.S57map.Feature;
+import s57.S57map.Snode;
+import render.*;
+
+public class Jicons {
+	
+	static int x = 0;
+	static int y = 0;
+	static int w = 0;
+	static int h = 0;
+	static double s = 0;
+
+	public static void main(String[] args) throws IOException {
+		Context context;
+		S57map map = null;
+		BufferedReader in;
+		int line = 0;
+		String format = "";
+		String file = "";
+		String k = "";
+		String v = "";
+
+		BufferedImage img;
+		Graphics2D g2;
+		boolean inIcons = false;
+		boolean inIcon = false;
+		
+		if (args.length < 2) {
+			System.err.println("Usage: java -jar jicons.jar icon_definition_file icons_directory");
+			System.exit(-1);
+		}
+		in = new BufferedReader(new FileReader(args[0]));
+		
+		context = new Context();
+		String ln;
+		while ((ln = in.readLine()) != null) {
+			line++;
+			if (inIcons) {
+				if (inIcon) {
+					if (ln.contains("</icon")) {
+						inIcon = false;
+						map.tagsDone(0);
+						// generate icon file
+						switch (format) {
+						case "PNG":
+							img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+							g2 = img.createGraphics();
+							Renderer.reRender(g2, 16, s / Renderer.symbolScale[16], map, context);
+							try {
+								ImageIO.write(img, "png", new File(args[1] + file + ".png"));
+							} catch (Exception e) {
+								System.err.println("Line " + line + ": PNG write Exception");
+							}
+							System.err.println(file + ".png");
+							break;
+						case "SVG":
+							DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+							String svgNS = "http://www.w3.org/2000/svg";
+							Document document = domImpl.createDocument(svgNS, "svg", null);
+							SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
+							svgGenerator.setSVGCanvasSize(new Dimension(w, h));
+							Renderer.reRender(svgGenerator, 16, s / Renderer.symbolScale[16], map, context);
+							boolean useCSS = true;
+							Writer out = null;
+							try {
+								out = new OutputStreamWriter(new FileOutputStream(args[1] + file + ".svg"), "UTF-8");
+							} catch (IOException e1) {
+								System.err.println("Line " + line + ": SVG file Exception");
+							}
+							try {
+								svgGenerator.stream(out, useCSS);
+							} catch (SVGGraphics2DIOException e) {
+								System.err.println("Line " + line + ": SVG write Exception");
+							}
+							System.err.println(file + ".svg");
+							break;
+						}
+					} else if (ln.contains("<tag")) {
+						k = v = "";
+						String[] token = ln.split("k=");
+						k = token[1].split("[\"\']")[1];
+						token = token[1].split("v=");
+						v = token[1].split("[\"\']")[1];
+						if (k.isEmpty()) {
+							System.err.println("Line " + line + ": No key in tag");
+							System.exit(-1);
+						}
+						if (v.isEmpty()) {
+							System.err.println("Line " + line + ": No value in tag");
+							System.exit(-1);
+						}
+						map.addTag(k, v);
+					}
+				} else if (ln.contains("<icon")) {
+					inIcon = true;
+					h = w = x = y = -1;
+					s = 0;
+					file = format = "";
+					map = new S57map();
+					map.addNode(0, 0, 0);
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^width=.+")) {
+							w = Integer.parseInt(token.split("[\"\']")[1]);
+						} else if (token.matches("^height=.+")) {
+							h = Integer.parseInt(token.split("[\"\']")[1]);
+						} else if (token.matches("^x=.+")) {
+							x = Integer.parseInt(token.split("[\"\']")[1]);
+						} else if (token.matches("^y=.+")) {
+							y = Integer.parseInt(token.split("[\"\']")[1]);
+						} else if (token.matches("^scale=.+")) {
+							s = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^file=.+")) {
+							file = (token.split("[\"\']")[1]);
+						} else if (token.matches("^format=.+")) {
+							format = (token.split("[\"\']")[1]);
+						}
+					}
+					if (file.isEmpty()) {
+						System.err.println("Line " + line + ": No filename");
+						System.exit(-1);
+					}
+					if (format.isEmpty()) {
+						System.err.println("Line " + line + ": No format");
+						System.exit(-1);
+					}
+					if ((h < 0) && (w < 0)) {
+						System.err.println("Line " + line + ": No icon size");
+						System.exit(-1);
+					}
+					if (w < 0) {
+						w = h;
+					}
+					if (h < 0) {
+						h = w;
+					}
+					if (x < 0) {
+						x = w / 2;
+					}
+					if (y < 0) {
+						y = h / 2;
+					}
+					if (s == 0) {
+						s = 1;
+					}
+				} else if (ln.contains("</icons")) {
+					inIcons = false;
+					break;
+				}
+			} else if (ln.contains("<icons")) {
+				inIcons = true;
+			}
+		}
+		in.close();
+		System.err.println("Finished");
+		System.exit(0);
+	}
+	
+	static class Context implements ChartContext {
+		
+		@Override
+		public Point2D getPoint(Snode coord) {
+			return new Point2D.Double(x, y);
+		}
+
+		@Override
+		public double mile(Feature feature) {
+			return Math.min(w, h);
+		}
+	}
+}
Index: /applications/editors/josm/plugins/seachart/jicons/src/render
===================================================================
--- /applications/editors/josm/plugins/seachart/jicons/src/render	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jicons/src/render	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/render
Index: /applications/editors/josm/plugins/seachart/jicons/src/s57
===================================================================
--- /applications/editors/josm/plugins/seachart/jicons/src/s57	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jicons/src/s57	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/s57
Index: /applications/editors/josm/plugins/seachart/jicons/src/symbols
===================================================================
--- /applications/editors/josm/plugins/seachart/jicons/src/symbols	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jicons/src/symbols	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/symbols
Index: /applications/editors/josm/plugins/seachart/jplotter/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jplotter/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jplotter/build.xml	(revision 30894)
@@ -0,0 +1,27 @@
+<project name="jplotter" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jplotter.jar"/>
+
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}"/>
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jplotter.Jplotter"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jplotter/src/jplotter/Jplotter.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jplotter/src/jplotter/Jplotter.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jplotter/src/jplotter/Jplotter.java	(revision 30894)
@@ -0,0 +1,25 @@
+package jplotter;
+
+import java.awt.*;
+import javax.swing.*;
+
+public class Jplotter {
+
+	public static void main(String[] args) {
+		JFrame frame = new JFrame("Chart Plotter");
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.setLayout(null);
+		Container c = frame.getContentPane();
+
+		JPanel map = new JPanel(new BorderLayout());
+		map.setSize(600, 600);
+		map.setLocation(50, 35);
+		map.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder()));
+		map.setLayout(null);
+		map.setVisible(true);
+		c.add(map);
+
+		frame.setSize(700, 700);
+		frame.setVisible(true);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/jrender/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jrender/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jrender/build.xml	(revision 30894)
@@ -0,0 +1,39 @@
+<project name="jrender" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jrender.jar"/>
+  <property name="ant.build.javac.target" value="1.7"/>
+  <property name="ant.build.javac.source" value="1.7"/>
+  <property name="batik.dir" value="/usr/local/bin/batik-1.7/"/>
+  <path id="classpath">
+    <fileset dir="${batik.dir}" includes="**/batik*.jar"/>
+  </path>
+            
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}" classpathref="classpath" encoding="UTF-8" />
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jrender.Jrender"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-svggen.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-dom.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-util.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-awt-util.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-ext.jar" />
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-xml.jar" />
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jrender/src/jrender/Jrender.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jrender/src/jrender/Jrender.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jrender/src/jrender/Jrender.java	(revision 30894)
@@ -0,0 +1,319 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jrender;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.imageio.ImageIO;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import render.ChartContext;
+import render.Renderer;
+import s57.S57map;
+import s57.S57map.Feature;
+import s57.S57map.Snode;
+
+public class Jrender {
+
+	static String srcdir;
+	static String dstdir;
+	static int xtile;
+	static int ytile;
+	static int zoom;
+	static double minlat;
+	static double minlon;
+	static double maxlat;
+	static double maxlon;
+	static ArrayList<String> buf;
+	static ArrayList<String> send;
+	static HashMap<String, Boolean> deletes;
+	static Context context;
+	static S57map map;
+	static int empty;
+
+	static class Context implements ChartContext {
+		
+	  static double top = 0;
+	  static double mile = 0;
+	  
+	  public Context () {
+			top = (1.0 - Math.log(Math.tan(Math.toRadians(maxlat)) + 1.0 / Math.cos(Math.toRadians(maxlat))) / Math.PI) / 2.0 * 256.0 * 4096.0;
+			mile = 768 / ((maxlat - minlat) * 60);
+	  }
+	  
+		@Override
+		public Point2D getPoint(Snode coord) {
+			double x = (Math.toDegrees(coord.lon) - minlon) * 256.0 * 2048.0 / 180.0;
+			double y = ((1.0 - Math.log(Math.tan(coord.lat) + 1.0 / Math.cos(coord.lat)) / Math.PI) / 2.0 * 256.0 * 4096.0) - top;
+			return new Point2D.Double(x, y);
+		}
+
+		@Override
+		public double mile(Feature feature) {
+			return mile;
+		}
+	}
+	
+	public static void tileMap(ArrayList<String> buf, String idir, int zoom) throws IOException {
+		String k = "";
+		String v = "";
+		
+		double lat = 0;
+		double lon = 0;
+		long id = 0;
+
+		BufferedImage img;
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+		boolean inRel = false;
+		
+		context = new Context();
+
+		for (String ln : buf) {
+			if (inOsm) {
+				if ((inNode || inWay || inRel) && (ln.contains("<tag"))) {
+					k = v = "";
+					String[] token = ln.split("k=");
+					k = token[1].split("[\"\']")[1];
+					token = token[1].split("v=");
+					v = token[1].split("[\"\']")[1];
+					if (!k.isEmpty() && !v.isEmpty()) {
+						map.addTag(k, v);
+					}
+				}
+				if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						} else if (token.matches("^lat=.+")) {
+							lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					map.addNode(id, lat, lon);
+					if (ln.contains("/>")) {
+						map.tagsDone(id);
+					} else {
+						inNode = true;
+					}
+				} else if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							}
+						}
+						map.addToEdge(ref);
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					map.addEdge(id);
+					if (ln.contains("/>")) {
+						map.tagsDone(0);
+					} else {
+						inWay = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				} else if (inRel) {
+					if (ln.contains("<member")) {
+						String type = "";
+						String role = "";
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							} else if (token.matches("^type=.+")) {
+								type = (token.split("[\"\']")[1]);
+							} else if (token.matches("^role=.+")) {
+								role = (token.split("[\"\']")[1]);
+							}
+						}
+						if ((role.equals("outer") || role.equals("inner")) && type.equals("way"))
+							map.addToArea(ref, role.equals("outer"));
+					}
+					if (ln.contains("</relation")) {
+						inRel = false;
+						map.tagsDone(id);
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					map.addArea(id);
+					if (ln.contains("/>")) {
+						map.tagsDone(id);
+					} else {
+						inRel = true;
+					}
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+				map = new S57map();
+			}
+		}
+		
+		img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+		Renderer.reRender(img.createGraphics(), 12, 1, map, context);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		ImageIO.write(img, "png", bos);
+		empty = bos.size();
+		tile(zoom, 1, 0, 0);
+
+		for (int z = 12; z <= 18; z++) {
+			DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+			Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
+			SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
+			svgGenerator.setSVGCanvasSize(new Dimension(256, 256));
+			svgGenerator.setClip(0, 0, 256, 256);
+			svgGenerator.translate(-256, -256);
+			Renderer.reRender(svgGenerator, z, 1, map, context);
+			svgGenerator.stream(dstdir + "tst_" + z + ".svg");
+		}
+	}
+	
+	static void tile(int zoom, int s, int xn, int yn) throws IOException {
+		int scale = (int) Math.pow(2, zoom - 12);
+		int xdir = (scale * xtile) + xn;
+		int ynam = (scale * ytile) + yn;
+		BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+		Graphics2D g2 = img.createGraphics();
+		g2.scale(s, s);
+		g2.translate(-(256 + (xn * 256 / s)), -(256 + (yn * 256 / s)));
+		Renderer.reRender(g2, zoom, 1, map, context);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		ImageIO.write(img, "png", bos);
+		if (bos.size() > empty) {
+			String dstnam = dstdir + zoom + "/" + xdir + "/" + ynam + ".png";
+			deletes.remove(dstnam);
+			send.add("put " + dstnam + " cache/tiles-" + zoom + "-" + xdir + "-" + ynam + ".png");
+			File ofile = new File(dstdir + "/" + zoom + "/" + xdir + "/");
+			ofile.mkdirs();
+			FileOutputStream fos = new FileOutputStream(dstdir + "/" + zoom + "/" + xdir + "/" + ynam + ".png");
+			bos.writeTo(fos);
+			fos.close();
+			if (send.size() > 10) {
+				PrintWriter writer = new PrintWriter(srcdir + zoom + "-" + xdir + "-" + ynam + ".send", "UTF-8");
+				for (String str : send) {
+					writer.println(str);
+				}
+				writer.close();
+				send = new ArrayList<String>();
+			}
+		}
+		if ((zoom >= 12) && (zoom < 18) && ((zoom < 16) || (bos.size() > empty))) {
+			for (int x = 0; x < 2; x++) {
+				for (int y = 0; y < 2; y++) {
+					tile((zoom + 1), (s * 2), (xn * 2 + x), (yn * 2 + y));
+				}
+			}
+		}
+	}
+	
+	static void clean(int z, int xn, int yn) throws Exception {
+		int scale = (int) Math.pow(2, z - 12);
+		int xdir = (scale * xtile) + xn;
+		int ynam = (scale * ytile) + yn;
+		String delnam = dstdir + z + "/" + xdir + "/" + ynam + ".png";
+		File delfile = new File(delnam);
+		if (delfile.exists()) {
+			deletes.put(delnam, true);
+			delfile.delete();
+		}
+		if ((z < 18)) {
+			for (int x = 0; x < 2; x++) {
+				for (int y = 0; y < 2; y++) {
+					clean((z + 1), (xn * 2 + x), (yn * 2 + y));
+				}
+			}
+		}
+	}
+	
+	public static void main(String[] args) throws Exception {
+		srcdir = args[0];
+		dstdir = args[1];
+		zoom = Integer.parseInt(args[2]);
+		xtile = Integer.parseInt(args[3]);
+		ytile = Integer.parseInt(args[4]);
+		buf = new ArrayList<String>();
+		send = new ArrayList<String>();
+		deletes = new HashMap<String, Boolean>();
+		BufferedReader in = new BufferedReader(new FileReader(srcdir + xtile + "-" + ytile + "-" + zoom + ".osm"));
+		String ln;
+		while ((ln = in.readLine()) != null) {
+			if (ln.contains("<bounds")) {
+				for (String token : ln.split("[ ]+")) {
+					if (token.matches("^minlat=.+")) {
+						minlat = Double.parseDouble(token.split("[\"\']")[1]);
+					} else if (token.matches("^minlon=.+")) {
+						minlon = Double.parseDouble(token.split("[\"\']")[1]);
+					} else if (token.matches("^maxlat=.+")) {
+						maxlat = Double.parseDouble(token.split("[\"\']")[1]);
+					} else if (token.matches("^maxlon=.+")) {
+						maxlon = Double.parseDouble(token.split("[\"\']")[1]);
+					}
+				}
+			} else {
+				buf.add(ln);
+			}
+		}
+		in.close();
+		if (zoom == 12) {
+			clean(12, 0, 0);
+		}
+		tileMap(buf, dstdir, zoom);
+		if ((send.size() + deletes.size()) > 0) {
+			PrintWriter writer = new PrintWriter(srcdir + zoom + "-" + xtile + "-" + ytile + ".send", "UTF-8");
+			for (String str : send) {
+				writer.println(str);
+			}
+			for (String del : deletes.keySet()) {
+				writer.println("rm " + del);
+			}
+			writer.close();
+		}
+		System.exit(0);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/jrender/src/render
===================================================================
--- /applications/editors/josm/plugins/seachart/jrender/src/render	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jrender/src/render	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/render
Index: /applications/editors/josm/plugins/seachart/jrender/src/s57
===================================================================
--- /applications/editors/josm/plugins/seachart/jrender/src/s57	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jrender/src/s57	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/s57
Index: /applications/editors/josm/plugins/seachart/jrender/src/symbols
===================================================================
--- /applications/editors/josm/plugins/seachart/jrender/src/symbols	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jrender/src/symbols	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/symbols
Index: /applications/editors/josm/plugins/seachart/js57toosm/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/js57toosm/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/js57toosm/build.xml	(revision 30894)
@@ -0,0 +1,29 @@
+<project name="js57toosm" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./js57toosm.jar"/>
+  <property name="ant.build.javac.target" value="1.7"/>
+  <property name="ant.build.javac.source" value="1.7"/>
+    
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}" encoding="UTF-8"/>
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="js57toosm.Js57toosm"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/js57toosm/src/js57toosm/Js57toosm.java
===================================================================
--- /applications/editors/josm/plugins/seachart/js57toosm/src/js57toosm/Js57toosm.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/js57toosm/src/js57toosm/Js57toosm.java	(revision 30894)
@@ -0,0 +1,199 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package js57toosm;
+
+import java.io.*;
+import java.util.*;
+
+import s57.S57obj;
+import s57.S57obj.*;
+import s57.S57att;
+import s57.S57att.*;
+import s57.S57val;
+import s57.S57val.*;
+import s57.S57map;
+import s57.S57map.*;
+import s57.S57dec;
+
+public class Js57toosm {
+	
+	static FileInputStream in;
+	static PrintStream out;
+	static S57map map;
+	
+	public static void main(String[] args) throws IOException {
+
+		ArrayList<Long> done = new ArrayList<Long>();
+
+		if (args.length < 3) {
+			System.err.println("Usage: java -jar js57toosm.jar S57_filename types_filename OSM_filename");
+			System.exit(-1);
+		}
+		in = new FileInputStream(args[0]);
+		out = new PrintStream(args[2]);
+		ArrayList<Obj> types = new ArrayList<Obj>();
+			Scanner tin = new Scanner(new FileInputStream(args[1]));
+			while (tin.hasNext()) {
+				Obj type = S57obj.enumType(tin.next());
+				if (type != Obj.UNKOBJ)
+					types.add(type);
+			}
+			tin.close();
+		
+		map = new S57map();
+		MapBounds bounds = S57dec.decodeFile(in, map);
+
+		out.format("<?xml version='1.0' encoding='UTF-8'?>%n");
+		out.format("<osm version='0.6' upload='false' generator='js57toosm'>%n");
+		out.format("<bounds minlat='%.8f' minlon='%.8f' maxlat='%.8f' maxlon='%.8f'/>%n", bounds.minlat, bounds.minlon, bounds.maxlat, bounds.maxlon);
+
+		for (long id : map.index.keySet()) {
+			Feature feature = map.index.get(id);
+			String type = S57obj.stringType(feature.type);
+			if (!type.isEmpty() && (types.isEmpty() || types.contains(feature.type))) {
+				if (feature.reln == Rflag.MASTER) {
+					if (feature.geom.prim == Pflag.POINT) {
+						for (Prim prim : feature.geom.elems) {
+							long ref = prim.id;
+							Snode node;
+							while ((node = map.nodes.get(ref)) != null) {
+								if (!done.contains(ref)) {
+									out.format("  <node id='%d' lat='%.8f' lon='%.8f' version='1'>%n", -ref, Math.toDegrees(node.lat), Math.toDegrees(node.lon));
+									out.format("    <tag k='seamark:type' v=\"%s\"/>%n", type);
+									if ((feature.type == Obj.SOUNDG) && (node.flg == S57map.Nflag.DPTH))
+										out.format("    <tag k='seamark:sounding:depth' v='%.1f'/>%n", ((Dnode) node).val);
+									writeAtts(feature, type);
+									out.format("  </node>%n");
+									done.add(ref);
+								}
+								ref++;
+							}
+						}
+					}
+				}
+			}
+		}
+		for (long id : map.index.keySet()) {
+			Feature feature = map.index.get(id);
+			String type = S57obj.stringType(feature.type);
+			if (!type.isEmpty() && (types.isEmpty() || types.contains(feature.type))) {
+				if (feature.reln == Rflag.MASTER) {
+					if ((feature.geom.prim == Pflag.LINE) || ((feature.geom.prim == Pflag.AREA) && (feature.geom.outers == 1) && (feature.geom.inners == 0))) {
+						GeomIterator git = map.new GeomIterator(feature.geom);
+						while (git.hasComp()) {
+							git.nextComp();
+							while (git.hasEdge()) {
+								git.nextEdge();
+								while (git.hasNode()) {
+									long ref = git.nextRef();
+									Snode node = map.nodes.get(ref);
+									if (!done.contains(ref)) {
+										out.format("  <node id='%d' lat='%.8f' lon='%.8f' version='1'/>%n", -ref, Math.toDegrees(node.lat), Math.toDegrees(node.lon));
+										done.add(ref);
+									}
+								}
+							}
+						}
+						git = map.new GeomIterator(feature.geom);
+						while (git.hasComp()) {
+							long edge = git.nextComp();
+							out.format("  <way id='%d' version='1'>%n", -edge);
+							while (git.hasEdge()) {
+								git.nextEdge();
+								while (git.hasNode()) {
+									long ref = git.nextRef();
+									out.format("    <nd ref='%d'/>%n", -ref);
+								}
+							}
+							out.format("    <tag k='seamark:type' v='%s'/>%n", type);
+							writeAtts(feature, type);
+							out.format("  </way>%n");
+						}
+					} else if (feature.geom.prim == Pflag.AREA) {
+						GeomIterator git = map.new GeomIterator(feature.geom);
+						while (git.hasComp()) {
+							git.nextComp();
+							while (git.hasEdge()) {
+								git.nextEdge();
+								while (git.hasNode()) {
+									long ref = git.nextRef();
+									Snode node = map.nodes.get(ref);
+									if (!done.contains(ref)) {
+										out.format("  <node id='%d' lat='%.8f' lon='%.8f' version='1'/>%n", -ref, Math.toDegrees(node.lat), Math.toDegrees(node.lon));
+										done.add(ref);
+									}
+								}
+							}
+						}
+						git = map.new GeomIterator(feature.geom);
+						while (git.hasComp()) {
+							long ref = git.nextComp();
+							out.format("  <way id='%d' version='1'>%n", -ref);
+							while (git.hasEdge()) {
+								git.nextEdge();
+								while (git.hasNode()) {
+									ref = git.nextRef();
+									out.format("    <nd ref='%d'/>%n", -ref);
+								}
+							}
+							out.format("  </way>%n");
+						}
+						out.format("  <relation id='%d' version='1'>%n", -map.ref++);
+						out.format("    <tag k='type' v='multipolygon'/>%n");
+						git = map.new GeomIterator(feature.geom);
+						int outers = feature.geom.outers;
+						while (git.hasComp()) {
+							long ref = git.nextComp();
+							if (outers-- > 0) {
+								out.format("    <member type='way' ref='%d' role='outer'/>%n", -ref);
+							} else {
+								out.format("    <member type='way' ref='%d' role='inner'/>%n", -ref);
+							}
+						}
+						out.format("    <tag k='seamark:type' v='%s'/>%n", type);
+						writeAtts(feature, type);
+						out.format("  </relation>%n");
+					}
+				}
+			}
+		}
+		out.println("</osm>\n");
+		out.close();
+		System.err.println("Finished");
+	}
+	
+	static void writeAtts(Feature feature, String type) {
+		for (Map.Entry<Att, AttVal<?>> item : feature.atts.entrySet()) {
+			String attstr = S57att.stringAttribute(item.getKey());
+			String valstr = S57val.stringValue(item.getValue());
+			if (!attstr.isEmpty() && !valstr.isEmpty())
+				out.format("    <tag k='seamark:%s:%s' v='%s'/>%n", type, attstr, valstr);
+		}
+		for (Obj obj : feature.objs.keySet()) {
+			ObjTab tab = feature.objs.get(obj);
+			for (int ix : tab.keySet()) {
+				type = S57obj.stringType(obj);
+				AttMap atts = tab.get(ix);
+				for (Map.Entry<Att, AttVal<?>> item : atts.entrySet()) {
+					String attstr = S57att.stringAttribute(item.getKey());
+					String valstr = S57val.stringValue(item.getValue());
+					if (!attstr.isEmpty() && !valstr.isEmpty()) {
+						if ((ix == 0) && (tab.size() == 1)) {
+							out.format("    <tag k='seamark:%s:%s' v='%s'/>%n", type, attstr, valstr);
+						} else {
+							out.format("    <tag k='seamark:%s:%d:%s' v='%s'/>%n", type, ix + 1, attstr, valstr);
+						}
+					}
+				}
+			}
+		}
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/js57toosm/src/s57
===================================================================
--- /applications/editors/josm/plugins/seachart/js57toosm/src/s57	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/js57toosm/src/s57	(revision 30894)
@@ -0,0 +1,1 @@
+link ../../src/s57
Index: /applications/editors/josm/plugins/seachart/jsearch/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jsearch/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jsearch/build.xml	(revision 30894)
@@ -0,0 +1,29 @@
+<project name="jsearch" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jsearch.jar"/>
+  <property name="ant.build.javac.target" value="1.7"/>
+  <property name="ant.build.javac.source" value="1.7"/>
+            
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}" encoding="UTF-8" />
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jsearch.Jsearch"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Extract.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Extract.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Extract.java	(revision 30894)
@@ -0,0 +1,254 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jsearch;
+
+import java.io.*;
+import java.util.*;
+
+import jsearch.Jsearch.MapBB;
+
+public class Extract {
+
+	public static ArrayList<String> extractData(String filename, MapBB box) throws IOException {
+
+		HashMap<Long, Long> nodes = new HashMap<Long, Long>();
+		HashMap<Long, Long> ways = new HashMap<Long, Long>();
+		HashMap<Long, Long> rels = new HashMap<Long, Long>();
+
+		ArrayList<String> buf = new ArrayList<String>();
+		BufferedReader in;
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+		boolean inRel = false;
+		
+		double lat = 0;
+		double lon = 0;
+		long id = 0;
+		ArrayList<Long> refs = null;
+		boolean needed = false;
+		String ln;
+
+		in = new BufferedReader(new FileReader(filename));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						} else if (token.matches("^lat=.+")) {
+							lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					if ((lat > box.minlat) && (lat <= box.maxlat) && (lon > box.minlon) && (lon <= box.maxlon)) {
+						nodes.put(id, null);
+					}
+					if (!ln.contains("/>")) {
+						inNode = true;
+					}
+				} else if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+								refs.add(ref);
+								if (nodes.containsKey(ref)) {
+									needed = true;
+								}
+							}
+						}
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+						if (needed) {
+							for (Long nd : refs) {
+								nodes.put(nd, null);
+							}
+							ways.put(id, null);
+						}
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					refs = new ArrayList<Long>();
+					needed = false;
+					if (!ln.contains("/>")) {
+						inWay = true;
+					}
+				} else if (inRel) {
+					if (ln.contains("<member")) {
+						String type = "";
+						String role = "";
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+							} else if (token.matches("^type=.+")) {
+								type = (token.split("[\"\']")[1]);
+							} else if (token.matches("^role=.+")) {
+								role = (token.split("[\"\']")[1]);
+							}
+						}
+						if ((role.equals("outer") || role.equals("inner")) && type.equals("way")) {
+							needed = ways.containsKey(ref);
+							refs.add(ref);
+						}
+					}
+					if (ln.contains("</relation")) {
+						inRel = false;
+						if (needed) {
+							for (Long way : refs) {
+								ways.put(way, null);
+							}
+							rels.put(id, null);
+						}
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					refs = new ArrayList<Long>();
+					needed = false;
+					if (!ln.contains("/>")) {
+						inRel = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+			}
+		}
+		in.close();
+		
+		in = new BufferedReader(new FileReader(filename));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inWay) {
+					if (ln.contains("<nd")) {
+						long ref = 0;
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								ref = Long.parseLong(token.split("[\"\']")[1]);
+								if (needed) {
+									nodes.put(ref, null);
+								}
+							}
+						}
+					}
+					if (ln.contains("</way")) {
+						inWay = false;
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (!ln.contains("/>")) {
+						needed = ways.containsKey(id);
+						inWay = true;
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					break;
+				}
+			} else if (ln.contains("<osm")) {
+				inOsm = true;
+			}
+		}
+		in.close();
+		
+		in = new BufferedReader(new FileReader(filename));
+		buf.add("<?xml version='1.0' encoding='UTF-8'?>");
+		buf.add("<osm version='0.6' upload='false' generator='Jrender'>");
+		buf.add(String.format("<bounds minlat='%.8f' minlon='%.8f' maxlat='%.8f' maxlon='%.8f'/>", box.minlat, box.minlon, box.maxlat, box.maxlon));
+		while ((ln = in.readLine()) != null) {
+			if (inOsm) {
+				if (inNode) {
+					buf.add(ln);
+					if (ln.contains("</node")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<node")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (nodes.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inNode = true;
+						}
+					}
+				} else if (inWay) {
+					buf.add(ln);
+					if (ln.contains("</way")) {
+						inWay = false;
+					}
+				} else if (ln.contains("<way")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (ways.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inWay = true;
+						}
+					}
+				} else if (inRel) {
+					buf.add(ln);
+					if (ln.contains("</relation")) {
+						inRel = false;
+					}
+				} else if (ln.contains("<relation")) {
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						}
+					}
+					if (rels.containsKey(id)) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inRel = true;
+						}
+					}
+				} else if (ln.contains("</osm")) {
+					inOsm = false;
+					buf.add(ln);
+					break;
+				}
+			} else {
+				if (ln.contains("<osm")) {
+					inOsm = true;
+				}
+			}
+		}
+		in.close();
+		
+		return buf;
+	}
+}
Index: /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Jsearch.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Jsearch.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jsearch/src/jsearch/Jsearch.java	(revision 30894)
@@ -0,0 +1,320 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jsearch;
+
+import java.io.*;
+import java.util.*;
+
+public class Jsearch {
+	public static class MapBB {
+		public double minlat;
+		public double minlon;
+		public double maxlat;
+		public double maxlon;
+	}
+	
+	public static void main(String[] args) throws Exception {
+		HashMap<Long, Boolean> cnodes = new HashMap<Long, Boolean>();
+		HashMap<Long, Boolean> cways = new HashMap<Long, Boolean>();
+		HashMap<Long, Boolean> crels = new HashMap<Long, Boolean>();
+		HashMap<Long, Boolean> nnodes = new HashMap<Long, Boolean>();
+		HashMap<Long, Boolean> nways = new HashMap<Long, Boolean>();
+		HashMap<Long, Boolean> nrels = new HashMap<Long, Boolean>();
+		String dir = args[0];
+		long id = 0;
+		HashMap<Integer, Boolean> z9s = new HashMap<Integer, Boolean>();
+		HashMap<Integer, Boolean> z10s = new HashMap<Integer, Boolean>();
+		HashMap<Integer, Boolean> z11s = new HashMap<Integer, Boolean>();
+		HashMap<Integer, Boolean> z12s = new HashMap<Integer, Boolean>();
+		BufferedReader in = new BufferedReader(new FileReader(dir + "diffs"));
+		String ln;
+		while ((ln = in.readLine()) != null) {
+			for (String token : ln.split("[ ]+")) {
+				if (token.matches("^id=.+")) {
+					id = Long.parseLong(token.split("[\"\']")[1]);
+					break;
+				}
+			}
+			if (ln.matches("^<.+")) {
+				if (ln.contains("<node")) {
+					cnodes.put(id, true);
+				} else if (ln.contains("<way")) {
+					cways.put(id, true);
+				} else if (ln.contains("<relation")) {
+					crels.put(id, true);
+				}
+			} else if (ln.matches("^>.+")) {
+				if (ln.contains("<node")) {
+					nnodes.put(id, true);
+				} else if (ln.contains("<way")) {
+					nways.put(id, true);
+				} else if (ln.contains("<relation")) {
+					nrels.put(id, true);
+				}
+			}
+		}
+		in.close();
+		
+		boolean next = false;
+		do {
+			if (next) {
+				in = new BufferedReader(new FileReader(dir + "next.osm"));
+			} else {
+				in = new BufferedReader(new FileReader(dir + "world.osm"));
+			}
+			boolean inOsm = false;
+			boolean inNode = false;
+			boolean inWay = false;
+			boolean inRel = false;
+			ArrayList<String> buf = new ArrayList<String>();
+			while ((ln = in.readLine()) != null) {
+				if (inOsm) {
+					if (inNode) {
+						if (ln.contains("</node")) {
+							buf.add(ln);
+							inNode = false;
+						}
+					} else if (ln.contains("<node")) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inNode = true;
+						}
+					} else if (inWay) {
+						if (ln.contains("<nd")) {
+							buf.add(ln);
+						}
+						if (ln.contains("</way")) {
+							buf.add(ln);
+							inWay = false;
+						}
+					} else if (ln.contains("<way")) {
+						buf.add(ln);
+						if (!ln.contains("/>")) {
+							inWay = true;
+						}
+					} else if (inRel) {
+						if (ln.contains("<member")) {
+							String type = "";
+							String role = "";
+							long ref = 0;
+							for (String token : ln.split("[ ]+")) {
+								if (token.matches("^ref=.+")) {
+									ref = Long.parseLong(token.split("[\"\']")[1]);
+								} else if (token.matches("^type=.+")) {
+									type = (token.split("[\"\']")[1]);
+								} else if (token.matches("^role=.+")) {
+									role = (token.split("[\"\']")[1]);
+								}
+							}
+							if ((role.equals("outer") || role.equals("inner")) && type.equals("way")) {
+								if (next) {
+									nways.put(ref, true);
+								} else {
+									cways.put(ref, true);
+								}
+							}
+						}
+						if (ln.contains("</relation")) {
+							inRel = false;
+						}
+					} else if (ln.contains("<relation")) {
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^id=.+")) {
+								id = Long.parseLong(token.split("[\"\']")[1]);
+							}
+						}
+						if (((next && nrels.containsKey(id)) || (!next && crels.containsKey(id))) && !ln.contains("/>")) {
+							inRel = true;
+						}
+					} else if (ln.contains("</osm")) {
+						buf.add(ln);
+						inOsm = false;
+						break;
+					}
+				} else if (ln.contains("<osm")) {
+					buf.add(ln);
+					inOsm = true;
+				}
+			}
+			in.close();
+			inOsm = false;
+			inWay = false;
+			for (String line : buf) {
+				ln = line;
+				if (inOsm) {
+					if (inWay) {
+						if (ln.contains("<nd")) {
+							for (String token : ln.split("[ ]+")) {
+								if (token.matches("^ref=.+")) {
+									id = Long.parseLong(token.split("[\"\']")[1]);
+								}
+							}
+							if (next) {
+								nnodes.put(id, true);
+							} else {
+								cnodes.put(id, true);
+							}
+						}
+						if (ln.contains("</way")) {
+							inWay = false;
+						}
+					} else if (ln.contains("<way")) {
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^id=.+")) {
+								id = Long.parseLong(token.split("[\"\']")[1]);
+							}
+						}
+						if (((next && nways.containsKey(id)) || (!next && cways.containsKey(id))) && !ln.contains("/>")) {
+							inWay = true;
+						}
+					} else if (ln.contains("</osm")) {
+						inOsm = false;
+						break;
+					}
+				} else if (ln.contains("<osm")) {
+					inOsm = true;
+				}
+			}
+			for (String line : buf) {
+				ln = line;
+				if (ln.contains("<node")) {
+					Double lat = 0.0;
+					Double lon = 0.0;
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							id = Long.parseLong(token.split("[\"\']")[1]);
+						} else if (token.matches("^lat=.+")) {
+							lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					if ((next && nnodes.containsKey(id)) || (!next && cnodes.containsKey(id))) {
+						int xtile = lon2xtile(lon, 12);
+						int ytile = lat2ytile(lat, 12);
+						z9s.put(((xtile / 8) * 512) + (ytile / 8), true);
+						z10s.put(((xtile / 4) * 1024) + (ytile / 4), true);
+						z11s.put(((xtile / 2) * 2048) + (ytile / 2), true);
+						for (int x = xtile - 1; x <= xtile + 1; x++) {
+							for (int y = ytile - 1; y <= ytile + 1; y++) {
+								if ((y >= 0) && (y <= 4095))
+									z12s.put((((x < 0) ? 4095 : (x > 4095) ? 0 : x) * 4096) + y, true);
+							}
+						}
+					}
+				}
+			}
+			next = !next;
+		} while (next);
+		
+		for (int t : z9s.keySet()) {
+			int x = (t / 512) * 8;
+			int y = (t % 512) * 8;
+			MapBB bb = new MapBB();
+			bb.minlon = tile2lon((x + 4094) % 4096, 12);
+			bb.maxlon = tile2lon((x + 10) % 4095, 12);
+			bb.minlat = tile2lat(Math.min((y + 10), 4095), 12);
+			bb.maxlat = tile2lat(Math.max((y - 2), 0), 12);
+			ArrayList<String> ext = Extract.extractData(dir + "next.osm", bb);
+			PrintStream out = new PrintStream(dir + "tmp/" + (t / 512) + "-" + (t % 512) + "-9.osm");
+			for (String line : ext) {
+				out.println(line);
+			}
+			out.close();
+		}
+		for (int t : z10s.keySet()) {
+			int x = (t / 1024) * 4;
+			int y = (t % 1024) * 4;
+			MapBB bb = new MapBB();
+			bb.minlon = tile2lon((x + 4094) % 4096, 12);
+			bb.maxlon = tile2lon((x + 6) % 4095, 12);
+			bb.minlat = tile2lat(Math.min((y + 6), 4095), 12);
+			bb.maxlat = tile2lat(Math.max((y - 2), 0), 12);
+			ArrayList<String> ext = Extract.extractData(dir + "tmp/" + ((t / 1024) / 2) + "-" + ((t % 1024) / 2) + "-9.osm", bb);
+			PrintStream out = new PrintStream(dir + "tmp/" + (t / 1024) + "-" + (t % 1024) + "-10.osm");
+			for (String line : ext) {
+				out.println(line);
+			}
+			out.close();
+		}
+		for (int t : z11s.keySet()) {
+			int x = (t / 2048) * 2;
+			int y = (t % 2048) * 2;
+			MapBB bb = new MapBB();
+			bb.minlon = tile2lon((x + 4094) % 4096, 12);
+			bb.maxlon = tile2lon((x + 4) % 4095, 12);
+			bb.minlat = tile2lat(Math.min((y + 4), 4095), 12);
+			bb.maxlat = tile2lat(Math.max((y - 2), 0), 12);
+			ArrayList<String> ext = Extract.extractData(dir + "tmp/" + ((t / 2048) / 2) + "-" + ((t % 2048) / 2) + "-10.osm", bb);
+			String z11nam = dir + "tmp/" + (t / 2048) + "-" + (t % 2048) + "-11.osm";
+			PrintStream out = new PrintStream(z11nam);
+			for (String line : ext) {
+				out.println(line);
+			}
+			out.close();
+			for (int i = (x+4095)%4096; i < x+3; i = (i+1)%4096) {
+				for (int j = Math.max(y-1, 0); j < y+3; j = Math.min(j+1, 4095)) {
+					if (z12s.containsKey(i*4096+j)) {
+						z12s.remove(i*4096+j);
+						bb = new MapBB();
+						bb.minlon = tile2lon((i + 4095) % 4096, 12);
+						bb.maxlon = tile2lon((i + 2) % 4095, 12);
+						bb.minlat = tile2lat(Math.min((j + 2), 4095), 12);
+						bb.maxlat = tile2lat(Math.max((j - 1), 0), 12);
+						ext = Extract.extractData(z11nam, bb);
+						out = new PrintStream(dir + "tmp/" + i + "-" + j + "-12.osm");
+						for (String line : ext) {
+							out.println(line);
+						}
+						out.close();
+					}
+				}
+			}
+		}
+		
+		System.exit(0);
+	}
+
+	static int lon2xtile(double lon, int zoom) {
+		int xtile = (int) Math.floor((lon + 180) / 360 * (1 << zoom));
+		if (xtile < 0)
+			xtile = 0;
+		if (xtile >= (1 << zoom))
+			xtile = ((1 << zoom) - 1);
+		return (xtile);
+	}
+
+	static int lat2ytile(double lat, int zoom) {
+		int ytile = (int) Math.floor((1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * (1 << zoom));
+		if (ytile < 0)
+			ytile = 0;
+		if (ytile >= (1 << zoom))
+			ytile = ((1 << zoom) - 1);
+		return (ytile);
+	}
+
+	MapBB tile2bb(final int x, final int y, final int zoom) {
+		MapBB bb = new MapBB();
+		bb.maxlat = tile2lat(y, zoom);
+		bb.minlat = tile2lat(y + 1, zoom);
+		bb.minlon = tile2lon(x, zoom);
+		bb.maxlon = tile2lon(x + 1, zoom);
+		return bb;
+	}
+
+	static double tile2lon(int x, int z) {
+		return x / Math.pow(2.0, z) * 360.0 - 180;
+	}
+
+	static double tile2lat(int y, int z) {
+		double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
+		return Math.toDegrees(Math.atan(Math.sinh(n)));
+	}
+}
Index: /applications/editors/josm/plugins/seachart/jseas/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jseas/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jseas/build.xml	(revision 30894)
@@ -0,0 +1,27 @@
+<project name="jseas" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jseas.jar"/>
+
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}"/>
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jseas.Jseas"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jseas/src/jseas/Jseas.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jseas/src/jseas/Jseas.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jseas/src/jseas/Jseas.java	(revision 30894)
@@ -0,0 +1,269 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jseas;
+
+import java.io.*;
+import java.util.*;
+
+public class Jseas {
+
+	static class Node {
+		public double lat;
+		public double lon;
+
+		public Node() {
+			lat = 0.0;
+			lon = 0.0;
+		}
+
+		public Node(double iLat, double iLon) {
+			lat = iLat;
+			lon = iLon;
+		}
+	}
+	
+	static class Sea {
+		public String name;
+		public int level;
+		public int buoyage;
+		public boolean system;
+		public double minlat;
+		public double minlon;
+		public double maxlat;
+		public double maxlon;
+		public ArrayList<Node> nodes;
+		
+		public Sea() {
+			name = "";
+			level = 0;
+			buoyage = -1;
+			system = true;
+			minlat = 90.0;
+			minlon = 180.0;
+			maxlat = -90.0;
+			maxlon = -180.0;
+			nodes = new ArrayList<Node>();
+		}
+	}
+	
+	static class SeaInfo {
+		public String name;
+		public int buoyage;
+		public boolean system;
+		public boolean wmm;
+		public double magvar;
+		public SeaInfo() {
+			name = "";
+			buoyage = -1;
+			system = true;
+			wmm = false;
+		}
+	}
+	
+	static HashMap<Long, Node> nodes = new HashMap<Long, Node>();
+	static ArrayList<Sea> seas = new ArrayList<Sea>();
+
+	public static void main(String[] args) throws IOException {
+
+		if (args.length < 1) {
+			System.err.println("Usage: java -jar jseas.jar seas_OSM_file");
+			System.exit(-1);
+		}
+		BufferedReader inf = new BufferedReader(new FileReader(args[0]));
+		makeSeas(inf);
+		inf.close();
+		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));		
+		PrintStream out = System.out;
+
+		String ln;
+		out.println("Enter lat,lon:");
+		while (true) {
+			ln = in.readLine();
+			String token[] = ln.split(",");
+			if ((token.length == 2) && !token[0].isEmpty() && !token[1].isEmpty()) {
+				try {
+					Double lat = Double.parseDouble(token[0]);
+					Double lon = Double.parseDouble(token[1]);
+					SeaInfo info = getSeaInfo(lat, lon);
+					if (info.name.isEmpty())
+						out.println("No match");
+					else
+						out.println(info.name);
+					if (info.buoyage >= 0)
+						out.println("Buoyage: " + info.buoyage);
+					if (info.wmm) {
+						System.out.println("Magnetic Var: " + info.magvar);
+					}
+				} catch (Exception e) {
+					out.println("Error! Enter lat,lon:");
+				}
+			} else {
+				out.println("Error! Enter lat,lon:");
+			}
+		}
+	}
+	
+	public static void makeSeas(BufferedReader inf) throws NumberFormatException, IOException {
+		Sea sea = null;
+		boolean inOsm = false;
+		boolean inNode = false;
+		boolean inWay = false;
+
+		String ln;
+		while ((ln = inf.readLine()) != null) {
+			if (inOsm) {
+				if (ln.contains("</osm")) {
+					inOsm = false;
+				} else if (inNode) {
+					if (ln.contains("</node")) {
+						inNode = false;
+					}
+				} else if (inWay) {
+					if (ln.contains("</way")) {
+						inWay = false;
+						seas.add(sea);
+					} else if (ln.contains("<nd")) {
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^ref=.+")) {
+								Long ref = Long.parseLong(token.split("[\"\']")[1]);
+								Node node = nodes.get(ref);
+								sea.nodes.add(node);
+								if (node.lat < sea.minlat) sea.minlat = node.lat;
+								if (node.lon < sea.minlon) sea.minlon = node.lon;
+								if (node.lat > sea.maxlat) sea.maxlat = node.lat;
+								if (node.lon > sea.maxlon) sea.maxlon = node.lon;
+							}
+						}
+					} else if (ln.contains("<tag")) {
+						String key = "";
+						for (String token : ln.split("[ ]+")) {
+							if (token.matches("^k=.+")) {
+								key = token.split("[\"\']")[1];
+							} else if (token.matches("^v=.+")) {
+								switch (key) {
+								case "seamark:name":
+									sea.name = ln.split("v=[\"\']")[1].split("[\"\']")[0];
+									break;
+								case "seamark:sea_area:tier":
+									sea.level = Integer.parseInt(token.split("[\"\']")[1]);
+									break;
+								case "seamark:navigational_system:orientation":
+									sea.buoyage = Integer.parseInt(token.split("[\"\']")[1]);
+									break;
+								case "seamark:navigational_system:system":
+									String val = token.split("[\"\']")[1];
+									switch (val) {
+									case "iala-a":
+									case "cevni":
+									case "riwr":
+										sea.system = true;
+										break;
+									case "iala-b":
+									case "bniwr2":
+									case "bniwr":
+									case "ppwbc":
+										sea.system = false;
+										break;
+										default:
+											sea.system = true;
+									}
+									break;
+								}
+							}
+						}
+					}
+				} else if (ln.contains("<node")) {
+					inNode = true;
+					Node node = new Node();
+					for (String token : ln.split("[ ]+")) {
+						if (token.matches("^id=.+")) {
+							long id = Long.parseLong(token.split("[\"\']")[1]);
+							nodes.put(id, node);
+						} else if (token.matches("^lat=.+")) {
+							node.lat = Double.parseDouble(token.split("[\"\']")[1]);
+						} else if (token.matches("^lon=.+")) {
+							node.lon = Double.parseDouble(token.split("[\"\']")[1]);
+						}
+					}
+					if (ln.contains("/>")) {
+						inNode = false;
+					}
+				} else if (ln.contains("<way")) {
+					inWay = true;
+					sea = new Sea();
+					if (ln.contains("/>")) {
+						inWay = false;
+					}
+				}
+			} else {
+				if (ln.contains("<osm")) {
+					inOsm = true;
+				}
+			}
+		}
+	}
+	
+	public static SeaInfo getSeaInfo(double lat, double lon) {
+		SeaInfo info = new SeaInfo();
+		String name0 = "";
+		String name1 = "";
+		String name2 = "";
+		for (Sea tsea : seas) {
+			if ((lat >= tsea.minlat) && (lat <= tsea.maxlat) && (lon >= tsea.minlon) && (lon <= tsea.maxlon) && !tsea.name.isEmpty()) {
+				int cross = 0;
+				Node last = tsea.nodes.get(0);
+				for (Node next : tsea.nodes) {
+					if (((last.lon < lon) && (next.lon > lon)) || ((last.lon > lon) && (next.lon < lon)) && ((last.lat > lat) || (next.lat > lat))) {
+						if ((last.lat + ((lon - last.lon) * ((next.lat - last.lat) / (next.lon - last.lon)))) > lat) cross++;
+					}
+					last = next;
+				}
+				if ((cross % 2) == 1) {
+					switch (tsea.level) {
+					case 0:
+						name0 = tsea.name;
+						break;
+					case 1:
+						name1 = tsea.name;
+						break;
+					case 2:
+						name2 = tsea.name;
+						 info.buoyage = tsea.buoyage;
+						break;
+					}
+				}
+			}
+		}
+		if (!name2.isEmpty()) {
+			if (!name0.isEmpty())
+				name0 = ", " + name0;
+			name0 = name2 + name0;
+		}
+		if (!name1.isEmpty()) {
+			if (!name0.isEmpty())
+				name0 = ", " + name0;
+			name0 = name1 + name0;
+		}
+		info.name = name0;
+		try {
+			GregorianCalendar cal = new GregorianCalendar();
+			double date = cal.get(Calendar.YEAR) + (cal.get(Calendar.DAY_OF_YEAR) / 365.25);
+			Process p = Runtime.getRuntime().exec("wmm" + " " + lat + " " + lon + " " + date);
+			BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
+			String s = stdInput.readLine();
+			info.magvar = Double.parseDouble(s);
+			info.wmm = true;
+		} catch (Exception e) {
+			// No mag var
+		}
+		return info;
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/jtile/build.xml
===================================================================
--- /applications/editors/josm/plugins/seachart/jtile/build.xml	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jtile/build.xml	(revision 30894)
@@ -0,0 +1,34 @@
+<project name="jtile" default="dist" basedir=".">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="jarfile" location="./jtile.jar"/>
+  <property name="ant.build.javac.target" value="1.7"/>
+  <property name="ant.build.javac.source" value="1.7"/>
+  <property name="batik.dir" value="/usr/local/bin/batik-1.7/"/>
+  <path id="classpath">
+    <fileset dir="${batik.dir}" includes="**/batik*.jar"/>
+  </path>
+            
+  <target name="init">
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="compile" depends="init" description="compile the source " >
+    <javac includeantruntime="false" srcdir="${src}" destdir="${build}" classpathref="classpath" encoding="UTF-8" />
+  </target>
+
+  <target name="dist" depends="compile" description="generate the distribution" >
+    <jar jarfile="${jarfile}" basedir="${build}" >
+      <manifest>
+        <attribute name="Main-Class" value="jtile.Jtile"/>
+        <attribute name="Class-Path" value="$jarfile"/>
+      </manifest>
+      <zipgroupfileset dir="${batik.dir}" includes="**/batik-*.jar" />
+    </jar>
+  </target>
+
+  <target name="clean" description="clean up" >
+    <delete dir="${build}"/>
+    <delete file="${jarfile}"/>
+  </target>
+</project>
Index: /applications/editors/josm/plugins/seachart/jtile/src/jtile/Jtile.java
===================================================================
--- /applications/editors/josm/plugins/seachart/jtile/src/jtile/Jtile.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/jtile/src/jtile/Jtile.java	(revision 30894)
@@ -0,0 +1,171 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package jtile;
+
+import java.awt.Rectangle;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.PNGTranscoder;
+
+public class Jtile {
+
+	static PNGTranscoder trans;
+	static String srcdir;
+	static String dstdir;
+	static int xtile;
+	static int ytile;
+	static int zoom;
+	static ArrayList<String> send;
+	static HashMap<String, Boolean> deletes;
+
+	static void tile(int z, int dxy, int xn, int yn) throws Exception {
+
+		trans = new PNGTranscoder();
+		trans.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(256));
+		trans.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, new Float(256));
+		trans.addTranscodingHint(PNGTranscoder.KEY_AOI, new Rectangle(256+(xn*dxy), 256+(yn*dxy), dxy, dxy));
+
+		String svgURI = new File(srcdir + xtile + "-" + ytile + "-" + z + ".svg").toURI().toURL().toString();
+		TranscoderInput input = new TranscoderInput(svgURI);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		TranscoderOutput output = new TranscoderOutput(bos);
+		try {
+			trans.transcode(input, output);
+			if (bos.size() > 446) {
+				int scale = (int) Math.pow(2, z - 12);
+				int xdir = (scale * xtile) + xn;
+				int ynam = (scale * ytile) + yn;
+				String dstnam = dstdir + z + "/" + xdir + "/" + ynam + ".png";
+				deletes.remove(dstnam);
+				send.add("put " + dstnam + " cache/tiles-" + z + "-" + xdir + "-" + ynam + ".png");
+				File ofile = new File(dstdir + "/" + z + "/" + xdir + "/");
+				ofile.mkdirs();
+				OutputStream ostream = new FileOutputStream(dstdir + "/" + z + "/" + xdir + "/" + ynam + ".png");
+				bos.writeTo(ostream);
+				ostream.flush();
+				ostream.close();
+				if (send.size() > 10) {
+					PrintWriter writer = new PrintWriter(srcdir + z + "-" + xdir + "-" + ynam + ".send", "UTF-8");
+					for (String str : send) {
+						writer.println(str);
+					}
+					writer.close();
+					send = new ArrayList<String>();
+				}
+			}
+		} catch (Exception e) {
+			System.err.println("TranscoderException: " + z + " " + xn + " " + yn);
+		}
+		if ((z < 18) && ((z < 16) || (bos.size() > 446))) {
+			for (int x = 0; x < 2; x++) {
+				for (int y = 0; y < 2; y++) {
+					tile((z + 1), (dxy / 2), (xn * 2 + x), (yn * 2 + y));
+				}
+			}
+		}
+	}
+
+	static void tile91011() throws Exception {
+
+		trans = new PNGTranscoder();
+		trans.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(256));
+		trans.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, new Float(256));
+		trans.addTranscodingHint(PNGTranscoder.KEY_AOI, new Rectangle(512, 512, 256 * (int) (Math.pow(2, 12 - zoom)), 256 * (int) (Math.pow(2, 12 - zoom))));
+
+		String svgURI = new File(srcdir + xtile + "-" + ytile + "-" + zoom + ".svg").toURI().toURL().toString();
+		TranscoderInput input = new TranscoderInput(svgURI);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		TranscoderOutput output = new TranscoderOutput(bos);
+		try {
+			trans.transcode(input, output);
+			String dstnam = dstdir + zoom + "/" + xtile + "/" + ytile + ".png";
+			if (bos.size() > 446) {
+				send.add("put " + dstnam + " cache/tiles-" + zoom + "-" + xtile + "-" + ytile + ".png");
+				File ofile = new File(dstdir + "/" + zoom + "/" + xtile + "/");
+				ofile.mkdirs();
+				OutputStream ostream = new FileOutputStream(dstdir + "/" + zoom + "/" + xtile + "/" + ytile + ".png");
+				bos.writeTo(ostream);
+				ostream.flush();
+				ostream.close();
+			} else {
+				File old = new File(dstnam);
+				if (old.exists()) {
+					old.delete();
+					deletes.put(dstnam, true);
+				}
+			}
+		} catch (Exception e) {
+			System.err.println("TranscoderException");
+		}
+	}
+
+	static void clean(int z, int xn, int yn) throws Exception {
+		
+		int scale = (int) Math.pow(2, z - 12);
+		int xdir = (scale * xtile) + xn;
+		int ynam = (scale * ytile) + yn;
+		String delnam = dstdir + z + "/" + xdir + "/" + ynam + ".png";
+		File delfile = new File(delnam);
+		if (delfile.exists()) {
+			deletes.put(delnam, true);
+			delfile.delete();
+		}
+		if ((z < 18)) {
+			for (int x = 0; x < 2; x++) {
+				for (int y = 0; y < 2; y++) {
+					clean((z + 1), (xn * 2 + x), (yn * 2 + y));
+				}
+			}
+		}
+	}
+	
+	public static void main(String[] args) throws Exception {
+		srcdir = args[0];
+		dstdir = args[1];
+		zoom = Integer.parseInt(args[2]);
+		xtile = Integer.parseInt(args[3]);
+		ytile = Integer.parseInt(args[4]);
+		send = new ArrayList<String>();
+		deletes = new HashMap<String, Boolean>();
+		if (zoom == 12) {
+			clean(12, 0, 0);
+			tile(12, 256, 0, 0);
+		} else {
+			tile91011();
+		}
+		if ((send.size() + deletes.size()) > 0) {
+			PrintWriter writer = new PrintWriter(srcdir + zoom + "-" + xtile + "-" + ytile + ".send", "UTF-8");
+			for (String str : send) {
+				writer.println(str);
+			}
+			for (String del : deletes.keySet()) {
+				writer.println("rm " + del);
+			}
+			writer.close();
+		}
+		if (zoom == 12) {
+			for (int zz = 12; zz <= 18; zz++) {
+				(new File(srcdir + xtile + "-" + ytile + "-" + zz + ".svg")).delete();
+			}
+		} else {
+			(new File(srcdir + xtile + "-" + ytile + "-" + zoom + ".svg")).delete();
+		}
+		System.exit(0);
+	}
+	
+}
Index: /applications/editors/josm/plugins/seachart/src/render/ChartContext.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/render/ChartContext.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/render/ChartContext.java	(revision 30894)
@@ -0,0 +1,19 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package render;
+
+import java.awt.geom.Point2D;
+
+import s57.S57map.*;
+
+public interface ChartContext {
+	Point2D getPoint(Snode coord);
+	double mile(Feature feature);
+}
Index: /applications/editors/josm/plugins/seachart/src/render/Renderer.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/render/Renderer.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/render/Renderer.java	(revision 30894)
@@ -0,0 +1,614 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package render;
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import java.util.*;
+
+import s57.S57val.*;
+import s57.S57map;
+import s57.S57map.*;
+import symbols.Areas;
+import symbols.Symbols;
+import symbols.Symbols.*;
+
+public class Renderer {
+
+	public static final double symbolScale[] = { 256.0, 128.0, 64.0, 32.0, 16.0, 8.0, 4.0, 2.0, 1.0, 0.61, 0.372, 0.227, 0.138, 0.0843, 0.0514, 0.0313, 0.0191, 0.0117, 0.007 };
+
+	public enum LabelStyle { NONE, RRCT, RECT, ELPS, CIRC, VCLR, PCLR, HCLR }
+
+	static ChartContext context;
+	static S57map map;
+	static double sScale;
+	static Graphics2D g2;
+	static int zoom;
+
+	public static void reRender(Graphics2D g, int z, double factor, S57map m, ChartContext c) {
+		g2 = g;
+		zoom = z;
+		context = c;
+		map = m;
+		sScale = symbolScale[zoom] * factor;
+		if (map != null) {
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
+			g2.setStroke(new BasicStroke(0, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
+			Rules.rules();
+		}
+	}
+
+	public static void symbol(Feature feature, Symbol symbol) {
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, null);
+	}
+	public static void symbol(Feature feature, Symbol symbol, Scheme scheme) {
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, null);
+	}
+	public static void symbol(Feature feature, Symbol symbol, Delta delta) {
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), null, delta);
+	}
+	public static void symbol(Feature feature, Symbol symbol, Scheme scheme, Delta delta) {
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), scheme, delta);
+	}
+	
+	public static void cluster(Feature feature, ArrayList<Symbol> symbols) {
+		Rectangle2D.Double bbox = null;
+		if (symbols.size() > 4) {
+			for (Instr instr : symbols.get(0)) {
+				if (instr.type == Form.BBOX) {
+					bbox = (Rectangle2D.Double) instr.params;
+					break;
+				}
+			}
+			if (bbox == null) return;
+		}
+		switch (symbols.size()) {
+		case 1:
+			symbol(feature, symbols.get(0), new Delta(Handle.CC, new AffineTransform()));
+			break;
+		case 2:
+			symbol(feature, symbols.get(0), new Delta(Handle.RC, new AffineTransform()));
+			symbol(feature, symbols.get(1), new Delta(Handle.LC, new AffineTransform()));
+			break;
+		case 3:
+			symbol(feature, symbols.get(0), new Delta(Handle.BC, new AffineTransform()));
+			symbol(feature, symbols.get(1), new Delta(Handle.TR, new AffineTransform()));
+			symbol(feature, symbols.get(2), new Delta(Handle.TL, new AffineTransform()));
+			break;
+		case 4:
+			symbol(feature, symbols.get(0), new Delta(Handle.BR, new AffineTransform()));
+			symbol(feature, symbols.get(1), new Delta(Handle.BL, new AffineTransform()));
+			symbol(feature, symbols.get(2), new Delta(Handle.TR, new AffineTransform()));
+			symbol(feature, symbols.get(3), new Delta(Handle.TL, new AffineTransform()));
+			break;
+		case 5:
+			symbol(feature, symbols.get(0), new Delta(Handle.BR, new AffineTransform()));
+			symbol(feature, symbols.get(1), new Delta(Handle.BL, new AffineTransform()));
+			symbol(feature, symbols.get(2), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(3), new Delta(Handle.TC, new AffineTransform()));
+			symbol(feature, symbols.get(4), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			break;
+		case 6:
+			symbol(feature, symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(1), new Delta(Handle.BC, new AffineTransform()));
+			symbol(feature, symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			symbol(feature, symbols.get(3), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(4), new Delta(Handle.TC, new AffineTransform()));
+			symbol(feature, symbols.get(5), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			break;
+		case 7:
+			symbol(feature, symbols.get(0), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2)));
+			symbol(feature, symbols.get(1), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(2), new Delta(Handle.CC, new AffineTransform()));
+			symbol(feature, symbols.get(3), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			symbol(feature, symbols.get(4), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2)));
+			symbol(feature, symbols.get(5), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2)));
+			symbol(feature, symbols.get(6), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2)));
+			break;
+		case 8:
+			symbol(feature, symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(0, -bbox.height/2)));
+			symbol(feature, symbols.get(1), new Delta(Handle.BL, AffineTransform.getTranslateInstance(0, -bbox.height/2)));
+			symbol(feature, symbols.get(2), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(3), new Delta(Handle.CC, new AffineTransform()));
+			symbol(feature, symbols.get(4), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			symbol(feature, symbols.get(5), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2)));
+			symbol(feature, symbols.get(6), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2)));
+			symbol(feature, symbols.get(7), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2)));
+			break;
+		case 9:
+			symbol(feature, symbols.get(0), new Delta(Handle.BR, AffineTransform.getTranslateInstance(-bbox.width/2, -bbox.height/2)));
+			symbol(feature, symbols.get(1), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -bbox.height/2)));
+			symbol(feature, symbols.get(2), new Delta(Handle.BL, AffineTransform.getTranslateInstance(bbox.width/2, -bbox.height/2)));
+			symbol(feature, symbols.get(3), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-bbox.width/2, 0)));
+			symbol(feature, symbols.get(4), new Delta(Handle.CC, new AffineTransform()));
+			symbol(feature, symbols.get(5), new Delta(Handle.LC, AffineTransform.getTranslateInstance(bbox.width/2, 0)));
+			symbol(feature, symbols.get(6), new Delta(Handle.TR, AffineTransform.getTranslateInstance(-bbox.width/2, bbox.height/2)));
+			symbol(feature, symbols.get(7), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, bbox.height/2)));
+			symbol(feature, symbols.get(8), new Delta(Handle.TL, AffineTransform.getTranslateInstance(bbox.width/2, bbox.height/2)));
+			break;
+		}
+	}
+
+	private static Rectangle2D.Double symbolSize(Symbol symbol) {
+		Symbol ssymb = symbol;
+		while (ssymb != null) {
+			for (Instr item : symbol) {
+				if (item.type == Form.BBOX) {
+					return (Rectangle2D.Double) item.params;
+				}
+				if (item.type == Form.SYMB) {
+					ssymb = ((SubSymbol) item.params).instr;
+					break;
+				}
+			}
+			if (ssymb == symbol)
+				break;
+		}
+		return null;
+	}
+
+	public static void lineSymbols(Feature feature, Symbol prisymb, double space, Symbol secsymb, Symbol tersymb, int ratio, Color col) {
+		if ((feature.geom.prim == Pflag.NOSP) || (feature.geom.prim == Pflag.POINT))
+			return;
+		Rectangle2D.Double prect = symbolSize(prisymb);
+		Rectangle2D.Double srect = symbolSize(secsymb);
+		Rectangle2D.Double trect = symbolSize(tersymb);
+		if (srect == null)
+			ratio = 0;
+		if (prect != null) {
+			double psize = Math.abs(prect.getY()) * sScale;
+			double ssize = (srect != null) ? Math.abs(srect.getY()) * sScale : 0;
+			double tsize = (trect != null) ? Math.abs(srect.getY()) * sScale : 0;
+			Point2D prev = new Point2D.Double();
+			Point2D next = new Point2D.Double();
+			Point2D curr = new Point2D.Double();
+			Point2D succ = new Point2D.Double();
+			boolean gap = true;
+			boolean piv = false;
+			double len = 0;
+			double angle = 0;
+			int stcount = ratio;
+			boolean stflag = false;
+			Symbol symbol = prisymb;
+			GeomIterator git = map.new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				boolean first = true;
+				while (git.hasEdge()) {
+					git.nextEdge();
+					while (git.hasNode()) {
+						prev = next;
+						next = context.getPoint(git.next());
+						angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX());
+						piv = true;
+						if (first) {
+							curr = succ = next;
+							gap = (space > 0);
+							stcount = ratio - 1;
+							symbol = prisymb;
+							len = gap ? psize * space * 0.5 : psize;
+							first = false;
+						} else {
+							while (curr.distance(next) >= len) {
+								if (piv) {
+									double rem = len;
+									double s = prev.distance(next);
+									double p = curr.distance(prev);
+									if ((s > 0) && (p > 0)) {
+										double n = curr.distance(next);
+										double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p);
+										double phi = Math.asin(p / len * Math.sin(theta));
+										rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta);
+									}
+									succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle)));
+									piv = false;
+								} else {
+									succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle)));
+								}
+								if (!gap) {
+									Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Scheme(col),
+											new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))));
+								}
+								if (space > 0)
+									gap = !gap;
+								curr = succ;
+								len = gap ? (psize * space) : (--stcount == 0) ? (stflag ? tsize : ssize) : psize;
+								if (stcount == 0) {
+									symbol = stflag ? tersymb : secsymb;
+									if (trect != null)
+										stflag = !stflag;
+									stcount = ratio;
+								} else {
+									symbol = prisymb;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public static void lineVector(Feature feature, LineStyle style) {
+		Path2D.Double p = new Path2D.Double();
+		p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		Point2D point;
+		GeomIterator git = map.new GeomIterator(feature.geom);
+		while (git.hasComp()) {
+			git.nextComp();
+			while (git.hasEdge()) {
+				git.nextEdge();
+				point = context.getPoint(git.next());
+				p.moveTo(point.getX(), point.getY());
+				while (git.hasNode()) {
+					point = context.getPoint(git.next());
+					p.lineTo(point.getX(), point.getY());
+				}
+			}
+		}
+		if (style.line != null) {
+			if (style.dash != null) {
+				float[] dash = new float[style.dash.length];
+				System.arraycopy(style.dash, 0, dash, 0, style.dash.length);
+				for (int i = 0; i < style.dash.length; i++) {
+					dash[i] *= (float) sScale;
+				}
+				g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, dash, 0));
+			} else {
+				g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
+			}
+			g2.setPaint(style.line);
+			g2.draw(p);
+		}
+		if (style.fill != null) {
+			g2.setPaint(style.fill);
+			g2.fill(p);
+		}
+	}
+	
+	public static void lineCircle(Feature feature, LineStyle style, double radius, UniHLU units) {
+		switch (units) {
+		case HLU_FEET:
+			radius /= 6076;
+			break;
+		case HLU_KMTR:
+			radius /= 1.852;
+			break;
+		case HLU_HMTR:
+			radius /= 18.52;
+			break;
+		case HLU_SMIL:
+			radius /= 1.15078;
+			break;
+		case HLU_NMIL:
+			break;
+		default:
+			radius /= 1852;
+			break;
+		}
+		radius *= context.mile(feature);
+		Symbol circle = new Symbol();
+		if (style.fill != null) {
+			circle.add(new Instr(Form.FILL, style.fill));
+			circle.add(new Instr(Form.RSHP, new Ellipse2D.Double(-radius,-radius,radius*2,radius*2)));
+		}
+		circle.add(new Instr(Form.FILL, style.line));
+		circle.add(new Instr(Form.STRK, new BasicStroke(style.width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, style.dash, 0)));
+		circle.add(new Instr(Form.ELPS, new Ellipse2D.Double(-radius,-radius,radius*2,radius*2)));
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, circle, 1, point.getX(), point.getY(), null, null);
+	}
+
+	
+	public static void fillPattern(Feature feature, BufferedImage image) {
+		Path2D.Double p = new Path2D.Double();
+		p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		Point2D point;
+		switch (feature.geom.prim) {
+		case POINT:
+			point = context.getPoint(feature.geom.centre);
+			g2.drawImage(image, new AffineTransformOp(AffineTransform.getScaleInstance(sScale, sScale), AffineTransformOp.TYPE_NEAREST_NEIGHBOR),
+					(int)(point.getX() - (50 * sScale)), (int)(point.getY() - (50 * sScale)));
+			break;
+		case AREA:
+			GeomIterator git = map.new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				while (git.hasEdge()) {
+					git.nextEdge();
+					point = context.getPoint(git.next());
+					p.moveTo(point.getX(), point.getY());
+					while (git.hasNode()) {
+						point = context.getPoint(git.next());
+						p.lineTo(point.getX(), point.getY());
+					}
+				}
+			}
+	    g2.setPaint(new TexturePaint(image, new Rectangle(0, 0, 1 + (int)(100 * sScale), 1 + (int)(100 * sScale))));
+	    g2.fill(p);
+	    break;
+		default:
+			break;
+		}
+	}
+	
+	public static void labelText(Feature feature, String str, Font font, Color tc) {
+		labelText(feature, str, font, tc, LabelStyle.NONE, null, null, null);
+	}
+	public static void labelText(Feature feature, String str, Font font, Color tc, Delta delta) {
+		labelText(feature, str, font, tc, LabelStyle.NONE, null, null, delta);
+	}
+	public static void labelText(Feature feature, String str, Font font, Color tc, LabelStyle style, Color fg) {
+		labelText(feature, str, font, tc, style, fg, null, null);
+	}
+	public static void labelText(Feature feature, String str, Font font, Color tc, LabelStyle style, Color fg, Color bg) {
+		labelText(feature, str, font, tc, style, fg, bg, null);
+	}
+	public static void labelText(Feature feature, String str, Font font, Color tc, LabelStyle style, Color fg, Delta delta) {
+		labelText(feature, str, font, tc, style, fg, null, delta);
+	}
+	public static void labelText(Feature feature, String str, Font font, Color tc, LabelStyle style, Color fg, Color bg, Delta delta) {
+		if (delta == null) delta = new Delta(Handle.CC);
+		if (bg == null) bg = new Color(0x00000000, true);
+		if ((str == null) || (str.isEmpty())) str = " ";
+    FontRenderContext frc = g2.getFontRenderContext();
+    GlyphVector gv = font.deriveFont((float)(font.getSize())).createGlyphVector(frc, str.equals(" ") ? "!" : str);
+    Rectangle2D bounds = gv.getVisualBounds();
+    double width = bounds.getWidth();
+    double height = bounds.getHeight();
+		Symbol label = new Symbol();
+		double lx, ly, tx, ty;
+		switch (style) {
+		case RRCT:
+			width += height * 1.0;
+			height *= 1.5;
+	    if (width < height) width = height;
+	    lx = -width / 2;
+	    ly = -height / 2;
+	    tx = lx + (height * 0.34);
+	    ty = ly + (height * 0.17);
+			label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height)));
+			label.add(new Instr(Form.FILL, bg));
+			label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height)));
+			label.add(new Instr(Form.FILL, fg));
+			label.add(new Instr(Form.STRK, new BasicStroke(1 + (int)(height/10), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+			label.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(lx,ly,width,height,height,height)));
+			break;
+		case VCLR:
+			width += height * 1.0;
+			height *= 2.0;
+	    if (width < height) width = height;
+	    lx = -width / 2;
+	    ly = -height / 2;
+	    tx = lx + (height * 0.27);
+	    ty = ly + (height * 0.25);
+			label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height)));
+			label.add(new Instr(Form.FILL, bg));
+			label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height)));
+			label.add(new Instr(Form.FILL, fg));
+			int sw = 1 + (int)(height/10);
+			double po = sw / 2;
+			label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+			Path2D.Double p = new Path2D.Double(); p.moveTo(-height*0.2,-ly-po); p.lineTo(height*0.2,-ly-po); p.moveTo(0,-ly-po); p.lineTo(0,-ly-po-(height*0.15));
+			p.moveTo(-height*0.2,ly+po); p.lineTo((height*0.2),ly+po); p.moveTo(0,ly+po); p.lineTo(0,ly+po+(height*0.15));
+			label.add(new Instr(Form.PLIN, p));
+			break;
+		case PCLR:
+			width += height * 1.0;
+			height *= 2.0;
+	    if (width < height) width = height;
+	    lx = -width / 2;
+	    ly = -height / 2;
+	    tx = lx + (height * 0.27);
+	    ty = ly + (height * 0.25);
+			label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height)));
+			label.add(new Instr(Form.FILL, bg));
+			label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height)));
+			label.add(new Instr(Form.FILL, fg));
+			sw = 1 + (int)(height/10);
+			po = sw / 2;
+			label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+			p = new Path2D.Double(); p.moveTo(-height*0.2,-ly-po); p.lineTo(height*0.2,-ly-po); p.moveTo(0,-ly-po); p.lineTo(0,-ly-po-(height*0.15));
+			p.moveTo(-height*0.2,ly+po); p.lineTo((height*0.2),ly+po); p.moveTo(0,ly+po); p.lineTo(0,ly+po+(height*0.15));
+			label.add(new Instr(Form.PLIN, p));
+			label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0,-1,1,0,-width/2,0)))));
+			label.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.CableFlash, 1, 0, 0, null, new Delta(Handle.CC, new AffineTransform(0,-1,1,0,width/2,0)))));
+			break;
+		case HCLR:
+			width += height * 1.5;
+			height *= 1.5;
+	    if (width < height) width = height;
+	    lx = -width / 2;
+	    ly = -height / 2;
+	    tx = lx + (height * 0.5);
+	    ty = ly + (height * 0.17);
+			label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height)));
+			label.add(new Instr(Form.FILL, bg));
+			label.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(lx,ly,width,height,height,height)));
+			label.add(new Instr(Form.FILL, fg));
+			sw = 1 + (int)(height/10);
+			double vo = height / 4;
+			label.add(new Instr(Form.STRK, new BasicStroke(sw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+			p = new Path2D.Double(); p.moveTo(-width*0.4-sw,-ly-vo); p.lineTo(-width*0.4-sw,ly+vo); p.moveTo(-width*0.4-sw,0); p.lineTo(-width*0.4+sw,0);
+			p.moveTo(width*0.4+sw,-ly-vo); p.lineTo(width*0.4+sw,ly+vo); p.moveTo(width*0.4-sw,0); p.lineTo(width*0.4+sw,0);
+			label.add(new Instr(Form.PLIN, p));
+			break;
+		default:
+			lx = -width / 2;
+			ly = -height / 2;
+			tx = lx;
+			ty = ly;
+			label.add(new Instr(Form.BBOX, new Rectangle2D.Double(lx,ly,width,height)));
+			break;
+		}
+		label.add(new Instr(Form.TEXT, new Caption(str, font, tc, new Delta(Handle.TL, AffineTransform.getTranslateInstance(tx, ty)))));
+		Point2D point = context.getPoint(feature.geom.centre);
+		Symbols.drawSymbol(g2, label, sScale, point.getX(), point.getY(), null, delta);
+	}
+
+	public static void lineText(Feature feature, String str, Font font, Color colour, double offset, double dy) {
+		if (!str.isEmpty()) {
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+	    g2.setPaint(colour);
+	    FontRenderContext frc = g2.getFontRenderContext();
+	    GlyphVector gv = font.deriveFont((float)(font.getSize()*sScale)).createGlyphVector(frc, (" " + str));
+	    GeneralPath path = new GeneralPath();
+			Point2D prev = new Point2D.Double();
+			Point2D next = new Point2D.Double();
+			Point2D curr = new Point2D.Double();
+			Point2D succ = new Point2D.Double();
+			boolean piv = false;
+			double angle = 0;
+			int index = 0;
+			double gwidth = offset * (feature.geom.length * context.mile(feature) - gv.getLogicalBounds().getWidth()) + gv.getGlyphMetrics(0).getAdvance();
+			GeomIterator git = map.new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				boolean first = true;
+				while (git.hasEdge()) {
+					git.nextEdge();
+					while (git.hasNode()) {
+						prev = next;
+						next = context.getPoint(git.next());
+						angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX());
+						piv = true;
+						if (first) {
+							curr = succ = next;
+							first = false;
+						} else {
+							while (curr.distance(next) >= gwidth) {
+								if (piv) {
+									double rem = gwidth;
+									double s = prev.distance(next);
+									double p = curr.distance(prev);
+									if ((s > 0) && (p > 0)) {
+										double n = curr.distance(next);
+										double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p);
+										double phi = Math.asin(p / gwidth * Math.sin(theta));
+										rem = gwidth * Math.sin(Math.PI - theta - phi) / Math.sin(theta);
+									}
+									succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle)));
+									piv = false;
+								} else {
+									succ = new Point2D.Double(curr.getX() + (gwidth * Math.cos(angle)), curr.getY() + (gwidth * Math.sin(angle)));
+								}
+								Shape shape = gv.getGlyphOutline(index);
+								Point2D point = gv.getGlyphPosition(index);
+								AffineTransform at = AffineTransform.getTranslateInstance(curr.getX(), curr.getY());
+								at.rotate(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())));
+								at.translate(-point.getX(), -point.getY() + (dy * sScale));
+								path.append(at.createTransformedShape(shape), false);
+								curr = succ;
+								if (++index < gv.getNumGlyphs()) {
+									gwidth = gv.getGlyphMetrics(index).getAdvance();
+								} else {
+									g2.fill(path);
+									return;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public static void lightSector(Feature feature, Color col1, Color col2, double radius, double s1, double s2, boolean dir, String str) {
+		if ((zoom >= 16) && (radius > 0.2)) {
+			radius = 0.2 / (Math.pow(2, zoom-16));
+		}
+		double mid = (((s1 + s2)  / 2) + (s1 > s2 ? 180 : 0)) % 360;
+		g2.setStroke(new BasicStroke((float) (3.0 * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, new float[] {20 * (float)sScale, 20 * (float)sScale}, 0));
+		g2.setPaint(Color.black);
+		Point2D.Double centre = (Point2D.Double) context.getPoint(feature.geom.centre);
+		double radial = radius * context.mile(feature);
+		if (dir) {
+			g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(mid)), centre.y + radial * Math.cos(Math.toRadians(mid))));
+		} else {
+			g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s1)), centre.y + radial * Math.cos(Math.toRadians(s1))));
+			g2.draw(new Line2D.Double(centre.x, centre.y, centre.x - radial * Math.sin(Math.toRadians(s2)), centre.y + radial * Math.cos(Math.toRadians(s2))));
+		}
+		double arcWidth =  10.0 * sScale;
+		g2.setStroke(new BasicStroke((float)arcWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1));
+		g2.setPaint(col1);
+		g2.draw(new Arc2D.Double(centre.x - radial, centre.y - radial, 2 * radial, 2 * radial, -(s1 + 90), (s1 - s2 - 360) % 360, Arc2D.OPEN));
+		if (col2 != null) {
+			g2.setPaint(col2);
+			g2.draw(new Arc2D.Double(centre.x - radial + arcWidth, centre.y - radial + arcWidth, 2 * (radial - arcWidth), 2 * (radial - arcWidth), -(s1 + 90), (s1 - s2 - 360) % 360, Arc2D.OPEN));
+		}
+		if ((str != null) && (!str.isEmpty())) {
+			g2.setPaint(Color.black);
+			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+	    FontRenderContext frc = g2.getFontRenderContext();
+	    Font font = new Font("Arial", Font.PLAIN, 40);
+	    GeneralPath path = new GeneralPath();
+	    GlyphVector gv = font.deriveFont((float)(font.getSize()*sScale)).createGlyphVector(frc, (" " + str));
+			double gwidth = gv.getLogicalBounds().getWidth();
+			boolean hand = false;
+	    double offset = 0;
+	    Point2D origin;
+			double arc = (s2 - s1 + 360) % 360;
+			if (dir) {
+				radial += 10 * sScale;
+				if (mid < 180) {
+					radial += gwidth;
+					hand = true;
+				}
+				origin = new Point2D.Double(centre.x - radial * Math.sin(Math.toRadians(mid)), centre.y + radial * Math.cos(Math.toRadians(mid)));
+		    int length = gv.getNumGlyphs();
+		    for (int i = 0; i < length; i++) {
+					Shape shape = gv.getGlyphOutline(i);
+					Point2D point = gv.getGlyphPosition(i);
+					AffineTransform at = AffineTransform.getTranslateInstance(origin.getX(), origin.getY());
+					at.rotate(Math.toRadians(mid + (hand ? -90 : 90)));
+					at.translate(-point.getX() + offset, -point.getY() + (15 * sScale));
+					path.append(at.createTransformedShape(shape), false);
+					offset += gv.getGlyphMetrics(i).getAdvance();
+					g2.fill(path);
+		    }
+			} else {
+				double awidth = (Math.toRadians(arc) * radial);
+				if (gwidth < awidth) {
+					offset = 0;
+					double phi = 0;
+					if ((mid > 270) || (mid < 90)) {
+						hand = true;
+						phi = Math.toRadians(s2) - ((awidth - gwidth) / 2) /radial;
+						radial -= 20 * sScale;
+					} else {
+						phi = Math.toRadians(s1) + (((awidth - gwidth) / 2)) /radial;
+						radial += 20 * sScale;
+					}
+					origin = new Point2D.Double(centre.x - radial * Math.sin(phi), centre.y + radial * Math.cos(phi));
+			    int length = gv.getNumGlyphs();
+			    for (int i = 0; i < length; i++) {
+						Shape shape = gv.getGlyphOutline(i);
+						Point2D point = gv.getGlyphPosition(i);
+						AffineTransform at = AffineTransform.getTranslateInstance(origin.getX(), origin.getY());
+						at.rotate(phi + (hand ? 0 : Math.toRadians(180)));
+						at.translate(-point.getX() + offset, -point.getY());
+						path.append(at.createTransformedShape(shape), false);
+						double advance = gv.getGlyphMetrics(i).getAdvance();
+						offset += advance;
+						phi += (hand ? -0.5 : +0.5) * advance / radial;
+						g2.fill(path);
+			    }
+				}
+			}
+		}
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/render/Rules.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/render/Rules.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/render/Rules.java	(revision 30894)
@@ -0,0 +1,1119 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package render;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashMap;
+
+import s57.S57val.*;
+import s57.S57att.*;
+import s57.S57obj.*;
+import s57.S57map.*;
+import render.Renderer.*;
+import symbols.*;
+import symbols.Symbols.*;
+
+public class Rules {
+
+	public static final Color Yland = new Color(0x50b0ff);
+	public static final Color Mline = new Color(0xc480ff);
+	public static final Color Msymb = new Color(0xa30075);
+	
+	static final EnumMap<ColCOL, Color> bodyColours = new EnumMap<ColCOL, Color>(ColCOL.class);
+	static {
+		bodyColours.put(ColCOL.COL_UNK, new Color(0, true));
+		bodyColours.put(ColCOL.COL_WHT, new Color(0xffffff));
+		bodyColours.put(ColCOL.COL_BLK, new Color(0x000000));
+		bodyColours.put(ColCOL.COL_RED, new Color(0xd40000));
+		bodyColours.put(ColCOL.COL_GRN, new Color(0x00d400));
+		bodyColours.put(ColCOL.COL_BLU, Color.blue);
+		bodyColours.put(ColCOL.COL_YEL, new Color(0xffd400));
+		bodyColours.put(ColCOL.COL_GRY, Color.gray);
+		bodyColours.put(ColCOL.COL_BRN, new Color(0x8b4513));
+		bodyColours.put(ColCOL.COL_AMB, new Color(0xfbf00f));
+		bodyColours.put(ColCOL.COL_VIO, new Color(0xee82ee));
+		bodyColours.put(ColCOL.COL_ORG, Color.orange);
+		bodyColours.put(ColCOL.COL_MAG, new Color(0xf000f0));
+		bodyColours.put(ColCOL.COL_PNK, Color.pink);
+	}
+
+	static final EnumMap<ColPAT, Patt> pattMap = new EnumMap<ColPAT, Patt>(ColPAT.class);
+	static {
+		pattMap.put(ColPAT.PAT_UNKN, Patt.Z);
+		pattMap.put(ColPAT.PAT_HORI, Patt.H);
+		pattMap.put(ColPAT.PAT_VERT, Patt.V);
+		pattMap.put(ColPAT.PAT_DIAG, Patt.D);
+		pattMap.put(ColPAT.PAT_BRDR, Patt.B);
+		pattMap.put(ColPAT.PAT_SQUR, Patt.S);
+		pattMap.put(ColPAT.PAT_CROS, Patt.C);
+		pattMap.put(ColPAT.PAT_SALT, Patt.X);
+		pattMap.put(ColPAT.PAT_STRP, Patt.H);
+	}
+	
+	static String getName(Feature feature) {
+		AttVal<?> name = feature.atts.get(Att.OBJNAM);
+		if (name == null) {
+			AttMap atts = feature.objs.get(feature.type).get(0);
+			if (atts != null) {
+				name = atts.get(Att.OBJNAM);
+			}
+		}
+		return (name != null) ? (String)name.val: null;
+	}
+
+	public static void addName(Feature feature, int z, Font font) {
+		addName(feature, z, font, Color.black, new Delta(Handle.CC, new AffineTransform()));
+	}
+	public static void addName(Feature feature, int z, Font font, Color colour) {
+		addName(feature, z, font, colour, new Delta(Handle.CC, new AffineTransform()));
+	}
+	public static void addName(Feature feature, int z, Font font, Delta delta) {
+		addName(feature, z, font, Color.black, delta);
+	}
+	public static void addName(Feature feature, int z, Font font, Color colour, Delta delta) {
+		if (Renderer.zoom >= z) {
+			String name = getName(feature);
+			if (name != null) {
+				Renderer.labelText(feature, name, font,  colour, delta);
+			}
+		}
+	}
+
+	static AttMap getAtts(Feature feature, Obj obj, int idx) {
+		HashMap<Integer, AttMap> objs = feature.objs.get(obj);
+		if (objs == null)
+			return null;
+		else
+			return objs.get(idx);
+	}
+
+	public static Object getAttVal(Feature feature, Obj obj, int idx, Att att) {
+		AttMap atts;
+		HashMap<Integer, AttMap> objs;
+		AttVal<?> item;
+		if ((objs = feature.objs.get(obj)) != null)
+			atts = objs.get(idx);
+		else
+			return null;
+		if ((item = atts.get(att)) == null)
+			return null;
+		else
+			return item.val;
+	}
+	
+	static Scheme getScheme(Feature feature, Obj obj) {
+		ArrayList<Color> colours = new ArrayList<Color>();
+		if (colours.size() > 0) {
+			for (ColCOL col : (ArrayList<ColCOL>) getAttVal(feature, obj, 0, Att.COLOUR)) {
+				colours.add(bodyColours.get(col));
+			}
+		}
+		ArrayList<Patt> patterns = new ArrayList<Patt>();
+		if (patterns.size() > 0) {
+			for (ColPAT pat : (ArrayList<ColPAT>) getAttVal(feature, obj, 0, Att.COLPAT)) {
+				patterns.add(pattMap.get(pat));
+			}
+		}
+		return new Scheme(patterns, colours);
+	}
+	
+	static boolean testAttribute(Feature feature, Obj obj, int idx, Att att, Object val) {
+		AttMap atts;
+		if ((atts = getAtts(feature, obj, idx)) != null) {
+			AttVal<?> item = atts.get(att);
+			if (item != null) {
+				switch (item.conv) {
+				case S:
+				case A:
+					return ((String)item.val).equals(val);
+				case L:
+					return ((ArrayList<?>)item.val).contains(val);
+				case E:
+				case F:
+				case I:
+					return item.val.equals(val);
+				}
+			}
+		}
+		return false;
+	}
+	
+	public static void rules () {
+		ArrayList<Feature> objects;
+		if ((objects = Renderer.map.features.get(Obj.SLCONS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) shoreline(feature);
+		if ((objects = Renderer.map.features.get(Obj.PIPSOL)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) pipelines(feature);
+		if ((objects = Renderer.map.features.get(Obj.CBLSUB)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) cables(feature);
+		if ((objects = Renderer.map.features.get(Obj.PIPOHD)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) pipelines(feature);
+		if ((objects = Renderer.map.features.get(Obj.CBLOHD)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) cables(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSEZNE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSSCRS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSSRON)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSELNE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSSLPT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.TSSBND)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.ISTZNE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) separation(feature);
+		if ((objects = Renderer.map.features.get(Obj.SNDWAV)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.OSPARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.FAIRWY)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.DRGARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.RESARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.SPLARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.SEAARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.OBSTRN)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) obstructions(feature);
+		if ((objects = Renderer.map.features.get(Obj.UWTROC)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) obstructions(feature);
+		if ((objects = Renderer.map.features.get(Obj.MARCUL)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) areas(feature);
+		if ((objects = Renderer.map.features.get(Obj.WTWAXS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) waterways(feature);
+		if ((objects = Renderer.map.features.get(Obj.RECTRC)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) transits(feature);
+		if ((objects = Renderer.map.features.get(Obj.NAVLNE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) transits(feature);
+		if ((objects = Renderer.map.features.get(Obj.HRBFAC)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) harbours(feature);
+		if ((objects = Renderer.map.features.get(Obj.ACHARE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) harbours(feature);
+		if ((objects = Renderer.map.features.get(Obj.ACHBRT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) harbours(feature);
+		if ((objects = Renderer.map.features.get(Obj.BERTHS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) harbours(feature);
+		if ((objects = Renderer.map.features.get(Obj.LOKBSN)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) locks(feature);
+		if ((objects = Renderer.map.features.get(Obj.LKBSPT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) locks(feature);
+		if ((objects = Renderer.map.features.get(Obj.GATCON)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) locks(feature);
+		if ((objects = Renderer.map.features.get(Obj.DISMAR)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) distances(feature);
+		if ((objects = Renderer.map.features.get(Obj.HULKES)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) ports(feature);
+		if ((objects = Renderer.map.features.get(Obj.CRANES)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) ports(feature);
+		if ((objects = Renderer.map.features.get(Obj.LNDMRK)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) landmarks(feature);
+		if ((objects = Renderer.map.features.get(Obj.BUISGL)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) harbours(feature);
+		if ((objects = Renderer.map.features.get(Obj.MORFAC)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) moorings(feature);
+		if ((objects = Renderer.map.features.get(Obj.NOTMRK)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) notices(feature);
+		if ((objects = Renderer.map.features.get(Obj.SMCFAC)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) marinas(feature);
+		if ((objects = Renderer.map.features.get(Obj.BRIDGE)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) bridges(feature);
+		if ((objects = Renderer.map.features.get(Obj.PILPNT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) lights(feature);
+		if ((objects = Renderer.map.features.get(Obj.LITMIN)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) lights(feature);
+		if ((objects = Renderer.map.features.get(Obj.LITMAJ)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) lights(feature);
+		if ((objects = Renderer.map.features.get(Obj.LIGHTS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) lights(feature);
+		if ((objects = Renderer.map.features.get(Obj.SISTAT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.SISTAW)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.CGUSTA)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.RDOSTA)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.RADSTA)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.RTPBCN)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.RSCSTA)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.PILBOP)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) stations(feature);
+		if ((objects = Renderer.map.features.get(Obj.WTWGAG)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) gauges(feature);
+		if ((objects = Renderer.map.features.get(Obj.OFSPLF)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) platforms(feature);
+		if ((objects = Renderer.map.features.get(Obj.WRECKS)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) wrecks(feature);
+		if ((objects = Renderer.map.features.get(Obj.LITVES)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) floats(feature);
+		if ((objects = Renderer.map.features.get(Obj.LITFLT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) floats(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYINB)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) floats(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYLAT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYCAR)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYISD)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYSAW)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYSPP)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BOYWTW)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) buoys(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNLAT)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNCAR)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNISD)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNSAW)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNSPP)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+		if ((objects = Renderer.map.features.get(Obj.BCNWTW)) != null) for (Feature feature : objects) if (feature.reln == Rflag.MASTER) beacons(feature);
+	}
+	
+	private static void areas(Feature feature) {
+		String name = getName(feature);
+		switch (feature.type) {
+		case DRGARE:
+			if (Renderer.zoom < 16)
+				Renderer.lineVector(feature, new LineStyle(Color.black, 8, new float[] { 25, 25 }, new Color(0x40ffffff, true)));
+			else
+				Renderer.lineVector(feature, new LineStyle(Color.black, 8, new float[] { 25, 25 }));
+			addName(feature, 12, new Font("Arial", Font.PLAIN, 100), new Delta(Handle.CC, new AffineTransform()));
+			break;
+		case FAIRWY:
+			if (feature.geom.area > 2.0) {
+				if (Renderer.zoom < 16)
+					Renderer.lineVector(feature, new LineStyle(Mline, 8, new float[] { 50, 50 }, new Color(0x40ffffff, true)));
+				else
+					Renderer.lineVector(feature, new LineStyle(Mline, 8, new float[] { 50, 50 }));
+			} else {
+				if (Renderer.zoom >= 14)
+					Renderer.lineVector(feature, new LineStyle(null, 0, new Color(0x40ffffff, true)));
+			}
+			break;
+		case MARCUL:
+			if (Renderer.zoom >= 12) {
+				if (Renderer.zoom >= 14) {
+					Renderer.symbol(feature, Areas.MarineFarm);
+				}
+				if ((feature.geom.area > 0.2) || ((feature.geom.area > 0.05) && (Renderer.zoom >= 14)) || ((feature.geom.area > 0.005) && (Renderer.zoom >= 16))) {
+					Renderer.lineVector(feature, new LineStyle(Color.black, 4, new float[] { 10, 10 }));
+				}
+			}
+			break;
+		case OSPARE:
+			if (testAttribute(feature, feature.type, 0, Att.CATPRA, CatPRA.PRA_WFRM)) {
+				Renderer.symbol(feature, Areas.WindFarm);
+				Renderer.lineVector(feature, new LineStyle(Color.black, 20, new float[] { 40, 40 }));
+				addName(feature, 15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 10)));
+			}
+			break;
+		case RESARE:
+		case MIPARE:
+			if (Renderer.zoom >= 12) {
+				Renderer.lineSymbols(feature, Areas.Restricted, 1.0, null, null, 0, Mline);
+				if (testAttribute(feature, feature.type, 0, Att.CATREA, CatREA.REA_NWAK)) {
+					Renderer.symbol(feature, Areas.NoWake);
+				}
+			}
+			break;
+		case SEAARE:
+			CatSEA cat;
+			if ((cat = (CatSEA) getAttVal(feature, feature.type, 0, Att.CATSEA)) != null) {
+				switch (cat) {
+				case SEA_RECH:
+					if ((Renderer.zoom >= 10) && (name != null))
+						if (feature.geom.prim == Pflag.LINE) {
+							Renderer.lineText(feature, name, new Font("Arial", Font.PLAIN, 150), Color.black, 0.5, -40);
+						} else {
+							Renderer.labelText(feature, name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40)));
+						}
+					break;
+				case SEA_BAY:
+					if ((Renderer.zoom >= 12) && (name != null))
+						if (feature.geom.prim == Pflag.LINE) {
+							Renderer.lineText(feature, name, new Font("Arial", Font.PLAIN, 150), Color.black, 0.5, -40);
+						} else {
+							Renderer.labelText(feature, name, new Font("Arial", Font.PLAIN, 150), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40)));
+						}
+					break;
+				case SEA_SHOL:
+					if (Renderer.zoom >= 14) {
+						if (feature.geom.prim == Pflag.AREA) {
+							Renderer.lineVector(feature, new LineStyle(new Color(0xc480ff), 4, new float[] { 25, 25 }));
+							if (name != null) {
+								Renderer.labelText(feature, name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40)));
+								Renderer.labelText(feature, "(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC));
+							}
+						} else if (feature.geom.prim == Pflag.LINE) {
+							if (name != null) {
+								Renderer.lineText(feature, name, new Font("Arial", Font.ITALIC, 75), Color.black, 0.5, -40);
+								Renderer.lineText(feature, "(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, 0.5, 0);
+							}
+						} else {
+							if (name != null) {
+								Renderer.labelText(feature, name, new Font("Arial", Font.ITALIC, 75), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -40)));
+								Renderer.labelText(feature, "(Shoal)", new Font("Arial", Font.PLAIN, 60), Color.black, new Delta(Handle.BC));
+							}
+						}
+					}
+					break;
+				case SEA_GAT:
+				case SEA_NRRW:
+					addName(feature, 12, new Font("Arial", Font.PLAIN, 100));
+					break;
+				default:
+					break;
+				}
+				break;
+			}
+		case SNDWAV:
+			if (Renderer.zoom >= 12) Renderer.fillPattern(feature, Areas.Sandwaves);
+			break;
+		case SPLARE:
+			if (Renderer.zoom >= 12) {
+				Renderer.symbol(feature, Areas.Plane, new Scheme(Msymb));
+				Renderer.lineSymbols(feature, Areas.Restricted, 0.5, Areas.LinePlane, null, 10, Mline);
+			}
+			addName(feature, 15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -90)));
+			break;
+		default:
+			break;
+		}
+	}
+	
+	private static void beacons(Feature feature) {
+		if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BCNLAT) || (feature.type == Obj.BCNCAR)))) {
+			CatLAM cat;
+			BcnSHP shape = (BcnSHP) getAttVal(feature, feature.type, 0, Att.BCNSHP);
+			if (shape == null)
+				shape = BcnSHP.BCN_PILE;
+			if ((shape == BcnSHP.BCN_WTHY) && (feature.type == Obj.BCNLAT)) {
+				if ((cat = (CatLAM) getAttVal(feature, feature.type, 0, Att.CATLAM)) != null) {
+					switch (cat) {
+					case LAM_PORT:
+						Renderer.symbol(feature, Beacons.WithyPort);
+						break;
+					case LAM_STBD:
+						Renderer.symbol(feature, Beacons.WithyStarboard);
+						break;
+					default:
+						Renderer.symbol(feature, Beacons.Stake, getScheme(feature, feature.type));
+					}
+				}
+			} else if ((shape == BcnSHP.BCN_PRCH) && (feature.type == Obj.BCNLAT) && !(feature.objs.containsKey(Obj.TOPMAR))) {
+				if ((cat = (CatLAM) getAttVal(feature, feature.type, 0, Att.CATLAM)) != null) {
+					switch (cat) {
+					case LAM_PORT:
+						Renderer.symbol(feature, Beacons.PerchPort);
+						break;
+					case LAM_STBD:
+						Renderer.symbol(feature, Beacons.PerchStarboard);
+						break;
+					default:
+						Renderer.symbol(feature, Beacons.Stake, getScheme(feature, feature.type));
+					}
+				} else {
+					Renderer.symbol(feature, Beacons.Shapes.get(shape), getScheme(feature, feature.type));
+					if (feature.objs.containsKey(Obj.TOPMAR)) {
+						Symbol topmark = Topmarks.Shapes.get(feature.objs.get(Obj.TOPMAR).get(0).get(Att.TOPSHP).val);
+						if (topmark != null)
+							Renderer.symbol(feature, Topmarks.Shapes.get(feature.objs.get(Obj.TOPMAR).get(0).get(Att.TOPSHP).val), getScheme(feature, Obj.TOPMAR), Topmarks.BeaconDelta);
+					} else if (feature.objs.containsKey(Obj.DAYMAR)) {
+						Symbol topmark = Topmarks.Shapes.get(feature.objs.get(Obj.DAYMAR).get(0).get(Att.TOPSHP).val);
+						if (topmark != null)
+							Renderer.symbol(feature, Topmarks.Shapes.get(feature.objs.get(Obj.DAYMAR).get(0).get(Att.TOPSHP).val), getScheme(feature, Obj.DAYMAR), Topmarks.BeaconDelta);
+					}
+				}
+				Signals.addSignals(feature);
+			}
+		}
+	}
+	
+	private static void buoys(Feature feature) {
+		if ((Renderer.zoom >= 14) || ((Renderer.zoom >= 12) && ((feature.type == Obj.BOYLAT) || (feature.type == Obj.BOYCAR)))) {
+			BoySHP shape = (BoySHP) getAttVal(feature, feature.type, 0, Att.BOYSHP);
+			if (shape == null) shape = BoySHP.BOY_PILR;
+			Renderer.symbol(feature, Buoys.Shapes.get(shape), getScheme(feature, feature.type));
+			if (feature.objs.containsKey(Obj.TOPMAR)) {
+				AttMap topmap = feature.objs.get(Obj.TOPMAR).get(0);
+				if (topmap.containsKey(Att.TOPSHP)) {
+					Symbol topmark = Topmarks.Shapes.get(topmap.get(Att.TOPSHP).val);
+					if (topmark != null)
+						Renderer.symbol(feature, topmark, getScheme(feature, Obj.TOPMAR), Topmarks.BuoyDeltas.get(shape));
+				}
+			} else if (feature.objs.containsKey(Obj.DAYMAR)) {
+				AttMap topmap = feature.objs.get(Obj.DAYMAR).get(0);
+				if (topmap.containsKey(Att.TOPSHP)) {
+					Symbol topmark = Topmarks.Shapes.get(topmap.get(Att.TOPSHP).val);
+					if (topmark != null)
+						Renderer.symbol(feature, topmark, getScheme(feature, Obj.DAYMAR), Topmarks.BuoyDeltas.get(shape));
+				}
+			}
+			Signals.addSignals(feature);
+		}
+	}
+	
+	private static void bridges(Feature feature) {
+		if (Renderer.zoom >= 16) {
+			double verclr, verccl, vercop, horclr;
+			AttMap atts = feature.objs.get(Obj.BRIDGE).get(0);
+			String vstr = "";
+			String hstr = "";
+			if (atts != null) {
+				if (atts.containsKey(Att.HORCLR)) {
+					horclr = (Double) atts.get(Att.HORCLR).val;
+					hstr = String.valueOf(horclr);
+				}
+					if (atts.containsKey(Att.VERCLR)) {
+						verclr = (Double) atts.get(Att.VERCLR).val;
+				} else {
+					verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0;
+				}
+				verccl = atts.containsKey(Att.VERCCL) ? (Double) atts.get(Att.VERCCL).val : 0;
+				vercop = atts.containsKey(Att.VERCOP) ? (Double) atts.get(Att.VERCOP).val : 0;
+				if (verclr > 0) {
+					vstr += String.valueOf(verclr);
+				} else if (verccl > 0) {
+					if (vercop == 0) {
+						vstr += String.valueOf(verccl) + "/-";
+					} else {
+						vstr += String.valueOf(verccl) + "/" + String.valueOf(vercop);
+					}
+				}
+				if (hstr.isEmpty() && !vstr.isEmpty()) {
+					Renderer.labelText(feature, vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.CC));
+				} else if (!hstr.isEmpty() && !vstr.isEmpty()) {
+					Renderer.labelText(feature, vstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.VCLR, Color.black, Color.white, new Delta(Handle.BC));
+					Renderer.labelText(feature, hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.TC));
+				} else if (!hstr.isEmpty() && vstr.isEmpty()) {
+					Renderer.labelText(feature, hstr, new Font("Arial", Font.PLAIN, 30), Color.black, LabelStyle.HCLR, Color.black, Color.white, new Delta(Handle.CC));
+				}
+			}
+		}
+	}
+	
+	private static void cables(Feature feature) {
+		if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) {
+			if (feature.type == Obj.CBLSUB) {
+				Renderer.lineSymbols(feature, Areas.Cable, 0.0, null, null, 0, Mline);
+			} else if (feature.type == Obj.CBLOHD) {
+				AttMap atts = feature.objs.get(Obj.CBLOHD).get(0);
+				if ((atts != null) && (atts.containsKey(Att.CATCBL)) && (atts.get(Att.CATCBL).val == CatCBL.CBL_POWR)) {
+					Renderer.lineSymbols(feature, Areas.CableDash, 0, Areas.CableDot, Areas.CableFlash, 2, Color.black);
+				} else {
+					Renderer.lineSymbols(feature, Areas.CableDash, 0, Areas.CableDot, null, 2, Color.black);
+				}
+				if (atts != null) {
+					if (atts.containsKey(Att.VERCLR)) {
+						Renderer.labelText(feature, String.valueOf((Double) atts.get(Att.VERCLR).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25)));
+					} else if (atts.containsKey(Att.VERCSA)) {
+						Renderer.labelText(feature, String.valueOf((Double) atts.get(Att.VERCSA).val), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.PCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25)));
+					}
+				}
+			}
+		}
+	}
+	
+	private static void distances(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			if (!testAttribute(feature, Obj.DISMAR, 0, Att.CATDIS, CatDIS.DIS_NONI)) {
+				Renderer.symbol(feature, Harbours.DistanceI);
+			} else {
+				Renderer.symbol(feature, Harbours.DistanceU);
+			}
+			if (Renderer.zoom >= 15) {
+				AttMap atts = getAtts(feature, Obj.DISMAR, 0);
+				if ((atts != null) && (atts.containsKey(Att.WTWDIS))) {
+					Double dist = (Double) atts.get(Att.WTWDIS).val;
+					String str = "";
+					if (atts.containsKey(Att.HUNITS)) {
+						switch ((UniHLU) atts.get(Att.HUNITS).val) {
+						case HLU_METR:
+							str += "m ";
+							break;
+						case HLU_FEET:
+							str += "ft ";
+							break;
+						case HLU_HMTR:
+							str += "hm ";
+							break;
+						case HLU_KMTR:
+							str += "km ";
+							break;
+						case HLU_SMIL:
+							str += "M ";
+							break;
+						case HLU_NMIL:
+							str += "NM ";
+							break;
+						default:
+							break;
+						}
+					}
+					str += String.format("%1.0f", dist);
+					Renderer.labelText(feature, str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.CC, AffineTransform.getTranslateInstance(0, 45)));
+				}
+			}
+		}
+	}
+	
+	private static void floats(Feature feature) {
+		switch (feature.type) {
+		case LITVES:
+			Renderer.symbol(feature, Buoys.Super, getScheme(feature, feature.type));
+			break;
+		case LITFLT:
+			Renderer.symbol(feature, Buoys.Float, getScheme(feature, feature.type));
+			break;
+		case BOYINB:
+			Renderer.symbol(feature, Buoys.Super, getScheme(feature, feature.type));
+			break;
+		default:
+			break;
+		}
+		if (feature.objs.get(Obj.TOPMAR) != null)
+			Renderer.symbol(feature, Topmarks.Shapes.get(feature.objs.get(Obj.TOPMAR).get(0).get(Att.TOPSHP).val), getScheme(feature, Obj.TOPMAR), Topmarks.FloatDelta);
+		Signals.addSignals(feature);
+	}
+	
+	private static void gauges(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			Renderer.symbol(feature, Harbours.TideGauge);
+			Signals.addSignals(feature);
+		}
+	}
+	
+	private static void harbours(Feature feature) {
+		String name = getName(feature);
+		switch (feature.type) {
+		case ACHBRT:
+			if (Renderer.zoom >= 14) {
+				Renderer.symbol(feature, Harbours.Anchorage, new Scheme(Mline));
+				if (Renderer.zoom >= 15) {
+					Renderer.labelText(feature, name == null ? "" : name, new Font("Arial", Font.PLAIN, 30), Msymb, LabelStyle.RRCT, Mline, Color.white, new Delta(Handle.BC));
+				}
+			}
+			double radius = (Double)getAttVal(feature, Obj.ACHBRT, 0, Att.RADIUS);
+			if (radius != 0) {
+				UniHLU units = (UniHLU)getAttVal(feature, Obj.ACHBRT, 0, Att.HUNITS);
+				Renderer.lineCircle (feature, new LineStyle(Mline, 4, new float[] { 10, 10 }, null), radius, units);
+			}
+			break;
+		case ACHARE:
+			if (Renderer.zoom >= 12) {
+				if (feature.geom.prim != Pflag.AREA) {
+					Renderer.symbol(feature, Harbours.Anchorage, new Scheme(Color.black));
+				} else {
+					Renderer.symbol(feature, Harbours.Anchorage, new Scheme(Mline));
+					Renderer.lineSymbols(feature, Areas.Restricted, 1.0, Areas.LineAnchor, null, 10, Mline);
+				}
+				addName(feature, 15, new Font("Arial", Font.BOLD, 60), Mline, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0)));
+				ArrayList<StsSTS> sts = (ArrayList<StsSTS>)getAttVal(feature, Obj.ACHARE, 0, Att.STATUS);
+				if ((Renderer.zoom >= 15) && (sts != null) && (sts.contains(StsSTS.STS_RESV))) {
+					Renderer.labelText(feature, "Reserved", new Font("Arial", Font.PLAIN, 50), Mline, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0, 60)));
+				}
+			}
+			ArrayList<CatACH> cats;
+			if ((cats = (ArrayList<CatACH>) getAttVal(feature, Obj.ACHARE, 0, Att.CATACH)) != null) {
+				int dy = (cats.size() - 1) * -30;
+				for (CatACH cat : cats) {
+					switch (cat) {
+					case ACH_DEEP:
+						Renderer.labelText(feature, "DW", new Font("Arial", Font.BOLD, 50), Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					case ACH_TANK:
+						Renderer.labelText(feature, "Tanker", new Font("Arial", Font.BOLD, 50), Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					case ACH_H24P:
+						Renderer.labelText(feature, "24h", new Font("Arial", Font.BOLD, 50), Msymb, new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					case ACH_EXPL:
+						Renderer.symbol(feature, Harbours.Explosives, new Scheme(Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					case ACH_QUAR:
+						Renderer.symbol(feature, Harbours.Hospital, new Scheme(Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					case ACH_SEAP:
+						Renderer.symbol(feature, Areas.Seaplane, new Scheme(Msymb), new Delta(Handle.RC, AffineTransform.getTranslateInstance(-60, dy)));
+						dy += 60;
+						break;
+					default:
+					}
+				}
+			}
+			break;
+		case BERTHS:
+			if (Renderer.zoom >= 14) {
+				Renderer.lineVector(feature, new LineStyle(Mline, 6, new float[] { 20, 20 }));
+				Renderer.labelText(feature, name == null ? " " : name, new Font("Arial", Font.PLAIN, 40), Msymb, LabelStyle.RRCT, Mline, Color.white);
+			}
+			break;
+		case BUISGL:
+			if (Renderer.zoom >= 16) {
+				ArrayList<Symbol> symbols = new ArrayList<Symbol>();
+				ArrayList<FncFNC> fncs;
+				if ((fncs = (ArrayList<FncFNC>) getAttVal(feature, Obj.BUISGL, 0, Att.FUNCTN)) != null) {
+					for (FncFNC fnc : fncs) {
+						symbols.add(Landmarks.Funcs.get(fnc));
+					}
+					if (feature.objs.containsKey(Obj.SMCFAC)) {
+						ArrayList<CatSCF> scfs = (ArrayList<CatSCF>) getAttVal(feature, Obj.SMCFAC, 0, Att.CATSCF);
+						for (CatSCF scf : scfs) {
+							symbols.add(Facilities.Cats.get(scf));
+						}
+					}
+					Renderer.cluster(feature, symbols);
+				}
+			}
+			break;
+		case HRBFAC:
+			if (Renderer.zoom >= 12) {
+				ArrayList<CatHAF> cathaf;
+				if ((cathaf = (ArrayList<CatHAF>) getAttVal(feature, Obj.HRBFAC, 0, Att.CATHAF)) != null) {
+					if (cathaf.size() == 1) {
+						switch (cathaf.get(0)) {
+						case HAF_MRNA:
+							Renderer.symbol(feature, Harbours.Marina);
+							break;
+						case HAF_MANF:
+							Renderer.symbol(feature, Harbours.MarinaNF);
+							break;
+						case HAF_FISH:
+							Renderer.symbol(feature, Harbours.Fishing);
+							break;
+						default:
+							Renderer.symbol(feature, Harbours.Harbour);
+							break;
+						}
+					} else {
+						Renderer.symbol(feature, Harbours.Harbour);
+					}
+				}
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	
+	private static void landmarks(Feature feature) {
+		ArrayList<CatLMK> cats;
+		ArrayList<FncFNC> fncs;
+		Symbol catSym = new Symbol();
+		Symbol fncSym = new Symbol();
+		if ((cats = (ArrayList<CatLMK>) getAttVal(feature, feature.type, 0, Att.CATLMK)) != null) {
+			catSym = Landmarks.Shapes.get(cats.get(0));
+		}
+		if ((fncs = (ArrayList<FncFNC>) getAttVal(feature, feature.type, 0, Att.FUNCTN)) != null) {
+			fncSym = Landmarks.Funcs.get(fncs.get(0));
+		}
+		if ((fncs.get(0) == FncFNC.FNC_CHCH) && (cats.get(0) == CatLMK.LMK_TOWR))
+			catSym = Landmarks.ChurchTower;
+		if ((cats.get(0) == CatLMK.LMK_UNKN) && (fncs.get(0) == FncFNC.FNC_UNKN) && (feature.objs.get(Obj.LIGHTS) != null))
+			catSym = Beacons.LightMajor;
+		if (cats.get(0) == CatLMK.LMK_RADR)
+			fncSym = Landmarks.RadioTV;
+		Renderer.symbol(feature, catSym);
+		Renderer.symbol(feature, fncSym);
+		addName(feature, 15, new Font("Arial", Font.BOLD, 80), new Delta(Handle.BL, AffineTransform.getTranslateInstance(60, -50)));
+		Signals.addSignals(feature);
+	}
+	
+	private static void lights(Feature feature) {
+		switch (feature.type) {
+		case LITMAJ:
+			Renderer.symbol(feature, Beacons.LightMajor);
+			break;
+		case LITMIN:
+		case LIGHTS:
+			Renderer.symbol(feature, Beacons.LightMinor);
+			break;
+		case PILPNT:
+			if (feature.objs.containsKey(Obj.LIGHTS))
+				Renderer.symbol(feature, Beacons.LightMinor);
+			else
+				Renderer.symbol(feature, Harbours.Post);
+			break;
+		default:
+			break;
+		}
+		if (feature.objs.containsKey(Obj.TOPMAR)) {
+			Symbol topmark = Topmarks.Shapes.get(feature.objs.get(Obj.TOPMAR).get(0).get(Att.TOPSHP).val);
+			if (topmark != null)
+				Renderer.symbol(feature, Topmarks.Shapes.get(feature.objs.get(Obj.TOPMAR).get(0).get(Att.TOPSHP).val), getScheme(feature, Obj.TOPMAR), Topmarks.LightDelta);
+		} else	if (feature.objs.containsKey(Obj.DAYMAR)) {
+			Symbol topmark = Topmarks.Shapes.get(feature.objs.get(Obj.DAYMAR).get(0).get(Att.TOPSHP).val);
+			if (topmark != null)
+				Renderer.symbol(feature, Topmarks.Shapes.get(feature.objs.get(Obj.DAYMAR).get(0).get(Att.TOPSHP).val), getScheme(feature, Obj.DAYMAR), Topmarks.LightDelta);
+		}
+		Signals.addSignals(feature);
+	}
+
+	private static void locks(Feature feature) {
+	}
+
+	private static void marinas(Feature feature) {
+		if (Renderer.zoom >= 16) {
+			ArrayList<Symbol> symbols = new ArrayList<Symbol>();
+			ArrayList<CatSCF> scfs;
+			if ((scfs = (ArrayList<CatSCF>) getAttVal(feature, Obj.SMCFAC, 0, Att.CATSCF)) != null) {
+				for (CatSCF scf : scfs) {
+					symbols.add(Facilities.Cats.get(scf));
+				}
+				Renderer.cluster(feature, symbols);
+			}
+		}
+	}
+	
+	private static void moorings(Feature feature) {
+		CatMOR cat;
+		if ((cat = (CatMOR) getAttVal(feature, feature.type, 0, Att.CATMOR)) != null) {
+			switch (cat) {
+			case MOR_DLPN:
+				Renderer.symbol(feature, Harbours.Dolphin);
+				break;
+			case MOR_DDPN:
+				Renderer.symbol(feature, Harbours.DeviationDolphin);
+				break;
+			case MOR_BLRD:
+			case MOR_POST:
+				Renderer.symbol(feature, Harbours.Bollard);
+				break;
+			case MOR_BUOY:
+				BoySHP shape = (BoySHP) getAttVal(feature, feature.type, 0, Att.BOYSHP);
+				if (shape == BoySHP.BOY_UNKN)
+					shape = BoySHP.BOY_SPHR;
+				Renderer.symbol(feature, Buoys.Shapes.get(shape), getScheme(feature, feature.type));
+				Renderer.symbol(feature, Topmarks.TopMooring, Topmarks.BuoyDeltas.get(shape));
+				break;
+			default:
+				break;
+			}
+			Signals.addSignals(feature);
+		}
+	}
+
+	private static void notices(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			double dx = 0.0, dy = 0.0;
+			switch (feature.type) {
+			case BCNCAR:
+			case BCNISD:
+			case BCNLAT:
+			case BCNSAW:
+			case BCNSPP:
+			case BCNWTW:
+				dy = 45.0;
+				break;
+			case NOTMRK:
+				dy = 0.0;
+				break;
+			default:
+				return;
+			}
+			MarSYS sys = MarSYS.SYS_CEVN;
+			BnkWTW bnk = BnkWTW.BWW_UNKN;
+			AttVal att = feature.atts.get(Att.MARSYS);
+			if (att != null) sys = (MarSYS)att.val;
+			ObjTab objs = feature.objs.get(Obj.NOTMRK);
+			int n = objs.size();
+			if (n > 5) {
+				Renderer.symbol(feature, Notices.Notice, new Delta(Handle.CC, AffineTransform.getTranslateInstance(dx, dy)));
+			} else {
+				int i = 0;
+				for (AttMap atts : objs.values()) {
+					if (atts.get(Att.MARSYS) != null) sys = (MarSYS)atts.get(Att.MARSYS).val;
+					CatNMK cat = CatNMK.NMK_UNKN;
+					if (atts.get(Att.CATNMK) != null) cat = (CatNMK)atts.get(Att.CATNMK).val;
+					Symbol sym = Notices.getNotice(cat, sys);
+					Handle h = Handle.CC;
+					switch (i) {
+					case 0:
+						if (n != 1) h = null;
+						break;
+					case 1:
+						if (n <= 3)
+							h = Handle.RC;
+						else
+							h = Handle.BR;
+						break;
+					case 2:
+						if (n <= 3)
+							h = Handle.LC;
+						else
+							h = Handle.BL;
+						break;
+					case 3:
+						if (n == 4)
+							h = Handle.TC;
+						else
+							h = Handle.TR;
+						break;
+					case 4:
+						h = Handle.TL;
+						break;
+					}
+					if (h != null) Renderer.symbol(feature, sym, new Delta(h, AffineTransform.getTranslateInstance(dx, dy)));
+					i++;
+				}
+			}
+		}
+	}
+
+	private static void obstructions(Feature feature) {
+		if ((Renderer.zoom >= 12) && (feature.type == Obj.OBSTRN)) {
+			CatOBS cat;
+			if ((cat = (CatOBS) getAttVal(feature, feature.type, 0, Att.CATOBS)) != null) {
+			switch (cat) {
+			case OBS_BOOM:
+				Renderer.lineVector(feature, new LineStyle(Color.black, 5, new float[] { 20, 20 }, null));
+				if (Renderer.zoom >= 15) Renderer.lineText(feature, "Boom", new Font("Arial", Font.PLAIN, 80), Color.black, 0.5, -20);
+			default:
+				break;
+	      }
+	    }
+		}
+		if ((Renderer.zoom >= 14) && (feature.type == Obj.UWTROC)) {
+			WatLEV lvl;
+			if ((lvl = (WatLEV) getAttVal(feature, feature.type, 0, Att.WATLEV)) != null) {
+				switch (lvl) {
+				case LEV_CVRS:
+					Renderer.symbol(feature, Areas.RockC);
+					break;
+				case LEV_AWSH:
+					Renderer.symbol(feature, Areas.RockA);
+					break;
+				default:
+					Renderer.symbol(feature, Areas.Rock);
+				}
+			} else {
+				Renderer.symbol(feature, Areas.Rock);
+			}
+		}
+	}
+
+	private static void pipelines(Feature feature) {
+		if ((Renderer.zoom >= 16) && (feature.geom.length < 2)) {
+			if (feature.type == Obj.PIPSOL) {
+				Renderer.lineSymbols(feature, Areas.Pipeline, 1.0, null, null, 0, Mline);
+			} else if (feature.type == Obj.PIPOHD) {
+				Renderer.lineVector(feature, new LineStyle(Color.black, 8));
+				AttMap atts = feature.atts;
+				double verclr = 0;
+				if (atts != null) {
+					if (atts.containsKey(Att.VERCLR)) {
+						verclr = (Double) atts.get(Att.VERCLR).val;
+					} else {
+						verclr = atts.containsKey(Att.VERCSA) ? (Double) atts.get(Att.VERCSA).val : 0;
+					}
+					if (verclr > 0) {
+						Renderer.labelText(feature, String.valueOf(verclr), new Font("Arial", Font.PLAIN, 50), Color.black, LabelStyle.VCLR, Color.black, new Delta(Handle.TC, AffineTransform.getTranslateInstance(0,25)));
+					}
+				}
+			}
+		}
+	}
+
+	private static void platforms(Feature feature) {
+		ArrayList<CatOFP> cats;
+		if ((cats = (ArrayList<CatOFP>) getAttVal(feature, Obj.OFSPLF, 0, Att.CATOFP)) != null) {
+			if ((CatOFP) cats.get(0) == CatOFP.OFP_FPSO)
+				Renderer.symbol(feature, Buoys.Storage);
+			else
+				Renderer.symbol(feature, Landmarks.Platform);
+			addName(feature, 15, new Font("Arial", Font.BOLD, 40), new Delta(Handle.BL, AffineTransform.getTranslateInstance(20, -50)));
+			Signals.addSignals(feature);
+		}
+	}
+
+	private static void ports(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			if (feature.type == Obj.CRANES) {
+				if ((CatCRN) getAttVal(feature, feature.type, 0, Att.CATCRN) == CatCRN.CRN_CONT)
+					Renderer.symbol(feature, Harbours.ContainerCrane);
+				else
+					Renderer.symbol(feature, Harbours.PortCrane);
+			} else if (feature.type == Obj.HULKES) {
+				Renderer.lineVector(feature, new LineStyle(Color.black, 4, null, new Color(0xffe000)));
+				addName(feature, 15, new Font("Arial", Font.BOLD, 80));
+			}
+		}
+	}
+
+	private static void separation(Feature feature) {
+		switch (feature.type) {
+		case TSEZNE:
+		case TSSCRS:
+		case TSSRON:
+			if (Renderer.zoom <= 15)
+				Renderer.lineVector(feature, new LineStyle(null, 0, null, new Color(0x80c48080, true)));
+			else
+				Renderer.lineVector(feature, new LineStyle(new Color(0x80c48080, true), 20, null, null));
+			addName(feature, 10, new Font("Arial", Font.BOLD, 150), new Color(0x80c48080, true));
+			break;
+		case TSELNE:
+			Renderer.lineVector(feature, new LineStyle(new Color(0x80c48080, true), 20, null, null));
+			break;
+		case TSSLPT:
+			Renderer.lineSymbols(feature, Areas.LaneArrow, 0.5, null, null, 0, new Color(0x80c48080, true));
+			break;
+		case TSSBND:
+			Renderer.lineVector(feature, new LineStyle(new Color(0x80c48080, true), 20, new float[] { 40, 40 }, null));
+			break;
+		case ISTZNE:
+			Renderer.lineSymbols(feature, Areas.Restricted, 1.0, null, null, 0, new Color(0x80c48080, true));
+			break;
+		default:
+			break;
+		}
+	}
+
+	private static void shoreline(Feature feature) {
+		if (Renderer.zoom >= 12) {
+			CatSLC cat;
+			if ((cat = (CatSLC) getAttVal(feature, feature.type, 0, Att.CATSLC)) != null) {
+				switch (cat) {
+				case SLC_TWAL:
+					WatLEV lev;
+					if ((lev = (WatLEV) getAttVal(feature, feature.type, 0, Att.WATLEV)) != null) {
+						if (lev == WatLEV.LEV_CVRS) {
+							Renderer.lineVector(feature, new LineStyle(Color.black, 10, new float[] { 40, 40 }, null));
+							if (Renderer.zoom >= 15)
+								Renderer.lineText(feature, "(covers)", new Font("Arial", Font.PLAIN, 80), Color.black, 0.5, 80);
+						} else {
+							Renderer.lineVector(feature, new LineStyle(Color.black, 10, null, null));
+						}
+						if (Renderer.zoom >= 15)
+							Renderer.lineText(feature, "Training Wall", new Font("Arial", Font.PLAIN, 80), Color.black, 0.5, -30);
+						break;
+					}
+				case SLC_SWAY:
+					Renderer.lineVector(feature, new LineStyle(Color.black, 2, null, new Color(0xffe000)));
+					if ((Renderer.zoom >= 16) && feature.objs.containsKey(Obj.SMCFAC)) {
+						ArrayList<Symbol> symbols = new ArrayList<Symbol>();
+						ArrayList<CatSCF> scfs;
+						if ((scfs = (ArrayList<CatSCF>) getAttVal(feature, Obj.SMCFAC, 0, Att.CATSCF)) != null) {
+							for (CatSCF scf : scfs) {
+								symbols.add(Facilities.Cats.get(scf));
+							}
+							Renderer.cluster(feature, symbols);
+						}
+					}
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	private static void stations(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			String str = "";
+			switch (feature.type) {
+			case SISTAT:
+				Renderer.symbol(feature, Harbours.SignalStation);
+				str = "SS";
+				ArrayList<CatSIT> tcats = (ArrayList<CatSIT>)getAttVal(feature, Obj.SISTAT, 0, Att.CATSIT);
+				if (tcats != null) {
+					switch (tcats.get(0)) {
+					case SIT_IPT:
+						str += "(INT)";
+						break;
+					case SIT_PRTE:
+						str += "(Traffic)";
+						break;
+					case SIT_PRTC:
+						str += "(Port Control)";
+						break;
+					case SIT_LOCK:
+						str += "(Lock)";
+						break;
+					case SIT_BRDG:
+						str += "(Bridge)";
+						break;
+					default:
+						break;
+					}
+				}
+				break;
+			case SISTAW:
+				Renderer.symbol(feature, Harbours.SignalStation);
+				str = "SS";
+				str = "SS";
+				ArrayList<CatSIW> wcats = (ArrayList<CatSIW>)getAttVal(feature, Obj.SISTAW, 0, Att.CATSIW);
+				if (wcats != null) {
+					switch (wcats.get(0)) {
+					case SIW_STRM:
+						str += "(Storm)";
+						break;
+					case SIW_WTHR:
+						str += "(Weather)";
+						break;
+					case SIW_ICE:
+						str += "(Ice)";
+						break;
+					case SIW_TIDG:
+						str = "Tide gauge";
+						break;
+					case SIW_TIDS:
+						str = "Tide scale";
+						break;
+					case SIW_TIDE:
+						str += "(Tide)";
+						break;
+					case SIW_TSTR:
+						str += "(Stream)";
+						break;
+					case SIW_DNGR:
+						str += "(Danger)";
+						break;
+					case SIW_MILY:
+						str += "(Firing)";
+						break;
+					case SIW_TIME:
+						str += "(Time)";
+						break;
+					default:
+						break;
+					}
+				}
+				break;
+			case RDOSTA:
+			case RTPBCN:
+				Renderer.symbol(feature, Harbours.SignalStation);
+				Renderer.symbol(feature, Beacons.RadarStation);
+				break;
+			case RADSTA:
+				Renderer.symbol(feature, Harbours.SignalStation);
+				Renderer.symbol(feature, Beacons.RadarStation);
+				Renderer.labelText(feature, "Ra", new Font("Arial", Font.PLAIN, 40), Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70)));
+				break;
+			case PILBOP:
+				Renderer.symbol(feature, Harbours.Pilot);
+				addName(feature, 15, new Font("Arial", Font.BOLD, 50), Msymb , new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, -40)));
+				CatPIL cat = (CatPIL) getAttVal(feature, feature.type, 0, Att.CATPIL);
+				if ((cat != null) && (cat == CatPIL.PIL_HELI))
+					Renderer.labelText(feature, "H", new Font("Arial", Font.PLAIN, 40), Msymb, new Delta(Handle.LC, AffineTransform.getTranslateInstance(70, 0)));
+				break;
+			case CGUSTA:
+				Renderer.symbol(feature, Harbours.SignalStation);
+				str = "CG";
+			  if (feature.objs.containsKey(Obj.RSCSTA)) Renderer.symbol(feature, Harbours.Rescue, new Delta(Handle.CC, AffineTransform.getTranslateInstance(130, 0)));
+				break;
+			case RSCSTA:
+				Renderer.symbol(feature, Harbours.Rescue);
+				break;
+			default:
+				break;
+			}
+			if ((Renderer.zoom >= 15) && !str.isEmpty()) {
+				Renderer.labelText(feature, str, new Font("Arial", Font.PLAIN, 40), Color.black, new Delta(Handle.LC, AffineTransform.getTranslateInstance(40, 0)));
+			}
+			Signals.addSignals(feature);
+		}
+	}
+
+	private static void transits(Feature feature) {
+	  if (Renderer.zoom >= 14) {
+	  	if (feature.type == Obj.RECTRC) Renderer.lineVector (feature, new LineStyle(Color.black, 10, null, null));
+	  	else if (feature.type == Obj.NAVLNE) Renderer.lineVector (feature, new LineStyle(Color.black, 10, new float[] { 25, 25 }, null));
+	  }
+		if (Renderer.zoom >= 15) {
+			String str = "";
+			String name = getName(feature);
+			if (name != null)
+				str += name + " ";
+			Double ort;
+			if ((ort = (Double) getAttVal(feature, feature.type, 0, Att.ORIENT)) != null) {
+				if (ort != null)
+					str += ort.toString() + "\u0152";
+				if (!str.isEmpty())
+					Renderer.lineText(feature, str, new Font("Arial", Font.PLAIN, 80), Color.black, 0.5, -20);
+			}
+		}
+	}
+
+	private static void waterways(Feature feature) {
+		
+	}
+
+	private static void wrecks(Feature feature) {
+		if (Renderer.zoom >= 14) {
+			CatWRK cat;
+			if ((cat = (CatWRK) getAttVal(feature, feature.type, 0, Att.CATWRK)) != null) {
+				switch (cat) {
+				case WRK_DNGR:
+				case WRK_MSTS:
+					Renderer.symbol(feature, Areas.WreckD);
+					break;
+				case WRK_HULS:
+					Renderer.symbol(feature, Areas.WreckS);
+					break;
+				default:
+					Renderer.symbol(feature, Areas.WreckND);
+				}
+			}
+		}
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/render/Signals.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/render/Signals.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/render/Signals.java	(revision 30894)
@@ -0,0 +1,741 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package render;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.*;
+import java.util.ArrayList;
+import java.util.EnumMap;
+
+import s57.S57att.*;
+import s57.S57obj.*;
+import s57.S57val.*;
+import s57.S57map.*;
+import symbols.Beacons;
+import symbols.Topmarks;
+import symbols.Symbols.*;
+
+public class Signals {
+
+	static final EnumMap<ColCOL, Color> lightColours = new EnumMap<ColCOL, Color>(ColCOL.class);
+	static {
+		lightColours.put(ColCOL.COL_WHT, new Color(0xffff00));
+		lightColours.put(ColCOL.COL_RED, new Color(0xff0000));
+		lightColours.put(ColCOL.COL_GRN, new Color(0x00ff00));
+		lightColours.put(ColCOL.COL_BLU, new Color(0x0000ff));
+		lightColours.put(ColCOL.COL_YEL, new Color(0xffff00));
+		lightColours.put(ColCOL.COL_AMB, new Color(0xffc200));
+		lightColours.put(ColCOL.COL_VIO, new Color(0xee82ee));
+		lightColours.put(ColCOL.COL_ORG, Color.orange);
+		lightColours.put(ColCOL.COL_MAG, Color.magenta);
+	}
+
+	static final EnumMap<ColCOL, String> lightLetters = new EnumMap<ColCOL, String>(ColCOL.class);
+	static {
+		lightLetters.put(ColCOL.COL_WHT, "W");
+		lightLetters.put(ColCOL.COL_RED, "R");
+		lightLetters.put(ColCOL.COL_GRN, "G");
+		lightLetters.put(ColCOL.COL_BLU, "Bu");
+		lightLetters.put(ColCOL.COL_YEL, "Y");
+		lightLetters.put(ColCOL.COL_AMB, "Am");
+		lightLetters.put(ColCOL.COL_VIO, "Vi");
+		lightLetters.put(ColCOL.COL_ORG, "Or");
+	}
+
+	static final EnumMap<LitCHR, String> lightCharacters = new EnumMap<LitCHR, String>(LitCHR.class);
+	static {
+		lightCharacters.put(LitCHR.CHR_F, "W");
+		lightCharacters.put(LitCHR.CHR_FL, "Fl");
+		lightCharacters.put(LitCHR.CHR_LFL, "LFl");
+		lightCharacters.put(LitCHR.CHR_Q, "Q");
+		lightCharacters.put(LitCHR.CHR_VQ, "VQ");
+		lightCharacters.put(LitCHR.CHR_UQ, "UQ");
+		lightCharacters.put(LitCHR.CHR_ISO, "Iso");
+		lightCharacters.put(LitCHR.CHR_OC, "Oc");
+		lightCharacters.put(LitCHR.CHR_IQ, "IQ");
+		lightCharacters.put(LitCHR.CHR_IVQ, "IVQ");
+		lightCharacters.put(LitCHR.CHR_IUQ, "IUQ");
+		lightCharacters.put(LitCHR.CHR_MO, "Mo");
+		lightCharacters.put(LitCHR.CHR_FFL, "FFl");
+		lightCharacters.put(LitCHR.CHR_FLLFL, "FlLFl");
+		lightCharacters.put(LitCHR.CHR_OCFL, "OcFl");
+		lightCharacters.put(LitCHR.CHR_FLFL, "FLFl");
+		lightCharacters.put(LitCHR.CHR_ALOC, "Al.Oc");
+		lightCharacters.put(LitCHR.CHR_ALLFL, "Al.LFl");
+		lightCharacters.put(LitCHR.CHR_ALFL, "Al.Fl");
+		lightCharacters.put(LitCHR.CHR_ALGR, "Al.Gr");
+		lightCharacters.put(LitCHR.CHR_QLFL, "Q+LFl");
+		lightCharacters.put(LitCHR.CHR_VQLFL, "VQ+LFl");
+		lightCharacters.put(LitCHR.CHR_UQLFL, "UQ+LFl");
+		lightCharacters.put(LitCHR.CHR_AL, "Al");
+		lightCharacters.put(LitCHR.CHR_ALFFL, "Al.FFl");
+	}
+	
+	public static void addSignals(Feature feature) {
+	  if (feature.objs.containsKey(Obj.FOGSIG)) fogSignals(feature);
+	  if (feature.objs.containsKey(Obj.RTPBCN)) radarStations(feature);
+	  if (feature.objs.containsKey(Obj.RADSTA)) radarStations(feature);
+	  if (feature.objs.containsKey(Obj.RDOSTA)) radioStations(feature);
+	  if (feature.objs.containsKey(Obj.LIGHTS)) lights(feature);
+	}
+	
+	static final EnumMap<CatFOG, String> fogSignals = new EnumMap<CatFOG, String>(CatFOG.class);
+	static {
+		fogSignals.put(CatFOG.FOG_EXPL, "Explos");
+		fogSignals.put(CatFOG.FOG_DIA, "Dia");
+		fogSignals.put(CatFOG.FOG_SIRN, "Siren");
+		fogSignals.put(CatFOG.FOG_NAUT, "Horn");
+		fogSignals.put(CatFOG.FOG_REED, "Horn");
+		fogSignals.put(CatFOG.FOG_TYPH, "Horn");
+		fogSignals.put(CatFOG.FOG_BELL, "Bell");
+		fogSignals.put(CatFOG.FOG_WHIS, "Whis");
+		fogSignals.put(CatFOG.FOG_GONG, "Gong");
+		fogSignals.put(CatFOG.FOG_HORN, "Horn");
+	}
+
+	public static void fogSignals(Feature feature) {
+		Renderer.symbol(feature, Beacons.FogSignal);
+		AttMap atts = feature.objs.get(Obj.FOGSIG).get(0);
+		String str = "";
+		if (atts.containsKey(Att.CATFOG)) {
+			str += fogSignals.get(atts.get(Att.CATFOG).val);
+		}
+		if (atts.containsKey(Att.SIGGRP)) {
+			str += "(" + atts.get(Att.SIGGRP).val + ")";
+		} else {
+			str += " ";
+		}
+		if (atts.containsKey(Att.SIGPER)) {
+			str += atts.get(Att.SIGPER).val + "s";
+		}
+		if (atts.containsKey(Att.VALMXR)) {
+			str += atts.get(Att.VALMXR).val + "M";
+		}
+		if ((Renderer.zoom >= 15) && !str.isEmpty()) {
+			Renderer.labelText(feature, str, new Font("Arial", Font.PLAIN, 40),Color.black, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-60, -30)));
+		}
+	}
+
+	public static void radarStations(Feature feature) {
+		Renderer.symbol(feature, Beacons.RadarStation);
+		String bstr = "";
+		CatRTB cat = (CatRTB) Rules.getAttVal(feature, Obj.RTPBCN, 0, Att.CATRTB);
+		String wal = (String) Rules.getAttVal(feature, Obj.RTPBCN, 0, Att.RADWAL);
+		switch (cat) {
+		case RTB_RAMK:
+			bstr += " Ramark";
+			break;
+		case RTB_RACN:
+			bstr += " Racon";
+			String astr = (String) Rules.getAttVal(feature, Obj.RTPBCN, 0, Att.SIGGRP);
+			if (!astr.isEmpty()) {
+				bstr += "(" + astr + ")";
+			}
+			Double per = (Double) Rules.getAttVal(feature, Obj.RTPBCN, 0, Att.SIGPER);
+			Double mxr = (Double) Rules.getAttVal(feature, Obj.RTPBCN, 0, Att.VALMXR);
+			if ((per != 0) || (mxr != 0)) {
+				bstr += (astr.isEmpty() ? " " : "");
+				bstr += (per != 0) ? per.toString() + "s" : "";
+				bstr += (mxr != 0) ? mxr.toString() + "M" : "";
+			}
+			break;
+		default:
+			break;
+		}
+		if (wal!= null) {
+			switch (wal) {
+			case "0.03-X":
+				bstr += "(3cm)";
+				break;
+			case "0.10-S":
+				bstr += "(10cm)";
+				break;
+			}
+		}
+		if ((Renderer.zoom >= 15) && !bstr.isEmpty()) {
+			Renderer.labelText(feature, bstr, new Font("Arial", Font.PLAIN, 40), Rules.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -70)));
+		}
+	}
+
+	public static void radioStations(Feature feature) {
+		Renderer.symbol(feature, Beacons.RadarStation);
+		ArrayList<CatROS> cats = (ArrayList<CatROS>)Rules.getAttVal(feature, Obj.RDOSTA, 0, Att.CATROS);
+		boolean vais = false;
+		String bstr = "";
+		for (CatROS ros : cats) {
+			switch (ros) {
+			case ROS_OMNI:
+				bstr += " RC";
+				break;
+			case ROS_DIRL:
+				bstr += " RD";
+				break;
+			case ROS_ROTP:
+				bstr += " RW";
+				break;
+			case ROS_CNSL:
+				bstr += " Consol";
+				break;
+			case ROS_RDF:
+				bstr += " RG";
+				break;
+			case ROS_QTA:
+				bstr += " R";
+				break;
+			case ROS_AERO:
+				bstr += " AeroRC";
+				break;
+			case ROS_DECA:
+				bstr += " Decca";
+				break;
+			case ROS_LORN:
+				bstr += " Loran";
+				break;
+			case ROS_DGPS:
+				bstr += " DGPS";
+				break;
+			case ROS_TORN:
+				bstr += " Toran";
+				break;
+			case ROS_OMGA:
+				bstr += " Omega";
+				break;
+			case ROS_SYLD:
+				bstr += " Syledis";
+				break;
+			case ROS_CHKA:
+				bstr += " Chiaka";
+				break;
+			case ROS_PCOM:
+			case ROS_COMB:
+			case ROS_FACS:
+			case ROS_TIME:
+				break;
+			case ROS_PAIS:
+			case ROS_SAIS:
+				bstr += " AIS";
+				break;
+			case ROS_VAIS:
+				vais = true;
+				break;
+			case ROS_VANC:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopNorth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VASC:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopSouth, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VAEC:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopEast, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VAWC:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopWest, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VAPL:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopCan, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VASL:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopCone, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VAID:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopIsol, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VASW:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopSphere, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VASP:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopX, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			case ROS_VAWK:
+				vais = true;
+				Renderer.symbol(feature, Topmarks.TopCross, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, -25)));
+				break;
+			default:
+				break;
+			}
+		}
+		if (Renderer.zoom >= 15) {
+			if (vais) {
+				Renderer.labelText(feature, "V-AIS", new Font("Arial", Font.PLAIN, 40), Rules.Msymb, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 70)));
+			}
+			if (!bstr.isEmpty()) {
+				Renderer.labelText(feature, bstr, new Font("Arial", Font.PLAIN, 40), Rules.Msymb, new Delta(Handle.TR, AffineTransform.getTranslateInstance(-30, -110)));
+			}
+		}
+	}
+
+	public static void lights(Feature feature) {
+		Enum<ColCOL> col = null;
+		Enum<ColCOL> tcol = null;
+		ObjTab objs = feature.objs.get(Obj.LIGHTS);
+		for (AttMap atts : objs.values()) {
+			if (atts.containsKey(Att.COLOUR)) {
+				ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
+				if (cols.size() == 1) {
+					tcol = cols.get(0);
+					if (col == null) {
+						col = tcol;
+					} else if (tcol != col) {
+						col = ColCOL.COL_MAG;
+						break;
+					}
+				} else {
+					col = ColCOL.COL_MAG;
+					break;
+				}
+			}
+		}
+		Renderer.symbol(feature, Beacons.LightFlare, new Scheme(lightColours.get(col)), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.toRadians(120))));
+		if (objs.get(1) != null) {
+			for (AttMap atts : objs.values()) {
+				Enum<ColCOL> col1 = null;
+				Enum<ColCOL> col2 = null;
+				double radius = 0.2;
+				double s1 = 0;
+				double s2 = 0;
+				boolean dir = false;
+				if (atts.containsKey(Att.COLOUR)) {
+					ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
+					col1 = cols.get(0);
+					if (cols.size() > 1) col2 = cols.get(1);
+				} else {
+					continue;
+				}
+				if (atts.containsKey(Att.RADIUS)) {
+					radius = (Double) atts.get(Att.RADIUS).val;
+				}
+				if (atts.containsKey(Att.SECTR1)) {
+					s1 = (Double) atts.get(Att.SECTR1).val;
+				} else {
+					continue;
+				}
+				if (atts.containsKey(Att.SECTR2)) {
+					s2 = (Double) atts.get(Att.SECTR2).val;
+				} else {
+					continue;
+				}
+				if (atts.containsKey(Att.CATLIT)) {
+					ArrayList<CatLIT> cats = (ArrayList<CatLIT>) atts.get(Att.CATLIT).val;
+					if (cats.contains(CatLIT.LIT_DIR)) {
+						dir = true;
+					}
+				}
+				String str = "";
+				if (atts.containsKey(Att.LITCHR)) {
+					str += lightCharacters.get(atts.get(Att.LITCHR).val);
+				}
+				if (atts.containsKey(Att.SIGGRP)) {
+					str += "(" + atts.get(Att.SIGGRP).val + ")";
+				} else if (!str.isEmpty()) {
+					str += ".";
+				}
+				if (atts.containsKey(Att.COLOUR)) {
+					ArrayList<Enum<ColCOL>> cols = (ArrayList<Enum<ColCOL>>) atts.get(Att.COLOUR).val;
+					str += lightLetters.get(cols.get(0));
+					if (cols.size() > 1)
+						str += lightLetters.get(cols.get(1));
+				}
+				if (dir && atts.containsKey(Att.ORIENT)) {
+					double orient = (Double)atts.get(Att.ORIENT).val;
+					str += " " + orient + "°";
+					s1 = (orient - 4 + 360) % 360;
+					s2 = (orient + 4) % 360;
+					double n1 = 360;
+					double n2 = 360;
+					for (AttMap sect : objs.values()) {
+						if (sect != atts) {
+							
+						}
+					}
+				}
+				Renderer.lightSector(feature, lightColours.get(col1), lightColours.get(col2), radius, s1, s2, dir, str);
+			}
+		}
+	}
+
+	/*
+void renderSector(Item_t *item, int s, char *text, char *style, double offset, int dy) {
+  Obj_t *sector;
+  double start, end;
+  Att_t *att;
+  XY_t p0, p1;
+  double r0, r1;
+  double b0, b1, span;
+  char *col;
+  XY_t pos = findCentroid(item);
+  if ((sector = getObj(item, LIGHTS, s)) != NULL) {
+    strcpy(string1, (att = getAtt(sector, LITRAD)) != NULL ? att->val.val.a : "0.2");
+    if (((att = getAtt(sector, CATLIT)) != NULL) && (testAtt(att, LIT_DIR)) && ((att = getAtt(sector, ORIENT)) != NULL)) {
+      b0 = fmod(540.0 - att->val.val.f, 360.0);
+      if ((att = getAtt(sector, COLOUR)) != NULL) {
+        col = light_colours[att->val.val.l->val];
+        r0 = atof(string1);
+        p0 = radial(pos, r0, b0);
+        printf("<path d=\"M %g,%g L %g,%g\" style=\"fill:none;stroke:#808080;stroke-width:%g;stroke-dasharray:%g\"/>\n",
+               pos.x, pos.y, p0.x, p0.y, (4 * symbolScale[zoom]), (20 * symbolScale[zoom]));
+        start = fmod(b0 + 2.0, 360.0);
+        end = fmod(360.0 + b0 - 2.0, 360.0);
+        Obj_t *adj;
+        for (int i = s-1; i <= s+1; i++) {
+          if (i == s) continue;
+          if ((adj = getObj(item, LIGHTS, i)) == NULL) continue;
+          Att_t *att;
+          if (((att = getAtt(adj, CATLIT)) != NULL) && (testAtt(att, LIT_DIR)) && ((att = getAtt(adj, ORIENT)) != NULL)) {
+            b1 = fmod(540.0 - att->val.val.f, 360.0);
+            if (fabs(b0 - b1) > 180.0) {
+              if (b0 < b1) b0 += 360.0;
+              else b1 += 360.0;
+            }
+            if (fabs(b0 - b1) < 4.0) {
+              if (b1 > b0) start = fmod((720.0 + b0 + b1) / 2.0, 360.0);
+              else end = fmod((720.0 + b0 + b1) / 2.0, 360.0);
+            }
+          }
+        }
+        p0 = radial(pos, r0, start);
+        p1 = radial(pos, r0, end);
+        printf("<path id=\"%d\" d=\"M %g,%g A %g,%g,0,0,1,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g\"/>\n",
+               ++ref, p0.x, p0.y, r0*mile, r0*mile, p1.x, p1.y, col, (20 * symbolScale[zoom]));
+        if (att->val.val.l->next != NULL) {
+          char *col = light_colours[att->val.val.l->next->val];
+          r1 = r0 - (20 * symbolScale[zoom]/mile);
+          p0 = radial(pos, r1, start);
+          p1 = radial(pos, r1, end);
+          printf("<path d=\"M %g,%g A %g,%g,0,0,1,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g\"/>\n",
+                 p0.x, p0.y, r1*mile, r1*mile, p1.x, p1.y, col, (20 * symbolScale[zoom]));
+        }
+      }
+    } else if ((att = getAtt(sector, SECTR1)) != NULL) {
+      start = fmod(540.0 - att->val.val.f, 360.0);
+      if ((att = getAtt(sector, SECTR2)) != NULL) {
+        end = fmod(540.0 - att->val.val.f, 360.0);
+        start += start < end ? 360.0 : 0.0;
+        if ((att = getAtt(sector, COLOUR)) != NULL) {
+          char *ttok, *etok;
+          char *radstr = strdup(string1);
+          int arc = 0;
+          col = light_colours[att->val.val.l->val];
+          r0 = 0.0;
+          b0 = b1 = start;
+          for (char *tpl = strtok_r(radstr, ";", &ttok); tpl != NULL; tpl = strtok_r(NULL, ";", &ttok)) {
+            p0 = radial(pos, r0, b0);
+            span = 0.0;
+            char *ele = strtok_r(tpl, ":", &etok);
+            if ((*tpl == ':') && (r0 == 0.0)) {
+              r1 = 0.2;
+            } else if (*tpl != ':') {
+              r1 = atof(tpl);
+              ele = strtok_r(NULL, ":", &etok);
+            }
+            while (ele != NULL) {
+              if (isalpha(*ele)) {
+                if (strcmp(ele, "suppress") == 0) arc = 2;
+                else if (strcmp(ele, "dashed") == 0) arc = 1;
+                else arc = 0;
+              } else {
+                span = atof(ele);
+              }
+              ele = strtok_r(NULL, ":", &etok);
+            }
+            if (span == 0.0) {
+              char *back = (ttok != NULL) ? strstr(ttok, "-") : NULL;
+              if (back != NULL) {
+                span = b0 - end + atof(back);
+              } else {
+                span = b0 - end;
+              }
+            }
+            if (r1 != r0) {
+              p1 = radial(pos, r1, b0);
+              if (!((start == 180.0) && (end == 180.0)))
+                printf("<path d=\"M %g,%g L %g,%g\" style=\"fill:none;stroke:#808080;stroke-width:%g;stroke-dasharray:%g\"/>\n",
+                       p0.x, p0.y, p1.x, p1.y, (4 * symbolScale[zoom]), (20 * symbolScale[zoom]));
+              r0 = r1;
+              p0 = p1;
+            }
+            if (span < 0.0) {
+              b1 = end - span;
+              b1 = b1 > b0 ? b0 : b1;
+              b0 = b1;
+              b1 = end;
+              p0 = radial(pos, r0, b0);
+            } else {
+              b1 = b0 - span;
+              b1 = b1 < end ? end : b1;
+            }
+            p1 = radial(pos, r1, b1);
+            if ((b0 == 180.0) && (b1 == 180.0)) {
+              span = 360.0;
+              p1 = radial(pos, r1, b1+0.01);
+            }
+            if (arc == 0) {
+              if (p0.x < p1.x)
+                printf("<path id=\"%d\" d=\"M %g,%g A %g,%g,0,%d,1,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g\"/>\n",
+                       ++ref, p0.x, p0.y, r1*mile, r1*mile, span>180.0, p1.x, p1.y, col, (20 * symbolScale[zoom]));
+              else
+                printf("<path id=\"%d\" d=\"M %g,%g A %g,%g,0,%d,0,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g\"/>\n",
+                       ++ref, p1.x, p1.y, r1*mile, r1*mile, span>180.0, p0.x, p0.y, col, (20 * symbolScale[zoom]));
+              if (text != NULL) {
+                double chord = sqrt(pow((p0.x - p1.x), 2) + pow((p0.y - p1.y), 2));
+                if ((chord > (strlen(text) * textScale[zoom] * 50)) || ((b0 == 180.0) && (b1 == 180.0)))
+                  drawLineText(item, text, style, offset, dy, ref);
+              }
+            } else if (arc == 1) {
+              printf("<path d=\"M %g,%g A %g,%g,0,%d,1,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g;stroke-opacity:0.5;stroke-dasharray:%g\"/>\n",
+                     p0.x, p0.y, r1*mile, r1*mile, span>180.0, p1.x, p1.y, col, (10 * symbolScale[zoom]), (30 * symbolScale[zoom]));
+            }
+            if ((arc == 0) && (att->val.val.l->next != NULL)) {
+              char *col = light_colours[att->val.val.l->next->val];
+              double r2 = r1 - (20 * symbolScale[zoom]/mile);
+              XY_t p2 = radial(pos, r2, b0);
+              XY_t p3 = radial(pos, r2, b1);
+              printf("<path d=\"M %g,%g A %g,%g,0,%d,1,%g,%g\" style=\"fill:none;stroke:%s;stroke-width:%g\"/>\n",
+                     p2.x, p2.y, r1*mile, r1*mile, span>180.0, p3.x, p3.y, col, (20 * symbolScale[zoom]));
+            }
+            b0 = b1;
+            if (b0 == end) break;
+          }
+          if (!((start == 180.0) && (end == 180.0)))
+            printf("<path d=\"M %g,%g L %g,%g\" style=\"fill:none;stroke:#808080;stroke-width:%g;stroke-dasharray:%g\"/>\n",
+                   pos.x, pos.y, p1.x, p1.y, (4 * symbolScale[zoom]), (20 * symbolScale[zoom]));
+          free(radstr);
+        }
+      }
+    }
+  }
+}
+char *charString(Item_t *item, char *type, int idx) {
+  strcpy(string1, "");
+  Att_t *att = NULL;
+  Obj_t *obj = getObj(item, enumType(type), idx);
+  switch (enumType(type)) {
+    case LIGHTS:
+    {
+      int secmax = countObjects(item, "light");
+      if ((idx == 0) && (secmax > 0)) {
+        struct SECT {
+          struct SECT *next;
+          int dir;
+          LitCHR_t chr;
+          ColCOL_t col;
+          ColCOL_t alt;
+          char *grp;
+          double per;
+          double rng;
+        } *lights = NULL;
+        for (int i = secmax; i > 0; i--) {
+          struct SECT *tmp = calloc(1, sizeof(struct SECT));
+          tmp->next = lights;
+          lights = tmp;
+          obj = getObj(item, LIGHTS, i);
+          if ((att = getAtt(obj, CATLIT)) != NULL) {
+            lights->dir = testAtt(att, LIT_DIR);
+          }
+          if ((att = getAtt(obj, LITCHR)) != NULL) {
+            lights->chr = att->val.val.e;
+            switch (lights->chr) {
+              case CHR_AL:
+                lights->chr = CHR_F;
+                break;
+              case CHR_ALOC:
+                lights->chr = CHR_OC;
+                break;
+              case CHR_ALLFL:
+                lights->chr = CHR_LFL;
+                break;
+              case CHR_ALFL:
+                lights->chr = CHR_FL;
+                break;
+              case CHR_ALFFL:
+                lights->chr = CHR_FFL;
+                break;
+              default:
+                break;
+            }
+          }
+          if ((att = getAtt(obj, SIGGRP)) != NULL) {
+            lights->grp = att->val.val.a;
+          } else {
+            lights->grp = "";
+          }
+          if ((att = getAtt(obj, SIGPER)) != NULL) {
+            lights->per = att->val.val.f;
+          }
+          if ((att = getAtt(obj, VALNMR)) != NULL) {
+            lights->rng = att->val.val.f;
+          }
+          if ((att = getAtt(obj, COLOUR)) != NULL) {
+            lights->col = att->val.val.l->val;
+            if (att->val.val.l->next != NULL)
+              lights->alt = att->val.val.l->next->val;
+          }
+        }
+        struct COLRNG {
+          int col;
+          double rng;
+        } colrng[14];
+        while (lights != NULL) {
+          strcpy(string2, "");
+          bzero(colrng, 14*sizeof(struct COLRNG));
+          colrng[lights->col].col = 1;
+          colrng[lights->col].rng = lights->rng;
+          struct SECT *this = lights;
+          struct SECT *next = lights->next;
+          while (next != NULL) {
+            if ((this->dir == next->dir) && (this->chr == next->chr) &&
+                (strcmp(this->grp, next->grp) == 0) && (this->per == next->per)) {
+              colrng[next->col].col = 1;
+              if (next->rng > colrng[next->col].rng)
+                colrng[next->col].rng = next->rng;
+              struct SECT *tmp = lights;
+              while (tmp->next != next) tmp = tmp->next;
+              tmp->next = next->next;
+              free(next);
+              next = tmp->next;
+            } else {
+              next = next->next;
+            }
+          }
+          if (this->chr != CHR_UNKN) {
+            if (this->dir) strcpy(string2, "Dir.");
+            strcat(string2, light_characters[this->chr]);
+            if (strcmp(this->grp, "") != 0) {
+              if (this->grp[0] == '(')
+                sprintf(strchr(string2, 0), "%s", this->grp);
+              else
+                sprintf(strchr(string2, 0), "(%s)", this->grp);
+            } else {
+              if (strlen(string2) > 0) strcat(string2, ".");
+            }
+            int n = 0;
+            for (int i = 0; i < 14; i++) if (colrng[i].col) n++;
+            double max = 0.0;
+            for (int i = 0; i < 14; i++) if (colrng[i].col && (colrng[i].rng > max)) max = colrng[i].rng;
+            double min = max;
+            for (int i = 0; i < 14; i++) if (colrng[i].col && (colrng[i].rng > 0.0) && (colrng[i].rng < min)) min = colrng[i].rng;
+            if (min == max) {
+              for (int i = 0; i < 14; i++) if (colrng[i].col) strcat(string2, light_letters[i]);
+            } else {
+              for (int i = 0; i < 14; i++) if (colrng[i].col && (colrng[i].rng == max)) strcat(string2, light_letters[i]);
+              for (int i = 0; i < 14; i++) if (colrng[i].col && (colrng[i].rng < max) && (colrng[i].rng > min)) strcat(string2, light_letters[i]);
+              for (int i = 0; i < 14; i++) if (colrng[i].col && colrng[i].rng == min) strcat(string2, light_letters[i]);
+            }
+            strcat(string2, ".");
+            if (this->per > 0.0) sprintf(strchr(string2, 0), "%gs", this->per);
+            if (max > 0.0) {
+              sprintf(strchr(string2, 0), "%g", max);
+              if (min != max) {
+                if (n == 2) strcat(string2, "/");
+                else if (n > 2) strcat(string2, "-");
+                if (min < max) sprintf(strchr(string2, 0), "%g", min);
+              }
+              strcat(string2, "M");
+            }
+            if (strlen(string1) > 0) strcat(string1, "\n");
+            strcat(string1, string2);
+          }
+          lights = this->next;
+          free(this);
+          this = lights;
+        }
+      } else {
+        if ((att = getAtt(obj, CATLIT)) != NULL) {
+          if (testAtt(att, LIT_DIR))
+            strcat(string1, "Dir");
+        }
+        if ((att = getAtt(obj, MLTYLT)) != NULL)
+          sprintf(strchr(string1, 0), "%s", stringValue(att->val));
+        if ((att = getAtt(obj, LITCHR)) != NULL) {
+          char *chrstr = strdup(stringValue(att->val));
+          Att_t *grp = getAtt(obj, SIGGRP);
+          if (grp != NULL) {
+            char *strgrp = strdup(stringValue(grp->val));
+            char *grpstr = strtok(strgrp, "()");
+            switch (att->val.val.e) {
+              case CHR_QLFL:
+                sprintf(strchr(string1, 0), "Q(%s)+LFl", grpstr);
+                break;
+              case CHR_VQLFL:
+                sprintf(strchr(string1, 0), "VQ(%s)+LFl", grpstr);
+                break;
+              case CHR_UQLFL:
+                sprintf(strchr(string1, 0), "UQ(%s)+LFl", grpstr);
+                break;
+              default:
+                sprintf(strchr(string1, 0), "%s(%s)", chrstr, grpstr);
+                break;
+            }
+            free(strgrp);
+          } else {
+            sprintf(strchr(string1, 0), "%s", chrstr);
+          }
+          free(chrstr);
+        }
+        if ((att = getAtt(obj, COLOUR)) != NULL) {
+          int n = countValues(att);
+          if (!((n == 1) && (idx == 0) && (testAtt(att, COL_WHT)))) {
+            if ((strlen(string1) > 0) && ((string1[strlen(string1)-1] != ')')))
+              strcat(string1, ".");
+            Lst_t *lst = att->val.val.l;
+            while (lst != NULL) {
+              strcat(string1, light_letters[lst->val]);
+              lst = lst->next;
+            }
+          }
+        }
+        if ((idx == 0) && (att = getAtt(obj, CATLIT)) != NULL) {
+          if (testAtt(att, LIT_VERT))
+            strcat(string1, "(vert)");
+          if (testAtt(att, LIT_HORI))
+            strcat(string1, "(hor)");
+        }
+        if ((strlen(string1) > 0) &&
+            ((getAtt(obj, SIGPER) != NULL) ||
+             (getAtt(obj, HEIGHT) != NULL) ||
+             (getAtt(obj, VALMXR) != NULL)) &&
+            (string1[strlen(string1)-1] != ')'))
+          strcat(string1, ".");
+        if ((att = getAtt(obj, SIGPER)) != NULL)
+          sprintf(strchr(string1, 0), "%ss", stringValue(att->val));
+        if ((idx == 0) && (item->objs.obj != LITMIN)) {
+          if ((att = getAtt(obj, HEIGHT)) != NULL)
+            sprintf(strchr(string1, 0), "%sm", stringValue(att->val));
+          if ((att = getAtt(obj, VALNMR)) != NULL)
+            sprintf(strchr(string1, 0), "%sM", stringValue(att->val));
+        }
+        if ((idx == 0) && (att = getAtt(obj, CATLIT)) != NULL) {
+          if (testAtt(att, LIT_FRNT))
+            strcat(string1, "(Front)");
+          if (testAtt(att, LIT_REAR))
+            strcat(string1, "(Rear)");
+          if (testAtt(att, LIT_UPPR))
+            strcat(string1, "(Upper)");
+          if (testAtt(att, LIT_LOWR))
+            strcat(string1, "(Lower)");
+        }
+      }
+    }
+      break;
+    default: break;
+ }
+  return string1;
+}
+*/
+	
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57att.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57att.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57att.java	(revision 30894)
@@ -0,0 +1,403 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+import s57.S57obj.*;
+
+public class S57att {
+	
+	public enum Att {
+	  UNKATT, AGENCY, BCNSHP, BUISHP, BOYSHP, BURDEP, CALSGN, CATAIR, CATACH, CATBRG, CATBUA, CATCBL, CATCAN, CATCAM, CATCHP, CATCOA, CATCTR, CATCON, CATCRN, CATDAM,
+	  CATDIS, CATDOC, CATDPG, CATFNC, CATFRY, CATFIF, CATFOG, CATFOR, CATGAT, CATHAF, CATHLK, CATICE, CATINB, CATLND, CATLMK, CATLAM, CATLIT, CATMFA, CATMPA, CATMOR,
+	  CATNAV, CATOBS, CATOFP, CATOLB, CATPLE, CATPIL, CATPIP, CATPRA, CATPYL, CATRAS, CATRTB, CATROS, CATTRK, CATRSC, CATREA, CATROD, CATRUN, CATSEA, CATSLC, CATSIT,
+	  CATSIW, CATSIL, CATSLO, CATSCF, CATSPM, CATTSS, CATVEG, CATWAT, CATWED, CATWRK, COLOUR, COLPAT, COMCHA, CPDATE, CSCALE, CONDTN, CONRAD, CONVIS, CURVEL,
+	  DATEND, DATSTA, DRVAL1, DRVAL2, DUNITS, ELEVAT, ESTRNG, EXCLIT, EXPSOU, FUNCTN, HEIGHT, HUNITS, HORACC, HORCLR, HORLEN, HORWID, ICEFAC, INFORM, JRSDTN, LIFCAP,
+	  LITCHR, LITVIS, MARSYS, MLTYLT, NATION, NATCON, NATSUR, NATQUA, NMDATE, OBJNAM, ORIENT, PEREND, PERSTA, PICREP, PILDST, PRCTRY, PRODCT, PUBREF, QUASOU, RADWAL,
+	  RADIUS, RECDAT, RECIND, RYRMGV, RESTRN, SCAMAX, SCAMIN, SCVAL1, SCVAL2, SECTR1, SECTR2, SHIPAM, SIGFRQ, SIGGEN, SIGGRP, SIGPER, SIGSEQ, SOUACC, SDISMX, SDISMN,
+	  SORDAT, SORIND, STATUS, SURATH, SUREND, SURSTA, SURTYP, TECSOU, TXTDSC, TS_TSP, TS_TSV, T_ACWL, T_HWLW, T_MTOD, T_THDF, T_TINT, T_TSVL, T_VAHC, TIMEND, TIMSTA,
+	  TOPSHP, TRAFIC, VALACM, VALDCO, VALLMA, VALMAG, VALMXR, VALNMR, VALSOU, VERACC, VERCLR, VERCCL, VERCOP, VERCSA, VERDAT, VERLEN, WATLEV, CAT_TS, PUNITS, NINFOM,
+	  NOBJNM, NPLDST, NTXTDS, HORDAT, POSACC, QUAPOS, CLSDNG, DIRIMP, DISBK1, DISBK2, DISIPU, DISIPD, ELEVA1, ELEVA2, FNCTNM, WTWDIS, BUNVES, BNKWTW, COMCTN, HORCLL,
+	  HORCLW, TRSHGD, UNLOCD, HIGWAT, HIGNAM, LOWWAT, LOWNAM, MEAWAT, MEANAM, OTHWAT, OTHNAM, REFLEV, SDRLEV, VCRLEV, SCHREF, USESHP, CURVHW, CURVLW, CURVMW, CURVOW,
+	  APTREF, SHPTYP, UPDMSG, ADDMRK, CATBNK, CATNMK, CATBRT, CATBUN, CATCCL, CATCOM, CATHBR, CATRFD, CATTML, CATGAG, CATVTR, CATTAB, CATEXS, CATWWM, LG_SPD, LG_SPR,
+	  LG_BME, LG_LGS, LG_DRT, LG_WDP, LG_WDU, LG_REL, LG_FNC, LG_DES, LG_PBR, LC_CSI, LC_CSE, LC_ASI, LC_ASE, LC_CCI, LC_CCE, LC_BM1, LC_BM2, LC_LG1, LC_LG2, LC_DR1,
+	  LC_DR2, LC_SP1, LC_SP2, LC_WD1, LC_WD2, LITRAD, CATCVR
+	}
+
+	private static final EnumMap<Att, Integer> AttS57 = new EnumMap<Att, Integer>(Att.class);
+	static {
+		AttS57.put(Att.UNKATT, 0); AttS57.put(Att.AGENCY, 1); AttS57.put(Att.BCNSHP, 2); AttS57.put(Att.BUISHP, 3); AttS57.put(Att.BOYSHP, 4); AttS57.put(Att.BURDEP, 5);
+		AttS57.put(Att.CALSGN, 6); AttS57.put(Att.CATAIR, 7); AttS57.put(Att.CATACH, 8); AttS57.put(Att.CATBRG, 9); AttS57.put(Att.CATBUA, 10); AttS57.put(Att.CATCBL, 11);
+		AttS57.put(Att.CATCAN, 12); AttS57.put(Att.CATCAM, 13); AttS57.put(Att.CATCHP, 14); AttS57.put(Att.CATCOA, 15); AttS57.put(Att.CATCTR, 16); AttS57.put(Att.CATCON, 17);
+		AttS57.put(Att.CATCVR, 18);
+		AttS57.put(Att.CATCRN, 19); AttS57.put(Att.CATDAM, 20); AttS57.put(Att.CATDIS, 21); AttS57.put(Att.CATDOC, 22); AttS57.put(Att.CATDPG, 23);	AttS57.put(Att.CATFNC, 24);
+		AttS57.put(Att.CATFRY, 25); AttS57.put(Att.CATFIF, 26); AttS57.put(Att.CATFOG, 27); AttS57.put(Att.CATFOR, 28); AttS57.put(Att.CATGAT, 29); AttS57.put(Att.CATHAF, 30);
+		AttS57.put(Att.CATHLK, 31); AttS57.put(Att.CATICE, 32); AttS57.put(Att.CATINB, 33); AttS57.put(Att.CATLND, 34); AttS57.put(Att.CATLMK, 35);	AttS57.put(Att.CATLAM, 36);
+		AttS57.put(Att.CATLIT, 37); AttS57.put(Att.CATMFA, 38); AttS57.put(Att.CATMPA, 39); AttS57.put(Att.CATMOR, 40); AttS57.put(Att.CATNAV, 41);	AttS57.put(Att.CATOBS, 42);
+		AttS57.put(Att.CATOFP, 43); AttS57.put(Att.CATOLB, 44); AttS57.put(Att.CATPLE, 45); AttS57.put(Att.CATPIL, 46); AttS57.put(Att.CATPIP, 47);	AttS57.put(Att.CATPRA, 48);
+		AttS57.put(Att.CATPYL, 49); AttS57.put(Att.CATRAS, 51); AttS57.put(Att.CATRTB, 52); AttS57.put(Att.CATROS, 53);	AttS57.put(Att.CATTRK, 54); AttS57.put(Att.CATRSC, 55);
+		AttS57.put(Att.CATREA, 56); AttS57.put(Att.CATROD, 57); AttS57.put(Att.CATRUN, 58); AttS57.put(Att.CATSEA, 59);	AttS57.put(Att.CATSLC, 60); AttS57.put(Att.CATSIT, 61);
+		AttS57.put(Att.CATSIW, 62); AttS57.put(Att.CATSIL, 63); AttS57.put(Att.CATSLO, 64); AttS57.put(Att.CATSCF, 65);	AttS57.put(Att.CATSPM, 66); AttS57.put(Att.CATTSS, 67);
+		AttS57.put(Att.CATVEG, 68); AttS57.put(Att.CATWAT, 69); AttS57.put(Att.CATWED, 70); AttS57.put(Att.CATWRK, 71);	AttS57.put(Att.COLOUR, 75);
+		AttS57.put(Att.COLPAT, 76); AttS57.put(Att.COMCHA, 77); AttS57.put(Att.CONDTN, 81); AttS57.put(Att.CONRAD, 82);	AttS57.put(Att.CONVIS, 83); AttS57.put(Att.CURVEL, 84);
+		AttS57.put(Att.DATEND, 85); AttS57.put(Att.DATSTA, 86); AttS57.put(Att.DRVAL1, 87); AttS57.put(Att.DRVAL2, 88);	AttS57.put(Att.DUNITS, 89); AttS57.put(Att.ELEVAT, 90);
+		AttS57.put(Att.ESTRNG, 91); AttS57.put(Att.EXCLIT, 92); AttS57.put(Att.EXPSOU, 93); AttS57.put(Att.FUNCTN, 94);	AttS57.put(Att.HEIGHT, 95); AttS57.put(Att.HUNITS, 96);
+		AttS57.put(Att.HORACC, 97); AttS57.put(Att.HORCLR, 98); AttS57.put(Att.HORLEN, 99); AttS57.put(Att.HORWID, 100); AttS57.put(Att.ICEFAC, 101); AttS57.put(Att.INFORM, 102);
+		AttS57.put(Att.JRSDTN, 103); AttS57.put(Att.LIFCAP, 106); AttS57.put(Att.LITCHR, 107); AttS57.put(Att.LITVIS, 108);	AttS57.put(Att.MARSYS, 109); AttS57.put(Att.MLTYLT, 110);
+		AttS57.put(Att.NATION, 111); AttS57.put(Att.NATCON, 112); AttS57.put(Att.NATSUR, 113); AttS57.put(Att.NATQUA, 114);	AttS57.put(Att.NMDATE, 115); AttS57.put(Att.OBJNAM, 116);
+		AttS57.put(Att.ORIENT, 117); AttS57.put(Att.PEREND, 118);	AttS57.put(Att.PERSTA, 119); AttS57.put(Att.PICREP, 120);	AttS57.put(Att.PILDST, 121); AttS57.put(Att.PRCTRY, 122);
+		AttS57.put(Att.PRODCT, 123); AttS57.put(Att.PUBREF, 124);	AttS57.put(Att.QUASOU, 125); AttS57.put(Att.RADWAL, 126);	AttS57.put(Att.RADIUS, 127); AttS57.put(Att.RECDAT, 128);
+		AttS57.put(Att.RECIND, 129); AttS57.put(Att.RYRMGV, 130);	AttS57.put(Att.RESTRN, 131); AttS57.put(Att.SCAMAX, 132); AttS57.put(Att.SCAMIN, 133); AttS57.put(Att.SCVAL1, 134);
+		AttS57.put(Att.SCVAL2, 135); AttS57.put(Att.SECTR1, 136);	AttS57.put(Att.SECTR2, 137); AttS57.put(Att.SHIPAM, 138);
+		AttS57.put(Att.SIGFRQ, 139); AttS57.put(Att.SIGGEN, 140);	AttS57.put(Att.SIGGRP, 141); AttS57.put(Att.SIGPER, 142);	AttS57.put(Att.SIGSEQ, 143); AttS57.put(Att.SOUACC, 144);
+		AttS57.put(Att.SDISMX, 145); AttS57.put(Att.SDISMN, 146);	AttS57.put(Att.SORDAT, 147); AttS57.put(Att.SORIND, 148);	AttS57.put(Att.STATUS, 149); AttS57.put(Att.SURATH, 150);
+		AttS57.put(Att.SUREND, 151); AttS57.put(Att.SURSTA, 152);	AttS57.put(Att.SURTYP, 153); AttS57.put(Att.TECSOU, 156);	AttS57.put(Att.TXTDSC, 158); AttS57.put(Att.TIMEND, 168);
+		AttS57.put(Att.TIMSTA, 169); AttS57.put(Att.TOPSHP, 171);	AttS57.put(Att.TRAFIC, 172); AttS57.put(Att.VALACM, 173);	AttS57.put(Att.VALDCO, 174); AttS57.put(Att.VALLMA, 175);
+		AttS57.put(Att.VALMAG, 176); AttS57.put(Att.VALMXR, 177);	AttS57.put(Att.VALNMR, 178); AttS57.put(Att.VALSOU, 179);	AttS57.put(Att.VERACC, 180); AttS57.put(Att.VERCLR, 181);
+		AttS57.put(Att.VERCCL, 182); AttS57.put(Att.VERCOP, 183);	AttS57.put(Att.VERCSA, 184); AttS57.put(Att.VERDAT, 185);	AttS57.put(Att.VERLEN, 186); AttS57.put(Att.WATLEV, 187);
+		AttS57.put(Att.CAT_TS, 188); AttS57.put(Att.PUNITS, 189);	AttS57.put(Att.NINFOM, 300); AttS57.put(Att.NOBJNM, 301);	AttS57.put(Att.NPLDST, 302); AttS57.put(Att.NTXTDS, 304);
+		AttS57.put(Att.HORDAT, 400); AttS57.put(Att.POSACC, 401);	AttS57.put(Att.QUAPOS, 402);
+	}
+
+	private static final EnumMap<Att, Integer> AttIENC = new EnumMap<Att, Integer>(Att.class);
+	static {
+		AttIENC.put(Att.CATACH, 17000); AttIENC.put(Att.CATDIS, 17001); AttIENC.put(Att.CATSIT, 17002); AttIENC.put(Att.CATSIW, 17003); AttIENC.put(Att.RESTRN, 17004);
+		AttIENC.put(Att.VERDAT, 17005); AttIENC.put(Att.CATBRG, 17006); AttIENC.put(Att.CATFRY, 17007); AttIENC.put(Att.CATHAF, 17008); AttIENC.put(Att.MARSYS, 17009);
+		AttIENC.put(Att.CATCHP, 17010); AttIENC.put(Att.CATLAM, 17011); AttIENC.put(Att.CATSLC, 17012); AttIENC.put(Att.ADDMRK, 17050); AttIENC.put(Att.CATBNK, 17051);
+		AttIENC.put(Att.CATNMK, 17052); AttIENC.put(Att.CLSDNG, 17055); AttIENC.put(Att.DIRIMP, 17056); AttIENC.put(Att.DISBK1, 17057); AttIENC.put(Att.DISBK2, 17058);
+		AttIENC.put(Att.DISIPU, 17059); AttIENC.put(Att.DISIPD, 17060); AttIENC.put(Att.ELEVA1, 17061); AttIENC.put(Att.ELEVA2, 17062); AttIENC.put(Att.FNCTNM, 17063);
+		AttIENC.put(Att.WTWDIS, 17064); AttIENC.put(Att.BUNVES, 17065); AttIENC.put(Att.CATBRT, 17066); AttIENC.put(Att.CATBUN, 17067); AttIENC.put(Att.CATCCL, 17069);
+		AttIENC.put(Att.CATHBR, 17070); AttIENC.put(Att.CATRFD, 17071); AttIENC.put(Att.CATTML, 17072); AttIENC.put(Att.COMCTN, 17073); AttIENC.put(Att.HORCLL, 17074);
+		AttIENC.put(Att.HORCLW, 17075); AttIENC.put(Att.TRSHGD, 17076); AttIENC.put(Att.UNLOCD, 17077); AttIENC.put(Att.CATGAG, 17078); AttIENC.put(Att.HIGWAT, 17080);
+		AttIENC.put(Att.HIGNAM, 17081); AttIENC.put(Att.LOWWAT, 17082); AttIENC.put(Att.LOWNAM, 17083); AttIENC.put(Att.MEAWAT, 17084); AttIENC.put(Att.MEANAM, 17085);
+		AttIENC.put(Att.OTHWAT, 17086); AttIENC.put(Att.OTHNAM, 17087); AttIENC.put(Att.REFLEV, 17088); AttIENC.put(Att.SDRLEV, 17089); AttIENC.put(Att.VCRLEV, 17090);
+		AttIENC.put(Att.CATVTR, 17091); AttIENC.put(Att.CATTAB, 17092); AttIENC.put(Att.SCHREF, 17093); AttIENC.put(Att.USESHP, 17094); AttIENC.put(Att.CURVHW, 17095);
+		AttIENC.put(Att.CURVLW, 17096); AttIENC.put(Att.CURVMW, 17097); AttIENC.put(Att.CURVOW, 17098); AttIENC.put(Att.APTREF, 17099); AttIENC.put(Att.CATEXS, 17100);
+		AttIENC.put(Att.CATCBL, 17101); AttIENC.put(Att.CATHLK, 17102); AttIENC.put(Att.HUNITS, 17103); AttIENC.put(Att.WATLEV, 17104); AttIENC.put(Att.CATWWM, 17112);
+		AttIENC.put(Att.LG_SPD, 18001); AttIENC.put(Att.LG_SPR, 18002); AttIENC.put(Att.LG_BME, 18003); AttIENC.put(Att.LG_LGS, 18004); AttIENC.put(Att.LG_DRT, 18005);
+		AttIENC.put(Att.LG_WDP, 18006); AttIENC.put(Att.LG_WDU, 18007); AttIENC.put(Att.LG_REL, 18008); AttIENC.put(Att.LG_FNC, 18009); AttIENC.put(Att.LG_DES, 18010);
+		AttIENC.put(Att.LG_PBR, 18011); AttIENC.put(Att.LC_CSI, 18012); AttIENC.put(Att.LC_CSE, 18013); AttIENC.put(Att.LC_ASI, 18014); AttIENC.put(Att.LC_ASE, 18015);
+		AttIENC.put(Att.LC_CCI, 18016); AttIENC.put(Att.LC_CCE, 18017); AttIENC.put(Att.LC_BM1, 18018); AttIENC.put(Att.LC_BM2, 18019); AttIENC.put(Att.LC_LG1, 18020);
+		AttIENC.put(Att.LC_LG2, 18021); AttIENC.put(Att.LC_DR1, 18022); AttIENC.put(Att.LC_DR2, 18023); AttIENC.put(Att.LC_SP1, 18024); AttIENC.put(Att.LC_SP2, 18025);
+		AttIENC.put(Att.LC_WD1, 18026); AttIENC.put(Att.LC_WD2, 18027); AttIENC.put(Att.SHPTYP, 33066); AttIENC.put(Att.UPDMSG, 40000); AttIENC.put(Att.BNKWTW, 17999);
+	}
+	
+	private static final HashMap<Integer, Att> S57Att = new HashMap<Integer, Att>();
+	static {
+		for (Map.Entry<Att, Integer> entry : AttS57.entrySet()) {
+			S57Att.put(entry.getValue(), entry.getKey());
+		}
+		for (Map.Entry<Att, Integer> entry : AttIENC.entrySet()) {
+			S57Att.put(entry.getValue(), entry.getKey());
+		}
+	}
+	
+	private static final EnumMap<Att, String> AttStr = new EnumMap<Att, String>(Att.class);
+	static {
+		AttStr.put(Att.UNKATT, ""); AttStr.put(Att.AGENCY, "agency"); AttStr.put(Att.BCNSHP, "shape"); AttStr.put(Att.BUISHP, "shape"); AttStr.put(Att.BOYSHP, "shape");
+		AttStr.put(Att.BURDEP, "depth_buried"); AttStr.put(Att.CALSGN, "callsign"); AttStr.put(Att.CATAIR, "category"); AttStr.put(Att.CATACH, "category");
+		AttStr.put(Att.CATBRG, "category"); AttStr.put(Att.CATBUA, "category"); AttStr.put(Att.CATCBL, "category");
+		AttStr.put(Att.CATCAN, "category"); AttStr.put(Att.CATCAM, "category"); AttStr.put(Att.CATCHP, "category"); AttStr.put(Att.CATCOA, "category");
+		AttStr.put(Att.CATCTR, "category"); AttStr.put(Att.CATCON, "category"); AttStr.put(Att.CATCRN, "category"); AttStr.put(Att.CATDAM, "category");
+		AttStr.put(Att.CATDIS, "category"); AttStr.put(Att.CATDOC, "category"); AttStr.put(Att.CATDPG, "category"); AttStr.put(Att.CATFNC, "category");
+		AttStr.put(Att.CATFRY, "category"); AttStr.put(Att.CATFIF, "category"); AttStr.put(Att.CATFOG, "category"); AttStr.put(Att.CATFOR, "category");
+		AttStr.put(Att.CATGAT, "category"); AttStr.put(Att.CATHAF, "category"); AttStr.put(Att.CATHLK, "category"); AttStr.put(Att.CATICE, "category");
+		AttStr.put(Att.CATINB, "category"); AttStr.put(Att.CATLND, "category"); AttStr.put(Att.CATLMK, "category"); AttStr.put(Att.CATLAM, "category");
+		AttStr.put(Att.CATLIT, "category"); AttStr.put(Att.CATMFA, "category"); AttStr.put(Att.CATMPA, "category"); AttStr.put(Att.CATMOR, "category");
+		AttStr.put(Att.CATNAV, "category"); AttStr.put(Att.CATOBS, "category"); AttStr.put(Att.CATOFP, "category"); AttStr.put(Att.CATOLB, "category");
+		AttStr.put(Att.CATPLE, "category"); AttStr.put(Att.CATPIL, "category"); AttStr.put(Att.CATPIP, "category"); AttStr.put(Att.CATPRA, "category");
+		AttStr.put(Att.CATPYL, "category"); AttStr.put(Att.CATRAS, "category"); AttStr.put(Att.CATRTB, "category");
+		AttStr.put(Att.CATROS, "category"); AttStr.put(Att.CATTRK, "category"); AttStr.put(Att.CATRSC, "category"); AttStr.put(Att.CATREA, "category");
+		AttStr.put(Att.CATROD, "category"); AttStr.put(Att.CATRUN, "category"); AttStr.put(Att.CATSEA, "category"); AttStr.put(Att.CATSLC, "category");
+		AttStr.put(Att.CATSIT, "category"); AttStr.put(Att.CATSIW, "category"); AttStr.put(Att.CATSIL, "category"); AttStr.put(Att.CATSLO, "category");
+		AttStr.put(Att.CATSCF, "category"); AttStr.put(Att.CATSPM, "category"); AttStr.put(Att.CATTSS, "category"); AttStr.put(Att.CATVEG, "category");
+		AttStr.put(Att.CATWAT, "category"); AttStr.put(Att.CATWED, "category"); AttStr.put(Att.CATWRK, "category");
+		AttStr.put(Att.COLOUR, "colour"); AttStr.put(Att.COLPAT, "colour_pattern"); AttStr.put(Att.COMCHA, "channel"); AttStr.put(Att.CONDTN, "condition");
+		AttStr.put(Att.CONRAD, "reflectivity"); AttStr.put(Att.CONVIS, "conspicuity"); AttStr.put(Att.CURVEL, "velocity"); AttStr.put(Att.DATEND, "end_date");
+		AttStr.put(Att.DATSTA, "start_date"); AttStr.put(Att.DRVAL1, "minimum_depth"); AttStr.put(Att.DRVAL2, "maximum_depth"); AttStr.put(Att.DUNITS, "depth_units");
+		AttStr.put(Att.ELEVAT, "elevation"); AttStr.put(Att.ESTRNG, "estimated_range"); AttStr.put(Att.EXCLIT, "exhibition"); AttStr.put(Att.EXPSOU, "exposition");
+		AttStr.put(Att.FUNCTN, "function"); AttStr.put(Att.HEIGHT, "height"); AttStr.put(Att.HUNITS, "units"); AttStr.put(Att.HORACC, "accuracy");
+		AttStr.put(Att.HORCLR, "clearance_width"); AttStr.put(Att.HORLEN, "length"); AttStr.put(Att.HORWID, "width"); AttStr.put(Att.ICEFAC, "factor");
+		AttStr.put(Att.INFORM, "information"); AttStr.put(Att.JRSDTN, "jurisdiction"); AttStr.put(Att.LIFCAP, "maximum_load"); AttStr.put(Att.LITCHR, "character");
+		AttStr.put(Att.LITVIS, "visibility"); AttStr.put(Att.MARSYS, "system");	AttStr.put(Att.MLTYLT, "multiple"); AttStr.put(Att.NATION, "nationality");
+		AttStr.put(Att.NATCON, "construction"); AttStr.put(Att.NATSUR, "surface"); AttStr.put(Att.NATQUA, "surface_qualification"); AttStr.put(Att.NMDATE, "nm_date");
+		AttStr.put(Att.OBJNAM, "name"); AttStr.put(Att.ORIENT, "orientation"); AttStr.put(Att.PEREND, "period_end"); AttStr.put(Att.PERSTA, "period_start");
+		AttStr.put(Att.PICREP, "picture"); AttStr.put(Att.PILDST, "pilot_district");	AttStr.put(Att.PRCTRY, "producing_country"); AttStr.put(Att.PRODCT, "product");
+		AttStr.put(Att.PUBREF, "reference"); AttStr.put(Att.QUASOU, "quality");	AttStr.put(Att.RADWAL, "wavelength"); AttStr.put(Att.RADIUS, "radius");
+		AttStr.put(Att.RECDAT, "date"); AttStr.put(Att.RECIND, "indication");	AttStr.put(Att.RYRMGV, "year"); AttStr.put(Att.RESTRN, "restriction");
+		AttStr.put(Att.SECTR1, "sector_start"); AttStr.put(Att.SECTR2, "sector_end");	AttStr.put(Att.SHIPAM, "shift"); AttStr.put(Att.SIGFRQ, "frequency");
+		AttStr.put(Att.SIGGEN, "generation"); AttStr.put(Att.SIGGRP, "group"); AttStr.put(Att.SIGPER, "period"); AttStr.put(Att.SIGSEQ, "sequence");
+		AttStr.put(Att.SOUACC, "sounding_accuracy"); AttStr.put(Att.SDISMX, "maximum_sounding");	AttStr.put(Att.SDISMN, "minimum_sounding"); AttStr.put(Att.SORDAT, "");
+		AttStr.put(Att.SORIND, ""); AttStr.put(Att.STATUS, "status");	AttStr.put(Att.SURATH, "authority"); AttStr.put(Att.SUREND, "survey_end");
+		AttStr.put(Att.SURSTA, "survey_start"); AttStr.put(Att.SURTYP, "survey");	AttStr.put(Att.TECSOU, "technique"); AttStr.put(Att.TXTDSC, "document");
+		AttStr.put(Att.TIMEND, "end_time"); AttStr.put(Att.TIMSTA, "start_time");	AttStr.put(Att.TOPSHP, "shape"); AttStr.put(Att.TRAFIC, "traffic_flow");
+		AttStr.put(Att.VALACM, "variation_change"); AttStr.put(Att.VALDCO, "depth"); AttStr.put(Att.VALLMA, "anomaly"); AttStr.put(Att.VALMAG, "variation");
+		AttStr.put(Att.VALMXR, "maximum_range"); AttStr.put(Att.VALNMR, "range");	AttStr.put(Att.VALSOU, "depth"); AttStr.put(Att.VERACC, "vertical_accuracy");
+		AttStr.put(Att.VERCLR, "clearance_height");	AttStr.put(Att.VERCCL, "clearance_height_closed"); AttStr.put(Att.VERCOP, "clearance_height_open");
+		AttStr.put(Att.VERCSA, "clearance_height_safe"); AttStr.put(Att.VERDAT, "vertical_datum"); AttStr.put(Att.VERLEN, "vertical_length"); AttStr.put(Att.WATLEV, "water_level");
+		AttStr.put(Att.CAT_TS, "category");	AttStr.put(Att.PUNITS, "positional_units"); AttStr.put(Att.NINFOM, "national_information"); AttStr.put(Att.NOBJNM, "national_name");
+		AttStr.put(Att.NPLDST, "national_pilot_district"); AttStr.put(Att.NTXTDS, "national_description"); AttStr.put(Att.HORDAT, "horizontal_datum");
+		AttStr.put(Att.POSACC, "positional_accuracy"); AttStr.put(Att.QUAPOS, "position_quality"); AttStr.put(Att.ADDMRK, "addition"); AttStr.put(Att.BNKWTW, "bank");
+		AttStr.put(Att.CATBNK, "category");	AttStr.put(Att.CATNMK, "category"); AttStr.put(Att.CLSDNG, "danger_class"); AttStr.put(Att.DIRIMP, "impact");
+		AttStr.put(Att.DISBK1, "distance_start");	AttStr.put(Att.DISBK2, "distance_end");AttStr.put(Att.DISIPU, "distance_up"); AttStr.put(Att.DISIPD, "distance_down");
+		AttStr.put(Att.ELEVA1, "minimum_elevation"); AttStr.put(Att.ELEVA2, "maximum_elevation"); AttStr.put(Att.FNCTNM, "function"); AttStr.put(Att.WTWDIS, "distance");
+		AttStr.put(Att.BUNVES, "availability");	AttStr.put(Att.CATBRT, "category"); AttStr.put(Att.CATBUN, "category"); AttStr.put(Att.CATCCL, "category");
+		AttStr.put(Att.CATHBR, "category");	AttStr.put(Att.CATRFD, "category"); AttStr.put(Att.CATTML, "category"); AttStr.put(Att.COMCTN, "communication");
+		AttStr.put(Att.HORCLL, "horizontal_clearance_length");	AttStr.put(Att.HORCLW, "horizontal_clearance_width"); AttStr.put(Att.TRSHGD, "goods"); AttStr.put(Att.UNLOCD, "");
+		AttStr.put(Att.CATGAG, "category");	AttStr.put(Att.HIGWAT, "high_value"); AttStr.put(Att.HIGNAM, "high_name"); AttStr.put(Att.LOWWAT, "low_value");
+		AttStr.put(Att.LOWNAM, "low_name");	AttStr.put(Att.MEAWAT, "mean_value"); AttStr.put(Att.MEANAM, "mean_name"); AttStr.put(Att.OTHWAT, "local_value");
+		AttStr.put(Att.OTHNAM, "local_name");	AttStr.put(Att.REFLEV, "gravity_reference"); AttStr.put(Att.SDRLEV, "sounding_name"); AttStr.put(Att.VCRLEV, "vertical_name");
+		AttStr.put(Att.CATVTR, "category");	AttStr.put(Att.CATTAB, "operation"); AttStr.put(Att.SCHREF, "schedule"); AttStr.put(Att.USESHP, "use"); AttStr.put(Att.CURVHW, "high_velocity");
+		AttStr.put(Att.CURVLW, "low_velocity"); AttStr.put(Att.CURVMW, "mean_velocity"); AttStr.put(Att.CURVOW, "other_velocity"); AttStr.put(Att.APTREF, "passing_time");
+		AttStr.put(Att.CATCOM, "category"); AttStr.put(Att.CATCVR, "category"); AttStr.put(Att.CATEXS, "category"); AttStr.put(Att.CATWWM, "category"); AttStr.put(Att.SHPTYP, "ship");
+		AttStr.put(Att.UPDMSG, "message"); AttStr.put(Att.LITRAD, "radius");
+	}
+	
+	private static final EnumMap<Obj, Att> Accuracy = new EnumMap<Obj, Att>(Obj.class); static { Accuracy.put(Obj.UNKOBJ, Att.HORACC); }
+	private static final EnumMap<Obj, Att> Addition = new EnumMap<Obj, Att>(Obj.class); static { Addition.put(Obj.UNKOBJ, Att.ADDMRK); }
+	private static final EnumMap<Obj, Att> Agency = new EnumMap<Obj, Att>(Obj.class); static { Agency.put(Obj.UNKOBJ, Att.AGENCY); }
+	private static final EnumMap<Obj, Att> Anomaly = new EnumMap<Obj, Att>(Obj.class); static { Anomaly.put(Obj.UNKOBJ, Att.VALLMA); }
+	private static final EnumMap<Obj, Att> Authority = new EnumMap<Obj, Att>(Obj.class); static { Authority.put(Obj.UNKOBJ, Att.SURATH); }
+	private static final EnumMap<Obj, Att> Availability = new EnumMap<Obj, Att>(Obj.class); static { Availability.put(Obj.UNKOBJ, Att.BUNVES); }
+	private static final EnumMap<Obj, Att> Bank = new EnumMap<Obj, Att>(Obj.class); static { Bank.put(Obj.UNKOBJ, Att.BNKWTW); }
+	private static final EnumMap<Obj, Att> Callsign = new EnumMap<Obj, Att>(Obj.class); static { Callsign.put(Obj.UNKOBJ, Att.CALSGN); }
+	private static final EnumMap<Obj, Att> Category = new EnumMap<Obj, Att>(Obj.class); static {
+		Category.put(Obj.ACHARE, Att.CATACH); Category.put(Obj.ACHBRT, Att.CATACH); Category.put(Obj.AIRARE, Att.CATAIR); Category.put(Obj.BCNCAR, Att.CATCAM); Category.put(Obj.BCNLAT, Att.CATLAM);
+		Category.put(Obj.BCNSPP, Att.CATSPM); Category.put(Obj.BCNWTW, Att.CATWWM); Category.put(Obj.BOYLAT, Att.CATLAM); Category.put(Obj.BOYINB, Att.CATINB); Category.put(Obj.BOYSPP, Att.CATSPM);
+		Category.put(Obj.BRIDGE, Att.CATBRG); Category.put(Obj.BUAARE, Att.CATBUA); Category.put(Obj.BUNSTA, Att.CATBUN); Category.put(Obj.CANALS, Att.CATCAN); Category.put(Obj.CANBNK, Att.CATBNK);
+		Category.put(Obj.CBLARE, Att.CATCBL); Category.put(Obj.CBLOHD, Att.CATCBL); Category.put(Obj.CBLSUB, Att.CATCBL); Category.put(Obj.CHKPNT, Att.CATCHP); Category.put(Obj.COMARE, Att.CATCOM);
+		Category.put(Obj.COALNE, Att.CATCOA); Category.put(Obj.CONVYR, Att.CATCON); Category.put(Obj.CRANES, Att.CATCRN); Category.put(Obj.CTRPNT, Att.CATCTR); Category.put(Obj.DAMCON, Att.CATDAM);
+		Category.put(Obj.DISMAR, Att.CATDIS); Category.put(Obj.DMPGRD, Att.CATDPG); Category.put(Obj.DOCARE, Att.CATDOC); Category.put(Obj.EXCNST, Att.CATEXS); Category.put(Obj.FERYRT, Att.CATFRY);
+		Category.put(Obj.FNCLNE, Att.CATFNC); Category.put(Obj.FOGSIG, Att.CATFOG); Category.put(Obj.FORSTC, Att.CATFOR); Category.put(Obj.FSHFAC, Att.CATFIF); Category.put(Obj.GATCON, Att.CATGAT);
+		Category.put(Obj.HRBFAC, Att.CATHAF); Category.put(Obj.HRBARE, Att.CATHBR); Category.put(Obj.HRBBSN, Att.CATHBR); Category.put(Obj.HULKES, Att.CATHLK); Category.put(Obj.ICEARE, Att.CATICE);
+		Category.put(Obj.LNDRGN, Att.CATLND); Category.put(Obj.LNDMRK, Att.CATLMK); Category.put(Obj.LIGHTS, Att.CATLIT); Category.put(Obj.M_COVR, Att.CATCVR); Category.put(Obj.MARCUL, Att.CATMFA);
+		Category.put(Obj.MIPARE, Att.CATMPA); Category.put(Obj.MORFAC, Att.CATMOR); Category.put(Obj.NAVLNE, Att.CATNAV); Category.put(Obj.NOTMRK, Att.CATNMK); Category.put(Obj.OBSTRN, Att.CATOBS);
+		Category.put(Obj.OFSPLF, Att.CATOFP); Category.put(Obj.OILBAR, Att.CATOLB); Category.put(Obj.OSPARE, Att.CATPRA); Category.put(Obj.PILPNT, Att.CATPLE); Category.put(Obj.PILBOP, Att.CATPIL);
+		Category.put(Obj.PIPARE, Att.CATPIP); Category.put(Obj.PIPOHD, Att.CATPIP); Category.put(Obj.PIPSOL, Att.CATPIP); Category.put(Obj.PRDARE, Att.CATPRA); Category.put(Obj.PYLONS, Att.CATPYL);
+		Category.put(Obj.RADSTA, Att.CATRAS); Category.put(Obj.RCRTCL, Att.CATTRK); Category.put(Obj.RCTLPT, Att.CATTRK); Category.put(Obj.RDOSTA, Att.CATROS); Category.put(Obj.RDOCAL, Att.CATCOM);
+		Category.put(Obj.RECTRC, Att.CATTRK); Category.put(Obj.REFDMP, Att.CATRFD); Category.put(Obj.RESARE, Att.CATREA); Category.put(Obj.RIVBNK, Att.CATBNK); Category.put(Obj.RSCSTA, Att.CATRSC);
+		Category.put(Obj.RTPBCN, Att.CATRTB); Category.put(Obj.ROADWY, Att.CATROD); Category.put(Obj.RUNWAY, Att.CATRUN); Category.put(Obj.SEAARE, Att.CATSEA); Category.put(Obj.SILTNK, Att.CATSIL);
+		Category.put(Obj.SISTAT, Att.CATSIT); Category.put(Obj.SISTAW, Att.CATSIW); Category.put(Obj.SLCONS, Att.CATSLC); Category.put(Obj.SLOTOP, Att.CATSLO); Category.put(Obj.SLOGRD, Att.CATSLO);
+		Category.put(Obj.SMCFAC, Att.CATSCF); Category.put(Obj.TERMNL, Att.CATTML); Category.put(Obj.TS_FEB, Att.CAT_TS); Category.put(Obj.TSELNE, Att.CATTSS); Category.put(Obj.TSEZNE, Att.CATTSS);
+		Category.put(Obj.TSSBND, Att.CATTSS); Category.put(Obj.TSSCRS, Att.CATTSS); Category.put(Obj.TSSLPT, Att.CATTSS); Category.put(Obj.TSSRON, Att.CATTSS); Category.put(Obj.TWRTPT, Att.CATTRK);
+		Category.put(Obj.VEGATN, Att.CATVEG); Category.put(Obj.VEHTRF, Att.CATVTR); Category.put(Obj.WATTUR, Att.CATWAT); Category.put(Obj.WEDKLP, Att.CATWED); Category.put(Obj.WRECKS, Att.CATWRK);
+		Category.put(Obj.WTWAXS, Att.CATCCL); Category.put(Obj.WTWARE, Att.CATCCL); Category.put(Obj.WTWGAG, Att.CATGAG); Category.put(Obj.BERTHS, Att.CATBRT);
+	}
+	private static final EnumMap<Obj, Att> Channel = new EnumMap<Obj, Att>(Obj.class); static { Channel.put(Obj.UNKOBJ, Att.COMCHA); }
+	private static final EnumMap<Obj, Att> Character = new EnumMap<Obj, Att>(Obj.class); static { Character.put(Obj.UNKOBJ, Att.LITCHR); }
+	private static final EnumMap<Obj, Att> Clearance_height = new EnumMap<Obj, Att>(Obj.class); static { Clearance_height.put(Obj.UNKOBJ, Att.VERCLR); }
+	private static final EnumMap<Obj, Att> Clearance_height_closed = new EnumMap<Obj, Att>(Obj.class); static { Clearance_height_closed.put(Obj.UNKOBJ, Att.VERCCL); }
+	private static final EnumMap<Obj, Att> Clearance_height_open = new EnumMap<Obj, Att>(Obj.class); static { Clearance_height_open.put(Obj.UNKOBJ, Att.VERCOP); }
+	private static final EnumMap<Obj, Att> Clearance_height_safe = new EnumMap<Obj, Att>(Obj.class); static { Clearance_height_safe.put(Obj.UNKOBJ, Att.VERCSA); }
+	private static final EnumMap<Obj, Att> Clearance_width = new EnumMap<Obj, Att>(Obj.class); static { Clearance_width.put(Obj.UNKOBJ, Att.HORCLR); }
+	private static final EnumMap<Obj, Att> Colour = new EnumMap<Obj, Att>(Obj.class); static { Colour.put(Obj.UNKOBJ, Att.COLOUR); }
+	private static final EnumMap<Obj, Att> Colour_pattern = new EnumMap<Obj, Att>(Obj.class); static { Colour_pattern.put(Obj.UNKOBJ, Att.COLPAT); }
+	private static final EnumMap<Obj, Att> Communication = new EnumMap<Obj, Att>(Obj.class); static { Communication.put(Obj.UNKOBJ, Att.COMCTN); }
+	private static final EnumMap<Obj, Att> Condition = new EnumMap<Obj, Att>(Obj.class); static { Condition.put(Obj.UNKOBJ, Att.CONDTN); }
+	private static final EnumMap<Obj, Att> Conspicuity = new EnumMap<Obj, Att>(Obj.class); static { Conspicuity.put(Obj.UNKOBJ, Att.CONVIS); }
+	private static final EnumMap<Obj, Att> Construction = new EnumMap<Obj, Att>(Obj.class); static { Construction.put(Obj.UNKOBJ, Att.NATCON); }
+	private static final EnumMap<Obj, Att> Danger_class = new EnumMap<Obj, Att>(Obj.class); static { Danger_class.put(Obj.UNKOBJ, Att.CLSDNG); }
+	private static final EnumMap<Obj, Att> Date = new EnumMap<Obj, Att>(Obj.class); static { Date.put(Obj.UNKOBJ, Att.RECDAT); }
+	private static final EnumMap<Obj, Att> Depth = new EnumMap<Obj, Att>(Obj.class); static { Depth.put(Obj.UNKOBJ, Att.VALDCO); Depth.put(Obj.SOUNDG, Att.VALSOU); }
+	private static final EnumMap<Obj, Att> Depth_buried = new EnumMap<Obj, Att>(Obj.class); static { Depth_buried.put(Obj.UNKOBJ, Att.BURDEP); }
+	private static final EnumMap<Obj, Att> Depth_units = new EnumMap<Obj, Att>(Obj.class); static { Depth_units.put(Obj.UNKOBJ, Att.DUNITS); }
+	private static final EnumMap<Obj, Att> Description = new EnumMap<Obj, Att>(Obj.class); static { Description.put(Obj.UNKOBJ, Att.TXTDSC); }
+	private static final EnumMap<Obj, Att> Distance = new EnumMap<Obj, Att>(Obj.class); static { Distance.put(Obj.UNKOBJ, Att.WTWDIS); }
+	private static final EnumMap<Obj, Att> Distance_down = new EnumMap<Obj, Att>(Obj.class); static { Distance_down.put(Obj.UNKOBJ, Att.DISIPD); }
+	private static final EnumMap<Obj, Att> Distance_end = new EnumMap<Obj, Att>(Obj.class); static { Distance_end.put(Obj.UNKOBJ, Att.DISBK2); }
+	private static final EnumMap<Obj, Att> Distance_start = new EnumMap<Obj, Att>(Obj.class); static { Distance_start.put(Obj.UNKOBJ, Att.DISBK1); }
+	private static final EnumMap<Obj, Att> Distance_up = new EnumMap<Obj, Att>(Obj.class); static { Distance_up.put(Obj.UNKOBJ, Att.DISIPU); }
+	private static final EnumMap<Obj, Att> Elevation = new EnumMap<Obj, Att>(Obj.class); static { Elevation.put(Obj.UNKOBJ, Att.ELEVAT); }
+	private static final EnumMap<Obj, Att> End_date = new EnumMap<Obj, Att>(Obj.class); static { End_date.put(Obj.UNKOBJ, Att.DATEND); }
+	private static final EnumMap<Obj, Att> End_time = new EnumMap<Obj, Att>(Obj.class); static { End_time.put(Obj.UNKOBJ, Att.TIMEND); }
+	private static final EnumMap<Obj, Att> Estimated_range = new EnumMap<Obj, Att>(Obj.class); static { Estimated_range.put(Obj.UNKOBJ, Att.ESTRNG); }
+	private static final EnumMap<Obj, Att> Exhibition = new EnumMap<Obj, Att>(Obj.class); static { Exhibition.put(Obj.UNKOBJ, Att.EXCLIT); }
+	private static final EnumMap<Obj, Att> Exposition = new EnumMap<Obj, Att>(Obj.class); static { Exposition.put(Obj.UNKOBJ, Att.EXPSOU); }
+	private static final EnumMap<Obj, Att> Factor = new EnumMap<Obj, Att>(Obj.class); static { Factor.put(Obj.UNKOBJ, Att.ICEFAC); }
+	private static final EnumMap<Obj, Att> Frequency = new EnumMap<Obj, Att>(Obj.class); static { Frequency.put(Obj.UNKOBJ, Att.SIGFRQ); }
+	private static final EnumMap<Obj, Att> Function = new EnumMap<Obj, Att>(Obj.class); static { Function.put(Obj.BUISGL, Att.FUNCTN); Function.put(Obj.LNDMRK, Att.FUNCTN); Function.put(Obj.NOTMRK, Att.FNCTNM); }
+	private static final EnumMap<Obj, Att> Generation = new EnumMap<Obj, Att>(Obj.class); static { Generation.put(Obj.UNKOBJ, Att.SIGGEN); }
+	private static final EnumMap<Obj, Att> Goods = new EnumMap<Obj, Att>(Obj.class); static { Goods.put(Obj.UNKOBJ, Att.TRSHGD); }
+	private static final EnumMap<Obj, Att> Gravity_reference = new EnumMap<Obj, Att>(Obj.class); static { Gravity_reference.put(Obj.UNKOBJ, Att.REFLEV); }
+	private static final EnumMap<Obj, Att> Group = new EnumMap<Obj, Att>(Obj.class); static { Group.put(Obj.UNKOBJ, Att.SIGGRP); }
+	private static final EnumMap<Obj, Att> Height = new EnumMap<Obj, Att>(Obj.class); static { Height.put(Obj.UNKOBJ, Att.HEIGHT); }
+	private static final EnumMap<Obj, Att> High_name = new EnumMap<Obj, Att>(Obj.class); static { High_name.put(Obj.UNKOBJ, Att.HIGNAM); }
+	private static final EnumMap<Obj, Att> High_value = new EnumMap<Obj, Att>(Obj.class); static { High_value.put(Obj.UNKOBJ, Att.HIGWAT); }
+	private static final EnumMap<Obj, Att> High_velocity = new EnumMap<Obj, Att>(Obj.class); static { High_velocity.put(Obj.UNKOBJ, Att.CURVHW); }
+	private static final EnumMap<Obj, Att> Horizontal_clearance_length = new EnumMap<Obj, Att>(Obj.class); static { Horizontal_clearance_length.put(Obj.UNKOBJ, Att.HORCLL); }
+	private static final EnumMap<Obj, Att> Horizontal_clearance_width = new EnumMap<Obj, Att>(Obj.class); static { Horizontal_clearance_width.put(Obj.UNKOBJ, Att.HORCLW); }
+	private static final EnumMap<Obj, Att> Horizontal_datum = new EnumMap<Obj, Att>(Obj.class); static { Horizontal_datum.put(Obj.UNKOBJ, Att.HORDAT); }
+	private static final EnumMap<Obj, Att> Impact = new EnumMap<Obj, Att>(Obj.class); static { Impact.put(Obj.UNKOBJ, Att.DIRIMP); }
+	private static final EnumMap<Obj, Att> Indication = new EnumMap<Obj, Att>(Obj.class); static { Indication.put(Obj.UNKOBJ, Att.RECIND); }
+	private static final EnumMap<Obj, Att> Information = new EnumMap<Obj, Att>(Obj.class); static { Information.put(Obj.UNKOBJ, Att.INFORM); }
+	private static final EnumMap<Obj, Att> Jurisdiction = new EnumMap<Obj, Att>(Obj.class); static { Jurisdiction.put(Obj.UNKOBJ, Att.JRSDTN); }
+	private static final EnumMap<Obj, Att> Length = new EnumMap<Obj, Att>(Obj.class); static { Length.put(Obj.UNKOBJ, Att.HORLEN); }
+	private static final EnumMap<Obj, Att> Local_name = new EnumMap<Obj, Att>(Obj.class); static { Local_name.put(Obj.UNKOBJ, Att.OTHNAM); }
+	private static final EnumMap<Obj, Att> Local_value = new EnumMap<Obj, Att>(Obj.class); static { Local_value.put(Obj.UNKOBJ, Att.OTHWAT); }
+	private static final EnumMap<Obj, Att> Low_name = new EnumMap<Obj, Att>(Obj.class); static { Low_name.put(Obj.UNKOBJ, Att.LOWNAM); }
+	private static final EnumMap<Obj, Att> Low_value = new EnumMap<Obj, Att>(Obj.class); static { Low_value.put(Obj.UNKOBJ, Att.LOWWAT); }
+	private static final EnumMap<Obj, Att> Low_velocity = new EnumMap<Obj, Att>(Obj.class); static { Low_velocity.put(Obj.UNKOBJ, Att.CURVLW); }
+	private static final EnumMap<Obj, Att> Maximum_depth = new EnumMap<Obj, Att>(Obj.class); static { Maximum_depth.put(Obj.UNKOBJ, Att.DRVAL2); }
+	private static final EnumMap<Obj, Att> Maximum_elevation = new EnumMap<Obj, Att>(Obj.class); static { Maximum_elevation.put(Obj.UNKOBJ, Att.ELEVA2); }
+	private static final EnumMap<Obj, Att> Maximum_load = new EnumMap<Obj, Att>(Obj.class); static { Maximum_load.put(Obj.UNKOBJ, Att.LIFCAP); }
+	private static final EnumMap<Obj, Att> Maximum_range = new EnumMap<Obj, Att>(Obj.class); static { Maximum_range.put(Obj.UNKOBJ, Att.VALMXR); }
+	private static final EnumMap<Obj, Att> Maximum_sounding = new EnumMap<Obj, Att>(Obj.class); static { Maximum_sounding.put(Obj.UNKOBJ, Att.SDISMX); }
+	private static final EnumMap<Obj, Att> Mean_name = new EnumMap<Obj, Att>(Obj.class); static { Mean_name.put(Obj.UNKOBJ, Att.MEANAM); }
+	private static final EnumMap<Obj, Att> Mean_value = new EnumMap<Obj, Att>(Obj.class); static { Mean_value.put(Obj.UNKOBJ, Att.MEAWAT); }
+	private static final EnumMap<Obj, Att> Mean_velocity = new EnumMap<Obj, Att>(Obj.class); static { Mean_velocity.put(Obj.UNKOBJ, Att.CURVMW); }
+	private static final EnumMap<Obj, Att> Message = new EnumMap<Obj, Att>(Obj.class); static { Message.put(Obj.UNKOBJ, Att.UPDMSG); }
+	private static final EnumMap<Obj, Att> Minimum_depth = new EnumMap<Obj, Att>(Obj.class); static { Minimum_depth.put(Obj.UNKOBJ, Att.DRVAL1); }
+	private static final EnumMap<Obj, Att> Minimum_elevation = new EnumMap<Obj, Att>(Obj.class); static { Minimum_elevation.put(Obj.UNKOBJ, Att.ELEVA1); }
+	private static final EnumMap<Obj, Att> Minimum_sounding = new EnumMap<Obj, Att>(Obj.class); static { Minimum_sounding.put(Obj.UNKOBJ, Att.SDISMN); }
+	private static final EnumMap<Obj, Att> Multiple = new EnumMap<Obj, Att>(Obj.class); static { Multiple.put(Obj.UNKOBJ, Att.MLTYLT); }
+	private static final EnumMap<Obj, Att> Name = new EnumMap<Obj, Att>(Obj.class); static { Name.put(Obj.UNKOBJ, Att.OBJNAM); }
+	private static final EnumMap<Obj, Att> National_information = new EnumMap<Obj, Att>(Obj.class); static { National_information.put(Obj.UNKOBJ, Att.NINFOM); }
+	private static final EnumMap<Obj, Att> Nationality = new EnumMap<Obj, Att>(Obj.class); static { Nationality.put(Obj.UNKOBJ, Att.NATION); }
+	private static final EnumMap<Obj, Att> National_description = new EnumMap<Obj, Att>(Obj.class); static { National_description.put(Obj.UNKOBJ, Att.NTXTDS); }
+	private static final EnumMap<Obj, Att> National_name = new EnumMap<Obj, Att>(Obj.class); static { National_name.put(Obj.UNKOBJ, Att.NOBJNM); }
+	private static final EnumMap<Obj, Att> National_pilot_district = new EnumMap<Obj, Att>(Obj.class); static { National_pilot_district.put(Obj.UNKOBJ, Att.NPLDST); }
+	private static final EnumMap<Obj, Att> Nm_date = new EnumMap<Obj, Att>(Obj.class); static { Nm_date.put(Obj.UNKOBJ, Att.NMDATE); }
+	private static final EnumMap<Obj, Att> Other_velocity = new EnumMap<Obj, Att>(Obj.class); static { Other_velocity.put(Obj.UNKOBJ, Att.CURVOW); }
+	private static final EnumMap<Obj, Att> Operation = new EnumMap<Obj, Att>(Obj.class); static { Operation.put(Obj.UNKOBJ, Att.CATTAB); }
+	private static final EnumMap<Obj, Att> Orientation = new EnumMap<Obj, Att>(Obj.class); static { Orientation.put(Obj.UNKOBJ, Att.ORIENT); }
+	private static final EnumMap<Obj, Att> Passing_time = new EnumMap<Obj, Att>(Obj.class); static { Passing_time.put(Obj.UNKOBJ, Att.APTREF); }
+	private static final EnumMap<Obj, Att> Period = new EnumMap<Obj, Att>(Obj.class); static { Period.put(Obj.UNKOBJ, Att.SIGPER); }
+	private static final EnumMap<Obj, Att> Period_end = new EnumMap<Obj, Att>(Obj.class); static { Period_end.put(Obj.UNKOBJ, Att.PEREND); }
+	private static final EnumMap<Obj, Att> Period_start = new EnumMap<Obj, Att>(Obj.class); static { Period_start.put(Obj.UNKOBJ, Att.PERSTA); }
+	private static final EnumMap<Obj, Att> Pilot_district = new EnumMap<Obj, Att>(Obj.class); static { Pilot_district.put(Obj.UNKOBJ, Att.PILDST); }
+	private static final EnumMap<Obj, Att> Position_quality = new EnumMap<Obj, Att>(Obj.class); static { Position_quality.put(Obj.UNKOBJ, Att.QUAPOS); }
+	private static final EnumMap<Obj, Att> Positional_accuracy = new EnumMap<Obj, Att>(Obj.class); static { Positional_accuracy.put(Obj.UNKOBJ, Att.POSACC); }
+	private static final EnumMap<Obj, Att> Positional_units = new EnumMap<Obj, Att>(Obj.class); static { Positional_units.put(Obj.UNKOBJ, Att.PUNITS); }
+	private static final EnumMap<Obj, Att> Producing_country = new EnumMap<Obj, Att>(Obj.class); static { Producing_country.put(Obj.UNKOBJ, Att.PRCTRY); }
+	private static final EnumMap<Obj, Att> Product = new EnumMap<Obj, Att>(Obj.class); static { Product.put(Obj.UNKOBJ, Att.PRODCT); }
+	private static final EnumMap<Obj, Att> Quality = new EnumMap<Obj, Att>(Obj.class); static { Quality.put(Obj.UNKOBJ, Att.QUASOU); }
+	private static final EnumMap<Obj, Att> Radius = new EnumMap<Obj, Att>(Obj.class); static { Radius.put(Obj.UNKOBJ, Att.RADIUS); Radius.put(Obj.LIGHTS, Att.LITRAD); }
+	private static final EnumMap<Obj, Att> Range = new EnumMap<Obj, Att>(Obj.class); static { Range.put(Obj.UNKOBJ, Att.VALNMR); }
+	private static final EnumMap<Obj, Att> Reference = new EnumMap<Obj, Att>(Obj.class); static { Reference.put(Obj.UNKOBJ, Att.PUBREF); }
+	private static final EnumMap<Obj, Att> Reflectivity = new EnumMap<Obj, Att>(Obj.class); static { Reflectivity.put(Obj.UNKOBJ, Att.CONRAD); }
+	private static final EnumMap<Obj, Att> Restriction = new EnumMap<Obj, Att>(Obj.class); static { Restriction.put(Obj.UNKOBJ, Att.RESTRN); }
+	private static final EnumMap<Obj, Att> Schedule = new EnumMap<Obj, Att>(Obj.class); static { Schedule.put(Obj.UNKOBJ, Att.SCHREF); }
+	private static final EnumMap<Obj, Att> Shape = new EnumMap<Obj, Att>(Obj.class); static { Shape.put(Obj.BCNCAR, Att.BCNSHP); Shape.put(Obj.BCNISD, Att.BCNSHP);
+		Shape.put(Obj.BCNLAT, Att.BCNSHP); Shape.put(Obj.BCNSAW, Att.BCNSHP); Shape.put(Obj.BCNSPP, Att.BCNSHP); Shape.put(Obj.BCNWTW, Att.BCNSHP); Shape.put(Obj.BUISGL, Att.BUISHP);
+		Shape.put(Obj.BOYCAR, Att.BOYSHP); Shape.put(Obj.BOYISD, Att.BOYSHP); Shape.put(Obj.BOYLAT, Att.BOYSHP); Shape.put(Obj.BOYSAW, Att.BOYSHP); Shape.put(Obj.BOYSPP, Att.BOYSHP);
+		Shape.put(Obj.BOYWTW, Att.BOYSHP); Shape.put(Obj.BOYINB, Att.BOYSHP); Shape.put(Obj.DAYMAR, Att.TOPSHP); Shape.put(Obj.TOPMAR, Att.TOPSHP); Shape.put(Obj.MORFAC, Att.BOYSHP);
+		Shape.put(Obj.SILTNK, Att.BUISHP);
+	}
+	private static final EnumMap<Obj, Att> Sector_end = new EnumMap<Obj, Att>(Obj.class); static { Sector_end.put(Obj.UNKOBJ, Att.SECTR2); }
+	private static final EnumMap<Obj, Att> Sector_start = new EnumMap<Obj, Att>(Obj.class); static { Sector_start.put(Obj.UNKOBJ, Att.SECTR1); }
+	private static final EnumMap<Obj, Att> Sequence = new EnumMap<Obj, Att>(Obj.class); static { Sequence.put(Obj.UNKOBJ, Att.SIGSEQ); }
+	private static final EnumMap<Obj, Att> Shift = new EnumMap<Obj, Att>(Obj.class); static { Shift.put(Obj.UNKOBJ, Att.SHIPAM); }
+	private static final EnumMap<Obj, Att> Ship = new EnumMap<Obj, Att>(Obj.class); static { Ship.put(Obj.UNKOBJ, Att.SHPTYP); }
+	private static final EnumMap<Obj, Att> Sounding_accuracy = new EnumMap<Obj, Att>(Obj.class); static { Sounding_accuracy.put(Obj.UNKOBJ, Att.SOUACC); }
+	private static final EnumMap<Obj, Att> Sounding_name = new EnumMap<Obj, Att>(Obj.class); static { Sounding_name.put(Obj.UNKOBJ, Att.SDRLEV); }
+	private static final EnumMap<Obj, Att> Start_date = new EnumMap<Obj, Att>(Obj.class); static { Start_date.put(Obj.UNKOBJ, Att.DATSTA); }
+	private static final EnumMap<Obj, Att> Start_time = new EnumMap<Obj, Att>(Obj.class); static { Start_time.put(Obj.UNKOBJ, Att.TIMSTA); }
+	private static final EnumMap<Obj, Att> Status = new EnumMap<Obj, Att>(Obj.class); static { Status.put(Obj.UNKOBJ, Att.STATUS); }
+	private static final EnumMap<Obj, Att> Surface = new EnumMap<Obj, Att>(Obj.class); static { Surface.put(Obj.UNKOBJ, Att.NATSUR); }
+	private static final EnumMap<Obj, Att> Surface_qualification = new EnumMap<Obj, Att>(Obj.class); static { Surface_qualification.put(Obj.UNKOBJ, Att.NATQUA); }
+	private static final EnumMap<Obj, Att> Survey = new EnumMap<Obj, Att>(Obj.class); static { Survey.put(Obj.UNKOBJ, Att.SURTYP); }
+	private static final EnumMap<Obj, Att> Survey_end = new EnumMap<Obj, Att>(Obj.class); static { Survey_end.put(Obj.UNKOBJ, Att.SUREND); }
+	private static final EnumMap<Obj, Att> Survey_start = new EnumMap<Obj, Att>(Obj.class); static { Survey_start.put(Obj.UNKOBJ, Att.SURSTA); }
+	private static final EnumMap<Obj, Att> System = new EnumMap<Obj, Att>(Obj.class); static { System.put(Obj.UNKOBJ, Att.MARSYS); }
+	private static final EnumMap<Obj, Att> Technique = new EnumMap<Obj, Att>(Obj.class); static { Technique.put(Obj.UNKOBJ, Att.TECSOU); }
+	private static final EnumMap<Obj, Att> Traffic_flow = new EnumMap<Obj, Att>(Obj.class); static { Traffic_flow.put(Obj.UNKOBJ, Att.TRAFIC); }
+	private static final EnumMap<Obj, Att> Units = new EnumMap<Obj, Att>(Obj.class); static { Units.put(Obj.UNKOBJ, Att.HUNITS); }
+	private static final EnumMap<Obj, Att> Use = new EnumMap<Obj, Att>(Obj.class); static { Use.put(Obj.UNKOBJ, Att.USESHP); }
+	private static final EnumMap<Obj, Att> Variation = new EnumMap<Obj, Att>(Obj.class); static { Variation.put(Obj.UNKOBJ, Att.VALMAG); }
+	private static final EnumMap<Obj, Att> Variation_change = new EnumMap<Obj, Att>(Obj.class); static { Variation_change.put(Obj.UNKOBJ, Att.VALACM); }
+	private static final EnumMap<Obj, Att> Velocity = new EnumMap<Obj, Att>(Obj.class); static { Velocity.put(Obj.UNKOBJ, Att.CURVEL); }
+	private static final EnumMap<Obj, Att> Vertical_accuracy = new EnumMap<Obj, Att>(Obj.class); static { Vertical_accuracy.put(Obj.UNKOBJ, Att.VERACC); }
+	private static final EnumMap<Obj, Att> Vertical_datum = new EnumMap<Obj, Att>(Obj.class); static { Vertical_datum.put(Obj.UNKOBJ, Att.VERDAT); }
+	private static final EnumMap<Obj, Att> Vertical_length = new EnumMap<Obj, Att>(Obj.class); static { Vertical_length.put(Obj.UNKOBJ, Att.VERLEN); }
+	private static final EnumMap<Obj, Att> Vertical_name = new EnumMap<Obj, Att>(Obj.class); static { Vertical_name.put(Obj.UNKOBJ, Att.VCRLEV); }
+	private static final EnumMap<Obj, Att> Visibility = new EnumMap<Obj, Att>(Obj.class); static { Visibility.put(Obj.UNKOBJ, Att.LITVIS); }
+	private static final EnumMap<Obj, Att> Water_level = new EnumMap<Obj, Att>(Obj.class); static { Water_level.put(Obj.UNKOBJ, Att.WATLEV); }
+	private static final EnumMap<Obj, Att> Wavelength = new EnumMap<Obj, Att>(Obj.class); static { Wavelength.put(Obj.UNKOBJ, Att.RADWAL); }
+	private static final EnumMap<Obj, Att> Width = new EnumMap<Obj, Att>(Obj.class); static { Width.put(Obj.UNKOBJ, Att.HORWID); }
+	private static final EnumMap<Obj, Att> Year = new EnumMap<Obj, Att>(Obj.class); static { Year.put(Obj.UNKOBJ, Att.RYRMGV); }
+	
+	private static final HashMap<String, EnumMap<Obj, Att>> StrAtt = new HashMap<String, EnumMap<Obj, Att>>();
+	static {
+		StrAtt.put("accuracy", Accuracy); StrAtt.put("addition", Addition); StrAtt.put("agency", Agency); StrAtt.put("anomaly", Anomaly); StrAtt.put("authority", Authority);
+		StrAtt.put("availability", Availability); StrAtt.put("bank", Bank); StrAtt.put("callsign", Callsign); StrAtt.put("category", Category); StrAtt.put("channel", Channel);
+		StrAtt.put("character", Character); StrAtt.put("clearance_height", Clearance_height); StrAtt.put("clearance_height_closed", Clearance_height_closed);
+		StrAtt.put("clearance_height_open", Clearance_height_open); StrAtt.put("clearance_height_safe", Clearance_height_safe); StrAtt.put("clearance_width", Clearance_width);
+		StrAtt.put("colour", Colour); StrAtt.put("colour_pattern", Colour_pattern); StrAtt.put("communication", Communication); StrAtt.put("condition", Condition);
+		StrAtt.put("conspicuity", Conspicuity); StrAtt.put("construction", Construction); StrAtt.put("danger_class", Danger_class); StrAtt.put("date", Date); StrAtt.put("depth", Depth);
+		StrAtt.put("depth_buried", Depth_buried); StrAtt.put("depth_units", Depth_units); StrAtt.put("description", Description); StrAtt.put("distance", Distance);
+		StrAtt.put("distance_down", Distance_down); StrAtt.put("distance_end", Distance_end); StrAtt.put("distance_start", Distance_start); StrAtt.put("distance_up", Distance_up);
+		StrAtt.put("elevation", Elevation); StrAtt.put("end_date", End_date); StrAtt.put("end_time", End_time); StrAtt.put("estimated_range", Estimated_range);
+		StrAtt.put("exhibition", Exhibition); StrAtt.put("exposition", Exposition); StrAtt.put("factor", Factor); StrAtt.put("frequency", Frequency); StrAtt.put("function", Function);
+		StrAtt.put("generation", Generation); StrAtt.put("goods", Goods); StrAtt.put("gravity_reference", Gravity_reference); StrAtt.put("group", Group);
+		StrAtt.put("height", Height); StrAtt.put("high_name", High_name); StrAtt.put("high_value", High_value); StrAtt.put("high_velocity", High_velocity);
+		StrAtt.put("horizontal_clearance_length", Horizontal_clearance_length); StrAtt.put("horizontal_clearance_width", Horizontal_clearance_width);
+		StrAtt.put("horizontal_datum", Horizontal_datum); StrAtt.put("impact", Impact); StrAtt.put("indication", Indication); StrAtt.put("information", Information);
+		StrAtt.put("jurisdiction", Jurisdiction); StrAtt.put("length", Length); StrAtt.put("local_name", Local_name); StrAtt.put("local_value", Local_value); StrAtt.put("low_name", Low_name);
+		StrAtt.put("low_value", Low_value); StrAtt.put("low_velocity", Low_velocity); StrAtt.put("maximum_depth", Maximum_depth); StrAtt.put("maximum_elevation", Maximum_elevation);
+		StrAtt.put("maximum_load", Maximum_load); StrAtt.put("maximum_range", Maximum_range); StrAtt.put("maximum_sounding", Maximum_sounding); StrAtt.put("mean_name", Mean_name);
+		StrAtt.put("mean_value", Mean_value); StrAtt.put("mean_velocity", Mean_velocity); StrAtt.put("message", Message); StrAtt.put("minimum_depth", Minimum_depth);
+		StrAtt.put("minimum_elevation", Minimum_elevation); StrAtt.put("minimum_sounding", Minimum_sounding); StrAtt.put("multiple", Multiple); StrAtt.put("name", Name);
+		StrAtt.put("national_information", National_information); StrAtt.put("nationality", Nationality); StrAtt.put("national_description", National_description);
+		StrAtt.put("national_name", National_name); StrAtt.put("national_pilot_district", National_pilot_district); StrAtt.put("nm_date", Nm_date); StrAtt.put("other_velocity", Other_velocity);
+		StrAtt.put("operation", Operation); StrAtt.put("orientation", Orientation); StrAtt.put("passing_time", Passing_time); StrAtt.put("period", Period); StrAtt.put("period_end", Period_end);
+		StrAtt.put("period_start", Period_start); StrAtt.put("pilot_district", Pilot_district); StrAtt.put("position_quality", Position_quality); StrAtt.put("positional_accuracy", Positional_accuracy);
+		StrAtt.put("positional_units", Positional_units); StrAtt.put("producing_country", Producing_country); StrAtt.put("product", Product); StrAtt.put("quality", Quality);
+		StrAtt.put("radius", Radius); StrAtt.put("range", Range); StrAtt.put("reference", Reference); StrAtt.put("reflectivity", Reflectivity); StrAtt.put("restriction", Restriction);
+		StrAtt.put("schedule", Schedule); StrAtt.put("shape", Shape); StrAtt.put("sector_end", Sector_end); StrAtt.put("sector_start", Sector_start); StrAtt.put("sequence", Sequence);
+		StrAtt.put("shift", Shift); StrAtt.put("ship", Ship); StrAtt.put("sounding_accuracy", Sounding_accuracy); StrAtt.put("sounding_name", Sounding_name); StrAtt.put("start_date", Start_date);
+		StrAtt.put("start_time", Start_time); StrAtt.put("status", Status); StrAtt.put("surface", Surface); StrAtt.put("surface_qualification", Surface_qualification); StrAtt.put("survey", Survey);
+		StrAtt.put("survey_end", Survey_end); StrAtt.put("survey_start", Survey_start); StrAtt.put("system", System); StrAtt.put("technique", Technique); StrAtt.put("traffic_flow", Traffic_flow);
+		StrAtt.put("units", Units); StrAtt.put("use", Use); StrAtt.put("variation", Variation); StrAtt.put("variation_change", Variation_change); StrAtt.put("velocity", Velocity);
+		StrAtt.put("vertical_accuracy", Vertical_accuracy); StrAtt.put("vertical_datum", Vertical_datum); StrAtt.put("vertical_length", Vertical_length); StrAtt.put("vertical_name", Vertical_name);
+		StrAtt.put("visibility", Visibility); StrAtt.put("water_level", Water_level); StrAtt.put("wavelength", Wavelength); StrAtt.put("width", Width); StrAtt.put("year", Year);
+	}
+
+	public static Att decodeAttribute(long attribute) {	// Convert S57 attribute code to OSeaM attribute enumeration
+		Att att = S57Att.get((int)attribute);
+		return (att != null) ? att : Att.UNKATT;
+	}
+	
+	public static Integer encodeAttribute(String attribute) {	// Convert OSeaM attribute enumeration to S57 attribute code
+		if (AttS57.containsKey(attribute))
+			return AttS57.get(attribute);
+		else if (AttIENC.containsKey(attribute))
+			return AttIENC.get(attribute);
+		return 0;
+	}
+
+	public static Integer encodeAttribute(Att attribute) {	// Convert OSeaM attribute enumeration to S57 attribute code
+	  return AttS57.get(attribute) != 0 ? AttS57.get(attribute) : AttIENC.get(attribute);
+	}
+
+	public static String stringAttribute(Att attribute) {	// Convert OSeaM enumeration to OSeaM attribute string
+		String str = AttStr.get(attribute);
+		return str != null ? str : "";
+	}
+	
+	public static Att enumAttribute(String attribute, Obj obj) {	// Convert OSeaM attribute string to OSeaM enumeration
+	  if ((attribute != null) && !attribute.isEmpty()) {
+			EnumMap<Obj, Att> map = StrAtt.get(attribute);
+			if (map != null) {
+				if (map.containsKey(obj)) {
+					return map.get(obj);
+				} else if (map.containsKey(Obj.UNKOBJ)) {
+					return map.get(Obj.UNKOBJ);
+				} else {
+					return Att.UNKATT;
+				}
+			}
+	  }
+		return Att.UNKATT;
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57dat.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57dat.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57dat.java	(revision 30894)
@@ -0,0 +1,311 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+
+public class S57dat {
+	
+	public enum Dom { BT, GT, DG, DATE, INT, REAL, AN, HEX, CL }
+	
+	public static class S57conv {
+		int asc;	// 0=A(), 1+=A(n)
+		int bin;	// 0=ASCII, +ve=b1n, -ve=b2n
+		Dom dom;	// S57 data domain
+		S57conv(int a, int b, Dom d) {
+			asc = a; bin = b; dom = d;
+		}
+	}
+	
+	public enum S57subf { I8RN, RCNM, RCID, EXPP, INTU, DSNM, EDTN, UPDN, UADT, ISDT, STED, PRSP, PSDN, PRED, PROF, AGEN, COMT, DSTR, AALL, NALL, NOMR, NOCR, NOGR, NOLR, NOIN, NOCN,
+		NOED, NOFA, HDAT, VDAT, SDAT, CSCL, DUNI, HUNI, PUNI, COUN, COMF, SOMF, PROJ, PRP1, PRP2, PRP3, PRP4, FEAS, FNOR, FPMF, RPID, RYCO, RXCO, CURP, RXVL, RYVL, PRCO, ESDT,
+		LSDT, DCRT, CODT, PACC, HACC, SACC, FILE, LFIL, VOLM, IMPL, SLAT, WLON, NLAT, ELON, CRCS, NAM1, NAM2, OORA, OAAC, OACO, OALL, OATY, DEFN, AUTH, RFTP, RFVL, ATLB, ATDO,
+		ADMU, ADFT, RAVA, DVAL, DVSD, OBLB, ASET, PRIM, GRUP, OBJL, RVER, RUIN, FIDN, FIDS, ATTL, ATVL, FFUI, FFIX, NFPT, LNAM, RIND, FSUI, FSIX, NSPT, NAME, ORNT, USAG, MASK,
+		VPUI, VPIX, NVPT, TOPI, CCUI, CCIX, CCNC, YCOO, XCOO, VE3D, ATYP, SURF, ORDR, RESO, STPT, CTPT, ENPT, CDPM, CDPR }
+
+	private static final EnumMap<S57subf, S57conv> convs = new EnumMap<S57subf, S57conv>(S57subf.class);
+	static {
+		convs.put(S57subf.I8RN, new S57conv(5,2,Dom.INT));
+		convs.put(S57subf.RCNM, new S57conv(2,1,Dom.AN)); convs.put(S57subf.RCID, new S57conv(10,32,Dom.INT)); convs.put(S57subf.EXPP, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.INTU, new S57conv(1,1,Dom.INT)); convs.put(S57subf.DSNM, new S57conv(0,0,Dom.BT)); convs.put(S57subf.EDTN, new S57conv(0,0,Dom.BT));
+		convs.put(S57subf.UPDN, new S57conv(0,0,Dom.BT)); convs.put(S57subf.UADT, new S57conv(8,0,Dom.DATE)); convs.put(S57subf.ISDT, new S57conv(8,0,Dom.DATE));
+		convs.put(S57subf.STED, new S57conv(4,0,Dom.REAL)); convs.put(S57subf.PRSP, new S57conv(3,1,Dom.AN)); convs.put(S57subf.PSDN, new S57conv(0,0,Dom.BT));
+		convs.put(S57subf.PRED, new S57conv(0,0,Dom.BT)); convs.put(S57subf.PROF, new S57conv(2,1,Dom.AN)); convs.put(S57subf.AGEN, new S57conv(2,2,Dom.AN));
+		convs.put(S57subf.COMT, new S57conv(0,0,Dom.BT)); convs.put(S57subf.DSTR, new S57conv(2,1,Dom.AN)); convs.put(S57subf.AALL, new S57conv(1,1,Dom.INT));
+		convs.put(S57subf.NALL, new S57conv(1,1,Dom.INT)); convs.put(S57subf.NOMR, new S57conv(0,4,Dom.INT)); convs.put(S57subf.NOCR, new S57conv(0,4,Dom.INT));
+		convs.put(S57subf.NOGR, new S57conv(0,4,Dom.INT)); convs.put(S57subf.NOLR, new S57conv(0,4,Dom.INT)); convs.put(S57subf.NOIN, new S57conv(0,4,Dom.INT));
+		convs.put(S57subf.NOCN, new S57conv(0,4,Dom.INT)); convs.put(S57subf.NOED, new S57conv(0,4,Dom.INT)); convs.put(S57subf.NOFA, new S57conv(0,4,Dom.INT));
+		convs.put(S57subf.HDAT, new S57conv(3,1,Dom.INT)); convs.put(S57subf.VDAT, new S57conv(2,1,Dom.INT)); convs.put(S57subf.SDAT, new S57conv(2,1,Dom.INT));
+		convs.put(S57subf.CSCL, new S57conv(0,4,Dom.INT)); convs.put(S57subf.DUNI, new S57conv(2,1,Dom.INT)); convs.put(S57subf.HUNI, new S57conv(2,1,Dom.INT));
+		convs.put(S57subf.PUNI, new S57conv(2,1,Dom.INT)); convs.put(S57subf.COUN, new S57conv(2,1,Dom.AN)); convs.put(S57subf.COMF, new S57conv(0,4,Dom.INT));
+		convs.put(S57subf.SOMF, new S57conv(0,4,Dom.INT)); convs.put(S57subf.PROJ, new S57conv(3,1,Dom.AN)); convs.put(S57subf.PRP1, new S57conv(0,-4,Dom.REAL));
+		convs.put(S57subf.PRP2, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.PRP3, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.PRP4, new S57conv(0,-4,Dom.REAL));
+		convs.put(S57subf.FEAS, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.FNOR, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.FPMF, new S57conv(0,4,Dom.INT));
+		convs.put(S57subf.RPID, new S57conv(1,1,Dom.DG)); convs.put(S57subf.RYCO, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.RXCO, new S57conv(0,-4,Dom.REAL));
+		convs.put(S57subf.CURP, new S57conv(2,1,Dom.AN)); convs.put(S57subf.RXVL, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.RYVL, new S57conv(0,-4,Dom.REAL));
+		convs.put(S57subf.PRCO, new S57conv(2,2,Dom.AN)); convs.put(S57subf.ESDT, new S57conv(8,0,Dom.DATE)); convs.put(S57subf.LSDT, new S57conv(8,0,Dom.DATE));
+		convs.put(S57subf.DCRT, new S57conv(0,0,Dom.BT)); convs.put(S57subf.CODT, new S57conv(8,0,Dom.DATE)); convs.put(S57subf.PACC, new S57conv(0,4,Dom.REAL));
+		convs.put(S57subf.HACC, new S57conv(0,4,Dom.REAL)); convs.put(S57subf.SACC, new S57conv(0,4,Dom.REAL)); convs.put(S57subf.FILE, new S57conv(0,0,Dom.BT));
+		convs.put(S57subf.LFIL, new S57conv(0,0,Dom.BT)); convs.put(S57subf.VOLM, new S57conv(0,0,Dom.BT)); convs.put(S57subf.IMPL, new S57conv(3,0,Dom.AN));
+		convs.put(S57subf.SLAT, new S57conv(0,0,Dom.REAL)); convs.put(S57subf.WLON, new S57conv(0,0,Dom.REAL)); convs.put(S57subf.NLAT, new S57conv(0,0,Dom.REAL));
+		convs.put(S57subf.ELON, new S57conv(0,0,Dom.REAL)); convs.put(S57subf.CRCS, new S57conv(0,0,Dom.HEX)); convs.put(S57subf.NAM1, new S57conv(12,40,Dom.AN));
+		convs.put(S57subf.NAM2, new S57conv(12,40,Dom.AN)); convs.put(S57subf.OORA, new S57conv(1,1,Dom.AN)); convs.put(S57subf.OAAC, new S57conv(6,0,Dom.BT));
+		convs.put(S57subf.OACO, new S57conv(5,2,Dom.INT)); convs.put(S57subf.OALL, new S57conv(0,0,Dom.BT)); convs.put(S57subf.OATY, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.DEFN, new S57conv(0,0,Dom.BT)); convs.put(S57subf.AUTH, new S57conv(2,2,Dom.AN)); convs.put(S57subf.RFTP, new S57conv(2,1,Dom.AN));
+		convs.put(S57subf.RFVL, new S57conv(0,0,Dom.BT)); convs.put(S57subf.ATLB, new S57conv(5,2,Dom.INT)); convs.put(S57subf.ATDO, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.ADMU, new S57conv(0,0,Dom.BT)); convs.put(S57subf.ADFT, new S57conv(0,0,Dom.BT)); convs.put(S57subf.RAVA, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.DVAL, new S57conv(0,0,Dom.BT)); convs.put(S57subf.DVSD, new S57conv(0,0,Dom.BT)); convs.put(S57subf.OBLB, new S57conv(5,2,Dom.INT));
+		convs.put(S57subf.ASET, new S57conv(1,1,Dom.AN)); convs.put(S57subf.PRIM, new S57conv(1,1,Dom.AN)); convs.put(S57subf.GRUP, new S57conv(3,1,Dom.INT));
+		convs.put(S57subf.OBJL, new S57conv(5,2,Dom.INT)); convs.put(S57subf.RVER, new S57conv(3,2,Dom.INT)); convs.put(S57subf.RUIN, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.FIDN, new S57conv(10,4,Dom.INT)); convs.put(S57subf.FIDS, new S57conv(5,2,Dom.INT)); convs.put(S57subf.ATTL, new S57conv(5,2,Dom.INT));
+		convs.put(S57subf.ATVL, new S57conv(0,0,Dom.GT)); convs.put(S57subf.FFUI, new S57conv(1,1,Dom.AN)); convs.put(S57subf.FFIX, new S57conv(0,2,Dom.INT));
+		convs.put(S57subf.NFPT, new S57conv(0,2,Dom.INT)); convs.put(S57subf.LNAM, new S57conv(17,64,Dom.AN)); convs.put(S57subf.RIND, new S57conv(0,1,Dom.AN));
+		convs.put(S57subf.FSUI, new S57conv(1,1,Dom.AN)); convs.put(S57subf.FSIX, new S57conv(0,2,Dom.INT)); convs.put(S57subf.NSPT, new S57conv(0,2,Dom.INT));
+		convs.put(S57subf.NAME, new S57conv(12,40,Dom.AN)); convs.put(S57subf.ORNT, new S57conv(1,1,Dom.AN)); convs.put(S57subf.USAG, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.MASK, new S57conv(1,1,Dom.AN)); convs.put(S57subf.VPUI, new S57conv(1,1,Dom.AN)); convs.put(S57subf.VPIX, new S57conv(0,2,Dom.INT));
+		convs.put(S57subf.NVPT, new S57conv(0,2,Dom.INT)); convs.put(S57subf.TOPI, new S57conv(1,1,Dom.AN)); convs.put(S57subf.CCUI, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.CCIX, new S57conv(0,2,Dom.INT)); convs.put(S57subf.CCNC, new S57conv(0,2,Dom.INT)); convs.put(S57subf.YCOO, new S57conv(0,-4,Dom.REAL));
+		convs.put(S57subf.XCOO, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.VE3D, new S57conv(0,-4,Dom.REAL)); convs.put(S57subf.ATYP, new S57conv(1,1,Dom.AN));
+		convs.put(S57subf.SURF, new S57conv(1,1,Dom.AN)); convs.put(S57subf.ORDR, new S57conv(1,1,Dom.INT)); convs.put(S57subf.RESO, new S57conv(0,4,Dom.REAL));
+		convs.put(S57subf.STPT, new S57conv(0,0,Dom.CL)); convs.put(S57subf.CTPT, new S57conv(0,0,Dom.CL)); convs.put(S57subf.ENPT, new S57conv(0,0,Dom.CL));
+		convs.put(S57subf.CDPM, new S57conv(0,0,Dom.CL)); convs.put(S57subf.CDPR, new S57conv(0,0,Dom.CL));
+	}
+	
+	public enum S57field { I8RI, DSID, DSSI, DSPM, DSPR, DSRC, DSHT, DSAC, CATD, CATX, DDDF, DDDR, DDDI, DDOM, DDRF, DDSI, DDSC,
+		FRID, FOID, ATTF, NATF, FFPC, FFPT, FSPC, FSPT, VRID, ATTV, VRPC, VRPT, SGCC, SG2D, SG3D, ARCC, AR2D, EL2D, CT2D }
+	
+	private static ArrayList<S57subf> S57i8ri = new ArrayList<S57subf>(Arrays.asList(S57subf.I8RN));
+	private static ArrayList<S57subf> S57dsid = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.EXPP, S57subf.INTU, S57subf.DSNM, S57subf.EDTN, S57subf.UPDN,
+			S57subf.UADT, S57subf.ISDT, S57subf.STED, S57subf.PRSP, S57subf.PSDN, S57subf.PRED, S57subf.PROF, S57subf.AGEN, S57subf.COMT));
+	private static ArrayList<S57subf> S57dssi = new ArrayList<S57subf>(Arrays.asList(S57subf.DSTR, S57subf.AALL, S57subf.NALL, S57subf.NOMR, S57subf.NOCR, S57subf.NOGR, S57subf.NOLR,
+			S57subf.NOIN, S57subf.NOCN, S57subf.NOED, S57subf.NOFA ));
+	private static ArrayList<S57subf> S57dspm = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.HDAT, S57subf.VDAT, S57subf.SDAT, S57subf.CSCL, S57subf.DUNI,
+			S57subf.HUNI, S57subf.PUNI, S57subf.COUN, S57subf.COMF, S57subf.SOMF, S57subf.COMT ));
+	private static ArrayList<S57subf> S57dspr = new ArrayList<S57subf>(Arrays.asList(S57subf.PROJ, S57subf.PRP1, S57subf.PRP2, S57subf.PRP3, S57subf.PRP4, S57subf.FEAS, S57subf.FNOR,
+			S57subf.FPMF, S57subf.COMT ));
+	private static ArrayList<S57subf> S57dsrc = new ArrayList<S57subf>(Arrays.asList(S57subf.RPID, S57subf.RYCO, S57subf.RXCO, S57subf.CURP, S57subf.FPMF, S57subf.RXVL, S57subf.RYVL,
+			S57subf.COMT ));
+	private static ArrayList<S57subf> S57dsht = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.PRCO, S57subf.ESDT, S57subf.LSDT, S57subf.DCRT, S57subf.CODT, S57subf.COMT ));
+	private static ArrayList<S57subf> S57dsac = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.PACC, S57subf.HACC, S57subf.SACC, S57subf.FPMF, S57subf.COMT ));
+	private static ArrayList<S57subf> S57catd = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.FILE, S57subf.LFIL, S57subf.VOLM, S57subf.IMPL, S57subf.SLAT,
+			S57subf.WLON, S57subf.NLAT, S57subf.ELON, S57subf.CRCS, S57subf.COMT ));
+	private static ArrayList<S57subf> S57catx = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.NAM1, S57subf.NAM2, S57subf.COMT ));
+	private static ArrayList<S57subf> S57dddf = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.OORA, S57subf.OAAC, S57subf.OACO, S57subf.OALL, S57subf.OATY,
+			S57subf.DEFN, S57subf.AUTH, S57subf.COMT ));
+	private static ArrayList<S57subf> S57dddr = new ArrayList<S57subf>(Arrays.asList(S57subf.RFTP, S57subf.RFVL ));
+	private static ArrayList<S57subf> S57dddi = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.ATLB, S57subf.ATDO, S57subf.ADMU, S57subf.ADFT, S57subf.AUTH, S57subf.COMT ));
+	private static ArrayList<S57subf> S57ddom = new ArrayList<S57subf>(Arrays.asList(S57subf.RAVA, S57subf.DVAL, S57subf.DVSD, S57subf.DEFN, S57subf.AUTH ));
+	private static ArrayList<S57subf> S57ddrf = new ArrayList<S57subf>(Arrays.asList(S57subf.RFTP, S57subf.RFVL ));
+	private static ArrayList<S57subf> S57ddsi = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.OBLB ));
+	private static ArrayList<S57subf> S57ddsc = new ArrayList<S57subf>(Arrays.asList(S57subf.ATLB, S57subf.ASET, S57subf.AUTH ));
+	private static ArrayList<S57subf> S57frid = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.PRIM, S57subf.GRUP, S57subf.OBJL, S57subf.RVER, S57subf.RUIN ));
+//	private static ArrayList<S57subf> S57foid = new ArrayList<S57subf>(Arrays.asList(S57subf.AGEN, S57subf.FIDN, S57subf.FIDS ));
+	private static ArrayList<S57subf> S57foid = new ArrayList<S57subf>(Arrays.asList(S57subf.LNAM));
+	private static ArrayList<S57subf> S57attf = new ArrayList<S57subf>(Arrays.asList(S57subf.ATTL, S57subf.ATVL ));
+	private static ArrayList<S57subf> S57natf = new ArrayList<S57subf>(Arrays.asList(S57subf.ATTL, S57subf.ATVL ));
+	private static ArrayList<S57subf> S57ffpc = new ArrayList<S57subf>(Arrays.asList(S57subf.FFUI, S57subf.FFIX, S57subf.NFPT ));
+	private static ArrayList<S57subf> S57ffpt = new ArrayList<S57subf>(Arrays.asList(S57subf.LNAM, S57subf.RIND, S57subf.COMT ));
+	private static ArrayList<S57subf> S57fspc = new ArrayList<S57subf>(Arrays.asList(S57subf.FSUI, S57subf.FSIX, S57subf.NSPT ));
+	private static ArrayList<S57subf> S57fspt = new ArrayList<S57subf>(Arrays.asList(S57subf.NAME, S57subf.ORNT, S57subf.USAG, S57subf.MASK ));
+	private static ArrayList<S57subf> S57vrid = new ArrayList<S57subf>(Arrays.asList(S57subf.RCNM, S57subf.RCID, S57subf.RVER, S57subf.RUIN ));
+	private static ArrayList<S57subf> S57attv = new ArrayList<S57subf>(Arrays.asList(S57subf.ATTL, S57subf.ATVL ));
+	private static ArrayList<S57subf> S57vrpc = new ArrayList<S57subf>(Arrays.asList(S57subf.VPUI, S57subf.VPIX, S57subf.NVPT ));
+	private static ArrayList<S57subf> S57vrpt = new ArrayList<S57subf>(Arrays.asList(S57subf.NAME, S57subf.ORNT, S57subf.USAG, S57subf.TOPI, S57subf.MASK ));
+	private static ArrayList<S57subf> S57sgcc = new ArrayList<S57subf>(Arrays.asList(S57subf.CCUI, S57subf.CCIX, S57subf.CCNC ));
+	private static ArrayList<S57subf> S57sg2d = new ArrayList<S57subf>(Arrays.asList(S57subf.YCOO, S57subf.XCOO ));
+	private static ArrayList<S57subf> S57sg3d = new ArrayList<S57subf>(Arrays.asList(S57subf.YCOO, S57subf.XCOO, S57subf.VE3D ));
+	private static ArrayList<S57subf> S57arcc = new ArrayList<S57subf>(Arrays.asList(S57subf.ATYP, S57subf.SURF, S57subf.ORDR, S57subf.RESO, S57subf.FPMF ));
+	private static ArrayList<S57subf> S57ar2d = new ArrayList<S57subf>(Arrays.asList(S57subf.STPT, S57subf.CTPT, S57subf.ENPT, S57subf.YCOO, S57subf.XCOO ));
+	private static ArrayList<S57subf> S57el2d = new ArrayList<S57subf>(Arrays.asList(S57subf.STPT, S57subf.CTPT, S57subf.ENPT, S57subf.CDPM, S57subf.CDPR, S57subf.YCOO, S57subf.XCOO ));
+	private static ArrayList<S57subf> S57ct2d = new ArrayList<S57subf>(Arrays.asList(S57subf.YCOO, S57subf.XCOO ));
+	
+	private static final EnumMap<S57field, ArrayList<S57subf>> fields = new EnumMap<S57field, ArrayList<S57subf>>(S57field.class);
+	static {
+		fields.put(S57field.I8RI, S57i8ri);
+		fields.put(S57field.DSID, S57dsid); fields.put(S57field.DSSI, S57dssi); fields.put(S57field.DSPM, S57dspm); fields.put(S57field.DSPR, S57dspr);
+		fields.put(S57field.DSRC, S57dsrc); fields.put(S57field.DSHT, S57dsht); fields.put(S57field.DSAC, S57dsac); fields.put(S57field.CATD, S57catd);
+		fields.put(S57field.CATX, S57catx); fields.put(S57field.DDDF, S57dddf); fields.put(S57field.DDDR, S57dddr); fields.put(S57field.DDDI, S57dddi);
+		fields.put(S57field.DDOM, S57ddom); fields.put(S57field.DDRF, S57ddrf); fields.put(S57field.DDSI, S57ddsi); fields.put(S57field.DDSC, S57ddsc);
+		fields.put(S57field.FRID, S57frid); fields.put(S57field.FOID, S57foid); fields.put(S57field.ATTF, S57attf); fields.put(S57field.NATF, S57natf);
+		fields.put(S57field.FFPC, S57ffpc); fields.put(S57field.FFPT, S57ffpt); fields.put(S57field.FFPC, S57fspc); fields.put(S57field.FSPT, S57fspt);
+		fields.put(S57field.VRID, S57vrid); fields.put(S57field.ATTV, S57attv); fields.put(S57field.VRPC, S57vrpc); fields.put(S57field.VRPT, S57vrpt);
+		fields.put(S57field.SGCC, S57sgcc); fields.put(S57field.SG2D, S57sg2d); fields.put(S57field.SG3D, S57sg3d); fields.put(S57field.ARCC, S57arcc);
+		fields.put(S57field.AR2D, S57ar2d); fields.put(S57field.EL2D, S57el2d); fields.put(S57field.CT2D, S57ct2d); 
+	}
+
+	private static final EnumMap<S57field, String> FldStr = new EnumMap<S57field, String>(S57field.class);
+	static {
+		FldStr.put(S57field.I8RI, "0001");
+		FldStr.put(S57field.DSID, "DSID"); FldStr.put(S57field.DSSI, "DSSI"); FldStr.put(S57field.DSPM, "DSPM"); FldStr.put(S57field.DSPR, "DSPR");
+		FldStr.put(S57field.DSRC, "DSRC"); FldStr.put(S57field.DSHT, "DSHT"); FldStr.put(S57field.DSAC, "DSAC"); FldStr.put(S57field.CATD, "CATD");
+		FldStr.put(S57field.CATX, "CATX"); FldStr.put(S57field.DDDF, "DDDF"); FldStr.put(S57field.DDDR, "DDDR"); FldStr.put(S57field.DDDI, "DDDI");
+		FldStr.put(S57field.DDOM, "DDOM"); FldStr.put(S57field.DDRF, "DDRF"); FldStr.put(S57field.DDSI, "DDSI"); FldStr.put(S57field.DDSC, "DDSC");
+		FldStr.put(S57field.FRID, "FRID"); FldStr.put(S57field.FOID, "FOID"); FldStr.put(S57field.ATTF, "ATTF"); FldStr.put(S57field.NATF, "NATF");
+		FldStr.put(S57field.FFPC, "FFPC"); FldStr.put(S57field.FFPT, "FFPT"); FldStr.put(S57field.FFPC, "FFPC"); FldStr.put(S57field.FSPT, "FSPT");
+		FldStr.put(S57field.VRID, "VRID"); FldStr.put(S57field.ATTV, "ATTV"); FldStr.put(S57field.VRPC, "VRPC"); FldStr.put(S57field.VRPT, "VRPT");
+		FldStr.put(S57field.SGCC, "SGCC"); FldStr.put(S57field.SG2D, "SG2D"); FldStr.put(S57field.SG3D, "SG3D"); FldStr.put(S57field.ARCC, "ARCC");
+		FldStr.put(S57field.AR2D, "AR2D"); FldStr.put(S57field.EL2D, "EL2D"); FldStr.put(S57field.CT2D, "CT2D"); 
+	}
+	
+	public static String stringField (S57field field) {
+		return FldStr.get(field);
+	}
+	
+	public static S57field enumField (String field) {
+		for (S57field fld : FldStr.keySet()) {
+			if (FldStr.get(fld).equals(field))
+				return fld;
+		}
+		return null;
+	}
+
+	private static byte[] buffer;
+	private static int offset;
+	private static int maxoff;
+	private static int index;
+	private static S57field field;
+	private static String aall = "US-ASCII";
+	private static String nall = "US-ASCII";
+	public static int rnum;
+	
+	private static S57conv findSubf(S57subf subf) {
+		ArrayList<S57subf> subs = fields.get(field);
+		boolean wrap = false;
+		while (true) {
+			if (index == subs.size()) {
+				if (!wrap) {
+					index = 0;
+					wrap = true;
+				} else {
+					System.out.println("ERROR: Subfield not found " + subf.name() + " in " + field.name() + " in record " + rnum);
+					System.exit(-1);
+				}
+			}
+			S57subf sub = subs.get(index++);
+			S57conv conv = convs.get(sub);
+			if (sub == subf) {
+				return conv;
+			} else {
+				offset += (conv.bin != 0) ? ((conv.bin < 8) ? Math.abs(conv.bin) : conv.bin / 8) : conv.asc;
+			}
+		}
+	}
+	
+	public static void setField(byte[] buf, int off, S57field fld, int len) {
+		buffer = buf;
+		offset = off;
+		maxoff = off + len - 1;
+		field = fld;
+		index = 0;
+	}
+	
+	public static boolean more() {
+		return (offset < maxoff);
+	}
+	
+	public static Object getSubf(byte[] buf, int off, S57field fld, S57subf subf) {
+		buffer = buf;
+		offset = off;
+		index = 0;
+		return getSubf(fld, subf);
+	}
+	
+	public static Object getSubf(S57field fld, S57subf subf) {
+		field = fld;
+		index = 0;
+		return getSubf(subf);
+	}
+
+	public static Object getSubf(S57subf subf) {
+		S57conv conv = findSubf(subf);
+		if (conv.bin == 0) {
+			String str = "";
+			int i = 0;
+			if (conv.asc == 0) {
+				for (i=0; buffer[offset+i] != 0x1f; i++) {}
+				try {
+					String charset = "";
+					if (field == S57field.ATTF) charset = aall;
+					else if (field == S57field.NATF) charset = nall;
+					else charset = "US-ASCII";
+					str = new String(buffer, offset, i, charset);
+				} catch (UnsupportedEncodingException e) {
+					e.printStackTrace();
+				}
+				offset += i + 1;
+			} else {
+				str = new String(buffer, offset, conv.asc);
+				offset += conv.asc;
+			}
+			return str;
+		} else {
+			int f = Math.abs(conv.bin);
+			if (f < 8) {
+				long val = buffer[offset + --f];
+				if (conv.bin > 0)
+					val &= 0xff;
+				while (f > 0) {
+					val = (val << 8) + (buffer[offset + --f] & 0xff);
+				}
+				offset += Math.abs(conv.bin);
+				if ((subf == S57subf.AALL) || (subf == S57subf.NALL)) {
+					String charset = "";
+					switch ((int)val) {
+					case 0:
+						charset = "US-ASCII";
+						break;
+					case 1:
+						charset = "ISO-8859-1";
+						break;
+					case 2:
+						charset = "UTF-16LE";
+						break;
+					}
+					if (subf == S57subf.NALL) {
+						nall = charset;
+					} else {
+						aall = charset;
+					}
+				}
+				return val;
+			} else {
+				f /= 8;
+				long val = 0;
+				for (int i = 0; i < f; i++) {
+					val = (val << 8) + (buffer[offset++] & 0xff);
+				}
+				return val;
+			}
+		}
+	}
+
+	public static void putSubf(byte[] buf, int off, S57field fld, S57subf subf, Object val) {
+		buffer = buf;
+		offset = off;
+		index = 0;
+		putSubf(fld, subf, val);
+	}
+	
+	public static void putSubf(S57field fld, S57subf subf, Object val) {
+		field = fld;
+		index = 0;
+		putSubf(subf, val);
+	}
+
+	public static void putSubf(S57subf subf, Object val) {
+		S57conv conv = findSubf(subf);
+		if (conv.bin == 0) {
+		} else {
+		}
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57dec.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57dec.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57dec.java	(revision 30894)
@@ -0,0 +1,204 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import s57.S57dat.*;
+import s57.S57map.*;
+
+public class S57dec {
+
+	public static MapBounds decodeFile(FileInputStream in, S57map map) throws IOException {
+		S57dat.rnum = 0;
+		byte[] leader = new byte[24];
+		boolean ddr = false;
+		int length;
+		int fields;
+		int mapfl, mapfp, mapts, entry;
+		String tag;
+		int len;
+		int pos;
+		boolean inFeature = false;
+
+		double comf = 1;
+		double somf = 1;
+		long name = 0;
+		S57map.Nflag nflag = Nflag.ANON;
+		S57map.Pflag pflag = S57map.Pflag.NOSP;
+		long objl = 0;
+		MapBounds bounds = map.new MapBounds();
+		
+		while (in.read(leader) == 24) {
+			length = Integer.parseInt(new String(leader, 0, 5)) - 24;
+			ddr = (leader[6] == 'L');
+			fields = Integer.parseInt(new String(leader, 12, 5)) - 24;
+			mapfl = leader[20] - '0';
+			mapfp = leader[21] - '0';
+			mapts = leader[23] - '0';
+			entry = mapfl + mapfp + mapts;
+			byte[] record = new byte[length];
+			if (in.read(record) != length)
+				break;
+			for (int idx = 0; idx < fields-1; idx += entry) {
+				tag = new String(record, idx, mapts);
+				len = Integer.parseInt(new String(record, idx+mapts, mapfl));
+				pos = Integer.parseInt(new String(record, idx+mapts+mapfl, mapfp));
+				if (!ddr) {
+					switch (S57dat.enumField(tag)) {
+					case I8RI:
+						int i8rn = ((Long) S57dat.getSubf(record, fields + pos, S57field.I8RI, S57subf.I8RN)).intValue();
+						if (i8rn != ++S57dat.rnum) {
+							System.err.println("Out of order record ID");
+							in.close();
+							System.exit(-1);
+						}
+						break;
+					case DSSI:
+						S57dat.getSubf(record, fields + pos, S57field.DSSI, S57subf.AALL);
+						S57dat.getSubf(S57subf.NALL);
+						break;
+					case DSPM:
+						comf = (double) (Long) S57dat.getSubf(record, fields + pos, S57field.DSPM, S57subf.COMF);
+						somf = (double) (Long) S57dat.getSubf(S57subf.SOMF);
+						break;
+					case FRID:
+						inFeature = true;
+						switch (((Long)S57dat.getSubf(record, fields + pos, S57field.FRID, S57subf.PRIM)).intValue()) {
+						case 1:
+							pflag = S57map.Pflag.POINT;
+							break;
+						case 2:
+							pflag = S57map.Pflag.LINE;
+							break;
+						case 3:
+							pflag = S57map.Pflag.AREA;
+							break;
+						default:
+							pflag = S57map.Pflag.NOSP;
+						}
+						objl = (Long)S57dat.getSubf(S57subf.OBJL);
+						break;
+					case FOID:
+						name = (Long) S57dat.getSubf(record, fields + pos, S57field.FOID, S57subf.LNAM);
+						map.newFeature(name, pflag, objl);
+						break;
+					case ATTF:
+						S57dat.setField(record, fields + pos, S57field.ATTF, len);
+						do {
+							long attl = (Long) S57dat.getSubf(S57subf.ATTL);
+							String atvl = ((String) S57dat.getSubf(S57subf.ATVL)).trim();
+							if (!atvl.isEmpty()) {
+								map.newAtt(attl, atvl);
+							}
+						} while (S57dat.more());
+						break;
+					case FFPT:
+						S57dat.setField(record, fields + pos, S57field.FFPT, len);
+						do {
+							name = (Long) S57dat.getSubf(S57subf.LNAM);
+							int rind = ((Long) S57dat.getSubf(S57subf.RIND)).intValue();
+							S57dat.getSubf(S57subf.COMT);
+							map.newObj(name, rind);
+						} while (S57dat.more());
+						break;
+					case FSPT:
+						S57dat.setField(record, fields + pos, S57field.FSPT, len);
+						do {
+							name = (Long) S57dat.getSubf(S57subf.NAME) << 16;
+							map.newPrim(name, (Long) S57dat.getSubf(S57subf.ORNT), (Long) S57dat.getSubf(S57subf.USAG));
+							S57dat.getSubf(S57subf.MASK);
+						} while (S57dat.more());
+						break;
+					case VRID:
+						inFeature = false;
+						name = (long) (Long)S57dat.getSubf(record, fields + pos, S57field.VRID, S57subf.RCNM);
+						switch ((int) name) {
+						case 110:
+							nflag = Nflag.ISOL;
+							break;
+						case 120:
+							nflag = Nflag.CONN;
+							break;
+						default:
+							nflag = Nflag.ANON;
+							break;
+						}
+						name <<= 32;
+						name += (Long) S57dat.getSubf(S57subf.RCID);
+						name <<= 16;
+						if (nflag == Nflag.ANON) {
+							map.newEdge(name);
+						}
+						break;
+					case VRPT:
+						S57dat.setField(record, fields + pos, S57field.VRPT, len);
+						do {
+							long conn = (Long) S57dat.getSubf(S57subf.NAME) << 16;
+							int topi = ((Long) S57dat.getSubf(S57subf.TOPI)).intValue();
+							map.addConn(conn, topi);
+							S57dat.getSubf(S57subf.MASK);
+						} while (S57dat.more());
+						break;
+					case SG2D:
+						S57dat.setField(record, fields + pos, S57field.SG2D, len);
+						do {
+							double lat = (double) ((Long) S57dat.getSubf(S57subf.YCOO)) / comf;
+							double lon = (double) ((Long) S57dat.getSubf(S57subf.XCOO)) / comf;
+							if (nflag == Nflag.ANON) {
+								map.newNode(++name, lat, lon, nflag);
+							} else {
+								map.newNode(name, lat, lon, nflag);
+							}
+							if (lat < bounds.minlat)
+								bounds.minlat = lat;
+							if (lat > bounds.maxlat)
+								bounds.maxlat = lat;
+							if (lon < bounds.minlon)
+								bounds.minlon = lon;
+							if (lon > bounds.maxlon)
+								bounds.maxlon = lon;
+						} while (S57dat.more());
+						break;
+					case SG3D:
+						S57dat.setField(record, fields + pos, S57field.SG3D, len);
+						do {
+							double lat = (double) ((Long) S57dat.getSubf(S57subf.YCOO)) / comf;
+							double lon = (double) ((Long) S57dat.getSubf(S57subf.XCOO)) / comf;
+							double depth = (double) ((Long) S57dat.getSubf(S57subf.VE3D)) / somf;
+							map.newNode(name++, lat, lon, depth);
+							if (lat < bounds.minlat)
+								bounds.minlat = lat;
+							if (lat > bounds.maxlat)
+								bounds.maxlat = lat;
+							if (lon < bounds.minlon)
+								bounds.minlon = lon;
+							if (lon > bounds.maxlon)
+								bounds.maxlon = lon;
+						} while (S57dat.more());
+						break;
+					default:
+						break;
+					}
+				}
+				if (inFeature) {
+					map.endFeature();
+					inFeature = false;
+				}
+			}
+		}
+		map.endFile();
+		in.close();
+		
+		return bounds;
+	}
+	
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57map.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57map.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57map.java	(revision 30894)
@@ -0,0 +1,892 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.util.*;
+
+import s57.S57obj;
+import s57.S57obj.*;
+import s57.S57att;
+import s57.S57att.*;
+import s57.S57val;
+import s57.S57val.*;
+
+public class S57map {
+	
+	public class MapBounds {
+		public double minlat;
+		public double minlon;
+		public double maxlat;
+		public double maxlon;
+		public MapBounds() {
+			minlat = 90;
+			minlon = 180;
+			maxlat = -90;
+			maxlon = -180;
+		}
+	}
+
+	public enum Nflag {
+		ANON,	// Edge inner nodes
+		ISOL,	// Node not part of Edge
+		CONN,	// Edge first and last nodes
+		DPTH	// Sounding nodes
+	}
+
+	public class Snode {	// All coordinates in map
+		public double lat;	// Latitude
+		public double lon;	// Longitude
+		public Nflag flg;		// Role of node
+
+		public Snode() {
+			flg = Nflag.ANON;
+			lat = 0;
+			lon = 0;
+		}
+		public Snode(double ilat, double ilon) {
+			flg = Nflag.ANON;
+			lat = ilat;
+			lon = ilon;
+		}
+		public Snode(double ilat, double ilon, Nflag iflg) {
+			lat = ilat;
+			lon = ilon;
+			flg = iflg;
+		}
+	}
+
+	public class Dnode extends Snode {	// All depth soundings
+		public double val;	// Sounding value
+
+		public Dnode() {
+			flg = Nflag.DPTH;
+			lat = 0;
+			lon = 0;
+			val = 0;
+		}
+		public Dnode(double ilat, double ilon, double ival) {
+			flg = Nflag.DPTH;
+			lat = ilat;
+			lon = ilon;
+			val = ival;
+		}
+	}
+	
+	public class Edge {		// A polyline segment
+		public long first;	// First CONN node
+		public long last;		// Last CONN node
+		public ArrayList<Long> nodes; // Inner ANON nodes
+
+		public Edge() {
+			first = 0;
+			last = 0;
+			nodes = new ArrayList<Long>();
+		}
+	}
+	
+	public enum Rflag {
+		UNKN, MASTER, SLAVE
+	}
+	
+	public class Reln {
+		public long id;
+		public Rflag reln;
+		public Reln(long i, Rflag r) {
+			id = i;
+			reln = r;
+		}
+	}
+
+	public class RelTab extends ArrayList<Reln> {
+		public RelTab() {
+			super();
+		}
+	}
+
+	public class ObjTab extends HashMap<Integer, AttMap> {
+		public ObjTab() {
+			super();
+		}
+	}
+
+	public class ObjMap extends EnumMap<Obj, ObjTab> {
+		public ObjMap() {
+			super(Obj.class);
+		}
+	}
+
+	public class AttMap extends HashMap<Att, AttVal<?>> {
+		public AttMap() {
+			super();
+		}
+	}
+
+	public class NodeTab extends HashMap<Long, Snode> {
+		public NodeTab() {
+			super();
+		}
+	}
+
+	public class EdgeTab extends HashMap<Long, Edge> {
+		public EdgeTab() {
+			super();
+		}
+	}
+
+	public class FtrMap extends EnumMap<Obj, ArrayList<Feature>> {
+		public FtrMap() {
+			super(Obj.class);
+		}
+	}
+
+	public class FtrTab extends HashMap<Long, Feature> {
+		public FtrTab() {
+			super();
+		}
+	}
+
+	public class Prim {				// Spatial element
+		public long id;					// Snode ID for POINTs, Edge ID for LINEs & AREAs)
+		public boolean forward;	// Direction of vector used (LINEs & AREAs)
+		public boolean outer;		// Exterior/Interior boundary (AREAs)
+		public Prim() {
+			id = 0; forward = true; outer = true;
+		}
+		public Prim(long i) {
+			id = i; forward = true; outer = true;
+		}
+		public Prim(long i, boolean o) {
+			id = i; forward = true; outer = o;
+		}
+		public Prim(long i, boolean f, boolean o) {
+			id = i; forward = f; outer = o;
+		}
+	}
+	
+	public class Comp {			// Composite spatial element
+		public long ref;			// ID of Comp
+		public int size;			// Number of Prims in this Comp
+		public Comp(long r, int s) {
+			ref = r;
+			size = s;
+		}
+	}
+	
+	public enum Pflag {
+		NOSP, POINT, LINE, AREA
+	}
+	
+	public class Geom {							// Geometric structure of feature
+		public Pflag prim;						// Geometry type
+		public ArrayList<Prim> elems;	// Ordered list of elements
+		public int outers;						// Number of outers
+		public int inners;						// Number of inners
+		public ArrayList<Comp> refs;	// Ordered list of compounds
+		public double area;						// Area of feature
+		public double length;					// Length of feature
+		public Snode centre;					// Centre of feature
+		public Geom(Pflag p) {
+			prim = p;
+			elems = new ArrayList<Prim>();
+			outers = inners = 0;
+			refs = new ArrayList<Comp>();
+			area = 0;
+			length = 0;
+			centre = new Snode();
+		}
+	}
+	
+	public class Feature {
+		public Rflag reln;		// Relationship status
+		public Geom geom;			// Geometry data
+		public Obj type;			// Feature type
+		public AttMap atts;		// Feature attributes
+		public RelTab rels;		// Related objects
+		public ObjMap objs;		// Slave object attributes
+
+		Feature() {
+			reln = Rflag.UNKN;
+			geom = new Geom(Pflag.NOSP);
+			type = Obj.UNKOBJ;
+			atts = new AttMap();
+			rels = new RelTab();
+			objs = new ObjMap();
+		}
+	}
+
+	public NodeTab nodes;
+	public EdgeTab edges;
+
+	public FtrMap features;
+	public FtrTab index;
+
+	public long ref;
+	private Feature feature;
+	private Edge edge;
+
+	public S57map() {
+		nodes = new NodeTab();		// All nodes in map
+		edges = new EdgeTab();		// All edges in map
+		feature = new Feature();	// Current feature being built
+		features = new FtrMap();	// All features in map, grouped by type
+		index = new FtrTab();			// Feature look-up table
+		ref = 0x0000ffffffff0000L;// Compound reference generator
+	}
+
+	// S57 map building methods
+	
+	public void newNode(long id, double lat, double lon, Nflag flag) {
+		nodes.put(id, new Snode(Math.toRadians(lat), Math.toRadians(lon), flag));
+		if (flag == Nflag.ANON) {
+			edge.nodes.add(id);
+		}
+	}
+
+	public void newNode(long id, double lat, double lon, double depth) {
+		nodes.put(id, new Dnode(Math.toRadians(lat), Math.toRadians(lon), depth));
+	}
+
+	public void newFeature(long id, Pflag p, long objl) {
+		feature = new Feature();
+		Obj obj = S57obj.decodeType(objl);
+		if (obj == Obj.BCNWTW)
+			obj = Obj.BCNLAT;
+		if (obj == Obj.BOYWTW)
+			obj = Obj.BOYLAT;
+		if (obj == Obj.C_AGGR)
+			feature.reln = Rflag.UNKN;
+		feature.geom = new Geom(p);
+		feature.type = obj;
+		if (obj != Obj.UNKOBJ) {
+			index.put(id, feature);
+		}
+	}
+	
+	public void newObj(long id, int rind) {
+		Rflag r = Rflag.UNKN;
+		switch (rind) {
+		case 1:
+			r = Rflag.MASTER;
+			break;
+		case 2:
+			r = Rflag.SLAVE;
+			break;
+		case 3:
+			r = Rflag.UNKN;
+			break;
+		}
+		feature.rels.add(new Reln(id, r));
+	}
+	
+	public void endFeature() {
+		
+	}
+	
+	public void newAtt(long attl, String atvl) {
+		Att att = S57att.decodeAttribute(attl);
+		AttVal<?> val = S57val.decodeValue(atvl, att);
+		feature.atts.put(att, val);
+	}
+
+	public void newPrim(long id, long ornt, long usag) {
+		feature.geom.elems.add(new Prim(id, (ornt != 2), (usag != 2)));
+	}
+
+	public void addConn(long id, int topi) {
+		if (topi == 1) {
+			edge.first = id;
+		} else {
+			edge.last = id;
+		}
+	}
+
+	public void newEdge(long id) {
+		edge = new Edge();
+		edges.put(id, edge);
+	}
+
+	public void endFile() {
+		for (long id : index.keySet()) {
+			Feature feature = index.get(id);
+			sortGeom(feature);
+			for (Reln reln : feature.rels) {
+				Feature rel = index.get(reln.id);
+				if (cmpGeoms(feature.geom, rel.geom)) {
+					switch (reln.reln) {
+					case SLAVE:
+						feature.reln = Rflag.MASTER;
+						break;
+					default:
+						feature.reln = Rflag.UNKN;
+						break;
+					}
+					rel.reln = reln.reln; 
+				} else {
+					reln.reln = Rflag.UNKN;
+				}
+			}
+		}
+		for (long id : index.keySet()) {
+			Feature feature = index.get(id);
+			if (feature.reln == Rflag.UNKN) {
+				feature.reln = Rflag.MASTER;
+			}
+			if ((feature.type != Obj.UNKOBJ) && (feature.reln == Rflag.MASTER)) {
+				if (features.get(feature.type) == null) {
+					features.put(feature.type, new ArrayList<Feature>());
+				}
+				features.get(feature.type).add(feature);
+			}
+		}
+		for (long id : index.keySet()) {
+			Feature feature = index.get(id);
+			for (Reln reln : feature.rels) {
+				Feature rel = index.get(reln.id);
+				if (rel.reln == Rflag.SLAVE) {
+					if (feature.objs.get(rel.type) == null) {
+						feature.objs.put(rel.type, new ObjTab());
+					}
+					ObjTab tab = feature.objs.get(rel.type);
+					int ix = tab.size();
+					tab.put(ix, rel.atts);
+				}
+			}
+		}
+	}
+
+	// OSM map building methods
+	
+	public void addNode(long id, double lat, double lon) {
+		Snode node = new Snode(Math.toRadians(lat), Math.toRadians(lon));
+		nodes.put(id, node);
+		feature = new Feature();
+		feature.reln = Rflag.UNKN;
+		feature.geom.prim = Pflag.POINT;
+		feature.geom.elems.add(new Prim(id));
+		edge = null;
+	}
+
+	public void addEdge(long id) {
+		feature = new Feature();
+		feature.reln = Rflag.UNKN;
+		feature.geom.prim = Pflag.LINE;
+		feature.geom.elems.add(new Prim(id));
+		edge = new Edge();
+	}
+
+	public void addToEdge(long node) {
+		if (edge.first == 0) {
+			edge.first = node;
+			nodes.get(node).flg = Nflag.CONN;
+		} else {
+			if (edge.last != 0) {
+				edge.nodes.add(edge.last);
+			}
+			edge.last = node;
+		}
+	}
+
+	public void addArea(long id) {
+		feature = new Feature();
+		feature.reln = Rflag.UNKN;
+		feature.geom.prim = Pflag.AREA;
+		edge = null;
+	}
+
+	public void addToArea(long id, boolean outer) {
+		feature.geom.elems.add(new Prim(id, outer));
+	}
+
+	public void addTag(String key, String val) {
+		feature.reln = Rflag.MASTER;
+		String subkeys[] = key.split(":");
+		if ((subkeys.length > 1) && subkeys[0].equals("seamark")) {
+			Obj obj = S57obj.enumType(subkeys[1]);
+			if ((subkeys.length > 2) && (obj != Obj.UNKOBJ)) {
+				int idx = 0;
+				Att att = Att.UNKATT;
+				try {
+					idx = Integer.parseInt(subkeys[2]);
+					if (subkeys.length == 4) {
+						att = s57.S57att.enumAttribute(subkeys[3], obj);
+					}
+				} catch (Exception e) {
+					att = S57att.enumAttribute(subkeys[2], obj);
+				}
+				ObjTab objs = feature.objs.get(obj);
+				if (objs == null) {
+					objs = new ObjTab();
+					feature.objs.put(obj, objs);
+				}
+				AttMap atts = objs.get(idx);
+				if (atts == null) {
+					atts = new AttMap();
+					objs.put(idx, atts);
+				}
+				AttVal<?> attval = S57val.convertValue(val, att);
+				if (attval.val != null)
+					atts.put(att, attval);
+			} else {
+				if (subkeys[1].equals("type")) {
+					obj = S57obj.enumType(val);
+					feature.type = obj;
+					ObjTab objs = feature.objs.get(obj);
+					if (objs == null) {
+						objs = new ObjTab();
+						feature.objs.put(obj, objs);
+					}
+					AttMap atts = objs.get(0);
+					if (atts == null) {
+						atts = new AttMap();
+						objs.put(0, atts);
+					}
+				} else {
+					Att att = S57att.enumAttribute(subkeys[1], Obj.UNKOBJ);
+					if (att != Att.UNKATT) {
+						AttVal<?> attval = S57val.convertValue(val, att);
+						if (attval.val != null)
+							feature.atts.put(att, attval);
+					}
+				}
+			}
+		}
+	}
+
+	public void tagsDone(long id) {
+		switch (feature.geom.prim) {
+		case POINT:
+			Snode node = nodes.get(id);
+			if (node.flg != Nflag.CONN) {
+				node.flg = Nflag.ISOL;
+			}
+			break;
+		case LINE:
+			edges.put(id, edge);
+			nodes.get(edge.first).flg = Nflag.CONN;
+			nodes.get(edge.last).flg = Nflag.CONN;
+			if (edge.first == edge.last) {
+				feature.geom.prim = Pflag.AREA;
+			}
+			break;
+		case AREA:
+			break;
+		default:
+			break;
+		}
+		if ((sortGeom(feature)) && (feature.type != Obj.UNKOBJ) && !((edge != null) && (edge.last == 0))) {
+			index.put(id, feature);
+			if (features.get(feature.type) == null) {
+				features.put(feature.type, new ArrayList<Feature>());
+			}
+			features.get(feature.type).add(feature);
+			feature.geom.centre = findCentroid(feature);
+		}
+	}
+
+	// Utility methods
+	
+	public boolean sortGeom(Feature feature) {
+		Geom sort = new Geom(feature.geom.prim);
+		long first = 0;
+		long last = 0;
+		Comp comp = null;
+		boolean next = true;
+		feature.geom.length = 0;
+		feature.geom.area = 0;
+		if (feature.geom.prim == Pflag.POINT) { 
+			return true;
+		}	else {
+			int sweep = feature.geom.elems.size();
+			while (!feature.geom.elems.isEmpty()) {
+				Prim prim = feature.geom.elems.remove(0);
+				Edge edge = edges.get(prim.id);
+				if (edge == null) {
+					return false;
+				}
+				if (next == true) {
+					next = false;
+					if (prim.forward) {
+						first = edge.first;
+						last = edge.last;
+					} else {
+						first = edge.last;
+						last = edge.first;
+					}
+					sort.elems.add(prim);
+					if (prim.outer) {
+						sort.outers++;
+					} else {
+						sort.inners++;
+					}
+					comp = new Comp(ref++, 1);
+					sort.refs.add(comp);
+				} else {
+					if (prim.forward) {
+						if (edge.first == last) {
+							sort.elems.add(prim);
+							last = edge.last;
+							comp.size++;
+						} else if (edge.last == first) {
+							sort.elems.add(0, prim);
+							first = edge.first;
+							comp.size++;
+						} else {
+							feature.geom.elems.add(prim);
+						}
+					} else {
+						if (edge.last == last) {
+							sort.elems.add(prim);
+							last = edge.first;
+							comp.size++;
+						} else if (edge.first == first) {
+							sort.elems.add(0, prim);
+							first = edge.last;
+							comp.size++;
+						} else {
+							feature.geom.elems.add(prim);
+						}
+					}
+				}
+				if (--sweep == 0) {
+					next = true;
+					sweep = feature.geom.elems.size();
+				}
+			}
+			if ((sort.prim == Pflag.LINE) && (sort.outers == 1) && (sort.inners == 0) && (first == last)) {
+				sort.prim = Pflag.AREA;
+			}
+			feature.geom = sort;
+		}
+		if (feature.geom.prim == Pflag.AREA) {
+			ArrayList<Prim> outers = new ArrayList<Prim>();
+			ArrayList<Prim> inners = new ArrayList<Prim>();
+			for (Prim prim : feature.geom.elems) {
+				if (prim.outer) {
+					outers.add(prim);
+				} else {
+					inners.add(prim);
+				}
+			}
+			ArrayList<Prim> sorting = outers.size() > 0 ? outers : inners;
+			ArrayList<Prim> closed = null;
+			sort = new Geom(feature.geom.prim);
+			sort.outers = feature.geom.outers;
+			sort.inners = feature.geom.inners;
+			sort.refs = feature.geom.refs;
+			next = true;
+			while (!sorting.isEmpty()) {
+				Prim prim = sorting.remove(0);
+				Edge edge = edges.get(prim.id);
+				if (next == true) {
+					next = false;
+					closed = new ArrayList<Prim>();
+					closed.add(prim);
+					if (prim.forward) {
+						first = edge.first;
+						last = edge.last;
+					} else {
+						first = edge.last;
+						last = edge.first;
+					}
+				} else {
+					if (prim.forward) {
+						if (edge.first == last) {
+							last = edge.last;
+							closed.add(prim);
+						} else {
+							sorting.add(0, prim);
+							next = true;
+						}
+					} else {
+						if (edge.last == last) {
+							last = edge.first;
+							closed.add(prim);
+						} else {
+							sorting.add(0, prim);
+							next = true;
+						}
+					}
+				}
+				if (first == last) {
+					sort.elems.addAll(closed);
+					next = true;
+				}
+				if (sorting.isEmpty() && sorting == outers) {
+					sorting = inners;
+					next = true;
+				}
+			}
+			feature.geom = sort;
+		}
+		feature.geom.length = calcLength(feature.geom);
+		feature.geom.area = calcArea(feature.geom);
+		return true;
+	}
+	
+	public boolean cmpGeoms (Geom g1, Geom g2) {
+		return ((g1.prim == g2.prim) && (g1.outers == g2.outers) && (g1.inners == g2.inners) && (g1.elems.size() == g2.elems.size()));
+	}
+	
+	public class EdgeIterator {
+		Edge edge;
+		boolean forward;
+		ListIterator<Long> it;
+
+		public EdgeIterator(Edge e, boolean dir) {
+			edge = e;
+			forward = dir;
+			it = null;
+		}
+
+		public boolean hasNext() {
+			return (edge != null);
+		}
+
+		public long nextRef() {
+			long ref = 0;
+			if (forward) {
+				if (it == null) {
+					ref = edge.first;
+					it = edge.nodes.listIterator();
+				} else {
+					if (it.hasNext()) {
+						ref = it.next();
+					} else {
+						ref = edge.last;
+						edge = null;
+					}
+				}
+			} else {
+				if (it == null) {
+					ref = edge.last;
+					it = edge.nodes.listIterator(edge.nodes.size());
+				} else {
+					if (it.hasPrevious()) {
+						ref = it.previous();
+					} else {
+						ref = edge.first;
+						edge = null;
+					}
+				}
+			}
+			return ref;
+		}
+		
+		public Snode next() {
+			return nodes.get(nextRef());
+		}
+	}
+
+	public class GeomIterator {
+		Geom geom;
+		Prim prim;
+		EdgeIterator eit;
+		ListIterator<S57map.Prim> ite;
+		ListIterator<Comp> itc;
+		Comp comp;
+		int ec;
+		long lastref;
+		
+		public GeomIterator(Geom g) {
+			geom = g;
+			lastref = 0;
+			ite = geom.elems.listIterator();
+			itc = geom.refs.listIterator();
+		}
+		
+		public boolean hasComp() {
+			return (itc.hasNext());
+		}
+		
+		public long nextComp() {
+			comp = itc.next();
+			ec = comp.size;
+			lastref = 0;
+			return comp.ref;
+		}
+		
+		public boolean hasEdge() {
+			return (ec > 0) && ite.hasNext();
+		}
+		
+		public long nextEdge() {
+			prim = ite.next();
+			eit = new EdgeIterator(edges.get(prim.id), prim.forward);
+			ec--;
+			return prim.id;
+		}
+		
+		public boolean hasNode() {
+			return (eit.hasNext());
+		}
+		
+		public long nextRef(boolean all) {
+			long ref = eit.nextRef();
+			if (!all && (ref == lastref)) {
+				ref = eit.nextRef();
+			}
+			lastref = ref;
+			return ref;
+		}
+		
+		public long nextRef() {
+			return nextRef(false);
+		}
+		
+		public Snode next() {
+			return nodes.get(nextRef());
+		}
+	}
+	
+	double signedArea(Geom geom) {
+		Snode node;
+		double lat, lon, llon, llat;
+		lat = lon = llon = llat = 0;
+		double sigma = 0;
+		GeomIterator git = new GeomIterator(geom);
+		if (git.hasComp()) {
+			git.nextComp();
+			while (git.hasEdge()) {
+				git.nextEdge();
+				while (git.hasNode()) {
+					llon = lon;
+					llat = lat;
+					node = git.next();
+					lat = node.lat;
+					lon = node.lon;
+					sigma += (lon * Math.sin(llat)) - (llon * Math.sin(lat));
+				}
+			}
+		}
+		return sigma / 2.0;
+	}
+
+	public boolean handOfArea(Geom geom) {
+		return (signedArea(geom) < 0);
+	}
+
+	public double calcArea(Geom geom) {
+		return Math.abs(signedArea(geom)) * 3444 * 3444;
+	}
+
+	public double calcLength(Geom geom) {
+		Snode node;
+		double lat, lon, llon, llat;
+		lat = lon = llon = llat = 0;
+		double sigma = 0;
+		boolean first = true;
+		GeomIterator git = new GeomIterator(geom);
+		while (git.hasComp()) {
+			git.nextComp();
+			while (git.hasEdge()) {
+				git.nextEdge();
+				while (git.hasNode()) {
+					node = git.next();
+					if (first) {
+						first = false;
+						lat = node.lat;
+						lon = node.lon;
+					} else {
+						llat = lat;
+						llon = lon;
+						lat = node.lat;
+						lon = node.lon;
+						sigma += Math.acos(Math.sin(lat) * Math.sin(llat) + Math.cos(lat) * Math.cos(llat) * Math.cos(llon - lon));
+					}
+				}
+			}
+		}
+		return sigma * 3444;
+	}
+
+	public Snode findCentroid(Feature feature) {
+		double lat, lon, slat, slon, llat, llon;
+		llat = llon = lat = lon = slat = slon = 0;
+		double sarc = 0;
+		boolean first = true;
+		switch (feature.geom.prim) {
+		case POINT:
+			return nodes.get(feature.geom.elems.get(0).id);
+		case LINE:
+			GeomIterator git = new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				while (git.hasEdge()) {
+					git.nextEdge();
+					while (git.hasNode()) {
+						Snode node = git.next();
+						lat = node.lat;
+						lon = node.lon;
+						if (first) {
+							first = false;
+						} else {
+							sarc += (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+						}
+						llat = lat;
+						llon = lon;
+					}
+				}
+			}
+			double harc = sarc / 2;
+			sarc = 0;
+			first = true;
+			git = new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				while (git.hasEdge()) {
+					git.nextEdge();
+					while (git.hasNode()) {
+						Snode node = git.next();
+						lat = node.lat;
+						lon = node.lon;
+						if (first) {
+							first = false;
+						} else {
+							sarc = (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+							if (sarc > harc)
+								break;
+						}
+						harc -= sarc;
+						llat = lat;
+						llon = lon;
+					}
+				}
+			}
+			return new Snode(llat + ((lat - llat) * harc / sarc), llon + ((lon - llon) * harc / sarc));
+		case AREA:
+			git = new GeomIterator(feature.geom);
+			while (git.hasComp()) {
+				git.nextComp();
+				while (git.hasEdge()) {
+					git.nextEdge();
+					while (git.hasNode()) {
+						Snode node = git.next();
+						lat = node.lat;
+						lon = node.lon;
+						if (first) {
+							first = false;
+						} else {
+							double arc = (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
+							slat += ((lat + llat) / 2 * arc);
+							slon += ((lon + llon) / 2 * arc);
+							sarc += arc;
+						}
+						llon = lon;
+						llat = lat;
+					}
+				}
+			}
+			return new Snode((sarc > 0.0 ? slat / sarc : 0.0), (sarc > 0.0 ? slon / sarc : 0.0));
+		default:
+		}
+		return null;
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57obj.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57obj.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57obj.java	(revision 30894)
@@ -0,0 +1,182 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+public class S57obj {
+	
+	public enum Obj {
+		UNKOBJ, AIRARE, ACHBRT, ACHARE, BCNCAR, BCNISD, BCNLAT, BCNSAW, BCNSPP, BERTHS, BRIDGE, BUISGL, BUAARE, BOYCAR, BOYINB,
+		BOYISD, BOYLAT, BOYSAW, BOYSPP, CBLARE, CBLOHD, CBLSUB, CANALS, CANBNK, CTSARE, CAUSWY, CTNARE, CHKPNT, CGUSTA, COALNE, CONZNE,
+		COSARE, CTRPNT, CONVYR, CRANES, CURENT, CUSZNE, DAMCON, DAYMAR, DWRTCL, DWRTPT, DEPARE, DEPCNT, DISMAR, DOCARE, DRGARE, DRYDOC,
+		DMPGRD, DYKCON, EXEZNE, FAIRWY, FNCLNE, FERYRT, FSHZNE, FSHFAC, FSHGRD, FLODOC, FOGSIG, FORSTC, FRPARE, GATCON, GRIDRN, HRBARE,
+		HRBFAC, HULKES, ICEARE, ICNARE, ISTZNE, LAKARE, LAKSHR, LNDARE, LNDELV, LNDRGN, LNDMRK, LIGHTS, LITFLT, LITVES, LOCMAG, LOKBSN,
+		LOGPON, MAGVAR, MARCUL, MIPARE, MORFAC, MPAARE, NAVLNE, OBSTRN, OFSPLF, OSPARE, OILBAR, PILPNT, PILBOP, PIPARE, PIPOHD, PIPSOL,
+		PONTON, PRCARE, PRDARE, PYLONS, RADLNE, RADRNG, RADRFL, RADSTA, RTPBCN, RDOCAL, RDOSTA, RAILWY, RAPIDS, RCRTCL, RECTRC, RCTLPT,
+		RSCSTA, RESARE, RETRFL, RIVERS, RIVBNK, ROADWY, RUNWAY, SNDWAV, SEAARE, SPLARE, SBDARE, SLCONS, SISTAT, SISTAW, SILTNK, SLOTOP,
+		SLOGRD, SMCFAC, SOUNDG, SPRING, SQUARE, STSLNE, SUBTLN, SWPARE, TESARE, TS_PRH, TS_PNH, TS_PAD, TS_TIS, T_HMON, T_NHMN, T_TIMS,
+		TIDEWY, TOPMAR, TSELNE, TSSBND, TSSCRS, TSSLPT, TSSRON, TSEZNE, TUNNEL, TWRTPT, UWTROC, UNSARE, VEGATN, WATTUR, WATFAL, WEDKLP,
+		WRECKS, TS_FEB, NOTMRK, WTWAXS, WTWPRF, BRGARE, BUNSTA, COMARE, HRBBSN, LOKARE, LKBSPT, PRTARE, BCNWTW, BOYWTW, REFDMP, RTPLPT,
+		TERMNL, TRNBSN, WTWARE, WTWGAG, TISDGE, VEHTRF, EXCNST, LG_SDM, LG_VSP, LITMIN, LITMAJ, C_AGGR, M_COVR, M_NSYS
+	}
+
+	private static final EnumMap<Obj, Integer> ObjS57 = new EnumMap<Obj, Integer>(Obj.class);
+	static {
+		ObjS57.put(Obj.UNKOBJ,0);
+		ObjS57.put(Obj.AIRARE,2); ObjS57.put(Obj.ACHBRT,3); ObjS57.put(Obj.ACHARE,4); ObjS57.put(Obj.BCNCAR,5);
+		ObjS57.put(Obj.BCNISD,6); ObjS57.put(Obj.BCNLAT,7); ObjS57.put(Obj.BCNSAW,8); ObjS57.put(Obj.BCNSPP,9); ObjS57.put(Obj.BERTHS,10);
+		ObjS57.put(Obj.BRIDGE,11); ObjS57.put(Obj.BUISGL,12); ObjS57.put(Obj.BUAARE,13); ObjS57.put(Obj.BOYCAR,14); ObjS57.put(Obj.BOYINB,15);
+		ObjS57.put(Obj.BOYISD,16); ObjS57.put(Obj.BOYLAT,17); ObjS57.put(Obj.BOYSAW,18); ObjS57.put(Obj.BOYSPP,19); ObjS57.put(Obj.CBLARE,20);
+		ObjS57.put(Obj.CBLOHD,21); ObjS57.put(Obj.CBLSUB,22); ObjS57.put(Obj.CANALS,23); ObjS57.put(Obj.CANBNK,24); ObjS57.put(Obj.CTSARE,25);
+		ObjS57.put(Obj.CAUSWY,26); ObjS57.put(Obj.CTNARE,27); ObjS57.put(Obj.CHKPNT,28); ObjS57.put(Obj.CGUSTA,29); ObjS57.put(Obj.COALNE,30);
+		ObjS57.put(Obj.CONZNE,31); ObjS57.put(Obj.COSARE,32); ObjS57.put(Obj.CTRPNT,33); ObjS57.put(Obj.CONVYR,34); ObjS57.put(Obj.CRANES,35);
+		ObjS57.put(Obj.CURENT,36); ObjS57.put(Obj.CUSZNE,37); ObjS57.put(Obj.DAMCON,38); ObjS57.put(Obj.DAYMAR,39); ObjS57.put(Obj.DWRTCL,40);
+		ObjS57.put(Obj.DWRTPT,41); ObjS57.put(Obj.DEPARE,42); ObjS57.put(Obj.DEPCNT,43); ObjS57.put(Obj.DISMAR,44); ObjS57.put(Obj.DOCARE,45);
+		ObjS57.put(Obj.DRGARE,46); ObjS57.put(Obj.DRYDOC,47); ObjS57.put(Obj.DMPGRD,48); ObjS57.put(Obj.DYKCON,49); ObjS57.put(Obj.EXEZNE,50);
+		ObjS57.put(Obj.FAIRWY,51); ObjS57.put(Obj.FNCLNE,52); ObjS57.put(Obj.FERYRT,53); ObjS57.put(Obj.FSHZNE,54); ObjS57.put(Obj.FSHFAC,55);
+		ObjS57.put(Obj.FSHGRD,56); ObjS57.put(Obj.FLODOC,57); ObjS57.put(Obj.FOGSIG,58); ObjS57.put(Obj.FORSTC,59); ObjS57.put(Obj.FRPARE,60);
+		ObjS57.put(Obj.GATCON,61); ObjS57.put(Obj.GRIDRN,62); ObjS57.put(Obj.HRBARE,63); ObjS57.put(Obj.HRBFAC,64); ObjS57.put(Obj.HULKES,65);
+		ObjS57.put(Obj.ICEARE,66); ObjS57.put(Obj.ICNARE,67); ObjS57.put(Obj.ISTZNE,68); ObjS57.put(Obj.LAKARE,69); ObjS57.put(Obj.LAKSHR,70);
+		ObjS57.put(Obj.LNDARE,71); ObjS57.put(Obj.LNDELV,72); ObjS57.put(Obj.LNDRGN,73); ObjS57.put(Obj.LNDMRK,74); ObjS57.put(Obj.LIGHTS,75);
+		ObjS57.put(Obj.LITFLT,76); ObjS57.put(Obj.LITVES,77); ObjS57.put(Obj.LOCMAG,78); ObjS57.put(Obj.LOKBSN,79); ObjS57.put(Obj.LOGPON,80);
+		ObjS57.put(Obj.MAGVAR,81); ObjS57.put(Obj.MARCUL,82); ObjS57.put(Obj.MIPARE,83); ObjS57.put(Obj.MORFAC,84); ObjS57.put(Obj.NAVLNE,85);
+		ObjS57.put(Obj.OBSTRN,86); ObjS57.put(Obj.OFSPLF,87); ObjS57.put(Obj.OSPARE,88); ObjS57.put(Obj.OILBAR,89); ObjS57.put(Obj.PILPNT,90);
+		ObjS57.put(Obj.PILBOP,91); ObjS57.put(Obj.PIPARE,92); ObjS57.put(Obj.PIPOHD,93); ObjS57.put(Obj.PIPSOL,94); ObjS57.put(Obj.PONTON,95);
+		ObjS57.put(Obj.PRCARE,96); ObjS57.put(Obj.PRDARE,97); ObjS57.put(Obj.PYLONS,98); ObjS57.put(Obj.RADLNE,99); ObjS57.put(Obj.RADRNG,100);
+		ObjS57.put(Obj.RADRFL,101); ObjS57.put(Obj.RADSTA,102); ObjS57.put(Obj.RTPBCN,103);	ObjS57.put(Obj.RDOCAL,104); ObjS57.put(Obj.RDOSTA,105);
+		ObjS57.put(Obj.RAILWY,106);	ObjS57.put(Obj.RAPIDS,107);	ObjS57.put(Obj.RCRTCL,108);	ObjS57.put(Obj.RECTRC,109); ObjS57.put(Obj.RCTLPT,110);
+		ObjS57.put(Obj.RSCSTA,111);	ObjS57.put(Obj.RESARE,112);	ObjS57.put(Obj.RETRFL,113);	ObjS57.put(Obj.RIVERS,114); ObjS57.put(Obj.RIVBNK,115);
+		ObjS57.put(Obj.ROADWY,116);	ObjS57.put(Obj.RUNWAY,117);	ObjS57.put(Obj.SNDWAV,118);	ObjS57.put(Obj.SEAARE,119); ObjS57.put(Obj.SPLARE,120);
+		ObjS57.put(Obj.SBDARE,121);	ObjS57.put(Obj.SLCONS,122);	ObjS57.put(Obj.SISTAT,123);	ObjS57.put(Obj.SISTAW,124); ObjS57.put(Obj.SILTNK,125);
+		ObjS57.put(Obj.SLOTOP,126);	ObjS57.put(Obj.SLOGRD,127);	ObjS57.put(Obj.SMCFAC,128);	ObjS57.put(Obj.SOUNDG,129); ObjS57.put(Obj.SPRING,130);
+		ObjS57.put(Obj.SQUARE,131);	ObjS57.put(Obj.STSLNE,132);	ObjS57.put(Obj.SUBTLN,133);	ObjS57.put(Obj.SWPARE,134); ObjS57.put(Obj.TESARE,135);
+		ObjS57.put(Obj.TS_PRH,136);	ObjS57.put(Obj.TS_PNH,137); ObjS57.put(Obj.TS_PAD,138);	ObjS57.put(Obj.TS_TIS,139); ObjS57.put(Obj.T_HMON,140);
+		ObjS57.put(Obj.T_NHMN,141);	ObjS57.put(Obj.T_TIMS,142);	ObjS57.put(Obj.TIDEWY,143);	ObjS57.put(Obj.TOPMAR,144); ObjS57.put(Obj.TSELNE,145);
+		ObjS57.put(Obj.TSSBND,146);	ObjS57.put(Obj.TSSCRS,147);	ObjS57.put(Obj.TSSLPT,148);	ObjS57.put(Obj.TSSRON,149); ObjS57.put(Obj.TSEZNE,150);
+		ObjS57.put(Obj.TUNNEL,151);	ObjS57.put(Obj.TWRTPT,152);	ObjS57.put(Obj.UWTROC,153);	ObjS57.put(Obj.UNSARE,154); ObjS57.put(Obj.VEGATN,155);
+		ObjS57.put(Obj.WATTUR,156);	ObjS57.put(Obj.WATFAL,157);	ObjS57.put(Obj.WEDKLP,158);	ObjS57.put(Obj.WRECKS,159); ObjS57.put(Obj.TS_FEB,160);
+		ObjS57.put(Obj.MPAARE,199); ObjS57.put(Obj.C_AGGR,400); ObjS57.put(Obj.M_COVR,302); ObjS57.put(Obj.M_NSYS,306);
+	}
+
+	private static final EnumMap<Obj, Integer> ObjIENC = new EnumMap<Obj, Integer>(Obj.class);
+	static {
+		ObjIENC.put(Obj.UNKOBJ, 0);
+		ObjIENC.put(Obj.ACHBRT, 17000);	ObjIENC.put(Obj.ACHARE, 17001);	ObjIENC.put(Obj.CANBNK, 17002);	ObjIENC.put(Obj.DEPARE, 17003); ObjIENC.put(Obj.DISMAR, 17004);
+		ObjIENC.put(Obj.RESARE, 17005);	ObjIENC.put(Obj.RIVBNK, 17006);	ObjIENC.put(Obj.SISTAT, 17007);	ObjIENC.put(Obj.SISTAW, 17008); ObjIENC.put(Obj.TOPMAR, 17009);
+		ObjIENC.put(Obj.BERTHS, 17010);	ObjIENC.put(Obj.BRIDGE, 17011);	ObjIENC.put(Obj.CBLOHD, 17012);	ObjIENC.put(Obj.FERYRT, 17013); ObjIENC.put(Obj.HRBARE, 17014);
+		ObjIENC.put(Obj.HRBFAC, 17015);	ObjIENC.put(Obj.LOKBSN, 17016);	ObjIENC.put(Obj.RDOCAL, 17017); ObjIENC.put(Obj.CURENT, 17019); ObjIENC.put(Obj.HULKES, 17020);
+		ObjIENC.put(Obj.PONTON, 17021);	ObjIENC.put(Obj.PIPOHD, 17024);	ObjIENC.put(Obj.FLODOC, 17025);	ObjIENC.put(Obj.CHKPNT, 17027); ObjIENC.put(Obj.BCNLAT, 17028);
+		ObjIENC.put(Obj.BOYLAT, 17029);	ObjIENC.put(Obj.CRANES, 17030);	ObjIENC.put(Obj.GATCON, 17031);	ObjIENC.put(Obj.SLCONS, 17032); ObjIENC.put(Obj.UWTROC, 17033);
+		ObjIENC.put(Obj.CONVYR, 17034);	ObjIENC.put(Obj.NOTMRK, 17050);	ObjIENC.put(Obj.WTWAXS, 17051);	ObjIENC.put(Obj.WTWPRF, 17052); ObjIENC.put(Obj.BRGARE, 17053);
+		ObjIENC.put(Obj.BUNSTA, 17054);	ObjIENC.put(Obj.COMARE, 17055);	ObjIENC.put(Obj.HRBBSN, 17056);	ObjIENC.put(Obj.LOKARE, 17057); ObjIENC.put(Obj.LKBSPT, 17058);
+		ObjIENC.put(Obj.PRTARE, 17059);	ObjIENC.put(Obj.BCNWTW, 17060);	ObjIENC.put(Obj.BOYWTW, 17061);	ObjIENC.put(Obj.REFDMP, 17062); ObjIENC.put(Obj.RTPLPT, 17063);
+		ObjIENC.put(Obj.TERMNL, 17064);	ObjIENC.put(Obj.TRNBSN, 17065);	ObjIENC.put(Obj.WTWARE, 17066);	ObjIENC.put(Obj.WTWGAG, 17067); ObjIENC.put(Obj.TISDGE, 17068);
+		ObjIENC.put(Obj.VEHTRF, 17069);	ObjIENC.put(Obj.EXCNST, 17070);	ObjIENC.put(Obj.LG_SDM, 18001);	ObjIENC.put(Obj.LG_VSP, 18002);
+	}
+
+	private static final HashMap<Integer, Obj> S57Obj = new HashMap<Integer, Obj>();
+	static {
+		for (Map.Entry<Obj, Integer> entry : ObjS57.entrySet()) {
+			S57Obj.put(entry.getValue(), entry.getKey());
+		}
+		for (Map.Entry<Obj, Integer> entry : ObjIENC.entrySet()) {
+			S57Obj.put(entry.getValue(), entry.getKey());
+		}
+	}
+	
+	private static final EnumMap<Obj, String> ObjStr = new EnumMap<Obj, String>(Obj.class);
+	static {
+		ObjStr.put(Obj.UNKOBJ, "");	ObjStr.put(Obj.AIRARE, "airfield");	ObjStr.put(Obj.ACHBRT, "anchor_berth");
+		ObjStr.put(Obj.ACHARE, "anchorage"); ObjStr.put(Obj.BCNCAR, "beacon_cardinal");	ObjStr.put(Obj.BCNISD, "beacon_isolated_danger");
+		ObjStr.put(Obj.BCNLAT, "beacon_lateral");	ObjStr.put(Obj.BCNSAW, "beacon_safe_water"); ObjStr.put(Obj.BCNSPP, "beacon_special_purpose");
+		ObjStr.put(Obj.BERTHS, "berth"); ObjStr.put(Obj.BRIDGE, "bridge"); ObjStr.put(Obj.BUISGL, "building"); ObjStr.put(Obj.BUAARE, "built-up_area");
+		ObjStr.put(Obj.BOYCAR, "buoy_cardinal"); ObjStr.put(Obj.BOYINB, "buoy_installation");	ObjStr.put(Obj.BOYISD, "buoy_isolated_danger");
+		ObjStr.put(Obj.BOYLAT, "buoy_lateral");	ObjStr.put(Obj.BOYSAW, "buoy_safe_water"); ObjStr.put(Obj.BOYSPP, "buoy_special_purpose");
+		ObjStr.put(Obj.CBLARE, "cable_area");	ObjStr.put(Obj.CBLOHD, "cable_overhead");	ObjStr.put(Obj.CBLSUB, "cable_submarine"); ObjStr.put(Obj.CANALS, "canal");
+		ObjStr.put(Obj.CANBNK, "canal_bank");	ObjStr.put(Obj.CTSARE, "cargo_area");	ObjStr.put(Obj.CAUSWY, "causeway");	ObjStr.put(Obj.CTNARE, "caution_area");
+		ObjStr.put(Obj.CHKPNT, "checkpoint");	ObjStr.put(Obj.CGUSTA, "coastguard_station");	ObjStr.put(Obj.COALNE, "coastline"); ObjStr.put(Obj.CONZNE, "contiguous_zone");
+		ObjStr.put(Obj.COSARE, "continental_shelf"); ObjStr.put(Obj.CTRPNT, "control_point");	ObjStr.put(Obj.CONVYR, "conveyor");	ObjStr.put(Obj.CRANES, "crane");
+		ObjStr.put(Obj.CURENT, "current"); ObjStr.put(Obj.CUSZNE, "custom_zone");	ObjStr.put(Obj.DAMCON, "dam"); ObjStr.put(Obj.DAYMAR, "daymark");
+		ObjStr.put(Obj.DWRTCL, "deep_water_route_centreline"); ObjStr.put(Obj.DWRTPT, "deep_water_route"); ObjStr.put(Obj.DEPARE, "depth_area");
+		ObjStr.put(Obj.DEPCNT, "depth_contour"); ObjStr.put(Obj.DISMAR, "distance_mark");	ObjStr.put(Obj.DOCARE, "dock");	ObjStr.put(Obj.DRGARE, "dredged_area");
+		ObjStr.put(Obj.DRYDOC, "dry_dock");	ObjStr.put(Obj.DMPGRD, "dumping_ground");	ObjStr.put(Obj.DYKCON, "dyke");	ObjStr.put(Obj.EXEZNE, "exclusive_economic_zone");
+		ObjStr.put(Obj.FAIRWY, "fairway"); ObjStr.put(Obj.FNCLNE, "wall"); ObjStr.put(Obj.FERYRT, "ferry_route");	ObjStr.put(Obj.FSHZNE, "fishery_zone");
+		ObjStr.put(Obj.FSHFAC, "fishing_facility");	ObjStr.put(Obj.FSHGRD, "fishing_ground");	ObjStr.put(Obj.FLODOC, "floating_dock"); ObjStr.put(Obj.FOGSIG, "fog_signal");
+		ObjStr.put(Obj.FORSTC, "fortified_structure"); ObjStr.put(Obj.FRPARE, "free_port_area"); ObjStr.put(Obj.GATCON, "gate"); ObjStr.put(Obj.GRIDRN, "gridiron");
+		ObjStr.put(Obj.HRBARE, "harbour_area");	ObjStr.put(Obj.HRBFAC, "harbour"); ObjStr.put(Obj.HULKES, "hulk"); ObjStr.put(Obj.ICEARE, "ice_area");
+		ObjStr.put(Obj.ICNARE, "incineration_zone"); ObjStr.put(Obj.ISTZNE, "inshore_traffic_zone"); ObjStr.put(Obj.LAKARE, "lake"); ObjStr.put(Obj.LAKSHR, "lake_shore");
+		ObjStr.put(Obj.LNDARE, "land_area"); ObjStr.put(Obj.LNDELV, "land_elevation"); ObjStr.put(Obj.LNDRGN, "land_region");	ObjStr.put(Obj.LNDMRK, "landmark");
+		ObjStr.put(Obj.LIGHTS, "light"); ObjStr.put(Obj.LITFLT, "light_float");	ObjStr.put(Obj.LITVES, "light_vessel");	ObjStr.put(Obj.LOCMAG, "local_magnetic_anomaly");
+		ObjStr.put(Obj.LOKBSN, "lock_basin");	ObjStr.put(Obj.LOGPON, "log_pond");	ObjStr.put(Obj.MAGVAR, "magnetic_variation");	ObjStr.put(Obj.MARCUL, "marine_farm");
+		ObjStr.put(Obj.MIPARE, "military_area"); ObjStr.put(Obj.MORFAC, "mooring");	ObjStr.put(Obj.NAVLNE, "navigation_line"); ObjStr.put(Obj.OBSTRN, "obstruction");
+		ObjStr.put(Obj.OFSPLF, "platform");	ObjStr.put(Obj.OSPARE, "production_area"); ObjStr.put(Obj.OILBAR, "oil_barrier");	ObjStr.put(Obj.PILPNT, "pile");
+		ObjStr.put(Obj.PILBOP, "pilot_boarding");	ObjStr.put(Obj.PIPARE, "pipeline_area"); ObjStr.put(Obj.PIPOHD, "pipeline_overhead");	ObjStr.put(Obj.PIPSOL, "pipeline_submarine");
+		ObjStr.put(Obj.PONTON, "pontoon"); ObjStr.put(Obj.PRCARE, "precautionary_area"); ObjStr.put(Obj.PRDARE, "land_production_area");ObjStr.put(Obj.PYLONS, "pylon");
+		ObjStr.put(Obj.RADLNE, "radar_line");	ObjStr.put(Obj.RADRNG, "radar_range"); ObjStr.put(Obj.RADRFL, "radar_reflector");	ObjStr.put(Obj.RADSTA, "radar_station");
+		ObjStr.put(Obj.RTPBCN, "radar_transponder"); ObjStr.put(Obj.RDOCAL, "calling-in_point"); ObjStr.put(Obj.RDOSTA, "radio_station");	ObjStr.put(Obj.RAILWY, "railway");
+		ObjStr.put(Obj.RAPIDS, "rapids");	ObjStr.put(Obj.RCRTCL, "recommended_route_centreline");	ObjStr.put(Obj.RECTRC, "recommended_track");
+		ObjStr.put(Obj.RCTLPT, "recommended_traffic_lane");	ObjStr.put(Obj.RSCSTA, "rescue_station");	ObjStr.put(Obj.RESARE, "restricted_area");
+		ObjStr.put(Obj.RETRFL, "retro_reflector"); ObjStr.put(Obj.RIVERS, "river");	ObjStr.put(Obj.RIVBNK, "river_bank");	ObjStr.put(Obj.ROADWY, "road");
+		ObjStr.put(Obj.RUNWAY, "runway");	ObjStr.put(Obj.SNDWAV, "sand_waves");	ObjStr.put(Obj.SEAARE, "sea_area");	ObjStr.put(Obj.SPLARE, "seaplane_landing_area");
+		ObjStr.put(Obj.SBDARE, "seabed_area"); ObjStr.put(Obj.SLCONS, "shoreline_construction"); ObjStr.put(Obj.SISTAT, "signal_station_traffic");
+		ObjStr.put(Obj.SISTAW, "signal_station_warning");	ObjStr.put(Obj.SILTNK, "tank");	ObjStr.put(Obj.SLOTOP, "slope_topline"); ObjStr.put(Obj.SLOGRD, "sloping_ground");
+		ObjStr.put(Obj.SMCFAC, "small_craft_facility");	ObjStr.put(Obj.SOUNDG, "sounding");	ObjStr.put(Obj.SPRING, "spring");	ObjStr.put(Obj.SQUARE, "square");
+		ObjStr.put(Obj.STSLNE, "territorial_baseline");	ObjStr.put(Obj.SUBTLN, "submarine_transit_lane");	ObjStr.put(Obj.SWPARE, "swept_area");
+		ObjStr.put(Obj.TESARE, "territorial_area");	ObjStr.put(Obj.TIDEWY, "tideway"); ObjStr.put(Obj.TOPMAR, "topmark");
+		ObjStr.put(Obj.TSELNE, "separation_line"); ObjStr.put(Obj.TSSBND, "separation_boundary");	ObjStr.put(Obj.TSSCRS, "separation_crossing");
+		ObjStr.put(Obj.TSSLPT, "separation_lane"); ObjStr.put(Obj.TSSRON, "separation_roundabout");	ObjStr.put(Obj.TSEZNE, "separation_zone"); ObjStr.put(Obj.TUNNEL, "tunnel");
+		ObjStr.put(Obj.TWRTPT, "two-way_route"); ObjStr.put(Obj.UWTROC, "rock"); ObjStr.put(Obj.UNSARE, "unsurveyed_area");	ObjStr.put(Obj.VEGATN, "vegetation");
+		ObjStr.put(Obj.WATTUR, "water_turbulence");	ObjStr.put(Obj.WATFAL, "waterfall"); ObjStr.put(Obj.WEDKLP, "weed"); ObjStr.put(Obj.WRECKS, "wreck");
+		ObjStr.put(Obj.TS_FEB, "tidal_stream");	ObjStr.put(Obj.NOTMRK, "notice");	ObjStr.put(Obj.WTWAXS, "waterway_axis"); ObjStr.put(Obj.WTWPRF, "waterway_profile");
+		ObjStr.put(Obj.BRGARE, "bridge_area"); ObjStr.put(Obj.BUNSTA, "bunker_station");	ObjStr.put(Obj.COMARE, "communication_area");	ObjStr.put(Obj.HRBBSN, "harbour_basin");
+		ObjStr.put(Obj.LOKARE, "lock_area"); ObjStr.put(Obj.LKBSPT, "lock_basin_part"); ObjStr.put(Obj.PRTARE, "port_area");	ObjStr.put(Obj.BCNWTW, "beacon_waterway");
+		ObjStr.put(Obj.BOYWTW, "buoy_waterway"); ObjStr.put(Obj.REFDMP, "refuse_dump"); ObjStr.put(Obj.RTPLPT, "route_planning_point"); ObjStr.put(Obj.TERMNL, "terminal");
+		ObjStr.put(Obj.TRNBSN, "turning_basin"); ObjStr.put(Obj.WTWARE, "waterway_area"); ObjStr.put(Obj.WTWGAG, "waterway_gauge"); ObjStr.put(Obj.TISDGE, "time_schedule");
+		ObjStr.put(Obj.VEHTRF, "vehicle_transfer"); ObjStr.put(Obj.EXCNST, "exceptional_structure"); ObjStr.put(Obj.MPAARE, "protected_area");
+		ObjStr.put(Obj.LITMAJ, "light_major"); ObjStr.put(Obj.LITMIN, "light_minor"); ObjStr.put(Obj.M_COVR, "coverage"); ObjStr.put(Obj.M_NSYS, "navigational_system");
+	}
+	
+	private static final HashMap<String, Obj> StrObj = new HashMap<String, Obj>();
+	static {
+		for (Map.Entry<Obj, String> entry : ObjStr.entrySet()) {
+			if (!entry.getValue().isEmpty())
+				StrObj.put(entry.getValue(), entry.getKey());
+		}
+	}
+	
+	public static Obj decodeType(long objl) { // Convert S57 feature code to OSeaM object enumeration
+		Obj obj = S57Obj.get((int)objl);
+		return (obj != null) ? obj : Obj.UNKOBJ;
+	}
+
+	public static long encodeType(Obj type) { // Convert OSM object enumeration to S57 feature code
+		if (ObjS57.containsKey(type))
+			return ObjS57.get(type);
+		else if (ObjIENC.containsKey(type))
+			return ObjIENC.get(type);
+		return 0;
+	}
+
+	public static String stringType(Obj type) { // Convert OSeaM object enumeration to OSeaM object string
+		String str = ObjStr.get(type);
+			return str != null ? str : "";
+	}
+
+	public static Obj enumType(String type) { // Convert OSeaM object string to OSeaM object enumeration
+		if ((type != null) && !type.isEmpty() && (StrObj.containsKey(type)))
+			return StrObj.get(type);
+		else
+			return Obj.UNKOBJ;
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/src/s57/S57val.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/s57/S57val.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/s57/S57val.java	(revision 30894)
@@ -0,0 +1,1237 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package s57;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+
+import s57.S57att.*;
+
+public class S57val {
+
+	static class S57enum {
+		Integer atvl;
+		String val;
+		S57enum(Integer a, String v) {
+			atvl = a; val = v;
+		}
+	}
+	
+	public enum Conv { S, A, L, E, F, I }
+	
+	static class S57key {
+		Conv conv;
+		EnumMap<?, ?> map;
+		S57key(Conv c, EnumMap<?, S57enum> m) {
+			conv = c; map = m;
+		}
+	}
+	
+	public static class AttVal<V> {
+		public Att att;
+		public Conv conv;
+		public V val;
+		AttVal(Att a, Conv c, V v) {
+			att = a; conv = c; val = v;
+		}
+	}
+	
+	public enum BcnSHP { BCN_UNKN, BCN_STAK, BCN_WTHY, BCN_TOWR, BCN_LATT, BCN_PILE, BCN_CARN, BCN_BUOY, BCN_POLE, BCN_PRCH, BCN_POST	}
+	private static final EnumMap<BcnSHP, S57enum> Bcnshp = new EnumMap<BcnSHP, S57enum>(BcnSHP.class); static { Bcnshp.put(BcnSHP.BCN_UNKN, new S57enum(0, ""));
+		Bcnshp.put(BcnSHP.BCN_STAK, new S57enum(1, "stake")); Bcnshp.put(BcnSHP.BCN_WTHY, new S57enum(2, "withy")); Bcnshp.put(BcnSHP.BCN_TOWR, new S57enum(3, "tower"));
+		Bcnshp.put(BcnSHP.BCN_LATT, new S57enum(4, "lattice")); Bcnshp.put(BcnSHP.BCN_PILE, new S57enum(5, "pile")); Bcnshp.put(BcnSHP.BCN_CARN, new S57enum(6, "cairn"));
+		Bcnshp.put(BcnSHP.BCN_BUOY, new S57enum(7, "buoyant")); Bcnshp.put(BcnSHP.BCN_POLE, new S57enum(1, "pole")); Bcnshp.put(BcnSHP.BCN_PRCH, new S57enum(1, "perch"));
+		Bcnshp.put(BcnSHP.BCN_POST, new S57enum(1, "post"));
+	}
+	public enum BuiSHP { BUI_UNKN, BUI_HIRS, BUI_PYRD, BUI_CYLR, BUI_SPHR, BUI_CUBE	}
+	private static final EnumMap<BuiSHP, S57enum> Buishp = new EnumMap<BuiSHP, S57enum>(BuiSHP.class); static { Buishp.put(BuiSHP.BUI_UNKN, new S57enum(0, ""));
+		Buishp.put(BuiSHP.BUI_HIRS, new S57enum(5, "high-rise")); Buishp.put(BuiSHP.BUI_PYRD, new S57enum(6, "pyramid")); Buishp.put(BuiSHP.BUI_CYLR, new S57enum(7, "cylindrical"));
+		Buishp.put(BuiSHP.BUI_SPHR, new S57enum(8, "spherical")); Buishp.put(BuiSHP.BUI_CUBE, new S57enum(9, "cubic"));
+	}
+	public enum BoySHP { BOY_UNKN, BOY_CONE, BOY_CAN, BOY_SPHR, BOY_PILR, BOY_SPAR, BOY_BARL, BOY_SUPR, BOY_ICE	}
+	private static final EnumMap<BoySHP, S57enum> Boyshp = new EnumMap<BoySHP, S57enum>(BoySHP.class); static { Boyshp.put(BoySHP.BOY_UNKN, new S57enum(0, ""));
+		Boyshp.put(BoySHP.BOY_CONE, new S57enum(1, "conical")); Boyshp.put(BoySHP.BOY_CAN, new S57enum(2, "can")); Boyshp.put(BoySHP.BOY_SPHR, new S57enum(3, "spherical"));
+		Boyshp.put(BoySHP.BOY_PILR, new S57enum(4, "pillar")); Boyshp.put(BoySHP.BOY_SPAR, new S57enum(5, "spar")); Boyshp.put(BoySHP.BOY_BARL, new S57enum(6, "barrel"));
+	  Boyshp.put(BoySHP.BOY_SUPR, new S57enum(7, "super-buoy")); Boyshp.put(BoySHP.BOY_ICE, new S57enum(8, "ice_buoy"));
+	}
+	public enum CatAIR { AIR_UNKN, AIR_MILA, AIR_CIVA, AIR_MILH, AIR_CIVH, AIR_GLDR, AIR_SMLP, AIR_EMRG }
+	private static final EnumMap<CatAIR, S57enum> Catair = new EnumMap<CatAIR, S57enum>(CatAIR.class); static { Catair.put(CatAIR.AIR_UNKN, new S57enum(0, ""));
+		Catair.put(CatAIR.AIR_MILA, new S57enum(1, "military")); Catair.put(CatAIR.AIR_CIVA, new S57enum(2, "civil")); Catair.put(CatAIR.AIR_MILH, new S57enum(3, "military_heliport"));
+		Catair.put(CatAIR.AIR_CIVH, new S57enum(4, "civil_heliport")); Catair.put(CatAIR.AIR_GLDR, new S57enum(5, "glider")); Catair.put(CatAIR.AIR_SMLP, new S57enum(6, "small_planes"));
+		Catair.put(CatAIR.AIR_EMRG, new S57enum(8, "emergency"));
+	}
+	public enum CatACH { ACH_UNKN, ACH_UNRD, ACH_DEEP, ACH_TANK, ACH_EXPL, ACH_QUAR, ACH_SEAP, ACH_SMCF, ACH_SMCM, ACH_H24P, ACH_LTPD, ACH_NPSH, ACH_DRYC, ACH_RAFT }
+	private static final EnumMap<CatACH, S57enum> Catach = new EnumMap<CatACH, S57enum>(CatACH.class); static {Catach.put(CatACH.ACH_UNKN, new S57enum(0, ""));
+		Catach.put(CatACH.ACH_UNRD, new S57enum(1, "unrestricted")); Catach.put(CatACH.ACH_DEEP, new S57enum(2, "deep_water")); Catach.put(CatACH.ACH_TANK, new S57enum(3, "tanker"));
+		Catach.put(CatACH.ACH_EXPL, new S57enum(4, "explosives")); Catach.put(CatACH.ACH_QUAR, new S57enum(5, "quarantine")); Catach.put(CatACH.ACH_SEAP, new S57enum(6, "seaplane"));
+		Catach.put(CatACH.ACH_SMCF, new S57enum(7, "small_craft")); Catach.put(CatACH.ACH_SMCM, new S57enum(8, "small_craft_mooring")); Catach.put(CatACH.ACH_H24P, new S57enum(9, "24_hour"));
+		Catach.put(CatACH.ACH_LTPD, new S57enum(10, "limited_period")); Catach.put(CatACH.ACH_NPSH, new S57enum(11, "non_pushing")); Catach.put(CatACH.ACH_DRYC, new S57enum(12, "dry_cargo"));
+		Catach.put(CatACH.ACH_RAFT, new S57enum(13, "raft"));
+	}
+	public enum CatBRG { BRG_UNKN, BRG_FIXD, BRG_OPEN, BRG_SWNG, BRG_LIFT, BRG_BASC, BRG_PONT, BRG_DRAW, BRG_TRNS, BRG_FOOT, BRG_VIAD, BRG_AQUA, BRG_SUSP }
+	private static final EnumMap<CatBRG, S57enum> Catbrg = new EnumMap<CatBRG, S57enum>(CatBRG.class); static {Catbrg.put(CatBRG.BRG_UNKN, new S57enum(0, ""));
+		Catbrg.put(CatBRG.BRG_FIXD, new S57enum(1, "fixed")); Catbrg.put(CatBRG.BRG_OPEN, new S57enum(2, "opening")); Catbrg.put(CatBRG.BRG_SWNG, new S57enum(3, "swing"));
+		Catbrg.put(CatBRG.BRG_LIFT, new S57enum(4, "lifting")); Catbrg.put(CatBRG.BRG_BASC, new S57enum(5, "bascule")); Catbrg.put(CatBRG.BRG_PONT, new S57enum(6, "pontoon"));
+		Catbrg.put(CatBRG.BRG_DRAW, new S57enum(7, "drawbridge")); Catbrg.put(CatBRG.BRG_TRNS, new S57enum(8, "transporter")); Catbrg.put(CatBRG.BRG_FOOT, new S57enum(9, "footbridge"));
+		Catbrg.put(CatBRG.BRG_VIAD, new S57enum(10, "viaduct")); Catbrg.put(CatBRG.BRG_AQUA, new S57enum(11, "aqueduct")); Catbrg.put(CatBRG.BRG_SUSP, new S57enum(12, "suspension"));
+	}
+	public enum CatBUA { BUA_UNKN, BUA_URBN, BUA_STTL, BUA_VLLG, BUA_TOWN, BUA_CITY, BUA_HOLV }
+	private static final EnumMap<CatBUA, S57enum> Catbua = new EnumMap<CatBUA, S57enum>(CatBUA.class); static { Catbua.put(CatBUA.BUA_UNKN, new S57enum(0, ""));
+		Catbua.put(CatBUA.BUA_URBN, new S57enum(1, "urban")); Catbua.put(CatBUA.BUA_STTL, new S57enum(2, "settlement")); Catbua.put(CatBUA.BUA_VLLG, new S57enum(3, "village"));
+		Catbua.put(CatBUA.BUA_TOWN, new S57enum(4, "town")); Catbua.put(CatBUA.BUA_CITY, new S57enum(5, "city")); Catbua.put(CatBUA.BUA_HOLV, new S57enum(6, "holiday_village"));
+	}
+	public enum CatCBL { CBL_UNKN, CBL_POWR, CBL_TRNS, CBL_TELE, CBL_TGPH, CBL_MOOR, CBL_OPTC, CBL_FERY } 
+	private static final EnumMap<CatCBL, S57enum> Catcbl = new EnumMap<CatCBL, S57enum>(CatCBL.class); static {Catcbl.put(CatCBL.CBL_UNKN, new S57enum(0, ""));
+		Catcbl.put(CatCBL.CBL_POWR, new S57enum(1, "power")); Catcbl.put(CatCBL.CBL_TRNS, new S57enum(3, "transmission")); Catcbl.put(CatCBL.CBL_TELE, new S57enum(4, "telephone"));
+		Catcbl.put(CatCBL.CBL_TGPH, new S57enum(5, "telegraph")); Catcbl.put(CatCBL.CBL_MOOR, new S57enum(6, "mooring")); Catcbl.put(CatCBL.CBL_OPTC, new S57enum(7, "optical"));
+		Catcbl.put(CatCBL.CBL_FERY, new S57enum(8, "ferry"));
+	}
+	public enum CatCAN { CAN_UNKN, CAN_TRNS, CAN_DRNG, CAN_IRGN }
+	private static final EnumMap<CatCAN, S57enum> Catcan = new EnumMap<CatCAN, S57enum>(CatCAN.class); static { Catcan.put(CatCAN.CAN_UNKN, new S57enum(0, ""));
+		Catcan.put(CatCAN.CAN_TRNS, new S57enum(1, "transportation")); Catcan.put(CatCAN.CAN_DRNG, new S57enum(2, "drainage")); Catcan.put(CatCAN.CAN_IRGN, new S57enum(3, "irrigation"));
+	}
+	public enum CatCAM { CAM_UNKN, CAM_NORTH, CAM_EAST, CAM_SOUTH, CAM_WEST }
+	private static final EnumMap<CatCAM, S57enum> Catcam = new EnumMap<CatCAM, S57enum>(CatCAM.class); static { Catcam.put(CatCAM.CAM_UNKN, new S57enum(0, ""));
+		Catcam.put(CatCAM.CAM_NORTH, new S57enum(1, "north")); Catcam.put(CatCAM.CAM_EAST, new S57enum(2, "east"));
+		Catcam.put(CatCAM.CAM_SOUTH, new S57enum(3, "south")); Catcam.put(CatCAM.CAM_WEST, new S57enum(4, "west"));
+	}
+	public enum CatCHP { CHP_UNKN, CHP_CSTM, CHP_BRDR }
+	private static final EnumMap<CatCHP, S57enum> Catchp = new EnumMap<CatCHP, S57enum>(CatCHP.class); static { Catchp.put(CatCHP.CHP_UNKN, new S57enum(0, ""));
+		Catchp.put(CatCHP.CHP_CSTM, new S57enum(1, "customs")); Catchp.put(CatCHP.CHP_BRDR, new S57enum(2, "border"));
+	}
+	public enum CatCOA { COA_UNKN, COA_STEP, COA_FLAT, COA_SAND, COA_STON, COA_SHNG, COA_GLCR, COA_MNGV, COA_MRSH, COA_CRRF, COA_ICE, COA_SHEL } 
+	private static final EnumMap<CatCOA, S57enum> Catcoa = new EnumMap<CatCOA, S57enum>(CatCOA.class); static { Catcoa.put(CatCOA.COA_UNKN, new S57enum(0, ""));
+		Catcoa.put(CatCOA.COA_STEP, new S57enum(1, "steep")); Catcoa.put(CatCOA.COA_FLAT, new S57enum(2, "flat")); Catcoa.put(CatCOA.COA_SAND, new S57enum(3, "sandy"));
+		Catcoa.put(CatCOA.COA_STON, new S57enum(4, "stony")); Catcoa.put(CatCOA.COA_SHNG, new S57enum(5, "shingly")); Catcoa.put(CatCOA.COA_GLCR, new S57enum(6, "glacier"));
+		Catcoa.put(CatCOA.COA_MNGV, new S57enum(7, "mangrove")); Catcoa.put(CatCOA.COA_MRSH, new S57enum(8, "marshy")); Catcoa.put(CatCOA.COA_CRRF, new S57enum(9, "coral_reef"));
+		Catcoa.put(CatCOA.COA_ICE, new S57enum(10, "ice")); Catcoa.put(CatCOA.COA_SHEL, new S57enum(11, "shelly"));
+	}
+	public enum CatCTR { CTR_UNKN, CTR_TRGN, CTR_OBSV, CTR_FIXD, CTR_BMRK, CTR_BDRY, CTR_HORM, CTR_HORS } 
+	private static final EnumMap<CatCTR, S57enum> Catctr = new EnumMap<CatCTR, S57enum>(CatCTR.class); static { Catctr.put(CatCTR.CTR_UNKN, new S57enum(0, ""));
+		Catctr.put(CatCTR.CTR_TRGN, new S57enum(1, "triangulation")); Catctr.put(CatCTR.CTR_OBSV, new S57enum(2, "observation")); Catctr.put(CatCTR.CTR_FIXD, new S57enum(3, "fixed"));
+		Catctr.put(CatCTR.CTR_BMRK, new S57enum(4, "benchmark")); Catctr.put(CatCTR.CTR_BDRY, new S57enum(5, "boundary")); Catctr.put(CatCTR.CTR_HORM, new S57enum(6, "horizontal_main"));
+		Catctr.put(CatCTR.CTR_HORS, new S57enum(7, "horizontal_secondary"));
+	}
+	public enum CatCON { CON_UNKN, CAT_AERL, CAT_BELT }
+	private static final EnumMap<CatCON, S57enum> Catcon = new EnumMap<CatCON, S57enum>(CatCON.class); static { Catcon.put(CatCON.CON_UNKN, new S57enum(0, ""));
+		Catcon.put(CatCON.CAT_AERL, new S57enum(1, "aerial")); Catcon.put(CatCON.CAT_BELT, new S57enum(2, "belt"));
+	}
+	public enum CatCRN { CRN_UNKN, CRN_NONS, CRN_CONT, CRN_SHRL, CRN_TRAV, CRN_AFRM } 
+	private static final EnumMap<CatCRN, S57enum> Catcrn = new EnumMap<CatCRN, S57enum>(CatCRN.class); static { Catcrn.put(CatCRN.CRN_UNKN, new S57enum(0, ""));
+		Catcrn.put(CatCRN.CRN_NONS, new S57enum(1, "non-specific")); Catcrn.put(CatCRN.CRN_CONT, new S57enum(2, "container")); Catcrn.put(CatCRN.CRN_SHRL, new S57enum(3, "sheerlegs"));
+		Catcrn.put(CatCRN.CRN_TRAV, new S57enum(4, "travelling")); Catcrn.put(CatCRN.CRN_AFRM , new S57enum(5, "a-frame"));
+	}
+	public enum CatDAM { DAM_UNKN, DAM_WEIR, DAM_DAM, DAM_FLDB }
+	private static final EnumMap<CatDAM, S57enum> Catdam = new EnumMap<CatDAM, S57enum>(CatDAM.class); static { Catdam.put(CatDAM.DAM_UNKN, new S57enum(0, ""));
+		Catdam.put(CatDAM.DAM_WEIR, new S57enum(1, "weir")); Catdam.put(CatDAM.DAM_DAM, new S57enum(2, "dam")); Catdam.put(CatDAM.DAM_FLDB, new S57enum(3, "flood_barrage"));
+	}
+	public enum CatDIS { DIS_UNKN, DIS_NONI, DIS_POLE, DIS_BORD, DIS_UKSH }
+	private static final EnumMap<CatDIS, S57enum> Catdis = new EnumMap<CatDIS, S57enum>(CatDIS.class); static { Catdis.put(CatDIS.DIS_UNKN, new S57enum(0, ""));
+		Catdis.put(CatDIS.DIS_NONI, new S57enum(1, "not_installed")); Catdis.put(CatDIS.DIS_POLE, new S57enum(2, "pole")); Catdis.put(CatDIS.DIS_BORD, new S57enum(3, "board"));
+		Catdis.put(CatDIS.DIS_UKSH, new S57enum(4, "unknown_shape"));
+	}
+	public enum CatDOC { DOC_UNKN, DOC_TIDL, DOC_NTDL }
+	private static final EnumMap<CatDOC, S57enum> Catdoc = new EnumMap<CatDOC, S57enum>(CatDOC.class); static { Catdoc.put(CatDOC.DOC_UNKN, new S57enum(0, ""));
+		Catdoc.put(CatDOC.DOC_TIDL, new S57enum(1, "tidal")); Catdoc.put(CatDOC.DOC_NTDL, new S57enum(2, "non-tidal"));
+	}
+	public enum CatDPG { DPG_UNKN, DPG_GENL, DPG_CHEM, DPG_NCLR, DPG_EXPL, DPG_SPIL, DPG_VSSL } 
+	private static final EnumMap<CatDPG, S57enum> Catdpg = new EnumMap<CatDPG, S57enum>(CatDPG.class); static { Catdpg.put(CatDPG.DPG_UNKN, new S57enum(0, ""));
+		Catdpg.put(CatDPG.DPG_GENL, new S57enum(1, "general")); Catdpg.put(CatDPG.DPG_CHEM, new S57enum(2, "chemical")); Catdpg.put(CatDPG.DPG_NCLR, new S57enum(3, "nuclear"));
+		Catdpg.put(CatDPG.DPG_EXPL, new S57enum(4, "explosives")); Catdpg.put(CatDPG.DPG_SPIL, new S57enum(5, "spoil")); Catdpg.put(CatDPG.DPG_VSSL, new S57enum(6, "vessel"));
+	}
+	public enum CatFNC { FNC_UNKN, FNC_FENC, FNC_MUIR, FNC_HEDG, FNC_WALL }
+	private static final EnumMap<CatFNC, S57enum> Catfnc = new EnumMap<CatFNC, S57enum>(CatFNC.class); static { Catfnc.put(CatFNC.FNC_UNKN, new S57enum(0, ""));
+		Catfnc.put(CatFNC.FNC_FENC, new S57enum(1, "fence")); Catfnc.put(CatFNC.FNC_MUIR, new S57enum(2, "muir")); Catfnc.put(CatFNC.FNC_HEDG, new S57enum(3, "hedge"));
+		Catfnc.put(CatFNC.FNC_WALL, new S57enum(4, "wall"));
+	}
+	public enum CatFRY { FRY_UNKN, FRY_FREE, FRY_CABL, FRY_ICE, FRY_SWWR } 
+	private static final EnumMap<CatFRY, S57enum> Catfry = new EnumMap<CatFRY, S57enum>(CatFRY.class); static { Catfry.put(CatFRY.FRY_UNKN, new S57enum(0, ""));
+		Catfry.put(CatFRY.FRY_FREE, new S57enum(1, "free")); Catfry.put(CatFRY.FRY_CABL, new S57enum(2, "cable")); Catfry.put(CatFRY.FRY_ICE, new S57enum(3, "ice"));
+		Catfry.put(CatFRY.FRY_SWWR, new S57enum(4, "swinging_wire"));
+	}
+	public enum CatFIF { FIF_UNKN, FIF_STAK, FIF_TRAP, FIF_WEIR, FIF_TUNY } 
+	private static final EnumMap<CatFIF, S57enum> Catfif = new EnumMap<CatFIF, S57enum>(CatFIF.class); static { Catfif.put(CatFIF.FIF_UNKN, new S57enum(0, ""));
+		Catfif.put(CatFIF.FIF_STAK, new S57enum(1, "stake")); Catfif.put(CatFIF.FIF_TRAP, new S57enum(2, "trap")); Catfif.put(CatFIF.FIF_WEIR, new S57enum(3, "weir"));
+		Catfif.put(CatFIF.FIF_TUNY, new S57enum(4, "tunny"));
+	}
+	public enum CatFOG { FOG_UNKN, FOG_EXPL, FOG_DIA, FOG_SIRN, FOG_NAUT, FOG_REED, FOG_TYPH, FOG_BELL, FOG_WHIS, FOG_GONG, FOG_HORN }
+	private static final EnumMap<CatFOG, S57enum> Catfog = new EnumMap<CatFOG, S57enum>(CatFOG.class); static {Catfog.put(CatFOG.FOG_UNKN, new S57enum(0, ""));
+		Catfog.put(CatFOG.FOG_EXPL, new S57enum(1, "explosive")); Catfog.put(CatFOG.FOG_DIA, new S57enum(2, "diaphone")); Catfog.put(CatFOG.FOG_SIRN, new S57enum(3, "siren"));
+		Catfog.put(CatFOG.FOG_NAUT, new S57enum(4, "nautophone")); Catfog.put(CatFOG.FOG_REED, new S57enum(5, "reed"));
+	  Catfog.put(CatFOG.FOG_TYPH, new S57enum(6, "tyfon")); Catfog.put(CatFOG.FOG_BELL, new S57enum(7, "bell")); Catfog.put(CatFOG.FOG_WHIS, new S57enum(8, "whistle"));
+	  Catfog.put(CatFOG.FOG_GONG, new S57enum(9, "gong")); Catfog.put(CatFOG.FOG_HORN, new S57enum(10, "horn"));
+	 }
+	public enum CatFOR { FOR_UNKN, FOR_CSTL, FOR_FORT, FOR_BTTY, FOR_BKHS, FOR_MTWR, FOR_RDBT } 
+	private static final EnumMap<CatFOR, S57enum> Catfor = new EnumMap<CatFOR, S57enum>(CatFOR.class); static { Catfor.put(CatFOR.FOR_UNKN, new S57enum(0, ""));
+		Catfor.put(CatFOR.FOR_CSTL, new S57enum(1, "castle")); Catfor.put(CatFOR.FOR_FORT, new S57enum(2, "fort")); Catfor.put(CatFOR.FOR_BTTY, new S57enum(3, "battery"));
+		Catfor.put(CatFOR.FOR_BKHS, new S57enum(4, "blockhouse")); Catfor.put(CatFOR.FOR_MTWR, new S57enum(5, "martello_tower")); Catfor.put(CatFOR.FOR_RDBT, new S57enum(6, "redoubt"));
+	}
+	public enum CatGAT { GAT_UNKN, GAT_GNRL, GAT_FLBG, GAT_CSSN, GAT_LOCK, GAT_DYKE, GAT_SLUC } 
+	private static final EnumMap<CatGAT, S57enum> Catgat = new EnumMap<CatGAT, S57enum>(CatGAT.class); static { Catgat.put(CatGAT.GAT_UNKN, new S57enum(0, ""));
+		Catgat.put(CatGAT.GAT_GNRL, new S57enum(1, "general")); Catgat.put(CatGAT.GAT_FLBG, new S57enum(2, "flood_barrage")); Catgat.put(CatGAT.GAT_CSSN, new S57enum(3, "caisson"));
+		Catgat.put(CatGAT.GAT_LOCK, new S57enum(4, "lock")); Catgat.put(CatGAT.GAT_DYKE, new S57enum(5, "dyke")); Catgat.put(CatGAT.GAT_SLUC, new S57enum(6, "sluice"));
+	}
+	public enum CatHAF { HAF_UNKN, HAF_RORO, HAF_TMBR, HAF_FERY, HAF_FISH, HAF_MRNA, HAF_NAVL, HAF_TNKR, HAF_PSGR, HAF_YARD, HAF_CNTR, HAF_BULK, HAF_SYNC, HAF_STCR, HAF_LUVB,
+		HAF_REPR, HAF_QUAR, HAF_SPLN, HAF_CARG, HAF_OFFS, HAF_SSUP, HAF_MANF } 
+	private static final EnumMap<CatHAF, S57enum> Cathaf = new EnumMap<CatHAF, S57enum>(CatHAF.class); static { Cathaf.put(CatHAF.HAF_UNKN, new S57enum(0, ""));
+		Cathaf.put(CatHAF.HAF_RORO, new S57enum(1, "roro")); Cathaf.put(CatHAF.HAF_FERY, new S57enum(3, "ferry")); Cathaf.put(CatHAF.HAF_FISH, new S57enum(4, "fishing"));
+		Cathaf.put(CatHAF.HAF_MRNA, new S57enum(5, "marina")); Cathaf.put(CatHAF.HAF_NAVL, new S57enum(6, "naval")); Cathaf.put(CatHAF.HAF_TNKR, new S57enum(7, "tanker"));
+		Cathaf.put(CatHAF.HAF_PSGR, new S57enum(8, "passenger")); Cathaf.put(CatHAF.HAF_YARD, new S57enum(9, "shipyard")); Cathaf.put(CatHAF.HAF_CNTR, new S57enum(10, "container"));
+		Cathaf.put(CatHAF.HAF_BULK, new S57enum(11, "bulk")); Cathaf.put(CatHAF.HAF_SYNC, new S57enum(12, "syncrolift")); Cathaf.put(CatHAF.HAF_STCR, new S57enum(13, "straddle_carrier"));
+		Cathaf.put(CatHAF.HAF_LUVB, new S57enum(14, "lay_up")); Cathaf.put(CatHAF.HAF_TMBR, new S57enum(15, "timber"));	Cathaf.put(CatHAF.HAF_REPR, new S57enum(16, "service_repair"));
+		Cathaf.put(CatHAF.HAF_QUAR, new S57enum(17, "quarantine")); Cathaf.put(CatHAF.HAF_SPLN, new S57enum(18, "seaplane")); Cathaf.put(CatHAF.HAF_CARG, new S57enum(19, "cargo"));
+		Cathaf.put(CatHAF.HAF_OFFS, new S57enum(20, "offshore_support"));  Cathaf.put(CatHAF.HAF_OFFS, new S57enum(21, "port_support_base"));
+		Cathaf.put(CatHAF.HAF_MANF, new S57enum(22, "marina_no_facilities"));
+	}
+	public enum CatHLK { HLK_UNKN, HLK_REST, HLK_HIST, HLK_MUSM, HLK_ACCM, HLK_BWTR, HLK_CSNO } 
+	private static final EnumMap<CatHLK, S57enum> Cathlk = new EnumMap<CatHLK, S57enum>(CatHLK.class); static { Cathlk.put(CatHLK.HLK_UNKN, new S57enum(0, ""));
+		Cathlk.put(CatHLK.HLK_REST, new S57enum(1, "floating_restaurant")); Cathlk.put(CatHLK.HLK_HIST, new S57enum(2, "historic")); Cathlk.put(CatHLK.HLK_MUSM, new S57enum(3, "museum"));
+		Cathlk.put(CatHLK.HLK_ACCM, new S57enum(4, "accommodation")); Cathlk.put(CatHLK.HLK_BWTR, new S57enum(5, "floating_breakwater")); Cathlk.put(CatHLK.HLK_CSNO, new S57enum(6, "casino_boat"));
+	}
+	public enum CatICE { ICE_UNKN, ICE_FAST, ICE_SEA, ICE_GRLR, ICE_PANK, ICE_GLAS, ICE_PEAK, ICE_PACK, ICE_POLR } 
+	private static final EnumMap<CatICE, S57enum> Catice = new EnumMap<CatICE, S57enum>(CatICE.class); static { Catice.put(CatICE.ICE_UNKN, new S57enum(0, ""));
+		Catice.put(CatICE.ICE_FAST, new S57enum(1, "fast")); Catice.put(CatICE.ICE_SEA, new S57enum(2, "sea")); Catice.put(CatICE.ICE_GRLR, new S57enum(3, "growler"));
+		Catice.put(CatICE.ICE_PANK, new S57enum(4, "pancake")); Catice.put(CatICE.ICE_GLAS, new S57enum(5, "glacier")); Catice.put(CatICE.ICE_PEAK, new S57enum(6, "peak"));
+		Catice.put(CatICE.ICE_PACK, new S57enum(7, "pack")); Catice.put(CatICE.ICE_POLR, new S57enum(8, "polar"));
+	}
+	public enum CatINB { INB_UNKN, INB_CALM, INB_SBM }
+	private static final EnumMap<CatINB, S57enum> Catinb = new EnumMap<CatINB, S57enum>(CatINB.class); static { Catinb.put(CatINB.INB_UNKN, new S57enum(0, ""));
+		Catinb.put(CatINB.INB_CALM, new S57enum(1, "calm")); Catinb.put(CatINB.INB_SBM, new S57enum(2, "sbm"));
+	}
+	public enum CatLND { LND_UNKN, LND_FEN, LND_MRSH, LND_BOG, LND_HTHL, LND_MNTN, LND_LOWL, LND_CNYN, LND_PDDY, LND_AGRI, LND_SVNA, LND_PARK, LND_SWMP, LND_LSLD, LND_LAVA,
+		LND_SLTP, LND_MORN, LND_CRTR, LND_CAVE, LND_PINCL, LND_CAY
+	}
+	private static final EnumMap<CatLND, S57enum> Catlnd = new EnumMap<CatLND, S57enum>(CatLND.class); static { Catlnd.put(CatLND.LND_UNKN, new S57enum(0, ""));
+		Catlnd.put(CatLND.LND_FEN, new S57enum(1, "fen")); Catlnd.put(CatLND.LND_MRSH, new S57enum(2, "marsh")); Catlnd.put(CatLND.LND_BOG, new S57enum(3, "bog"));
+		Catlnd.put(CatLND.LND_HTHL, new S57enum(4, "heathland")); Catlnd.put(CatLND.LND_MNTN, new S57enum(5, "mountain")); Catlnd.put(CatLND.LND_LOWL, new S57enum(6, "lowlands"));
+		Catlnd.put(CatLND.LND_CNYN, new S57enum(7, "canyon")); Catlnd.put(CatLND.LND_PDDY, new S57enum(8, "paddy")); Catlnd.put(CatLND.LND_AGRI, new S57enum(9, "agricultural"));
+		Catlnd.put(CatLND.LND_SVNA, new S57enum(10, "savanna")); Catlnd.put(CatLND.LND_PARK, new S57enum(11, "parkland")); Catlnd.put(CatLND.LND_SWMP, new S57enum(12, "swamp"));
+		Catlnd.put(CatLND.LND_LSLD, new S57enum(13, "landslide")); Catlnd.put(CatLND.LND_LAVA, new S57enum(14, "lava")); Catlnd.put(CatLND.LND_SLTP, new S57enum(15, "salt_pan"));
+		Catlnd.put(CatLND.LND_MORN, new S57enum(16, "moraine")); Catlnd.put(CatLND.LND_CRTR, new S57enum(17, "crater")); Catlnd.put(CatLND.LND_CAVE, new S57enum(18, "cave"));
+		Catlnd.put(CatLND.LND_PINCL, new S57enum(19, "rock_pinnacle")); Catlnd.put(CatLND.LND_CAY, new S57enum(20, "cay"));
+	}
+	public enum CatLMK { LMK_UNKN, LMK_CARN, LMK_CMTY, LMK_CHMY, LMK_DISH, LMK_FLAG, LMK_FLAR, LMK_MAST, LMK_WNDS, LMK_MNMT, LMK_CLMN, LMK_MEML,	LMK_OBLK, LMK_STAT, LMK_CROS,
+		LMK_DOME, LMK_RADR, LMK_TOWR, LMK_WNDM, LMK_WNDG, LMK_SPIR, LMK_BLDR, LMK_MNRT, LMK_WTRT }
+	private static final EnumMap<CatLMK, S57enum> Catlmk = new EnumMap<CatLMK, S57enum>(CatLMK.class); static {Catlmk.put(CatLMK.LMK_UNKN, new S57enum(0, ""));
+		Catlmk.put(CatLMK.LMK_CARN, new S57enum(1, "cairn")); Catlmk.put(CatLMK.LMK_CMTY, new S57enum(2, "cemetery")); Catlmk.put(CatLMK.LMK_CHMY, new S57enum(3, "chimney"));
+		Catlmk.put(CatLMK.LMK_DISH, new S57enum(4, "dish_aerial")); Catlmk.put(CatLMK.LMK_FLAG, new S57enum(5, "flagstaff")); Catlmk.put(CatLMK.LMK_FLAR, new S57enum(6, "flare_stack"));
+	  Catlmk.put(CatLMK.LMK_MAST, new S57enum(7, "mast")); Catlmk.put(CatLMK.LMK_WNDS, new S57enum(8, "windsock")); Catlmk.put(CatLMK.LMK_MNMT, new S57enum(9, "monument"));
+	  Catlmk.put(CatLMK.LMK_CLMN, new S57enum(10, "column")); Catlmk.put(CatLMK.LMK_MEML, new S57enum(11, "memorial")); Catlmk.put(CatLMK.LMK_OBLK, new S57enum(12, "obelisk"));
+	  Catlmk.put(CatLMK.LMK_STAT, new S57enum(13, "statue")); Catlmk.put(CatLMK.LMK_CROS, new S57enum(14, "cross")); Catlmk.put(CatLMK.LMK_DOME, new S57enum(15, "dome"));
+	  Catlmk.put(CatLMK.LMK_RADR, new S57enum(16, "radar_scanner")); Catlmk.put(CatLMK.LMK_TOWR, new S57enum(17, "tower")); Catlmk.put(CatLMK.LMK_WNDM, new S57enum(18, "windmill"));
+	  Catlmk.put(CatLMK.LMK_WNDG, new S57enum(19, "windmotor")); Catlmk.put(CatLMK.LMK_SPIR, new S57enum(20, "spire")); Catlmk.put(CatLMK.LMK_BLDR, new S57enum(21, "boulder"));
+	}
+	public enum CatLAM { LAM_UNKN, LAM_PORT, LAM_STBD, LAM_PCST, LAM_PCPT, LAM_WWLT, LAM_WWRT, LAM_CHLT, LAM_CHRT, LAM_WWSN, LAM_CHSN, LAM_CHRB, LAM_CHLB, LAM_CRRT, LAM_CRLT,
+		LAM_DRLT, LAM_DRRT, LAM_TOLT, LAM_TPRT, LAM_JBRT, LAM_JNLT, LAM_HBRT, LAM_HBLT, LAM_BRGP } 
+	private static final EnumMap<CatLAM, S57enum> Catlam = new EnumMap<CatLAM, S57enum>(CatLAM.class); static { Catlam.put(CatLAM.LAM_UNKN, new S57enum(0, ""));
+		Catlam.put(CatLAM.LAM_PORT, new S57enum(1, "port")); Catlam.put(CatLAM.LAM_STBD, new S57enum(2, "starboard")); Catlam.put(CatLAM.LAM_PCST, new S57enum(3, "preferred_channel_starboard"));
+		Catlam.put(CatLAM.LAM_PCPT, new S57enum(4, "preferred_channel_port")); Catlam.put(CatLAM.LAM_WWRT, new S57enum(5, "waterway_right")); Catlam.put(CatLAM.LAM_WWLT, new S57enum(6, "waterway_left"));
+		Catlam.put(CatLAM.LAM_CHRT, new S57enum(7, "channel_right")); Catlam.put(CatLAM.LAM_CHLT, new S57enum(8, "channel_left")); Catlam.put(CatLAM.LAM_WWSN, new S57enum(9, "waterway_separation"));
+		Catlam.put(CatLAM.LAM_CHSN, new S57enum(10, "channel_separation")); Catlam.put(CatLAM.LAM_CHRB, new S57enum(11, "channel_right_bank")); Catlam.put(CatLAM.LAM_CHLB, new S57enum(12, "channel_left_bank"));
+		Catlam.put(CatLAM.LAM_CRRT, new S57enum(13, "crossover_right")); Catlam.put(CatLAM.LAM_CRLT, new S57enum(14, "crossover_left")); Catlam.put(CatLAM.LAM_DRLT, new S57enum(15, "danger_right"));
+		Catlam.put(CatLAM.LAM_DRRT, new S57enum(16, "danger_left")); Catlam.put(CatLAM.LAM_TOLT, new S57enum(17, "turnoff_right")); Catlam.put(CatLAM.LAM_TPRT, new S57enum(18, "turnoff_left"));
+		Catlam.put(CatLAM.LAM_JBRT, new S57enum(19, "junction_right")); Catlam.put(CatLAM.LAM_JNLT, new S57enum(20, "junction_left")); Catlam.put(CatLAM.LAM_HBRT, new S57enum(21, "harbour_right"));
+		Catlam.put(CatLAM.LAM_HBLT, new S57enum(22, "harbour_left")); Catlam.put(CatLAM.LAM_BRGP, new S57enum(23, "bridge_pier"));
+	}
+	public enum CatLIT { LIT_UNKN, LIT_DIR, LIT_LEAD, LIT_AERO, LIT_AIR, LIT_FOG, LIT_FLDL, LIT_STRP, LIT_SUBS, LIT_SPOT, LIT_FRNT, LIT_REAR, LIT_LOWR, LIT_UPPR, LIT_MOIR, LIT_EMRG, LIT_BRNG, LIT_HORI, LIT_VERT }
+	private static final EnumMap<CatLIT, S57enum> Catlit = new EnumMap<CatLIT, S57enum>(CatLIT.class); static { Catlit.put(CatLIT.LIT_UNKN, new S57enum(0, ""));
+		Catlit.put(CatLIT.LIT_DIR, new S57enum(1, "directional")); Catlit.put(CatLIT.LIT_LEAD, new S57enum(4, "leading")); Catlit.put(CatLIT.LIT_AERO, new S57enum(5, "aero"));
+		Catlit.put(CatLIT.LIT_AIR, new S57enum(6, "air_obstruction")); Catlit.put(CatLIT.LIT_FOG, new S57enum(7, "fog_detector")); Catlit.put(CatLIT.LIT_FLDL, new S57enum(8, "floodlight"));
+		Catlit.put(CatLIT.LIT_STRP, new S57enum(9, "strip_light")); Catlit.put(CatLIT.LIT_SUBS, new S57enum(10, "subsidiary")); Catlit.put(CatLIT.LIT_SPOT, new S57enum(11, "spotlight"));
+		Catlit.put(CatLIT.LIT_FRNT, new S57enum(12, "front")); Catlit.put(CatLIT.LIT_REAR, new S57enum(13, "rear")); Catlit.put(CatLIT.LIT_LOWR, new S57enum(14, "lower"));
+		Catlit.put(CatLIT.LIT_UPPR, new S57enum(15, "upper")); Catlit.put(CatLIT.LIT_MOIR, new S57enum(16, "moire")); Catlit.put(CatLIT.LIT_EMRG, new S57enum(17, "emergency"));
+		Catlit.put(CatLIT.LIT_BRNG, new S57enum(18, "bearing")); Catlit.put(CatLIT.LIT_HORI, new S57enum(19, "horizontal")); Catlit.put(CatLIT.LIT_VERT, new S57enum(20, "vertical"));
+	}
+	public enum CatMFA { MFA_UNKN, MFA_CRST, MFA_OYMS, MFA_FISH, MFA_SEAW, MFA_PRLC }
+	private static final EnumMap<CatMFA, S57enum> Catmfa = new EnumMap<CatMFA, S57enum>(CatMFA.class); static { Catmfa.put(CatMFA.MFA_UNKN, new S57enum(0, ""));
+		Catmfa.put(CatMFA.MFA_CRST, new S57enum(1, "crustaceans")); Catmfa.put(CatMFA.MFA_OYMS, new S57enum(2, "oysters_mussels")); Catmfa.put(CatMFA.MFA_FISH, new S57enum(3, "fish"));
+		Catmfa.put(CatMFA.MFA_SEAW, new S57enum(4, "seaweed")); Catmfa.put(CatMFA.MFA_PRLC, new S57enum(5, "pearl_culture"));
+	}
+	public enum CatMPA { MPA_UNKN, MPA_PRCT, MPA_TRPD, MPA_SUBM, MPA_FIRG, MPA_MINL, MPA_SMLA } 
+	private static final EnumMap<CatMPA, S57enum> Catmpa = new EnumMap<CatMPA, S57enum>(CatMPA.class); static { Catmpa.put(CatMPA.MPA_UNKN, new S57enum(0, ""));
+		Catmpa.put(CatMPA.MPA_PRCT, new S57enum(1, "practice")); Catmpa.put(CatMPA.MPA_TRPD, new S57enum(2, "torpedo")); Catmpa.put(CatMPA.MPA_SUBM, new S57enum(3, "submarine"));
+		Catmpa.put(CatMPA.MPA_FIRG, new S57enum(4, "firing")); Catmpa.put(CatMPA.MPA_MINL, new S57enum(5, "mine-laying")); Catmpa.put(CatMPA.MPA_SMLA, new S57enum(6, "small_arms"));
+	}
+	public enum CatMOR { MOR_UNKN, MOR_DLPN, MOR_DDPN, MOR_BLRD, MOR_WALL, MOR_PILE, MOR_CHAN, MOR_BUOY, MOR_SHRP, MOR_AUTO, MOR_POST, MOR_WIRE, MOR_CABL } 
+	private static final EnumMap<CatMOR, S57enum> Catmor = new EnumMap<CatMOR, S57enum>(CatMOR.class); static { Catmor.put(CatMOR.MOR_UNKN, new S57enum(0, ""));
+		Catmor.put(CatMOR.MOR_DLPN, new S57enum(1, "dolphin")); Catmor.put(CatMOR.MOR_DDPN, new S57enum(2, "deviation_dolphin")); Catmor.put(CatMOR.MOR_BLRD, new S57enum(3, "bollard"));
+		Catmor.put(CatMOR.MOR_WALL, new S57enum(4, "wall")); Catmor.put(CatMOR.MOR_PILE, new S57enum(5, "pile")); Catmor.put(CatMOR.MOR_CHAN, new S57enum(6, "chain"));
+		Catmor.put(CatMOR.MOR_BUOY, new S57enum(7, "buoy")); Catmor.put(CatMOR.MOR_SHRP, new S57enum(8, "shore_ropes")); Catmor.put(CatMOR.MOR_AUTO, new S57enum(9, "automatic"));
+		Catmor.put(CatMOR.MOR_POST, new S57enum(10, "post")); Catmor.put(CatMOR.MOR_WIRE, new S57enum(11, "wire")); Catmor.put(CatMOR.MOR_CABL, new S57enum(12, "cable"));
+	}
+	public enum CatNAV { NAV_UNKN, NAV_CLRG, NAV_TRST, NAV_LDNG }
+	private static final EnumMap<CatNAV, S57enum> Catnav = new EnumMap<CatNAV, S57enum>(CatNAV.class); static { Catnav.put(CatNAV.NAV_UNKN, new S57enum(0, ""));
+		Catnav.put(CatNAV.NAV_CLRG, new S57enum(1, "clearing")); Catnav.put(CatNAV.NAV_TRST, new S57enum(2, "transit")); Catnav.put(CatNAV.NAV_LDNG, new S57enum(3, "leading"));
+	}
+	public enum CatOBS { OBS_UNKN, OBS_STMP, OBS_WELH, OBS_DIFF, OBS_CRIB, OBS_FHVN, OBS_FLAR, OBS_FLGD, OBS_ICEB, OBS_GTKL, OBS_BOOM } 
+	private static final EnumMap<CatOBS, S57enum> Catobs = new EnumMap<CatOBS, S57enum>(CatOBS.class); static { Catobs.put(CatOBS.OBS_UNKN, new S57enum(0, ""));
+		Catobs.put(CatOBS.OBS_STMP, new S57enum(1, "stump")); Catobs.put(CatOBS.OBS_WELH, new S57enum(2, "wellhead")); Catobs.put(CatOBS.OBS_DIFF, new S57enum(3, "diffuser"));
+		Catobs.put(CatOBS.OBS_CRIB, new S57enum(4, "crib")); Catobs.put(CatOBS.OBS_FHVN, new S57enum(5, "fish_haven")); Catobs.put(CatOBS.OBS_FLAR, new S57enum(6, "foul_area"));
+		Catobs.put(CatOBS.OBS_FLGD, new S57enum(7, "foul_ground")); Catobs.put(CatOBS.OBS_ICEB, new S57enum(8, "ice_boom")); Catobs.put(CatOBS.OBS_GTKL, new S57enum(9, "ground_tackle"));
+		Catobs.put(CatOBS.OBS_BOOM, new S57enum(10, "boom"));
+	}
+	public enum CatOFP { OFP_UNKN, OFP_OIL, OFP_PROD, OFP_OBS, OFP_ALP, OFP_SALM, OFP_MOOR, OFP_AISL, OFP_FPSO, OFP_ACCN, OFP_NCCB } 
+	private static final EnumMap<CatOFP, S57enum> Catofp = new EnumMap<CatOFP, S57enum>(CatOFP.class); static { Catofp.put(CatOFP.OFP_UNKN, new S57enum(0, ""));
+		Catofp.put(CatOFP.OFP_OIL, new S57enum(1, "oil")); Catofp.put(CatOFP.OFP_PROD, new S57enum(2, "production")); Catofp.put(CatOFP.OFP_OBS, new S57enum(3, "observation"));
+		Catofp.put(CatOFP.OFP_ALP, new S57enum(4, "alp")); Catofp.put(CatOFP.OFP_SALM, new S57enum(5, "salm")); Catofp.put(CatOFP.OFP_MOOR, new S57enum(6, "mooring"));
+		Catofp.put(CatOFP.OFP_AISL, new S57enum(7, "artificial_island")); Catofp.put(CatOFP.OFP_FPSO, new S57enum(8, "fpso")); Catofp.put(CatOFP.OFP_ACCN, new S57enum(9, "accommodation"));
+		Catofp.put(CatOFP.OFP_NCCB, new S57enum(10, "nccb"));
+	}
+	public enum CatOLB { OLB_UNKN, OLB_RETN, OLB_FLTG }
+	private static final EnumMap<CatOLB, S57enum> Catolb = new EnumMap<CatOLB, S57enum>(CatOLB.class); static { Catolb.put(CatOLB.OLB_UNKN, new S57enum(0, ""));
+		Catolb.put(CatOLB.OLB_RETN, new S57enum(1, "retention")); Catolb.put(CatOLB.OLB_FLTG, new S57enum(2, "floating"));
+	}
+	public enum CatPLE { PLE_UNKN, PLE_STAK, PLE_SNAG, PLE_POST, PLE_TRIP }
+	private static final EnumMap<CatPLE, S57enum> Catple = new EnumMap<CatPLE, S57enum>(CatPLE.class); static { Catple.put(CatPLE.PLE_UNKN, new S57enum(0, ""));
+		Catple.put(CatPLE.PLE_STAK, new S57enum(1, "stake")); Catple.put(CatPLE.PLE_SNAG, new S57enum(2, "snag")); Catple.put(CatPLE.PLE_POST, new S57enum(3, "post"));
+		Catple.put(CatPLE.PLE_TRIP, new S57enum(4, "tripodal"));
+	}
+	public enum CatPIL { PIL_UNKN, PIL_CVSL, PIL_HELI, PIL_SHOR }
+	private static final EnumMap<CatPIL, S57enum> Catpil = new EnumMap<CatPIL, S57enum>(CatPIL.class); static { Catpil.put(CatPIL.PIL_UNKN, new S57enum(0, ""));
+		Catpil.put(CatPIL.PIL_CVSL, new S57enum(1, "cruising_vessel")); Catpil.put(CatPIL.PIL_HELI, new S57enum(2, "helicopter")); Catpil.put(CatPIL.PIL_SHOR, new S57enum(3, "from_shore"));
+	}
+	public enum CatPIP { PIP_UNKN, PIP_OFAL, PIP_ITAK, PIP_SEWR, PIP_BBLR, PIP_SPPL }
+	private static final EnumMap<CatPIP, S57enum> Catpip = new EnumMap<CatPIP, S57enum>(CatPIP.class); static { Catpip.put(CatPIP.PIP_UNKN, new S57enum(0, ""));
+		Catpip.put(CatPIP.PIP_OFAL, new S57enum(2, "outfall")); Catpip.put(CatPIP.PIP_ITAK, new S57enum(3, "intake")); Catpip.put(CatPIP.PIP_SEWR, new S57enum(4, "sewer"));
+		Catpip.put(CatPIP.PIP_BBLR, new S57enum(5, "bubbler")); Catpip.put(CatPIP.PIP_SPPL, new S57enum(6, "supply"));
+	}
+	public enum CatPRA { PRA_UNKN, PRA_QRRY, PRA_MINE, PRA_STPL, PRA_PSTN, PRA_RFNY, PRA_TYRD, PRA_FACT, PRA_TFRM, PRA_WFRM, PRA_SLAG, PRA_CURF, PRA_OILF, PRA_GASF, PRA_WAVE } 
+	private static final EnumMap<CatPRA, S57enum> Catpra = new EnumMap<CatPRA, S57enum>(CatPRA.class); static { Catpra.put(CatPRA.PRA_UNKN, new S57enum(0, ""));
+		Catpra.put(CatPRA.PRA_QRRY, new S57enum(1, "quarry")); Catpra.put(CatPRA.PRA_MINE, new S57enum(2, "mine")); Catpra.put(CatPRA.PRA_STPL, new S57enum(3, "stockpile"));
+		Catpra.put(CatPRA.PRA_PSTN, new S57enum(4, "power_station")); Catpra.put(CatPRA.PRA_RFNY, new S57enum(5, "refinery")); Catpra.put(CatPRA.PRA_TYRD, new S57enum(6, "timber_yard"));
+		Catpra.put(CatPRA.PRA_FACT, new S57enum(7, "factory")); Catpra.put(CatPRA.PRA_TFRM, new S57enum(8, "tank_farm")); Catpra.put(CatPRA.PRA_WFRM, new S57enum(9, "wind_farm"));
+		Catpra.put(CatPRA.PRA_SLAG, new S57enum(10, "slag_heap")); Catpra.put(CatPRA.PRA_CURF, new S57enum(11, "current_farm")); Catpra.put(CatPRA.PRA_OILF, new S57enum(12, "oil"));
+		Catpra.put(CatPRA.PRA_GASF, new S57enum(13, "gas")); Catpra.put(CatPRA.PRA_WAVE, new S57enum(14, "wave_energy"));
+	}
+	public enum CatPYL { PYL_UNKN, PYL_POWR, PYL_TELE, PYL_AERL, PYL_BRDG, PYL_PIER } 
+	private static final EnumMap<CatPYL, S57enum> Catpyl = new EnumMap<CatPYL, S57enum>(CatPYL.class); static { Catpyl.put(CatPYL.PYL_UNKN, new S57enum(0, ""));
+		Catpyl.put(CatPYL.PYL_POWR, new S57enum(1, "power")); Catpyl.put(CatPYL.PYL_TELE, new S57enum(2, "telecom")); Catpyl.put(CatPYL.PYL_AERL, new S57enum(3, "aerial"));
+		Catpyl.put(CatPYL.PYL_BRDG, new S57enum(4, "bridge")); Catpyl.put(CatPYL.PYL_PIER, new S57enum(5, "bridge_pier"));
+	}
+	public enum CatRAS { RAS_UNKN, RAS_SURV, RAS_COST }
+	private static final EnumMap<CatRAS, S57enum> Catras = new EnumMap<CatRAS, S57enum>(CatRAS.class); static { Catras.put(CatRAS.RAS_UNKN, new S57enum(0, ""));
+		Catras.put(CatRAS.RAS_SURV, new S57enum(1, "surveillance")); Catras.put(CatRAS.RAS_COST, new S57enum(2, "coast"));
+	}
+	public enum CatRTB { RTB_UNKN, RTB_RAMK, RTB_RACN, RTB_LDG }
+	private static final EnumMap<CatRTB, S57enum> Catrtb = new EnumMap<CatRTB, S57enum>(CatRTB.class); static {Catrtb.put(CatRTB.RTB_UNKN, new S57enum(0, ""));
+		Catrtb.put(CatRTB.RTB_RAMK, new S57enum(1, "ramark")); Catrtb.put(CatRTB.RTB_RACN, new S57enum(2, "racon")); Catrtb.put(CatRTB.RTB_LDG, new S57enum(3, "leading"));
+	}
+	public enum CatROS { ROS_UNKN, ROS_OMNI, ROS_DIRL, ROS_ROTP, ROS_CNSL, ROS_RDF, ROS_QTA, ROS_AERO, ROS_DECA, ROS_LORN, ROS_DGPS, ROS_TORN, ROS_OMGA, ROS_SYLD, ROS_CHKA,
+		ROS_PCOM, ROS_COMB, ROS_FACS, ROS_TIME, ROS_PAIS, ROS_SAIS, ROS_VAIS, ROS_VANC, ROS_VASC, ROS_VAEC, ROS_VAWC, ROS_VAPL, ROS_VASL, ROS_VAID, ROS_VASW, ROS_VASP, ROS_VAWK } 
+	private static final EnumMap<CatROS, S57enum> Catros = new EnumMap<CatROS, S57enum>(CatROS.class); static { Catros.put(CatROS.ROS_UNKN, new S57enum(0, ""));
+		Catros.put(CatROS.ROS_OMNI, new S57enum(1, "omnidirectional")); Catros.put(CatROS.ROS_DIRL, new S57enum(2, "directional"));	Catros.put(CatROS.ROS_ROTP, new S57enum(3, "rotating_pattern"));
+		Catros.put(CatROS.ROS_CNSL, new S57enum(4, "consol")); Catros.put(CatROS.ROS_RDF, new S57enum(5, "rdf")); Catros.put(CatROS.ROS_QTA, new S57enum(6, "qtg"));
+		Catros.put(CatROS.ROS_AERO, new S57enum(7, "aeronautical")); Catros.put(CatROS.ROS_DECA, new S57enum(8, "decca")); Catros.put(CatROS.ROS_LORN, new S57enum(9, "loran"));
+		Catros.put(CatROS.ROS_DGPS, new S57enum(10, "dgps")); Catros.put(CatROS.ROS_TORN, new S57enum(11, "toran")); Catros.put(CatROS.ROS_OMGA, new S57enum(12, "omega"));
+		Catros.put(CatROS.ROS_SYLD, new S57enum(13, "syledis")); Catros.put(CatROS.ROS_CHKA, new S57enum(14, "chiaka")); Catros.put(CatROS.ROS_PCOM, new S57enum(15, "public_communication"));
+		Catros.put(CatROS.ROS_COMB, new S57enum(16, "commercial_broadcast")); Catros.put(CatROS.ROS_FACS, new S57enum(17, "facsimile")); Catros.put(CatROS.ROS_TIME, new S57enum(18, "time_signal"));
+		Catros.put(CatROS.ROS_PAIS, new S57enum(19, "ais")); Catros.put(CatROS.ROS_SAIS, new S57enum(20, "s-ais")); Catros.put(CatROS.ROS_VAIS, new S57enum(21, "v-ais"));
+		Catros.put(CatROS.ROS_VANC, new S57enum(22, "v-ais_north_cardinal")); Catros.put(CatROS.ROS_VASC, new S57enum(23, "v-ais_south_cardinal"));
+		Catros.put(CatROS.ROS_VAEC, new S57enum(24, "v-ais_east_cardinal")); Catros.put(CatROS.ROS_VAWC, new S57enum(25, "v-ais_west_cardinal"));
+		Catros.put(CatROS.ROS_VAPL, new S57enum(26, "v-ais_port_lateral")); Catros.put(CatROS.ROS_VASL, new S57enum(27, "v-ais_starboard_lateral"));
+		Catros.put(CatROS.ROS_VAID, new S57enum(28, "v-ais_isolated_danger")); Catros.put(CatROS.ROS_VASW, new S57enum(29, "v-ais_safe_water"));
+		Catros.put(CatROS.ROS_VASP, new S57enum(30, "v-ais_special_purpose")); Catros.put(CatROS.ROS_VAWK, new S57enum(31, "v-ais_wreck")); 
+	}
+	public enum CatRSC { RSC_UNKN, RSC_LIFB, RSC_ROKT, RSC_LBRK, RSC_RFSW, RSC_RFIT, RSC_LBOM, RSC_RDIO, RSC_FSTA, RSC_SPLN, RSC_ACFT, RSC_STUG } 
+	private static final EnumMap<CatRSC, S57enum> Catrsc = new EnumMap<CatRSC, S57enum>(CatRSC.class); static { Catrsc.put(CatRSC.RSC_UNKN, new S57enum(0, ""));
+		Catrsc.put(CatRSC.RSC_LIFB, new S57enum(1, "lifeboat")); Catrsc.put(CatRSC.RSC_ROKT, new S57enum(2, "rocket")); Catrsc.put(CatRSC.RSC_LBRK, new S57enum(3, "lifeboat_rocket"));
+		Catrsc.put(CatRSC.RSC_RFSW, new S57enum(4, "refuge_shipwrecked")); Catrsc.put(CatRSC.RSC_RFIT, new S57enum(5, "refuge_intertidal")); Catrsc.put(CatRSC.RSC_LBOM, new S57enum(6, "lifeboat_on_mooring"));
+		Catrsc.put(CatRSC.RSC_RDIO, new S57enum(7, "radio")); Catrsc.put(CatRSC.RSC_FSTA, new S57enum(8, "first_aid")); Catrsc.put(CatRSC.RSC_SPLN, new S57enum(9, "seaplane"));
+		Catrsc.put(CatRSC.RSC_ACFT, new S57enum(10, "aircraft")); Catrsc.put(CatRSC.RSC_STUG, new S57enum(12, "tug"));
+	}
+	public enum CatREA { REA_UNKN, REA_SFTY, REA_NANC, REA_NFSH, REA_NATR, REA_BRDS, REA_GRSV, REA_SEAL, REA_DEGR, REA_MILY, REA_HIST, REA_INST,
+		REA_NASF, REA_STRD, REA_MINE, REA_NDIV, REA_TBAV, REA_PROH, REA_SWIM, REA_WAIT, REA_RSCH, REA_DREG, REA_FSNC, REA_ERES, REA_NWAK, REA_SWNG, REA_WSKI, REA_ESSA, REA_PSSA } 
+	private static final EnumMap<CatREA, S57enum> Catrea = new EnumMap<CatREA, S57enum>(CatREA.class); static { Catrea.put(CatREA.REA_UNKN, new S57enum(0, ""));
+		Catrea.put(CatREA.REA_SFTY, new S57enum(1, "safety")); Catrea.put(CatREA.REA_NANC, new S57enum(2, "no_anchoring")); Catrea.put(CatREA.REA_NFSH, new S57enum(3, "no_fishing"));
+		Catrea.put(CatREA.REA_NATR, new S57enum(4, "nature_reserve")); Catrea.put(CatREA.REA_BRDS, new S57enum(5, "bird_sanctuary")); Catrea.put(CatREA.REA_GRSV, new S57enum(6, "game_reserve"));
+		Catrea.put(CatREA.REA_SEAL, new S57enum(7, "seal_sanctuary")); Catrea.put(CatREA.REA_DEGR, new S57enum(8, "degaussing_range")); Catrea.put(CatREA.REA_MILY, new S57enum(9, "military"));
+	  Catrea.put(CatREA.REA_HIST, new S57enum(10, "historic_wreck")); Catrea.put(CatREA.REA_INST, new S57enum(11, "inshore_traffic")); Catrea.put(CatREA.REA_NASF, new S57enum(12, "navigational_aid_safety"));
+	  Catrea.put(CatREA.REA_STRD, new S57enum(13, "stranding_danger")); Catrea.put(CatREA.REA_MINE, new S57enum(14, "minefield")); Catrea.put(CatREA.REA_NDIV, new S57enum(15, "no_diving"));
+	  Catrea.put(CatREA.REA_TBAV, new S57enum(16, "to_be_avoided")); Catrea.put(CatREA.REA_PROH, new S57enum(17, "prohibited")); Catrea.put(CatREA.REA_SWIM, new S57enum(18, "swimming"));
+	  Catrea.put(CatREA.REA_WAIT, new S57enum(19, "waiting")); Catrea.put(CatREA.REA_RSCH, new S57enum(20, "research")); Catrea.put(CatREA.REA_DREG, new S57enum(21, "dredging"));
+	  Catrea.put(CatREA.REA_FSNC, new S57enum(22, "fish_sanctuary")); Catrea.put(CatREA.REA_ERES, new S57enum(23, "ecological_reserve")); Catrea.put(CatREA.REA_NWAK, new S57enum(24, "no_wake"));
+	  Catrea.put(CatREA.REA_SWNG, new S57enum(25, "swinging")); Catrea.put(CatREA.REA_WSKI, new S57enum(26, "water_skiing"));
+	  Catrea.put(CatREA.REA_ESSA, new S57enum(27, "environmentally_sensitive")); Catrea.put(CatREA.REA_PSSA, new S57enum(28, "particularly_sensitive"));
+	}
+	public enum CatROD { ROD_UNKN, ROD_MWAY, ROD_MAJR, ROD_MINR, ROD_TRAK, ROD_MAJS, ROD_MINS, ROD_CRSG, ROD_PATH } 
+	private static final EnumMap<CatROD, S57enum> Catrod = new EnumMap<CatROD, S57enum>(CatROD.class); static { Catrod.put(CatROD.ROD_UNKN, new S57enum(0, ""));
+		Catrod.put(CatROD.ROD_MWAY, new S57enum(1, "motorway")); Catrod.put(CatROD.ROD_MAJR, new S57enum(2, "major_road")); Catrod.put(CatROD.ROD_MINR, new S57enum(3, "minor_road"));
+		Catrod.put(CatROD.ROD_TRAK, new S57enum(4, "track")); Catrod.put(CatROD.ROD_MAJS, new S57enum(5, "major_street")); Catrod.put(CatROD.ROD_MINS, new S57enum(6, "minor_street"));
+		Catrod.put(CatROD.ROD_CRSG, new S57enum(7, "crossing")); Catrod.put(CatROD.ROD_PATH, new S57enum(8, "path"));
+	}
+	public enum CatRUN { RUN_UNKN, RUN_AERP, RUN_HELI }
+	private static final EnumMap<CatRUN, S57enum> Catrun = new EnumMap<CatRUN, S57enum>(CatRUN.class); static { Catrun.put(CatRUN.RUN_UNKN, new S57enum(0, ""));
+		Catrun.put(CatRUN.RUN_AERP, new S57enum(1, "aeroplane")); Catrun.put(CatRUN.RUN_HELI, new S57enum(2, "helicopter"));
+	}
+	public enum CatSEA { SEA_UNKN, SEA_GENL, SEA_GAT, SEA_BANK, SEA_DEEP, SEA_BAY, SEA_TRCH, SEA_BASN, SEA_MDFT, SEA_REEF, SEA_LEDG, SEA_CNYN, SEA_NRRW, SEA_SHOL,
+		SEA_KNOL, SEA_RIDG, SEA_SMNT, SEA_PNCL, SEA_APLN, SEA_PLTU, SEA_SPUR, SEA_SHLF, SEA_TRGH, SEA_SDDL, SEA_AHLL, SEA_APRN, SEA_AAPN, SEA_BLND, SEA_CMGN, SEA_CRIS,
+		SEA_ESCT, SEA_FAN, SEA_FZON, SEA_GAP, SEA_GUYT, SEA_HILL, SEA_HOLE, SEA_LEVE, SEA_MVLY, SEA_MOAT, SEA_MTNS, SEA_PEAK, SEA_PVNC, SEA_RISE, SEA_SCNL, SEA_SCHN,
+		SEA_SEDG, SEA_SILL, SEA_SLOP, SEA_TRRC, SEA_VLLY, SEA_CANL, SEA_LAKE, SEA_RIVR, SEA_RECH }
+	private static final EnumMap<CatSEA, S57enum> Catsea = new EnumMap<CatSEA, S57enum>(CatSEA.class); static { Catsea.put(CatSEA.SEA_UNKN, new S57enum(0, ""));
+		Catsea.put(CatSEA.SEA_GENL, new S57enum(1, "general")); Catsea.put(CatSEA.SEA_GAT, new S57enum(2, "gat")); Catsea.put(CatSEA.SEA_BANK, new S57enum(3, "bank"));
+		Catsea.put(CatSEA.SEA_DEEP, new S57enum(4, "deep")); Catsea.put(CatSEA.SEA_BAY, new S57enum(5, "bay")); Catsea.put(CatSEA.SEA_TRCH, new S57enum(6, "trench"));
+		Catsea.put(CatSEA.SEA_BASN, new S57enum(7, "basin")); Catsea.put(CatSEA.SEA_MDFT, new S57enum(8, "flat")); Catsea.put(CatSEA.SEA_REEF, new S57enum(9, "reef"));
+		Catsea.put(CatSEA.SEA_LEDG, new S57enum(10, "ledge")); Catsea.put(CatSEA.SEA_CNYN, new S57enum(11, "canyon")); Catsea.put(CatSEA.SEA_NRRW, new S57enum(12, "narrows"));
+		Catsea.put(CatSEA.SEA_SHOL, new S57enum(13, "shoal")); Catsea.put(CatSEA.SEA_KNOL, new S57enum(14, "knoll")); Catsea.put(CatSEA.SEA_RIDG, new S57enum(15, "ridge"));
+		Catsea.put(CatSEA.SEA_SMNT, new S57enum(16, "seamount")); Catsea.put(CatSEA.SEA_PNCL, new S57enum(17, "pinnacle")); Catsea.put(CatSEA.SEA_APLN, new S57enum(18, "abyssal_plain"));
+		Catsea.put(CatSEA.SEA_PLTU, new S57enum(19, "plateau")); Catsea.put(CatSEA.SEA_SPUR, new S57enum(20, "spur")); Catsea.put(CatSEA.SEA_SHLF, new S57enum(21, "shelf"));
+		Catsea.put(CatSEA.SEA_TRGH, new S57enum(22, "trough")); Catsea.put(CatSEA.SEA_SDDL, new S57enum(23, "saddle")); Catsea.put(CatSEA.SEA_AHLL, new S57enum(24, "abyssal_hills"));
+		Catsea.put(CatSEA.SEA_APRN, new S57enum(25, "apron")); Catsea.put(CatSEA.SEA_AAPN, new S57enum(26, "archipelagic_apron")); Catsea.put(CatSEA.SEA_BLND, new S57enum(27, "borderland"));
+		Catsea.put(CatSEA.SEA_CMGN, new S57enum(28, "continental_margin")); Catsea.put(CatSEA.SEA_CRIS, new S57enum(29, "continental_rise")); Catsea.put(CatSEA.SEA_ESCT, new S57enum(30, "escarpment"));
+		Catsea.put(CatSEA.SEA_FAN, new S57enum(31, "fan")); Catsea.put(CatSEA.SEA_FZON, new S57enum(32, "fracture_zone")); Catsea.put(CatSEA.SEA_GAP, new S57enum(33, "gap"));
+		Catsea.put(CatSEA.SEA_GUYT, new S57enum(34, "guyot")); Catsea.put(CatSEA.SEA_HILL, new S57enum(35, "hill")); Catsea.put(CatSEA.SEA_HOLE, new S57enum(36, "hole"));
+		Catsea.put(CatSEA.SEA_LEVE, new S57enum(37, "levee")); Catsea.put(CatSEA.SEA_MVLY, new S57enum(38, "median_valley")); Catsea.put(CatSEA.SEA_MOAT, new S57enum(39, "moat"));
+		Catsea.put(CatSEA.SEA_MTNS, new S57enum(40, "mountains")); Catsea.put(CatSEA.SEA_PEAK, new S57enum(41, "peak")); Catsea.put(CatSEA.SEA_PVNC, new S57enum(42, "province"));
+		Catsea.put(CatSEA.SEA_RISE, new S57enum(43, "rise")); Catsea.put(CatSEA.SEA_SCNL, new S57enum(44, "sea_channel")); Catsea.put(CatSEA.SEA_SCHN, new S57enum(45, "seamount_chain"));
+		Catsea.put(CatSEA.SEA_SEDG, new S57enum(46, "shelf-edge")); Catsea.put(CatSEA.SEA_SILL, new S57enum(47, "sill")); Catsea.put(CatSEA.SEA_SLOP, new S57enum(48, "slope"));
+		Catsea.put(CatSEA.SEA_TRRC, new S57enum(49, "terrace")); Catsea.put(CatSEA.SEA_VLLY, new S57enum(50, "valley")); Catsea.put(CatSEA.SEA_CANL, new S57enum(51, "canal")); 
+		Catsea.put(CatSEA.SEA_LAKE, new S57enum(52, "lake")); Catsea.put(CatSEA.SEA_RIVR, new S57enum(53, "river")); Catsea.put(CatSEA.SEA_RECH, new S57enum(54, "reach"));
+	}
+	public enum CatSLC { SLC_UNKN, SLC_BWTR, SLC_GRYN, SLC_MOLE, SLC_PIER, SLC_PPER, SLC_WHRF, SLC_TWAL, SLC_RPRP, SLC_RVMT, SLC_SWAL, SLC_LSTP,
+		SLC_RAMP, SLC_SWAY, SLC_FNDR, SLC_SFWF,  SLC_OFWF,  SLC_LRMP,  SLC_LWAL, SLC_ICEB } 
+	private static final EnumMap<CatSLC, S57enum> Catslc = new EnumMap<CatSLC, S57enum>(CatSLC.class); static { Catslc.put(CatSLC.SLC_UNKN, new S57enum(0, ""));
+		Catslc.put(CatSLC.SLC_BWTR, new S57enum(1, "breakwater")); Catslc.put(CatSLC.SLC_GRYN, new S57enum(2, "groyne")); Catslc.put(CatSLC.SLC_MOLE, new S57enum(3, "mole"));
+		Catslc.put(CatSLC.SLC_PIER, new S57enum(4, "pier")); Catslc.put(CatSLC.SLC_PPER, new S57enum(5, "promenade_pier")); Catslc.put(CatSLC.SLC_WHRF, new S57enum(6, "wharf"));
+		Catslc.put(CatSLC.SLC_TWAL, new S57enum(7, "training_wall")); Catslc.put(CatSLC.SLC_RPRP, new S57enum(8, "rip_rap")); Catslc.put(CatSLC.SLC_RVMT, new S57enum(9, "revetment"));
+		Catslc.put(CatSLC.SLC_SWAL, new S57enum(10, "sea_wall")); Catslc.put(CatSLC.SLC_LSTP, new S57enum(11, "landing_steps")); Catslc.put(CatSLC.SLC_RAMP, new S57enum(12, "ramp"));
+		Catslc.put(CatSLC.SLC_SWAY, new S57enum(13, "slipway")); Catslc.put(CatSLC.SLC_FNDR, new S57enum(14, "fender")); Catslc.put(CatSLC.SLC_SFWF, new S57enum(15, "solid_face_wharf"));
+		Catslc.put(CatSLC.SLC_OFWF, new S57enum(16, "open_face_wharf")); Catslc.put(CatSLC.SLC_LRMP, new S57enum(17, "log_ramp")); Catslc.put(CatSLC.SLC_LWAL, new S57enum(18, "lock_wall"));
+		Catslc.put(CatSLC.SLC_ICEB, new S57enum(18, "ice_breaker"));
+	}
+	public enum CatSIT { SIT_UNKN, SIT_PRTC, SIT_PRTE, SIT_IPT, SIT_BRTH, SIT_DOCK, SIT_LOCK, SIT_FLDB, SIT_BRDG, SIT_DRDG, SIT_TCLT, SIT_SPCL, SIT_PLTG, SIT_ONCT }
+	private static final EnumMap<CatSIT, S57enum>  Catsit = new EnumMap<CatSIT, S57enum>(CatSIT.class); static {Catsit.put(CatSIT.SIT_UNKN, new S57enum(0, ""));
+		Catsit.put(CatSIT.SIT_PRTC, new S57enum(1, "port_control")); Catsit.put(CatSIT.SIT_PRTE, new S57enum(2, "port_entry_departure")); Catsit.put(CatSIT.SIT_IPT, new S57enum(3, "ipt"));
+		Catsit.put(CatSIT.SIT_BRTH, new S57enum(4, "berthing")); Catsit.put(CatSIT.SIT_DOCK, new S57enum(5, "dock")); Catsit.put(CatSIT.SIT_LOCK, new S57enum(6, "lock"));
+		Catsit.put(CatSIT.SIT_FLDB, new S57enum(7, "flood_barrage")); Catsit.put(CatSIT.SIT_BRDG, new S57enum(8, "bridge_passage")); Catsit.put(CatSIT.SIT_DRDG, new S57enum(9, "dredging"));
+		Catsit.put(CatSIT.SIT_TCLT, new S57enum(10, "traffic_control")); Catsit.put(CatSIT.SIT_PLTG, new S57enum(11, "pilotage")); Catsit.put(CatSIT.SIT_SPCL, new S57enum(12, "special"));
+		Catsit.put(CatSIT.SIT_ONCT, new S57enum(13, "oncoming_traffic"));
+	}
+	public enum CatSIW { SIW_UNKN, SIW_DNGR, SIW_OBST, SIW_CABL, SIW_MILY, SIW_DSTR, SIW_WTHR, SIW_STRM, SIW_ICE, SIW_TIME, SIW_TIDE, SIW_TSTR,
+	  SIW_TIDG, SIW_TIDS, SIW_DIVE, SIW_WTLG, SIW_VRCL, SIW_HIWM, SIW_DPTH, SIW_CURR }
+	private static final EnumMap<CatSIW, S57enum>  Catsiw = new EnumMap<CatSIW, S57enum>(CatSIW.class); static {Catsiw.put(CatSIW.SIW_UNKN, new S57enum(0, ""));
+		Catsiw.put(CatSIW.SIW_DNGR, new S57enum(1, "danger")); Catsiw.put(CatSIW.SIW_OBST, new S57enum(2, "maritime_obstruction")); Catsiw.put(CatSIW.SIW_CABL, new S57enum(3, "cable"));
+		Catsiw.put(CatSIW.SIW_MILY, new S57enum(4, "military")); Catsiw.put(CatSIW.SIW_DSTR, new S57enum(5, "distress")); Catsiw.put(CatSIW.SIW_WTHR, new S57enum(6, "weather"));
+		Catsiw.put(CatSIW.SIW_STRM, new S57enum(7, "storm")); Catsiw.put(CatSIW.SIW_ICE, new S57enum(8, "ice")); Catsiw.put(CatSIW.SIW_TIME, new S57enum(9, "time"));
+		Catsiw.put(CatSIW.SIW_TIDE, new S57enum(10, "tide")); Catsiw.put(CatSIW.SIW_TSTR, new S57enum(11, "tidal_stream")); Catsiw.put(CatSIW.SIW_TIDG, new S57enum(12, "tide_gauge"));
+	  Catsiw.put(CatSIW.SIW_TIDS, new S57enum(13, "tide_scale")); Catsiw.put(CatSIW.SIW_DIVE, new S57enum(14, "diving")); Catsiw.put(CatSIW.SIW_WTLG, new S57enum(15, "water_level_gauge"));
+	  Catsiw.put(CatSIW.SIW_VRCL, new S57enum(16, "vertical_clearance")); Catsiw.put(CatSIW.SIW_HIWM, new S57enum(17, "high_water")); Catsiw.put(CatSIW.SIW_DPTH, new S57enum(18, "depth"));
+	  Catsiw.put(CatSIW.SIW_CURR, new S57enum(19, "current"));
+	}
+	public enum CatSIL { SIL_UNKN, SIL_SILO, SIL_TANK, SIL_GRNE, SIL_WTRT } 
+	private static final EnumMap<CatSIL, S57enum> Catsil = new EnumMap<CatSIL, S57enum>(CatSIL.class); static { Catsil.put(CatSIL.SIL_UNKN, new S57enum(0, ""));
+		Catsil.put(CatSIL.SIL_SILO, new S57enum(1, "silo")); Catsil.put(CatSIL.SIL_TANK, new S57enum(2, "tank")); Catsil.put(CatSIL.SIL_GRNE, new S57enum(3, "grain_elevator"));
+		Catsil.put(CatSIL.SIL_WTRT, new S57enum(4, "water_tower"));
+	}
+	public enum CatSLO { SLO_UNKN, SLO_CUTG, SLO_EMBK, SLO_DUNE, SLO_HILL, SLO_PINO, SLO_CLIF, SLO_SCRE } 
+	private static final EnumMap<CatSLO, S57enum> Catslo = new EnumMap<CatSLO, S57enum>(CatSLO.class); static { Catslo.put(CatSLO.SLO_UNKN, new S57enum(0, ""));
+		Catslo.put(CatSLO.SLO_CUTG, new S57enum(1, "cutting")); Catslo.put(CatSLO.SLO_EMBK, new S57enum(2, "embankment")); Catslo.put(CatSLO.SLO_DUNE, new S57enum(3, "dune"));
+		Catslo.put(CatSLO.SLO_HILL, new S57enum(4, "hill")); Catslo.put(CatSLO.SLO_PINO, new S57enum(5, "pingo")); Catslo.put(CatSLO.SLO_CLIF, new S57enum(6, "cliff")); Catslo.put(CatSLO.SLO_SCRE, new S57enum(7, "scree"));
+	}
+	public enum CatSCF { SCF_UNKN, SCF_VBTH, SCF_CLUB, SCF_BHST, SCF_SMKR, SCF_BTYD, SCF_INN, SCF_RSRT, SCF_CHDR, SCF_PROV, SCF_DCTR, SCF_PHRM,
+		SCF_WTRT, SCF_FUEL, SCF_ELEC, SCF_BGAS, SCF_SHWR, SCF_LAUN, SCF_WC, SCF_POST, SCF_TELE, SCF_REFB, SCF_CARP, SCF_BTPK, SCF_CRVN, SCF_CAMP,
+		SCF_PMPO, SCF_EMRT, SCF_SLPW, SCF_VMOR, SCF_SCRB, SCF_PCNC, SCF_MECH, SCF_SECS }
+	private static final EnumMap<CatSCF, S57enum> Catscf = new EnumMap<CatSCF, S57enum>(CatSCF.class); static { Catscf.put(CatSCF.SCF_UNKN, new S57enum(0, ""));
+		Catscf.put(CatSCF.SCF_VBTH, new S57enum(1, "visitor_berth")); Catscf.put(CatSCF.SCF_CLUB, new S57enum(2, "nautical_club")); Catscf.put(CatSCF.SCF_BHST, new S57enum(3, "boat_hoist"));
+		Catscf.put(CatSCF.SCF_SMKR, new S57enum(4, "sailmaker")); Catscf.put(CatSCF.SCF_BTYD, new S57enum(5, "boatyard")); Catscf.put(CatSCF.SCF_INN, new S57enum(6, "public_inn"));
+		Catscf.put(CatSCF.SCF_RSRT, new S57enum(7, "restaurant")); Catscf.put(CatSCF.SCF_CHDR, new S57enum(8, "chandler")); Catscf.put(CatSCF.SCF_PROV, new S57enum(9, "provisions"));
+		Catscf.put(CatSCF.SCF_DCTR, new S57enum(10, "doctor")); Catscf.put(CatSCF.SCF_PHRM, new S57enum(11, "pharmacy")); Catscf.put(CatSCF.SCF_WTRT, new S57enum(12, "water_tap"));
+	  Catscf.put(CatSCF.SCF_FUEL, new S57enum(13, "fuel_station")); Catscf.put(CatSCF.SCF_ELEC, new S57enum(14, "electricity")); Catscf.put(CatSCF.SCF_BGAS, new S57enum(15, "bottle_gas"));
+	  Catscf.put(CatSCF.SCF_SHWR, new S57enum(16, "showers")); Catscf.put(CatSCF.SCF_LAUN, new S57enum(17, "laundrette")); Catscf.put(CatSCF.SCF_WC, new S57enum(18, "toilets"));
+	  Catscf.put(CatSCF.SCF_POST, new S57enum(19, "post_box")); Catscf.put(CatSCF.SCF_TELE, new S57enum(20, "telephone")); Catscf.put(CatSCF.SCF_REFB, new S57enum(21, "refuse_bin"));
+	  Catscf.put(CatSCF.SCF_CARP, new S57enum(22, "car_park")); Catscf.put(CatSCF.SCF_BTPK, new S57enum(23, "boat_trailers_park")); Catscf.put(CatSCF.SCF_CRVN, new S57enum(24, "caravan_site"));
+	  Catscf.put(CatSCF.SCF_CAMP, new S57enum(25, "camping_site"));  Catscf.put(CatSCF.SCF_PMPO, new S57enum(26, "pump-out")); Catscf.put(CatSCF.SCF_EMRT, new S57enum(27, "emergency_telephone"));
+	  Catscf.put(CatSCF.SCF_SLPW, new S57enum(28, "slipway")); Catscf.put(CatSCF.SCF_VMOR, new S57enum(29, "visitors_mooring")); Catscf.put(CatSCF.SCF_SCRB, new S57enum(30, "scrubbing_berth"));
+	  Catscf.put(CatSCF.SCF_PCNC, new S57enum(31, "picnic_area")); Catscf.put(CatSCF.SCF_MECH, new S57enum(32, "mechanics_workshop")); Catscf.put(CatSCF.SCF_SECS, new S57enum(33, "security_service"));
+	}
+	public enum CatSPM { SPM_UNKN, SPM_FDGA, SPM_TRGT, SPM_MSHP, SPM_DGRG, SPM_BARG, SPM_CABL, SPM_SPLG, SPM_OFAL, SPM_ODAS, SPM_RCDG, SPM_SPLA, SPM_RCZN, SPM_PRVT, SPM_MOOR, SPM_LNBY, SPM_LDNG, SPM_MDST,
+		SPM_NOTC, SPM_TSS, SPM_NANC, SPM_NBRT, SPM_NOTK, SPM_NTWT, SPM_RWAK, SPM_SPDL, SPM_STOP, SPM_WRNG, SPM_SSSN, SPM_RVCL, SPM_MVDT, SPM_RHCL, SPM_SCNT, SPM_BRTH, SPM_OHPC, SPM_CHEG, SPM_TELE, SPM_FCRS,
+		SPM_MTRL, SPM_PLIN, SPM_ANCH, SPM_CLRG, SPM_CTRL, SPM_DIVG, SPM_RBCN, SPM_FGND, SPM_YCHT, SPM_HPRT, SPM_GPS, SPM_SLDG, SPM_NENT, SPM_WRKP, SPM_UKPP, SPM_WELH, SPM_CHSP, SPM_MFRM, SPM_AREF } 
+	private static final EnumMap<CatSPM, S57enum> Catspm = new EnumMap<CatSPM, S57enum>(CatSPM.class); static { Catspm.put(CatSPM.SPM_UNKN, new S57enum(0, ""));
+		Catspm.put(CatSPM.SPM_FDGA, new S57enum(1, "firing_danger_area")); Catspm.put(CatSPM.SPM_TRGT, new S57enum(2, "target")); Catspm.put(CatSPM.SPM_MSHP, new S57enum(3, "marker_ship"));
+		Catspm.put(CatSPM.SPM_DGRG, new S57enum(4, "degaussing_range")); Catspm.put(CatSPM.SPM_BARG, new S57enum(5, "barge")); Catspm.put(CatSPM.SPM_CABL, new S57enum(6, "cable"));
+		Catspm.put(CatSPM.SPM_SPLG, new S57enum(7, "spoil_ground")); Catspm.put(CatSPM.SPM_OFAL, new S57enum(8, "outfall")); Catspm.put(CatSPM.SPM_ODAS, new S57enum(9, "odas"));
+		Catspm.put(CatSPM.SPM_RCDG, new S57enum(10, "recording")); Catspm.put(CatSPM.SPM_SPLA, new S57enum(11, "seaplane_anchorage")); Catspm.put(CatSPM.SPM_RCZN, new S57enum(12, "recreation_zone"));
+		Catspm.put(CatSPM.SPM_PRVT, new S57enum(13, "private")); Catspm.put(CatSPM.SPM_MOOR, new S57enum(14, "mooring")); Catspm.put(CatSPM.SPM_LNBY, new S57enum(15, "lanby"));
+		Catspm.put(CatSPM.SPM_LDNG, new S57enum(16, "leading")); Catspm.put(CatSPM.SPM_MDST, new S57enum(17, "measured_distance")); Catspm.put(CatSPM.SPM_NOTC, new S57enum(18, "notice"));
+		Catspm.put(CatSPM.SPM_TSS, new S57enum(19, "tss")); Catspm.put(CatSPM.SPM_NANC, new S57enum(20, "no_anchoring")); Catspm.put(CatSPM.SPM_NBRT, new S57enum(21, "no_berthing"));
+		Catspm.put(CatSPM.SPM_NOTK, new S57enum(22, "no_overtaking")); Catspm.put(CatSPM.SPM_NTWT, new S57enum(23, "no_two-way_traffic")); Catspm.put(CatSPM.SPM_RWAK, new S57enum(24, "reduced_wake"));
+		Catspm.put(CatSPM.SPM_SPDL, new S57enum(25, "speed_limit")); Catspm.put(CatSPM.SPM_STOP, new S57enum(26, "stop")); Catspm.put(CatSPM.SPM_WRNG, new S57enum(27, "warning"));
+		Catspm.put(CatSPM.SPM_SSSN, new S57enum(28, "sound_ship_siren")); Catspm.put(CatSPM.SPM_RVCL, new S57enum(29, "restricted_vertical_clearance"));
+		Catspm.put(CatSPM.SPM_MVDT, new S57enum(30, "maximum_vessel_draught")); Catspm.put(CatSPM.SPM_RHCL, new S57enum(31, "restricted_horizontal_clearance"));
+		Catspm.put(CatSPM.SPM_SCNT, new S57enum(32, "strong_current")); Catspm.put(CatSPM.SPM_BRTH, new S57enum(33, "berthing")); Catspm.put(CatSPM.SPM_OHPC, new S57enum(34, "overhead_power_cable"));
+		Catspm.put(CatSPM.SPM_CHEG, new S57enum(35, "channel_edge_gradient")); Catspm.put(CatSPM.SPM_TELE, new S57enum(36, "telephone")); Catspm.put(CatSPM.SPM_FCRS, new S57enum(37, "ferry_crossing"));
+		Catspm.put(CatSPM.SPM_MTRL, new S57enum(38, "marine_traffic_lights")); Catspm.put(CatSPM.SPM_PLIN, new S57enum(39, "pipeline")); Catspm.put(CatSPM.SPM_ANCH, new S57enum(40, "anchorage"));
+		Catspm.put(CatSPM.SPM_CLRG, new S57enum(41, "clearing")); Catspm.put(CatSPM.SPM_CTRL, new S57enum(42, "control")); Catspm.put(CatSPM.SPM_DIVG, new S57enum(43, "diving"));
+		Catspm.put(CatSPM.SPM_RBCN, new S57enum(44, "refuge_beacon")); Catspm.put(CatSPM.SPM_FGND, new S57enum(45, "foul_ground")); Catspm.put(CatSPM.SPM_YCHT, new S57enum(46, "yachting"));
+		Catspm.put(CatSPM.SPM_HPRT, new S57enum(47, "heliport")); Catspm.put(CatSPM.SPM_GPS, new S57enum(48, "gps")); Catspm.put(CatSPM.SPM_SLDG, new S57enum(49, "seaplane_landing"));
+	  Catspm.put(CatSPM.SPM_NENT, new S57enum(50, "no_entry")); Catspm.put(CatSPM.SPM_WRKP, new S57enum(51, "work_in_progress")); Catspm.put(CatSPM.SPM_UKPP, new S57enum(52, "unknown_purpose"));
+	  Catspm.put(CatSPM.SPM_WELH, new S57enum(53, "wellhead")); Catspm.put(CatSPM.SPM_CHSP, new S57enum(54, "channel_separation")); Catspm.put(CatSPM.SPM_MFRM, new S57enum(55, "marine_farm"));
+	  Catspm.put(CatSPM.SPM_AREF, new S57enum(56, "artificial_reef"));
+	}
+	public enum CatTRK { TRK_UNKN, TRK_FIXM, TRK_NFXM }
+	private static final EnumMap<CatTRK, S57enum> Cattrk = new EnumMap<CatTRK, S57enum>(CatTRK.class); static { Cattrk.put(CatTRK.TRK_UNKN, new S57enum(0, ""));
+		Cattrk.put(CatTRK.TRK_FIXM, new S57enum(1, "fixed_marks")); Cattrk.put(CatTRK.TRK_NFXM, new S57enum(2, "no_fixed_marks"));
+	}
+	public enum CatTSS { TSS_UNKN, TSS_IMOA, TSS_NIMO }
+	private static final EnumMap<CatTSS, S57enum> Cattss = new EnumMap<CatTSS, S57enum>(CatTSS.class); static { Cattss.put(CatTSS.TSS_UNKN, new S57enum(0, ""));
+		Cattss.put(CatTSS.TSS_IMOA, new S57enum(1, "imo_adopted")); Cattss.put(CatTSS.TSS_NIMO, new S57enum(2, "not_imo_adopted"));
+	}
+	public enum CatVEG { VEG_UNKN, VEG_GRAS, VEG_PDDY, VEG_BUSH, VEG_DCDW, VEG_CONW, VEG_WOOD, VEG_MGRV, VEG_PARK, VEG_PKLD, VEG_MCRP, VEG_REED, VEG_MOSS,
+		VEG_TREE, VEG_EVGT, VEG_CONT, VEG_PLMT, VEG_NPMT, VEG_CSAT, VEG_EUCT, VEG_DCDT, VEG_MRVT, VEG_FLOT }
+	private static final EnumMap<CatVEG, S57enum> Catveg = new EnumMap<CatVEG, S57enum>(CatVEG.class); static { Catveg.put(CatVEG.VEG_UNKN, new S57enum(0, ""));
+		Catveg.put(CatVEG.VEG_GRAS, new S57enum(1, "grass")); Catveg.put(CatVEG.VEG_PDDY, new S57enum(2, "paddy")); Catveg.put(CatVEG.VEG_BUSH, new S57enum(3, "bush"));
+		Catveg.put(CatVEG.VEG_DCDW, new S57enum(4, "deciduous_wood")); Catveg.put(CatVEG.VEG_CONW, new S57enum(5, "coniferous_wood")); Catveg.put(CatVEG.VEG_WOOD, new S57enum(6, "wood"));
+		Catveg.put(CatVEG.VEG_MGRV, new S57enum(7, "mangroves")); Catveg.put(CatVEG.VEG_PARK, new S57enum(8, "park")); Catveg.put(CatVEG.VEG_PKLD, new S57enum(9, "parkland"));
+		Catveg.put(CatVEG.VEG_MCRP, new S57enum(10, "mixed_crops")); Catveg.put(CatVEG.VEG_REED, new S57enum(11, "reed")); Catveg.put(CatVEG.VEG_MOSS, new S57enum(12, "moss"));
+		Catveg.put(CatVEG.VEG_TREE, new S57enum(13, "tree")); Catveg.put(CatVEG.VEG_EVGT, new S57enum(14, "evergreen_tree")); Catveg.put(CatVEG.VEG_CONT, new S57enum(15, "coniferous_tree"));
+		Catveg.put(CatVEG.VEG_PLMT, new S57enum(16, "palm_tree")); Catveg.put(CatVEG.VEG_NPMT, new S57enum(17, "nipa_palm_tree")); Catveg.put(CatVEG.VEG_CSAT, new S57enum(18, "casuarina_tree"));
+		Catveg.put(CatVEG.VEG_EUCT, new S57enum(19, "eucalypt_tree")); Catveg.put(CatVEG.VEG_DCDT, new S57enum(20, "deciduous_tree")); Catveg.put(CatVEG.VEG_MRVT, new S57enum(21, "mangrove_tree"));
+		Catveg.put(CatVEG.VEG_FLOT, new S57enum(22, "filao_tree"));
+	}
+	public enum CatWAT { WAT_UNKN, WAT_BKRS, WAT_EDDY, WAT_OVFL, WAT_TDRP, WAT_BMBR } 
+	private static final EnumMap<CatWAT, S57enum> Catwat = new EnumMap<CatWAT, S57enum>(CatWAT.class); static { Catwat.put(CatWAT.WAT_UNKN, new S57enum(0, ""));
+		Catwat.put(CatWAT.WAT_BKRS, new S57enum(1, "breakers")); Catwat.put(CatWAT.WAT_EDDY, new S57enum(2, "eddies")); Catwat.put(CatWAT.WAT_OVFL, new S57enum(3, "overfalls"));
+		Catwat.put(CatWAT.WAT_TDRP, new S57enum(4, "tide_rips")); Catwat.put(CatWAT.WAT_BMBR, new S57enum(5, "bombora"));
+	}
+	public enum CatWED { WED_UNKN, WED_KELP, WED_SWED, WED_SGRS, WED_SGSO } 
+	private static final EnumMap<CatWED, S57enum> Catwed = new EnumMap<CatWED, S57enum>(CatWED.class); static { Catwed.put(CatWED.WED_UNKN, new S57enum(0, ""));
+		Catwed.put(CatWED.WED_KELP, new S57enum(1, "kelp")); Catwed.put(CatWED.WED_SWED, new S57enum(2, "sea_weed")); Catwed.put(CatWED.WED_SGRS, new S57enum(3, "sea_grass"));
+		Catwed.put(CatWED.WED_SGSO, new S57enum(4, "sargasso"));
+	}
+	public enum CatWRK { WRK_UNKN, WRK_NDGR, WRK_DNGR, WRK_DREM, WRK_MSTS, WRK_HULS } 
+	private static final EnumMap<CatWRK, S57enum> Catwrk = new EnumMap<CatWRK, S57enum>(CatWRK.class); static { Catwrk.put(CatWRK.WRK_UNKN, new S57enum(0, ""));
+		Catwrk.put(CatWRK.WRK_NDGR, new S57enum(1, "non-dangerous")); Catwrk.put(CatWRK.WRK_DNGR, new S57enum(2, "dangerous")); Catwrk.put(CatWRK.WRK_DREM, new S57enum(3, "distributed_remains"));
+		Catwrk.put(CatWRK.WRK_MSTS, new S57enum(4, "mast_showing")); Catwrk.put(CatWRK.WRK_HULS, new S57enum(5, "hull_showing"));
+	}
+	public enum CatZOC { ZOC_UNKN, ZOC_A1, ZOC_A2, ZOC_B, ZOC_C, ZOC_D, ZOC_U } 
+	private static final EnumMap<CatZOC, S57enum> Catzoc = new EnumMap<CatZOC, S57enum>(CatZOC.class); static { Catzoc.put(CatZOC.ZOC_UNKN, new S57enum(0, ""));
+		Catzoc.put(CatZOC.ZOC_A1, new S57enum(1, "a1")); Catzoc.put(CatZOC.ZOC_A2, new S57enum(2, "a2")); Catzoc.put(CatZOC.ZOC_B, new S57enum(3, "b"));
+		Catzoc.put(CatZOC.ZOC_C, new S57enum(4, "c")); Catzoc.put(CatZOC.ZOC_D, new S57enum(5, "d")); Catzoc.put(CatZOC.ZOC_U, new S57enum(6, "u"));
+	}
+	public enum ColCOL { COL_UNK, COL_WHT, COL_BLK, COL_RED, COL_GRN, COL_BLU, COL_YEL, COL_GRY, COL_BRN, COL_AMB, COL_VIO, COL_ORG, COL_MAG, COL_PNK }
+	private static final EnumMap<ColCOL, S57enum> Colour = new EnumMap<ColCOL, S57enum>(ColCOL.class); static { Colour.put(ColCOL.COL_UNK, new S57enum(0, ""));
+		Colour.put(ColCOL.COL_WHT, new S57enum(1, "white")); Colour.put(ColCOL.COL_BLK, new S57enum(2, "black")); Colour.put(ColCOL.COL_RED, new S57enum(3, "red"));
+		Colour.put(ColCOL.COL_GRN, new S57enum(4, "green")); Colour.put(ColCOL.COL_BLU, new S57enum(5, "blue")); Colour.put(ColCOL.COL_YEL, new S57enum(6, "yellow"));
+		Colour.put(ColCOL.COL_GRY, new S57enum(7, "grey")); Colour.put(ColCOL.COL_BRN, new S57enum(8, "brown")); Colour.put(ColCOL.COL_AMB, new S57enum(9, "amber"));
+		Colour.put(ColCOL.COL_VIO, new S57enum(10, "violet")); Colour.put(ColCOL.COL_ORG, new S57enum(11, "orange")); Colour.put(ColCOL.COL_MAG, new S57enum(12, "magenta"));
+		Colour.put(ColCOL.COL_PNK, new S57enum(13, "pink"));
+	}
+	public enum ColPAT { PAT_UNKN, PAT_HORI, PAT_VERT, PAT_DIAG, PAT_SQUR, PAT_STRP, PAT_BRDR, PAT_CROS, PAT_SALT }
+	private static final EnumMap<ColPAT, S57enum> Colpat = new EnumMap<ColPAT, S57enum>(ColPAT.class); static { Colpat.put(ColPAT.PAT_UNKN, new S57enum(0, ""));
+		Colpat.put(ColPAT.PAT_HORI, new S57enum(1, "horizontal")); Colpat.put(ColPAT.PAT_VERT, new S57enum(2, "vertical")); Colpat.put(ColPAT.PAT_DIAG, new S57enum(3, "diagonal"));
+		Colpat.put(ColPAT.PAT_SQUR, new S57enum(4, "squared")); Colpat.put(ColPAT.PAT_STRP, new S57enum(5, "stripes")); Colpat.put(ColPAT.PAT_BRDR, new S57enum(6, "border"));
+		Colpat.put(ColPAT.PAT_CROS, new S57enum(7, "cross")); Colpat.put(ColPAT.PAT_SALT, new S57enum(8, "saltire"));
+	}
+	public enum CndCND { CND_UNKN, CND_UCNS, CND_RUIN, CND_URCL, CND_WLES, CND_PCNS } 
+	private static final EnumMap<CndCND, S57enum> Condtn = new EnumMap<CndCND, S57enum>(CndCND.class); static { Condtn.put(CndCND.CND_UNKN, new S57enum(0, ""));
+		Condtn.put(CndCND.CND_UCNS, new S57enum(1, "under_construction")); Condtn.put(CndCND.CND_RUIN, new S57enum(2, "ruined")); Condtn.put(CndCND.CND_URCL, new S57enum(3, "under_reclamation"));
+		Condtn.put(CndCND.CND_WLES, new S57enum(4, "wingless")); Condtn.put(CndCND.CND_PCNS, new S57enum(5, "planned_construction"));
+	}
+	public enum ConRAD { RAD_UNKN, RAD_CNSP, RAD_NCSP, RAD_REFL }
+	private static final EnumMap<ConRAD, S57enum> Conrad = new EnumMap<ConRAD, S57enum>(ConRAD.class); static { Conrad.put(ConRAD.RAD_UNKN, new S57enum(0, ""));
+		Conrad.put(ConRAD.RAD_CNSP, new S57enum(1, "conspicuous")); Conrad.put(ConRAD.RAD_NCSP, new S57enum(2, "not_conspicuous")); Conrad.put(ConRAD.RAD_REFL, new S57enum(3, "reflector"));
+	}
+	public enum ConVIS { VIS_UNKN, VIS_CNSP, VIS_NCSP }
+	private static final EnumMap<ConVIS, S57enum> Convis = new EnumMap<ConVIS, S57enum>(ConVIS.class); static { Convis.put(ConVIS.VIS_UNKN, new S57enum(0, ""));
+		Convis.put(ConVIS.VIS_CNSP, new S57enum(1, "conspicuous")); Convis.put(ConVIS.VIS_NCSP, new S57enum(2, "not_conspicuous"));
+	}
+	public enum UniDPU { DPU_UNKN, DPU_METR, DPU_FTFT, DPU_FTHM, DPU_FTFR }
+	private static final EnumMap<UniDPU, S57enum> Dunits = new EnumMap<UniDPU, S57enum>(UniDPU.class); static { Dunits.put(UniDPU.DPU_UNKN, new S57enum(0, ""));
+		Dunits.put(UniDPU.DPU_METR, new S57enum(1, "metres")); Dunits.put(UniDPU.DPU_FTFT, new S57enum(2, "fathoms_feet")); Dunits.put(UniDPU.DPU_FTHM, new S57enum(3, "fathoms"));
+		Dunits.put(UniDPU.DPU_FTFR, new S57enum(4, "fathoms_fractions"));
+	}
+	public enum ExcLIT { EXH_UNKN, EXH_24H, EXH_DAY, EXH_FOG, EXH_NGHT, EXH_WRNG, EXH_STRM } 
+	private static final EnumMap<ExcLIT, S57enum> Exclit = new EnumMap<ExcLIT, S57enum>(ExcLIT.class); static { Exclit.put(ExcLIT.EXH_UNKN, new S57enum(0, ""));
+		Exclit.put(ExcLIT.EXH_24H, new S57enum(1, "24h")); Exclit.put(ExcLIT.EXH_DAY, new S57enum(2, "day")); Exclit.put(ExcLIT.EXH_FOG, new S57enum(3, "fog")); Exclit.put(ExcLIT.EXH_NGHT, new S57enum(4, "night"));
+		Exclit.put(ExcLIT.EXH_WRNG, new S57enum(5, "warning")); Exclit.put(ExcLIT.EXH_STRM, new S57enum(6, "storm"));
+	}
+	public enum ExpSOU { EXP_UNKN, EXP_WTHN, EXP_SHLR, EXP_DEPR }
+	private static final EnumMap<ExpSOU, S57enum> Expsou = new EnumMap<ExpSOU, S57enum>(ExpSOU.class); static { Expsou.put(ExpSOU.EXP_UNKN, new S57enum(0, ""));
+		Expsou.put(ExpSOU.EXP_WTHN, new S57enum(1, "within")); Expsou.put(ExpSOU.EXP_SHLR, new S57enum(2, "shoaler")); Expsou.put(ExpSOU.EXP_DEPR, new S57enum(3, "deeper"));
+	}
+	public enum FncFNC { FNC_UNKN, FNC_HBRM, FNC_CSTM, FNC_HLTH, FNC_HOSP, FNC_POST, FNC_HOTL, FNC_RAIL, FNC_POLC, FNC_WPOL, FNC_PILO, FNC_PILL, FNC_BANK,
+		FNC_DIST, FNC_TRNS, FNC_FCTY, FNC_POWR, FNC_ADMIN, FNC_EDUC, FNC_CHCH, FNC_CHPL, FNC_TMPL, FNC_PGDA, FNC_SHSH, FNC_BTMP, FNC_MOSQ, FNC_MRBT,
+		FNC_LOOK, FNC_COMM, FNC_TV, FNC_RADO, FNC_RADR, FNC_LGHT, FNC_MCWV, FNC_COOL, FNC_OBS, FNC_TMBL, FNC_CLOK, FNC_CTRL, FNC_ASHM, FNC_STAD, FNC_BUSS }
+	private static final EnumMap<FncFNC, S57enum> Functn = new EnumMap<FncFNC, S57enum>(FncFNC.class); static {Functn.put(FncFNC.FNC_UNKN, new S57enum(0, ""));
+		Functn.put(FncFNC.FNC_HBRM, new S57enum(2, "harbour_master")); Functn.put(FncFNC.FNC_CSTM, new S57enum(3, "customs")); Functn.put(FncFNC.FNC_HLTH, new S57enum(4, "health"));
+		Functn.put(FncFNC.FNC_HOSP, new S57enum(5, "hospital")); Functn.put(FncFNC.FNC_POST, new S57enum(6, "post_office")); Functn.put(FncFNC.FNC_HOTL, new S57enum(7, "hotel"));
+	  Functn.put(FncFNC.FNC_RAIL, new S57enum(8, "railway_station")); Functn.put(FncFNC.FNC_POLC, new S57enum(9, "police_station")); Functn.put(FncFNC.FNC_WPOL, new S57enum(10, "water-police_station"));
+	  Functn.put(FncFNC.FNC_PILO, new S57enum(11, "pilot_office")); Functn.put(FncFNC.FNC_PILL, new S57enum(12, "pilot_lookout")); Functn.put(FncFNC.FNC_BANK, new S57enum(13, "bank"));
+	  Functn.put(FncFNC.FNC_DIST, new S57enum(14, "district_control")); Functn.put(FncFNC.FNC_TRNS, new S57enum(15, "transit_shed")); Functn.put(FncFNC.FNC_FCTY, new S57enum(16, "factory"));
+	  Functn.put(FncFNC.FNC_POWR, new S57enum(17, "power_station")); Functn.put(FncFNC.FNC_ADMIN, new S57enum(18, "administrative")); Functn.put(FncFNC.FNC_EDUC, new S57enum(19, "educational"));
+	  Functn.put(FncFNC.FNC_CHCH, new S57enum(20, "church")); Functn.put(FncFNC.FNC_CHPL, new S57enum(21, "chapel")); Functn.put(FncFNC.FNC_TMPL, new S57enum(22, "temple"));
+	  Functn.put(FncFNC.FNC_PGDA, new S57enum(23, "pagoda")); Functn.put(FncFNC.FNC_SHSH, new S57enum(24, "shinto_shrine")); Functn.put(FncFNC.FNC_BTMP, new S57enum(25, "buddhist_temple"));
+	  Functn.put(FncFNC.FNC_MOSQ, new S57enum(26, "mosque")); Functn.put(FncFNC.FNC_MRBT, new S57enum(27, "marabout")); Functn.put(FncFNC.FNC_LOOK, new S57enum(28, "lookout"));
+	  Functn.put(FncFNC.FNC_COMM, new S57enum(29, "communication")); Functn.put(FncFNC.FNC_TV, new S57enum(30, "television")); Functn.put(FncFNC.FNC_RADO, new S57enum(31, "radio"));
+	  Functn.put(FncFNC.FNC_RADR, new S57enum(32, "radar")); Functn.put(FncFNC.FNC_LGHT, new S57enum(33, "light_support")); Functn.put(FncFNC.FNC_MCWV, new S57enum(34, "microwave"));
+	  Functn.put(FncFNC.FNC_COOL, new S57enum(35, "cooling")); Functn.put(FncFNC.FNC_OBS, new S57enum(36, "observation")); Functn.put(FncFNC.FNC_TMBL, new S57enum(37, "time_ball"));
+	  Functn.put(FncFNC.FNC_CLOK, new S57enum(38, "clock")); Functn.put(FncFNC.FNC_CTRL, new S57enum(39, "control")); Functn.put(FncFNC.FNC_ASHM, new S57enum(40, "airship_mooring"));
+	  Functn.put(FncFNC.FNC_STAD, new S57enum(41, "stadium")); Functn.put(FncFNC.FNC_BUSS, new S57enum(42, "bus_station"));
+	}
+	public enum UniHLU { HLU_UNKN, HLU_METR, HLU_FEET, HLU_KMTR, HLU_HMTR, HLU_SMIL, HLU_NMIL }
+	private static final EnumMap<UniHLU, S57enum> Hunits = new EnumMap<UniHLU, S57enum>(UniHLU.class); static { Hunits.put(UniHLU.HLU_UNKN, new S57enum(0, ""));
+		Hunits.put(UniHLU.HLU_METR, new S57enum(1, "metres")); Hunits.put(UniHLU.HLU_FEET, new S57enum(2, "feet")); Hunits.put(UniHLU.HLU_KMTR, new S57enum(3, "kilometres"));
+		Hunits.put(UniHLU.HLU_HMTR, new S57enum(4, "hectometres")); Hunits.put(UniHLU.HLU_SMIL, new S57enum(5, "statute_miles")); Hunits.put(UniHLU.HLU_NMIL, new S57enum(6, "nautical_miles"));
+	}
+	public enum JrsJRS { JRS_UNKN, JRS_INT, JRS_NAT, JRS_NSD }
+	private static final EnumMap<JrsJRS, S57enum> Jrsdtn = new EnumMap<JrsJRS, S57enum>(JrsJRS.class); static { Jrsdtn.put(JrsJRS.JRS_UNKN, new S57enum(0, ""));
+		Jrsdtn.put(JrsJRS.JRS_INT, new S57enum(1, "international")); Jrsdtn.put(JrsJRS.JRS_NAT, new S57enum(2, "national")); Jrsdtn.put(JrsJRS.JRS_NSD, new S57enum(3, "national_sub-division"));
+	}
+	public enum LitCHR { CHR_UNKN, CHR_F, CHR_FL, CHR_LFL, CHR_Q, CHR_VQ, CHR_UQ, CHR_ISO, CHR_OC, CHR_IQ, CHR_IVQ, CHR_IUQ, CHR_MO, CHR_FFL,
+		CHR_FLLFL, CHR_OCFL, CHR_FLFL, CHR_ALOC, CHR_ALLFL, CHR_ALFL, CHR_ALGR, CHR_QLFL, CHR_VQLFL, CHR_UQLFL, CHR_AL, CHR_ALFFL }
+	private static final EnumMap<LitCHR, S57enum> Litchr = new EnumMap<LitCHR, S57enum>(LitCHR.class); static { Litchr.put(LitCHR.CHR_UNKN, new S57enum(0, ""));
+		Litchr.put(LitCHR.CHR_F, new S57enum(1, "F")); Litchr.put(LitCHR.CHR_FL, new S57enum(2, "Fl")); Litchr.put(LitCHR.CHR_LFL, new S57enum(3, "LFl")); Litchr.put(LitCHR.CHR_Q, new S57enum(4, "Q"));
+		Litchr.put(LitCHR.CHR_VQ, new S57enum(5, "VQ")); Litchr.put(LitCHR.CHR_UQ, new S57enum(6, "UQ")); Litchr.put(LitCHR.CHR_ISO, new S57enum(7, "Iso")); Litchr.put(LitCHR.CHR_OC, new S57enum(8, "Oc"));
+	  Litchr.put(LitCHR.CHR_IQ, new S57enum(9, "IQ")); Litchr.put(LitCHR.CHR_IVQ, new S57enum(10, "IVQ")); Litchr.put(LitCHR.CHR_IUQ, new S57enum(11, "IUQ")); Litchr.put(LitCHR.CHR_MO, new S57enum(12, "Mo"));
+	  Litchr.put(LitCHR.CHR_FFL, new S57enum(13, "FFl")); Litchr.put(LitCHR.CHR_FLLFL, new S57enum(14, "FlLFl")); Litchr.put(LitCHR.CHR_OCFL, new S57enum(15, "OcFl"));
+	  Litchr.put(LitCHR.CHR_FLFL, new S57enum(16, "FLFl")); Litchr.put(LitCHR.CHR_ALOC, new S57enum(17, "Al.Oc")); Litchr.put(LitCHR.CHR_ALLFL, new S57enum(18, "Al.LFl"));
+	  Litchr.put(LitCHR.CHR_ALFL, new S57enum(19, "Al.Fl")); Litchr.put(LitCHR.CHR_ALGR, new S57enum(20, "Al.Gr")); Litchr.put(LitCHR.CHR_QLFL, new S57enum(25, "Q+LFl"));
+	  Litchr.put(LitCHR.CHR_VQLFL, new S57enum(26, "VQ+LFl")); Litchr.put(LitCHR.CHR_UQLFL, new S57enum(27, "UQ+LFl")); Litchr.put(LitCHR.CHR_AL, new S57enum(28, "Al"));
+	  Litchr.put(LitCHR.CHR_ALFFL, new S57enum(29, "Al.FFl"));
+	}
+	public enum LitVIS { LIT_UNKN, LIT_HIGH, LIT_LOW, LIT_FANT, LIT_INTS, LIT_UINT, LIT_RSTR, LIT_OBSC, LIT_POBS }
+	private static final EnumMap<LitVIS, S57enum> Litvis = new EnumMap<LitVIS, S57enum>(LitVIS.class); static { Litvis.put(LitVIS.LIT_UNKN, new S57enum(0, ""));
+		Litvis.put(LitVIS.LIT_HIGH, new S57enum(1, "high")); Litvis.put(LitVIS.LIT_LOW, new S57enum(2, "low")); Litvis.put(LitVIS.LIT_FANT, new S57enum(3, "faint"));
+		Litvis.put(LitVIS.LIT_INTS, new S57enum(4, "intensified")); Litvis.put(LitVIS.LIT_UINT, new S57enum(5, "unintensified")); Litvis.put(LitVIS.LIT_RSTR, new S57enum(6, "restricted"));
+		Litvis.put(LitVIS.LIT_OBSC, new S57enum(7, "obscured")); Litvis.put(LitVIS.LIT_POBS, new S57enum(8, "part_obscured"));
+	}
+	public enum MarSYS { SYS_UNKN, SYS_IALA, SYS_IALB, SYS_NONE, SYS_OTHR, SYS_CEVN, SYS_RIWR, SYS_BWR2, SYS_BNWR, SYS_PPWB }
+	private static final EnumMap<MarSYS, S57enum> Marsys = new EnumMap<MarSYS, S57enum>(MarSYS.class); static { Marsys.put(MarSYS.SYS_UNKN, new S57enum(0, ""));
+		Marsys.put(MarSYS.SYS_IALA, new S57enum(1, "iala-a")); Marsys.put(MarSYS.SYS_IALB, new S57enum(2, "iala-b")); Marsys.put(MarSYS.SYS_NONE, new S57enum(9, "none"));
+		Marsys.put(MarSYS.SYS_OTHR, new S57enum(10, "other")); Marsys.put(MarSYS.SYS_CEVN, new S57enum(11, "cevni")); Marsys.put(MarSYS.SYS_RIWR, new S57enum(12, "riwr"));
+		Marsys.put(MarSYS.SYS_BWR2, new S57enum(13, "bniwr2")); Marsys.put(MarSYS.SYS_BNWR, new S57enum(14, "bniwr")); Marsys.put(MarSYS.SYS_PPWB, new S57enum(15, "ppwbc"));
+	}
+	public enum NatCON { CON_UNKN, CON_MSNY, CON_CONC, CON_BDRS, CON_HSRF, CON_USRF, CON_WOOD, CON_METL, CON_GRP, CON_PNTD, CON_FMWK }
+	private static final EnumMap<NatCON, S57enum> Natcon = new EnumMap<NatCON, S57enum>(NatCON.class); static { Natcon.put(NatCON.CON_UNKN, new S57enum(0, ""));
+		Natcon.put(NatCON.CON_MSNY, new S57enum(1, "masonry")); Natcon.put(NatCON.CON_CONC, new S57enum(2, "concreted")); Natcon.put(NatCON.CON_BDRS, new S57enum(3, "loose_boulders"));
+		Natcon.put(NatCON.CON_HSRF, new S57enum(4, "hard-surfaced")); Natcon.put(NatCON.CON_USRF, new S57enum(5, "unsurfaced")); Natcon.put(NatCON.CON_WOOD, new S57enum(6, "wooden"));
+		Natcon.put(NatCON.CON_METL, new S57enum(7, "metal")); Natcon.put(NatCON.CON_GRP, new S57enum(8, "grp")); Natcon.put(NatCON.CON_PNTD, new S57enum(9, "painted"));
+		Natcon.put(NatCON.CON_FMWK, new S57enum(10, "framework"));
+	}
+	public enum NatSUR { SUR_UNKN, SUR_MUD, SUR_CLAY, SUR_SILT, SUR_SAND, SUR_STON, SUR_GRVL, SUR_PBBL, SUR_CBBL, SUR_ROCK, SUR_LAVA, SUR_CORL, SUR_SHEL, SUR_BLDR } 
+	private static final EnumMap<NatSUR, S57enum> Natsur = new EnumMap<NatSUR, S57enum>(NatSUR.class); static { Natsur.put(NatSUR.SUR_UNKN, new S57enum(0, ""));
+		Natsur.put(NatSUR.SUR_MUD, new S57enum(1, "mud")); Natsur.put(NatSUR.SUR_CLAY, new S57enum(2, "clay")); Natsur.put(NatSUR.SUR_SILT, new S57enum(3, "silt"));
+		Natsur.put(NatSUR.SUR_SAND, new S57enum(4, "sand")); Natsur.put(NatSUR.SUR_STON, new S57enum(5, "stone")); Natsur.put(NatSUR.SUR_GRVL, new S57enum(6, "gravel"));
+		Natsur.put(NatSUR.SUR_PBBL, new S57enum(7, "pebbles")); Natsur.put(NatSUR.SUR_CBBL, new S57enum(8, "cobbles")); Natsur.put(NatSUR.SUR_ROCK, new S57enum(9, "rock"));
+		Natsur.put(NatSUR.SUR_LAVA, new S57enum(11, "lava")); Natsur.put(NatSUR.SUR_CORL, new S57enum(14, "coral")); Natsur.put(NatSUR.SUR_SHEL, new S57enum(17, "shells"));
+		Natsur.put(NatSUR.SUR_BLDR, new S57enum(18, "boulder"));
+	}
+	public enum NatQUA { QUA_UNKN, QUA_FINE, QUA_MEDM, QUA_CORS, QUA_BRKN, QUA_STKY, QUA_SOFT, QUA_STIF, QUA_VCNC, QUA_CALC, QUA_HARD } 
+	private static final EnumMap<NatQUA, S57enum> Natqua = new EnumMap<NatQUA, S57enum>(NatQUA.class); static { Natqua.put(NatQUA.QUA_UNKN, new S57enum(0, ""));
+		Natqua.put(NatQUA.QUA_FINE, new S57enum(1, "fine")); Natqua.put(NatQUA.QUA_MEDM, new S57enum(2, "medium")); Natqua.put(NatQUA.QUA_CORS, new S57enum(3, "coarse"));
+		Natqua.put(NatQUA.QUA_BRKN, new S57enum(4, "broken")); Natqua.put(NatQUA.QUA_STKY, new S57enum(5, "sticky")); Natqua.put(NatQUA.QUA_SOFT, new S57enum(6, "soft"));
+		Natqua.put(NatQUA.QUA_STIF, new S57enum(7, "stiff")); Natqua.put(NatQUA.QUA_VCNC, new S57enum(8, "volcanic")); Natqua.put(NatQUA.QUA_CALC, new S57enum(9, "calcareous"));
+		Natqua.put(NatQUA.QUA_HARD, new S57enum(10, "hard"));
+	}
+	public enum PrdPRD { PRD_UNKN, PRD_OIL, PRD_GAS, PRD_WATR, PRD_STON, PRD_COAL, PRD_ORE, PRD_CHEM, PRD_DWTR, PRD_MILK, PRD_BXIT, PRD_COKE, PRD_IIGS, PRD_SALT,
+		PRD_SAND, PRD_TMBR, PRD_SDST, PRD_SCRP, PRD_LNA, PRD_LPA, PRD_WINE, PRD_CMNT, PRD_GRAN }
+	private static final EnumMap<PrdPRD, S57enum> Prodct = new EnumMap<PrdPRD, S57enum>(PrdPRD.class); static { Prodct.put(PrdPRD.PRD_UNKN, new S57enum(0, ""));
+		Prodct.put(PrdPRD.PRD_OIL, new S57enum(1, "oil")); Prodct.put(PrdPRD.PRD_GAS, new S57enum(2, "gas")); Prodct.put(PrdPRD.PRD_WATR, new S57enum(3, "water"));
+		Prodct.put(PrdPRD.PRD_STON, new S57enum(4, "stone")); Prodct.put(PrdPRD.PRD_COAL, new S57enum(5, "coal")); Prodct.put(PrdPRD.PRD_ORE, new S57enum(6, "ore"));
+		Prodct.put(PrdPRD.PRD_CHEM, new S57enum(7, "chemicals")); Prodct.put(PrdPRD.PRD_DWTR, new S57enum(8, "drinking_water")); Prodct.put(PrdPRD.PRD_MILK, new S57enum(9, "milk"));
+		Prodct.put(PrdPRD.PRD_BXIT, new S57enum(10, "bauxite")); Prodct.put(PrdPRD.PRD_COKE, new S57enum(11, "coke")); Prodct.put(PrdPRD.PRD_IIGS, new S57enum(12, "iron_ingots"));
+		Prodct.put(PrdPRD.PRD_SALT, new S57enum(13, "salt")); Prodct.put(PrdPRD.PRD_SAND, new S57enum(14, "sand")); Prodct.put(PrdPRD.PRD_TMBR, new S57enum(15, "timber"));
+		Prodct.put(PrdPRD.PRD_SDST, new S57enum(16, "sawdust")); Prodct.put(PrdPRD.PRD_SCRP, new S57enum(17, "scrap")); Prodct.put(PrdPRD.PRD_LNA, new S57enum(18, "lng"));
+		Prodct.put(PrdPRD.PRD_LPA, new S57enum(19, "lpg")); Prodct.put(PrdPRD.PRD_WINE, new S57enum(20, "wine")); Prodct.put(PrdPRD.PRD_CMNT, new S57enum(21, "cement"));
+		Prodct.put(PrdPRD.PRD_GRAN, new S57enum(22, "grain"));
+	}
+	public enum QuaSOU { SOU_UNKN, SOU_KNWN, SOU_UKNN, SOU_DFUL, SOU_UNRL, SOU_NBFD, SOU_LKWN, SOU_LUKN, SOU_NSRV, SOU_NCNF, SOU_MANT, SOU_NMNT } 
+	private static final EnumMap<QuaSOU, S57enum> Quasou = new EnumMap<QuaSOU, S57enum>(QuaSOU.class); static { Quasou.put(QuaSOU.SOU_UNKN, new S57enum(0, ""));
+		Quasou.put(QuaSOU.SOU_KNWN, new S57enum(1, "known")); Quasou.put(QuaSOU.SOU_UKNN, new S57enum(2, "unknown")); Quasou.put(QuaSOU.SOU_DFUL, new S57enum(3, "doubtful"));
+		Quasou.put(QuaSOU.SOU_UNRL, new S57enum(4, "unreliable")); Quasou.put(QuaSOU.SOU_NBFD, new S57enum(5, "no_bottom_found")); Quasou.put(QuaSOU.SOU_LKWN, new S57enum(6, "least_known"));
+		Quasou.put(QuaSOU.SOU_LUKN, new S57enum(7, "least_unknown")); Quasou.put(QuaSOU.SOU_NSRV, new S57enum(8, "not_surveyed")); Quasou.put(QuaSOU.SOU_NCNF, new S57enum(9, "not_confirmed"));
+		Quasou.put(QuaSOU.SOU_MANT, new S57enum(10, "maintained")); Quasou.put(QuaSOU.SOU_NMNT, new S57enum(11, "not_maintained"));
+	}
+	public enum RstRST { RST_UNKN, RST_NANC, RST_RANC, RST_NFSH, RST_RFSH, RST_NTRL, RST_RTRL, RST_NENT, RST_RENT, RST_NDRG, RST_RDRG, RST_NDVG, RST_RDVG, RST_NWAK, RST_TBAV, RST_NCST, RST_NDSC,
+		RST_RDSC, RST_NEXD, RST_REXD, RST_NDRL, RST_RDRL, RST_NHAR, RST_NLTG, RST_NDRA, RST_NSTP, RST_NLND, RST_RSPD, RST_NOVT, RST_NCOV, RST_NPOV, RST_NBRT, RST_RBRT, RST_NMFT, RST_RMFT, RST_NTRN, RST_RFWD }
+	private static final EnumMap<RstRST, S57enum> Restrn = new EnumMap<RstRST, S57enum>(RstRST.class); static { Restrn.put(RstRST.RST_UNKN, new S57enum(0, ""));
+		Restrn.put(RstRST.RST_NANC, new S57enum(1, "no_anchoring")); Restrn.put(RstRST.RST_RANC, new S57enum(2, "restricted_anchoring")); Restrn.put(RstRST.RST_NFSH, new S57enum(3, "no_fishing"));
+		Restrn.put(RstRST.RST_RFSH, new S57enum(4, "restricted_fishing")); Restrn.put(RstRST.RST_NTRL, new S57enum(5, "no_trawling")); Restrn.put(RstRST.RST_RTRL, new S57enum(6, "restricted_trawling"));
+		Restrn.put(RstRST.RST_NENT, new S57enum(7, "no_entry")); Restrn.put(RstRST.RST_RENT, new S57enum(8, "restricted_entry")); Restrn.put(RstRST.RST_NDRG, new S57enum(9, "no_dredging"));
+		Restrn.put(RstRST.RST_RDRG, new S57enum(10, "restricted_dredging")); Restrn.put(RstRST.RST_NDVG, new S57enum(11, "no_diving")); Restrn.put(RstRST.RST_RDVG, new S57enum(12, "restricted_diving"));
+		Restrn.put(RstRST.RST_NWAK, new S57enum(13, "no_wake")); Restrn.put(RstRST.RST_TBAV, new S57enum(14, "to_be_avoided")); Restrn.put(RstRST.RST_NCST, new S57enum(15, "no_construction"));
+		Restrn.put(RstRST.RST_NDSC, new S57enum(16, "no_discharging")); Restrn.put(RstRST.RST_RDSC, new S57enum(17, "restricted_discharging"));
+		Restrn.put(RstRST.RST_NEXD, new S57enum(18, "no_exploration_development")); Restrn.put(RstRST.RST_REXD, new S57enum(19, "restricted_exploration_development"));
+		Restrn.put(RstRST.RST_NDRL, new S57enum(20, "no_drilling")); Restrn.put(RstRST.RST_RDRL, new S57enum(21, "restricted_drilling"));
+		Restrn.put(RstRST.RST_NHAR, new S57enum(22, "no_historical_artifacts_removal")); Restrn.put(RstRST.RST_NLTG, new S57enum(23, "no_lightering")); Restrn.put(RstRST.RST_NDRA, new S57enum(24, "no_dragging"));
+	  Restrn.put(RstRST.RST_NSTP, new S57enum(25, "no_stopping")); Restrn.put(RstRST.RST_NLND, new S57enum(26, "no_landing")); Restrn.put(RstRST.RST_RSPD, new S57enum(27, "restricted_speed"));
+	  Restrn.put(RstRST.RST_NOVT, new S57enum(28, "no_overtaking")); Restrn.put(RstRST.RST_NCOV, new S57enum(29, "no_convoy_overtaking")); Restrn.put(RstRST.RST_NPOV, new S57enum(30, "no_passing_overtaking"));
+	  Restrn.put(RstRST.RST_NBRT, new S57enum(31, "no_berthing")); Restrn.put(RstRST.RST_RBRT, new S57enum(32, "restricted_berthing")); Restrn.put(RstRST.RST_NMFT, new S57enum(33, "no_making_fast"));
+	  Restrn.put(RstRST.RST_RMFT, new S57enum(34, "restricted_making_fast")); Restrn.put(RstRST.RST_NTRN, new S57enum(35, "no_turning")); Restrn.put(RstRST.RST_RFWD, new S57enum(36, "restricted_fairway_depth"));
+	}
+	public enum SigGEN { GEN_UNKN, GEN_AUTO, GEN_WAVE, GEN_HAND, GEN_WIND }
+	private static final EnumMap<SigGEN, S57enum> Siggen = new EnumMap<SigGEN, S57enum>(SigGEN.class); static { Siggen.put(SigGEN.GEN_UNKN, new S57enum(0, ""));
+		Siggen.put(SigGEN.GEN_AUTO, new S57enum(1, "automatic")); Siggen.put(SigGEN.GEN_WAVE, new S57enum(2, "wave")); Siggen.put(SigGEN.GEN_HAND, new S57enum(3, "hand")); Siggen.put(SigGEN.GEN_WIND, new S57enum(4, "wind"));
+	}
+	public enum StsSTS { STS_UNKN, STS_PERM, STS_OCAS, STS_RCMD, STS_NIUS, STS_IMTT, STS_RESV, STS_TEMP, STS_PRIV, STS_MAND, STS_EXTD, STS_ILLD, STS_HIST, STS_PBLC,
+		STS_SYNC, STS_WCHD, STS_UWCD, STS_EDBT, STS_OREQ, STS_DPAW, STS_RSNG, STS_INCR, STS_DECR, TS_STNG, STS_GOOD, STS_MODY, STS_POOR } 
+	private static final EnumMap<StsSTS, S57enum> Status = new EnumMap<StsSTS, S57enum>(StsSTS.class); static { Status.put(StsSTS.STS_UNKN, new S57enum(0, ""));
+		Status.put(StsSTS.STS_PERM, new S57enum(1, "permanent")); Status.put(StsSTS.STS_OCAS, new S57enum(2, "occasional")); Status.put(StsSTS.STS_RCMD, new S57enum(3, "recommended")); 
+		Status.put(StsSTS.STS_NIUS, new S57enum(4, "not_in_use")); Status.put(StsSTS.STS_IMTT, new S57enum(5, "intermittent")); Status.put(StsSTS.STS_RESV, new S57enum(6, "reserved"));
+		Status.put(StsSTS.STS_TEMP, new S57enum(7, "temporary")); Status.put(StsSTS.STS_PRIV, new S57enum(8, "private")); Status.put(StsSTS.STS_MAND, new S57enum(9, "mandatory"));
+		Status.put(StsSTS.STS_EXTD, new S57enum(11, "extinguished")); Status.put(StsSTS.STS_ILLD, new S57enum(12, "illuminated")); Status.put(StsSTS.STS_HIST, new S57enum(13, "historic"));
+		Status.put(StsSTS.STS_PBLC, new S57enum(14, "public")); Status.put(StsSTS.STS_SYNC, new S57enum(15, "synchronised")); Status.put(StsSTS.STS_WCHD, new S57enum(16, "watched"));
+		Status.put(StsSTS.STS_UWCD, new S57enum(17, "unwatched")); Status.put(StsSTS.STS_EDBT, new S57enum(18, "existence_doubtful")); Status.put(StsSTS.STS_OREQ, new S57enum(19, "on_request"));
+		Status.put(StsSTS.STS_DPAW, new S57enum(20, "drop_away")); Status.put(StsSTS.STS_RSNG, new S57enum(21, "rising")); Status.put(StsSTS.STS_INCR, new S57enum(22, "increasing"));
+		Status.put(StsSTS.STS_DECR, new S57enum(23, "decreasing")); Status.put(StsSTS.TS_STNG, new S57enum(24, "strong")); Status.put(StsSTS.STS_GOOD, new S57enum(25, "good"));
+		Status.put(StsSTS.STS_MODY, new S57enum(26, "moderately")); Status.put(StsSTS.STS_POOR, new S57enum(27, "poor"));
+	}
+	public enum SurTYP { TYP_UNKN, TYP_SKCH, TYP_CTLD, TYP_PSSG, TYP_REMT }
+	private static final EnumMap<SurTYP, S57enum> Surtyp = new EnumMap<SurTYP, S57enum>(SurTYP.class); static { Surtyp.put(SurTYP.TYP_UNKN, new S57enum(0, ""));
+		Surtyp.put(SurTYP.TYP_SKCH, new S57enum(1, "sketch")); Surtyp.put(SurTYP.TYP_CTLD, new S57enum(2, "controlled")); Surtyp.put(SurTYP.TYP_PSSG, new S57enum(4, "examination"));
+		Surtyp.put(SurTYP.TYP_PSSG, new S57enum(5, "passage")); Surtyp.put(SurTYP.TYP_REMT, new S57enum(6, "remote"));
+	}
+	public enum TecSOU { SOU_UNKN, SOU_ESND, SOU_FSSN, SOU_MLBM, SOU_DIVR, SOU_LDLN, SOU_WDRG, SOU_LASR, SOU_VACC, SOU_EMAG, SOU_PHGY, SOU_SATL, SOU_LEVL, SOU_SSSN, SOU_COMP } 
+	private static final EnumMap<TecSOU, S57enum> Tecsou = new EnumMap<TecSOU, S57enum>(TecSOU.class); static { Tecsou.put(TecSOU.SOU_UNKN, new S57enum(0, ""));
+		Tecsou.put(TecSOU.SOU_ESND, new S57enum(1, "echo-sounder")); Tecsou.put(TecSOU.SOU_FSSN, new S57enum(2, "side-scan_sonar")); Tecsou.put(TecSOU.SOU_MLBM, new S57enum(3, "multi-beam"));
+		Tecsou.put(TecSOU.SOU_DIVR, new S57enum(4, "diver")); Tecsou.put(TecSOU.SOU_LDLN, new S57enum(5, "lead-line")); Tecsou.put(TecSOU.SOU_WDRG, new S57enum(6, "wire-drag"));
+		Tecsou.put(TecSOU.SOU_LASR, new S57enum(7, "laser")); Tecsou.put(TecSOU.SOU_VACC, new S57enum(8, "vertical_acoustic")); Tecsou.put(TecSOU.SOU_EMAG, new S57enum(9, "electromagnetic"));
+	  Tecsou.put(TecSOU.SOU_PHGY, new S57enum(10, "photogrammetry")); Tecsou.put(TecSOU.SOU_SATL, new S57enum(11, "satellite")); Tecsou.put(TecSOU.SOU_LEVL, new S57enum(12, "levelling"));
+	  Tecsou.put(TecSOU.SOU_SSSN, new S57enum(13, "side-scan_sonar_swept")); Tecsou.put(TecSOU.SOU_COMP, new S57enum(14, "computer"));
+	}
+	public enum TopSHP { TOP_UNKN, TOP_CONE, TOP_ICONE, TOP_SPHR, TOP_ISD, TOP_CAN, TOP_BORD, TOP_SALT, TOP_CROS, TOP_CUBE, TOP_WEST, TOP_EAST, TOP_RHOM,
+	  TOP_NORTH, TOP_SOUTH, TOP_BESM, TOP_IBESM, TOP_FLAG, TOP_SPRH, TOP_SQUR, TOP_HRECT, TOP_VRECT, TOP_TRAP, TOP_ITRAP, TOP_TRI, TOP_ITRI, TOP_CIRC,
+	  TOP_CRSS, TOP_T, TOP_TRCL, TOP_CRCL, TOP_RHCL, TOP_CLTR, TOP_OTHR }
+	private static final EnumMap<TopSHP, S57enum> Topshp = new EnumMap<TopSHP, S57enum>(TopSHP.class); static { Topshp.put(TopSHP.TOP_UNKN, new S57enum(0, ""));
+		Topshp.put(TopSHP.TOP_CONE, new S57enum(1, "cone, point up")); Topshp.put(TopSHP.TOP_ICONE, new S57enum(2, "cone, point down")); Topshp.put(TopSHP.TOP_SPHR, new S57enum(3, "sphere"));
+		Topshp.put(TopSHP.TOP_ISD, new S57enum(4, "2 spheres")); Topshp.put(TopSHP.TOP_CAN, new S57enum(5, "cylinder")); Topshp.put(TopSHP.TOP_BORD, new S57enum(6, "board"));
+		Topshp.put(TopSHP.TOP_SALT, new S57enum(7, "x-shape")); Topshp.put(TopSHP.TOP_CROS, new S57enum(8, "cross")); Topshp.put(TopSHP.TOP_CUBE, new S57enum(9, "cube, point up"));
+		Topshp.put(TopSHP.TOP_WEST, new S57enum(10, "2 cones point together")); Topshp.put(TopSHP.TOP_EAST, new S57enum(11, "2 cones base together")); Topshp.put(TopSHP.TOP_RHOM, new S57enum(12, "rhombus"));
+	  Topshp.put(TopSHP.TOP_NORTH, new S57enum(13, "2 cones up")); Topshp.put(TopSHP.TOP_SOUTH, new S57enum(14, "2 cones down")); Topshp.put(TopSHP.TOP_BESM, new S57enum(15, "besom, point up"));
+	  Topshp.put(TopSHP.TOP_IBESM, new S57enum(16, "besom, point down")); Topshp.put(TopSHP.TOP_FLAG, new S57enum(17, "flag")); Topshp.put(TopSHP.TOP_SPRH, new S57enum(18, "sphere over rhombus"));
+	  Topshp.put(TopSHP.TOP_SQUR, new S57enum(19, "square")); Topshp.put(TopSHP.TOP_HRECT, new S57enum(20, "rectangle, horizontal")); Topshp.put(TopSHP.TOP_VRECT, new S57enum(21, "rectangle, vertical"));
+	  Topshp.put(TopSHP.TOP_TRAP, new S57enum(22, "trapezium, up")); Topshp.put(TopSHP.TOP_ITRAP, new S57enum(23, "trapezium, down")); Topshp.put(TopSHP.TOP_TRI, new S57enum(24, "triangle, point up"));
+	  Topshp.put(TopSHP.TOP_ITRI, new S57enum(25, "triangle, point down")); Topshp.put(TopSHP.TOP_CIRC, new S57enum(26, "circle")); Topshp.put(TopSHP.TOP_CRSS, new S57enum(27, "2 upright crosses"));
+	  Topshp.put(TopSHP.TOP_T, new S57enum(28, "t-shape")); Topshp.put(TopSHP.TOP_TRCL, new S57enum(29, "triangle, point up over circle")); Topshp.put(TopSHP.TOP_CRCL, new S57enum(30, "upright cross over circle"));
+	  Topshp.put(TopSHP.TOP_RHCL, new S57enum(31, "rhombus over circle")); Topshp.put(TopSHP.TOP_CLTR, new S57enum(32, "circle over triangle, point up")); Topshp.put(TopSHP.TOP_OTHR, new S57enum(33, "other"));
+	}
+	public enum TrfTRF { TRF_UNKN, TRF_INBD, TRF_OBND, TRF_ONEW, TRF_TWOW }
+	private static final EnumMap<TrfTRF, S57enum> Trafic = new EnumMap<TrfTRF, S57enum>(TrfTRF.class); static { Trafic.put(TrfTRF.TRF_UNKN, new S57enum(0, ""));
+		Trafic.put(TrfTRF.TRF_INBD, new S57enum(1, "inbound")); Trafic.put(TrfTRF.TRF_OBND, new S57enum(2, "outbbound")); Trafic.put(TrfTRF.TRF_ONEW, new S57enum(3, "one-way"));
+		Trafic.put(TrfTRF.TRF_TWOW, new S57enum(4, "two-way"));
+	}
+	public enum WatLEV { LEV_UNKN, LEV_PSUB, LEV_DRY, LEV_SUBM, LEV_CVRS, LEV_AWSH, LEV_FLDS, LEV_FLTG, LEV_AMWL, LEV_BMWL }
+	private static final EnumMap<WatLEV, S57enum> Watlev = new EnumMap<WatLEV, S57enum>(WatLEV.class); static { Watlev.put(WatLEV.LEV_UNKN, new S57enum(0, ""));
+		Watlev.put(WatLEV.LEV_PSUB, new S57enum(1, "part-submerged")); Watlev.put(WatLEV.LEV_DRY, new S57enum(2, "dry")); Watlev.put(WatLEV.LEV_SUBM, new S57enum(3, "submerged"));
+		Watlev.put(WatLEV.LEV_CVRS, new S57enum(4, "covers")); Watlev.put(WatLEV.LEV_AWSH, new S57enum(5, "awash")); Watlev.put(WatLEV.LEV_FLDS, new S57enum(6, "floods"));
+		Watlev.put(WatLEV.LEV_FLTG, new S57enum(7, "floating")); Watlev.put(WatLEV.LEV_AMWL, new S57enum(8, "above_mwl")); Watlev.put(WatLEV.LEV_BMWL, new S57enum(9, "below_mwl"));
+	}
+	public enum Cat_TS { TS_UNKN, TS_FLOD, TS_EBB, TS_OTHR }
+	private static final EnumMap<Cat_TS, S57enum> Cat_ts = new EnumMap<Cat_TS, S57enum>(Cat_TS.class); static { Cat_ts.put(Cat_TS.TS_UNKN, new S57enum(0, ""));
+		Cat_ts.put(Cat_TS.TS_FLOD, new S57enum(1, "flood")); Cat_ts.put(Cat_TS.TS_EBB, new S57enum(2, "ebb")); Cat_ts.put(Cat_TS.TS_OTHR, new S57enum(3, "other"));
+	}
+	public enum UniPAU { PAU_UNKN, PAU_MTRS, PAU_DGRS, PAU_MMTR, PAU_FEET, PAU_CBLS } 
+	private static final EnumMap<UniPAU, S57enum> Punits = new EnumMap<UniPAU, S57enum>(UniPAU.class); static { Punits.put(UniPAU.PAU_UNKN, new S57enum(0, ""));
+		Punits.put(UniPAU.PAU_MTRS, new S57enum(1, "metres")); Punits.put(UniPAU.PAU_DGRS, new S57enum(2, "degrees")); Punits.put(UniPAU.PAU_MMTR, new S57enum(3, "millimetres"));
+		Punits.put(UniPAU.PAU_FEET, new S57enum(4, "feet")); Punits.put(UniPAU.PAU_CBLS, new S57enum(5, "cables"));
+	}
+	public enum QuaPOS { POS_UNKN, POS_SRVD, POS_USRV, POS_PSRV, POS_APRX, POS_DBTF, POS_URLB, POS_RSRV, POS_UCNF, POS_ESTM, POS_PRCS, POS_CALC } 
+	private static final EnumMap<QuaPOS, S57enum> Quapos = new EnumMap<QuaPOS, S57enum>(QuaPOS.class); static { Quapos.put(QuaPOS.POS_UNKN, new S57enum(0, ""));
+		Quapos.put(QuaPOS.POS_SRVD, new S57enum(1, "surveyed")); Quapos.put(QuaPOS.POS_USRV, new S57enum(2, "unsurveyed")); Quapos.put(QuaPOS.POS_PSRV, new S57enum(3, "part-surveyed"));
+		Quapos.put(QuaPOS.POS_APRX, new S57enum(4, "approximate")); Quapos.put(QuaPOS.POS_DBTF, new S57enum(5, "doubtful")); Quapos.put(QuaPOS.POS_URLB, new S57enum(6, "unreliable"));
+		Quapos.put(QuaPOS.POS_RSRV, new S57enum(7, "reported_unsurveyd")); Quapos.put(QuaPOS.POS_UCNF, new S57enum(8, "unconfirmed")); Quapos.put(QuaPOS.POS_ESTM, new S57enum(9, "estimated"));
+		Quapos.put(QuaPOS.POS_PRCS, new S57enum(10, "precise")); Quapos.put(QuaPOS.POS_CALC, new S57enum(11, "calculated"));
+	}
+	public enum VerDAT { DAT_UNKN, DAT_MLWS, DAT_MLLWS, DAT_MSL, DAT_LLW, DAT_MLW, DAT_LLWS, DAT_AMLWS, DAT_ISLW, DAT_LWS, DAT_ALAT, DAT_NLLW, DAT_MLLW, DAT_LW, DAT_AMLW, DAT_AMLLW,
+		DAT_MHW, DAT_MHWS, DAT_HW, DAT_AMSL, DAT_HWS, DAT_MHHW, DAT_ESLW, DAT_LAT, DAT_LOCAL, DAT_IGLD, DAT_MWL, DAT_LLWLT, DAT_HHWLT, DAT_NHHW, DAT_HAT, DAT_LLWRL, DAT_LHWRL,
+		DAT_LMWRL, DAT_EHW, DAT_HSHW, DAT_RLWL, DAT_HSHWD, DAT_DRLWRL, DAT_RPWL, DAT_RNBL, DAT_OHIO } 
+	private static final EnumMap<VerDAT, S57enum> Verdat = new EnumMap<VerDAT, S57enum>(VerDAT.class); static { Verdat.put(VerDAT.DAT_UNKN, new S57enum(0, ""));
+		Verdat.put(VerDAT.DAT_MLWS, new S57enum(1, "mlws")); Verdat.put(VerDAT.DAT_MLLWS, new S57enum(2, "mllws")); Verdat.put(VerDAT.DAT_MSL, new S57enum(3, "msl"));
+		Verdat.put(VerDAT.DAT_LLW, new S57enum(4, "llw")); Verdat.put(VerDAT.DAT_MLW, new S57enum(5, "mlw")); Verdat.put(VerDAT.DAT_LLWS, new S57enum(6, "llws"));
+		Verdat.put(VerDAT.DAT_AMLWS, new S57enum(7, "amlws")); Verdat.put(VerDAT.DAT_ISLW, new S57enum(8, "islw")); Verdat.put(VerDAT.DAT_LWS, new S57enum(9, "lws"));
+		Verdat.put(VerDAT.DAT_ALAT, new S57enum(10, "alat"));  Verdat.put(VerDAT.DAT_NLLW, new S57enum(11, "nllw")); Verdat.put(VerDAT.DAT_MLLW, new S57enum(12, "mllw"));
+		Verdat.put(VerDAT.DAT_LW, new S57enum(13, "lw")); Verdat.put(VerDAT.DAT_AMLW, new S57enum(14, "amlw")); Verdat.put(VerDAT.DAT_AMLLW, new S57enum(15, "amllw"));
+		Verdat.put(VerDAT.DAT_MHW, new S57enum(16, "mhw")); Verdat.put(VerDAT.DAT_MHWS, new S57enum(17, "mhws")); Verdat.put(VerDAT.DAT_HW, new S57enum(18, "hw"));
+		Verdat.put(VerDAT.DAT_AMSL, new S57enum(19, "amsl")); Verdat.put(VerDAT.DAT_HWS, new S57enum(20, "hws")); Verdat.put(VerDAT.DAT_MHHW, new S57enum(21, "mhhw"));
+		Verdat.put(VerDAT.DAT_ESLW, new S57enum(22, "eslw")); Verdat.put(VerDAT.DAT_LAT, new S57enum(23, "lat")); Verdat.put(VerDAT.DAT_LOCAL, new S57enum(24, "local"));
+		Verdat.put(VerDAT.DAT_IGLD, new S57enum(25, "igld1985")); Verdat.put(VerDAT.DAT_MWL, new S57enum(26, "mwl")); Verdat.put(VerDAT.DAT_LLWLT, new S57enum(27, "llwlt"));
+		Verdat.put(VerDAT.DAT_HHWLT, new S57enum(28, "hhwlt")); Verdat.put(VerDAT.DAT_NHHW, new S57enum(29, "nhhw")); Verdat.put(VerDAT.DAT_HAT, new S57enum(30, "hat"));
+		Verdat.put(VerDAT.DAT_LLWRL, new S57enum(31, "llwrl")); Verdat.put(VerDAT.DAT_LHWRL, new S57enum(32, "lhwrl")); Verdat.put(VerDAT.DAT_LMWRL, new S57enum(33, "lmwrl"));
+		Verdat.put(VerDAT.DAT_EHW, new S57enum(34, "ehw_dglw")); Verdat.put(VerDAT.DAT_HSHW, new S57enum(35, "hshw_dhsw")); Verdat.put(VerDAT.DAT_RLWL, new S57enum(36, "rlwl_donau"));
+		Verdat.put(VerDAT.DAT_HSHWD, new S57enum(37, "hshw_donau")); Verdat.put(VerDAT.DAT_DRLWRL, new S57enum(38, "drlwrl_olr")); Verdat.put(VerDAT.DAT_RPWL, new S57enum(39, "rpwl"));
+		Verdat.put(VerDAT.DAT_RNBL, new S57enum(40, "rnbl")); Verdat.put(VerDAT.DAT_OHIO, new S57enum(41, "ohio_rd"));
+	}
+	public enum AddMRK { MRK_UNKN, MRK_TOPB, MRK_BOTB, MRK_RTRI, MRK_LTRI, MRK_BTRI	}
+	private static final EnumMap<AddMRK, S57enum> Addmrk = new EnumMap<AddMRK, S57enum>(AddMRK.class); static { Addmrk.put(AddMRK.MRK_UNKN, new S57enum(0, ""));
+		Addmrk.put(AddMRK.MRK_TOPB, new S57enum(1, "top_board")); Addmrk.put(AddMRK.MRK_BOTB, new S57enum(2, "bottom_board")); Addmrk.put(AddMRK.MRK_RTRI, new S57enum(3, "right_triangle"));
+		Addmrk.put(AddMRK.MRK_LTRI, new S57enum(4, "left_triangle")); Addmrk.put(AddMRK.MRK_BTRI, new S57enum(5, "bottom_triangle"));
+	}
+	public enum BnkWTW { BWW_UNKN, BWW_LEFT, BWW_RGHT }
+	private static final EnumMap<BnkWTW, S57enum> Bnkwtw = new EnumMap<BnkWTW, S57enum>(BnkWTW.class); static { Bnkwtw.put(BnkWTW.BWW_UNKN, new S57enum(0, ""));
+	Bnkwtw.put(BnkWTW.BWW_LEFT, new S57enum(1, "left")); Bnkwtw.put(BnkWTW.BWW_RGHT, new S57enum(2, "right"));
+	}
+	public enum CatBNK { BNK_UNKN, BNK_STEP, BNK_FLAT, BNK_FAST, BNK_UFST }
+	private static final EnumMap<CatBNK, S57enum> Catbnk = new EnumMap<CatBNK, S57enum>(CatBNK.class); static { Catbnk.put(CatBNK.BNK_UNKN, new S57enum(0, ""));
+		Catbnk.put(CatBNK.BNK_STEP, new S57enum(1, "steep")); Catbnk.put(CatBNK.BNK_FLAT, new S57enum(2, "flat")); Catbnk.put(CatBNK.BNK_FAST, new S57enum(3, "fastened"));
+		Catbnk.put(CatBNK.BNK_UFST, new S57enum(4, "unfastened"));
+	}
+	public enum CatNMK { NMK_UNKN, NMK_NENT, NMK_CLSA, NMK_NOVK, NMK_NCOV, NMK_NPAS, NMK_NCPS, NMK_NBRT, NMK_NBLL, NMK_NANK, NMK_NMOR, NMK_NTRN, NMK_NWSH,
+		NMK_NPSL, NMK_NPSR, NMK_NMTC, NMK_NSPC, NMK_NWSK, NMK_NSLC, NMK_NUPC, NMK_NSLB, NMK_NWBK, NMK_NHSC, NMK_NLBG, NMK_MVTL, NMK_MVTR, NMK_MVTP,
+		NMK_MVTS, NMK_KPTP, NMK_KPTS, NMK_CSTP, NMK_CSTS, NMK_STOP, NMK_SPDL, NMK_SHRN, NMK_KPLO, NMK_GWJN, NMK_GWCS, NMK_MKRC, NMK_LMDP, NMK_LMHR,
+		NMK_LMWD, NMK_NAVR, NMK_CHDL, NMK_CHDR, NMK_CHTW, NMK_CHOW, NMK_OPTR, NMK_OPTL, NMK_PRTL, NMK_PRTR, NMK_ENTP, NMK_OVHC, NMK_WEIR, NMK_FERN,
+		NMK_FERI, NMK_BRTP, NMK_BTLL, NMK_BTLS, NMK_BTRL, NMK_BTUP, NMK_BTP1, NMK_BTP2, NMK_BTP3, NMK_BTUN, NMK_BTN1, NMK_BTN2, NMK_BTN3, NMK_BTUM,
+		NMK_BTU1, NMK_BTU2, NMK_BTU3, NMK_ANKP, NMK_MORP, NMK_VLBT, NMK_TRNA, NMK_SWWC, NMK_SWWR, NMK_SWWL, NMK_WRSA, NMK_WLSA, NMK_WRSL, NMK_WLSR,
+		NMK_WRAL, NMK_WLAR, NMK_MWWC, NMK_MWWJ, NMK_MWAR, NMK_MWAL, NMK_WARL, NMK_WALR, NMK_PEND, NMK_DWTR, NMK_TELE, NMK_MTCP, NMK_SPCP, NMK_WSKP,
+		NMK_SLCP, NMK_UPCP, NMK_SLBP, NMK_RADI, NMK_WTBP, NMK_HSCP, NMK_LBGP, NMK_KTPM, NMK_KTSM, NMK_KTMR, NMK_CRTP, NMK_CRTS, NMK_TRBM, NMK_RSPD }
+	private static final EnumMap<CatNMK, S57enum> Catnmk = new EnumMap<CatNMK, S57enum>(CatNMK.class); static { Catnmk.put(CatNMK.NMK_UNKN, new S57enum(0, ""));
+		Catnmk.put(CatNMK.NMK_NENT, new S57enum(1, "no_entry")); Catnmk.put(CatNMK.NMK_CLSA, new S57enum(2, "closed_area")); Catnmk.put(CatNMK.NMK_NOVK, new S57enum(3, "no_overtaking"));
+		Catnmk.put(CatNMK.NMK_NCOV, new S57enum(4, "no_convoy_overtaking")); Catnmk.put(CatNMK.NMK_NPAS, new S57enum(5, "no_passing")); Catnmk.put(CatNMK.NMK_NBRT, new S57enum(6, "no_berthing"));
+		Catnmk.put(CatNMK.NMK_NBLL, new S57enum(7, "no_berthing_lateral_limit")); Catnmk.put(CatNMK.NMK_NANK, new S57enum(8, "no_anchoring")); Catnmk.put(CatNMK.NMK_NMOR, new S57enum(9, "no_mooring"));
+		Catnmk.put(CatNMK.NMK_NTRN, new S57enum(10, "no_turning")); Catnmk.put(CatNMK.NMK_NWSH, new S57enum(11, "no_wash")); Catnmk.put(CatNMK.NMK_NPSL, new S57enum(12, "no_passage_left"));
+		Catnmk.put(CatNMK.NMK_NPSR, new S57enum(13, "no_passage_right")); Catnmk.put(CatNMK.NMK_NMTC, new S57enum(14, "no_motor_craft")); Catnmk.put(CatNMK.NMK_NSPC, new S57enum(15, "no_sport_craft"));
+		Catnmk.put(CatNMK.NMK_NWSK, new S57enum(16, "no_waterskiing")); Catnmk.put(CatNMK.NMK_NSLC, new S57enum(17, "no_sailing_craft")); Catnmk.put(CatNMK.NMK_NUPC, new S57enum(18, "no_unpowered_craft"));
+		Catnmk.put(CatNMK.NMK_NSLB, new S57enum(19, "no_sailboards")); Catnmk.put(CatNMK.NMK_NWBK, new S57enum(20, "no_waterbikes")); Catnmk.put(CatNMK.NMK_NHSC, new S57enum(21, "no_high_speeds"));
+		Catnmk.put(CatNMK.NMK_NLBG, new S57enum(22, "no_launching_beaching")); Catnmk.put(CatNMK.NMK_MVTL, new S57enum(23, "move_to_left")); Catnmk.put(CatNMK.NMK_MVTR, new S57enum(24, "move_to_right"));
+		Catnmk.put(CatNMK.NMK_MVTP, new S57enum(25, "move_to_port")); Catnmk.put(CatNMK.NMK_MVTS, new S57enum(26, "move_to_starboard")); Catnmk.put(CatNMK.NMK_KPTP, new S57enum(27, "keep_to_port"));
+		Catnmk.put(CatNMK.NMK_KPTS, new S57enum(28, "keep_to_starboard")); Catnmk.put(CatNMK.NMK_CSTP, new S57enum(29, "cross_to_port")); Catnmk.put(CatNMK.NMK_CSTS, new S57enum(30, "cross_to_starboard"));
+		Catnmk.put(CatNMK.NMK_STOP, new S57enum(31, "stop")); Catnmk.put(CatNMK.NMK_SPDL, new S57enum(32, "speed_limit")); Catnmk.put(CatNMK.NMK_SHRN, new S57enum(33, "sound_horn"));
+		Catnmk.put(CatNMK.NMK_KPLO, new S57enum(34, "keep_lookout")); Catnmk.put(CatNMK.NMK_GWJN, new S57enum(35, "give_way_junction")); Catnmk.put(CatNMK.NMK_GWCS, new S57enum(36, "give_way_crossing"));
+		Catnmk.put(CatNMK.NMK_MKRC, new S57enum(37, "make_radio_contact")); Catnmk.put(CatNMK.NMK_LMDP, new S57enum(38, "limited_depth")); Catnmk.put(CatNMK.NMK_LMHR, new S57enum(39, "limited_headroom"));
+		Catnmk.put(CatNMK.NMK_LMWD, new S57enum(40, "limited_width")); Catnmk.put(CatNMK.NMK_NAVR, new S57enum(41, "navigation_restrictions")); Catnmk.put(CatNMK.NMK_CHDL, new S57enum(42, "channel_distance_left"));
+		Catnmk.put(CatNMK.NMK_CHDR, new S57enum(43, "channel_distance_right")); Catnmk.put(CatNMK.NMK_CHTW, new S57enum(44, "channel_two_way")); Catnmk.put(CatNMK.NMK_CHOW, new S57enum(45, "channel_one_way"));
+		Catnmk.put(CatNMK.NMK_OPTR, new S57enum(46, "opening_to_right")); Catnmk.put(CatNMK.NMK_OPTL, new S57enum(47, "opening_to_left")); Catnmk.put(CatNMK.NMK_PRTL, new S57enum(48, "proceed_to_left"));
+		Catnmk.put(CatNMK.NMK_PRTR, new S57enum(49, "proceed_to_right")); Catnmk.put(CatNMK.NMK_ENTP, new S57enum(50, "entry_permitted")); Catnmk.put(CatNMK.NMK_OVHC, new S57enum(51, "overhead_cable"));
+		Catnmk.put(CatNMK.NMK_WEIR, new S57enum(52, "weir")); Catnmk.put(CatNMK.NMK_FERN, new S57enum(53, "ferry_non_independent"));  Catnmk.put(CatNMK.NMK_FERI, new S57enum(54, "ferry_independent"));
+		Catnmk.put(CatNMK.NMK_BRTP, new S57enum(55, "berthing_permitted")); Catnmk.put(CatNMK.NMK_BTLL, new S57enum(56, "berthing_lateral_limit")); Catnmk.put(CatNMK.NMK_BTLS, new S57enum(57, "berthing_lateral_limits"));
+	  Catnmk.put(CatNMK.NMK_BTRL, new S57enum(58, "berthing_rafting_limit"));  Catnmk.put(CatNMK.NMK_BTUP, new S57enum(59, "berthing_unmarked_pushing"));
+	  Catnmk.put(CatNMK.NMK_BTP1, new S57enum(60, "berthing_marked_pushing_1")); Catnmk.put(CatNMK.NMK_BTP2, new S57enum(61, "berthing_marked_pushing_2"));
+	  Catnmk.put(CatNMK.NMK_BTP3, new S57enum(62, "berthing_marked_pushing_3")); Catnmk.put(CatNMK.NMK_BTUN, new S57enum(63, "berthing_unmarked_non-pushing"));
+	  Catnmk.put(CatNMK.NMK_BTN1, new S57enum(64, "berthing_marked_non-pushing_1")); Catnmk.put(CatNMK.NMK_BTN2, new S57enum(65, "berthing_marked_non-pushing_2"));
+	  Catnmk.put(CatNMK.NMK_BTN3, new S57enum(66, "berthing_marked_non-pushing_3")); Catnmk.put(CatNMK.NMK_BTUM, new S57enum(67, "berthing_unmarked")); Catnmk.put(CatNMK.NMK_BTU1, new S57enum(68, "berthing_marked_1"));
+	  Catnmk.put(CatNMK.NMK_BTU2, new S57enum(69, "berthing_marked_2")); Catnmk.put(CatNMK.NMK_BTU3, new S57enum(70, "berthing_marked_3"));
+	  Catnmk.put(CatNMK.NMK_ANKP, new S57enum(71, "anchoring_permitted"));Catnmk.put(CatNMK.NMK_MORP, new S57enum(72, "mooring_permitted")); Catnmk.put(CatNMK.NMK_VLBT, new S57enum(73, "vehicle_loading_berth"));
+	  Catnmk.put(CatNMK.NMK_TRNA, new S57enum(74, "turning_area")); Catnmk.put(CatNMK.NMK_SWWC, new S57enum(75, "secondary_waterway_crossing")); Catnmk.put(CatNMK.NMK_SWWR, new S57enum(76, "secondary_waterway_right"));
+	  Catnmk.put(CatNMK.NMK_SWWL, new S57enum(77, "secondary_waterway_left")); Catnmk.put(CatNMK.NMK_WRSA, new S57enum(78, "main_waterway_right_secondary_ahead"));
+	  Catnmk.put(CatNMK.NMK_WLSA, new S57enum(79, "main_waterway_left_secondary_ahead")); Catnmk.put(CatNMK.NMK_WRSL, new S57enum(80, "main_waterway_right_secondary_left"));
+	  Catnmk.put(CatNMK.NMK_WLSR, new S57enum(81, "main_waterway_left_secondary_right")); Catnmk.put(CatNMK.NMK_WRAL, new S57enum(82, "main_waterway_right_secondary_ahead_left"));
+	  Catnmk.put(CatNMK.NMK_WLAR, new S57enum(83, "main_waterway_left_secondary_ahead_right")); Catnmk.put(CatNMK.NMK_MWWC, new S57enum(84, "main_waterway_crossing"));
+	  Catnmk.put(CatNMK.NMK_MWWJ, new S57enum(85, "main_waterway_junction")); Catnmk.put(CatNMK.NMK_MWAR, new S57enum(86, "main_waterway_ahead_right"));
+	  Catnmk.put(CatNMK.NMK_MWAL, new S57enum(87, "main_waterway_ahead_left")); Catnmk.put(CatNMK.NMK_WARL, new S57enum(88, "main_waterway_ahead_right_secondary_left"));
+	  Catnmk.put(CatNMK.NMK_WALR, new S57enum(89, "main_waterway_ahead_left_secondary_right")); Catnmk.put(CatNMK.NMK_PEND, new S57enum(90, "prohibition_ends"));
+	  Catnmk.put(CatNMK.NMK_DWTR, new S57enum(91, "drinking_water")); Catnmk.put(CatNMK.NMK_TELE, new S57enum(92, "telephone")); Catnmk.put(CatNMK.NMK_MTCP, new S57enum(93, "motor_craft_permitted"));
+	  Catnmk.put(CatNMK.NMK_SPCP, new S57enum(94, "sport_craft_permitted")); Catnmk.put(CatNMK.NMK_WSKP, new S57enum(95, "waterskiing_permitted")); Catnmk.put(CatNMK.NMK_SLCP, new S57enum(96, "sailing_craft_permitted"));
+	  Catnmk.put(CatNMK.NMK_UPCP, new S57enum(97, "unpowered_craft_permitted")); Catnmk.put(CatNMK.NMK_SLBP, new S57enum(98, "sailboards_permitted")); Catnmk.put(CatNMK.NMK_RADI, new S57enum(99, "radio_information"));
+	  Catnmk.put(CatNMK.NMK_WTBP, new S57enum(100, "waterbikes_permitted")); Catnmk.put(CatNMK.NMK_HSCP, new S57enum(101, "high_speeds_permitted")); Catnmk.put(CatNMK.NMK_LBGP, new S57enum(102, "launching_beaching_permitted"));
+	  Catnmk.put(CatNMK.NMK_KTPM, new S57enum(103, "keep_to_port_margin")); Catnmk.put(CatNMK.NMK_KTSM, new S57enum(104, "keep_to_starboard_margin")); Catnmk.put(CatNMK.NMK_KTMR, new S57enum(105, "keep_to_mid-river"));
+	  Catnmk.put(CatNMK.NMK_CRTP, new S57enum(106, "cross_river_to_port")); Catnmk.put(CatNMK.NMK_CRTS, new S57enum(107, "cross_river_to_starboard")); Catnmk.put(CatNMK.NMK_TRBM, new S57enum(108, "traffic_between_margins"));
+	  Catnmk.put(CatNMK.NMK_RSPD, new S57enum(109, "reduce_speed")); Catnmk.put(CatNMK.NMK_NCPS, new S57enum(199, "no_convoy_passing")); 
+	}
+	public enum ClsDNG { DNG_UNKN, DNG_1BLU, DNG_2BLU, DNG_3BLU, DNG_0BLU, DNG_1RED }
+	private static final EnumMap<ClsDNG, S57enum> Clsdng = new EnumMap<ClsDNG, S57enum>(ClsDNG.class); static { Clsdng.put(ClsDNG.DNG_UNKN, new S57enum(0, ""));
+		Clsdng.put(ClsDNG.DNG_1BLU, new S57enum(1, "one_blue")); Clsdng.put(ClsDNG.DNG_2BLU, new S57enum(2, "two_blue")); Clsdng.put(ClsDNG.DNG_3BLU, new S57enum(3, "three_blue"));
+		Clsdng.put(ClsDNG.DNG_0BLU, new S57enum(4, "no_blue")); Clsdng.put(ClsDNG.DNG_1RED, new S57enum(5, "one_red"));
+	}
+	public enum DirIMP { IMP_UNKN, IMP_UPST, IMP_DNST, IMP_LTBK, IMP_RTBK, IMP_THBR }
+	private static final EnumMap<DirIMP, S57enum> Dirimp = new EnumMap<DirIMP, S57enum>(DirIMP.class); static { Dirimp.put(DirIMP.IMP_UNKN, new S57enum(0, ""));
+		Dirimp.put(DirIMP.IMP_UPST, new S57enum(1, "upstream")); Dirimp.put(DirIMP.IMP_DNST, new S57enum(2, "downstream")); Dirimp.put(DirIMP.IMP_LTBK, new S57enum(3, "left_bank"));
+		Dirimp.put(DirIMP.IMP_RTBK, new S57enum(4, "right_bank")); Dirimp.put(DirIMP.IMP_THBR, new S57enum(5, "to_harbour"));
+	}
+	public enum FncFNM { FNM_UNKN, FNM_PRHB, FNM_RGLN, FNM_RSTN, FNM_RCMD, FNM_INFO }
+	private static final EnumMap<FncFNM, S57enum> Fnctnm = new EnumMap<FncFNM, S57enum>(FncFNM.class); static { Fnctnm.put(FncFNM.FNM_UNKN, new S57enum(0, ""));
+		Fnctnm.put(FncFNM.FNM_PRHB, new S57enum(1, "prohibition")); Fnctnm.put(FncFNM.FNM_RGLN, new S57enum(2, "regulation")); Fnctnm.put(FncFNM.FNM_RSTN, new S57enum(3, "restriction"));
+		Fnctnm.put(FncFNM.FNM_RCMD, new S57enum(4, "recommendation")); Fnctnm.put(FncFNM.FNM_INFO, new S57enum(5, "information"));
+	}
+	public enum BunVES { VES_UNKN, VES_BVAV, VES_NBVA }
+	private static final EnumMap<BunVES, S57enum> Bunves = new EnumMap<BunVES, S57enum>(BunVES.class); static { Bunves.put(BunVES.VES_UNKN, new S57enum(0, ""));
+		Bunves.put(BunVES.VES_BVAV, new S57enum(1, "bunker_vessel_available")); Bunves.put(BunVES.VES_NBVA, new S57enum(2, "no_bunker_vessel_available"));
+	}
+	public enum CatBRT { BRT_UNKN, BRT_LODG, BRT_ULDG, BRT_OVNT, BRT_PSHN, BRT_NPSH, BRT_FLTG, BRT_FCLS, BRT_SCLS } 
+	private static final EnumMap<CatBRT, S57enum> Catbrt = new EnumMap<CatBRT, S57enum>(CatBRT.class); static { Catbrt.put(CatBRT.BRT_UNKN, new S57enum(0, ""));
+		Catbrt.put(CatBRT.BRT_LODG, new S57enum(1, "loading")); Catbrt.put(CatBRT.BRT_ULDG, new S57enum(2, "unloading")); Catbrt.put(CatBRT.BRT_OVNT, new S57enum(3, "overnight_accommodation"));
+		Catbrt.put(CatBRT.BRT_PSHN, new S57enum(4, "pushing-navigation")); Catbrt.put(CatBRT.BRT_NPSH, new S57enum(5, "non-pushing-navigation"));
+		Catbrt.put(CatBRT.BRT_FLTG, new S57enum(6, "fleeting")); Catbrt.put(CatBRT.BRT_FCLS, new S57enum(7, "first_class")); Catbrt.put(CatBRT.BRT_SCLS, new S57enum(8, "second_class"));
+	}
+	public enum CatBUN { BUN_UNKN, BUN_DESL, BUN_WATR, BUN_BLST }
+	private static final EnumMap<CatBUN, S57enum> Catbun = new EnumMap<CatBUN, S57enum>(CatBUN.class); static { Catbun.put(CatBUN.BUN_UNKN, new S57enum(0, ""));
+		Catbun.put(CatBUN.BUN_DESL, new S57enum(1, "diesel")); Catbun.put(CatBUN.BUN_WATR, new S57enum(2, "water")); Catbun.put(CatBUN.BUN_BLST, new S57enum(3, "ballast"));
+	}
+	public enum CatCCL { CCL_UNKN, CCL_SMLV, CCL_PNCH, CCL_CMPB, CCL_DMEB, CCL_RHNB, CCL_1BPT, CCL_2PTL, CCL_2PTW, CCL_4BPT, CCL_6BPT, CCL_NCCL } 
+	private static final EnumMap<CatCCL, S57enum> Catccl = new EnumMap<CatCCL, S57enum>(CatCCL.class); static { Catccl.put(CatCCL.CCL_UNKN, new S57enum(0, ""));
+		Catccl.put(CatCCL.CCL_SMLV, new S57enum(1, "small_vessels")); Catccl.put(CatCCL.CCL_PNCH, new S57enum(2, "peniche")); Catccl.put(CatCCL.CCL_CMPB, new S57enum(3, "campine_barge"));
+		Catccl.put(CatCCL.CCL_DMEB, new S57enum(4, "dortmund-ems_barge")); Catccl.put(CatCCL.CCL_RHNB, new S57enum(5, "rhine-herne_barge")); Catccl.put(CatCCL.CCL_1BPT, new S57enum(6, "1-barge_push-tow"));
+	  Catccl.put(CatCCL.CCL_2PTL, new S57enum(7, "2-barge_push-tow_long")); Catccl.put(CatCCL.CCL_2PTW, new S57enum(8, "2-barge_push-tow_wide")); Catccl.put(CatCCL.CCL_4BPT, new S57enum(9, "4-barge_push-tow"));
+	  Catccl.put(CatCCL.CCL_6BPT, new S57enum(10, "6-barge_push-tow")); Catccl.put(CatCCL.CCL_NCCL, new S57enum(11, "no_cemt_class"));
+	}
+	public enum CatCOM { COM_UNKN, COM_VTSC, COM_VTSS, COM_IVSP, COM_MID, COM_LOCK, COM_BRDG, COM_CSTM, COM_HRBR } 
+	private static final EnumMap<CatCOM, S57enum> Catcom = new EnumMap<CatCOM, S57enum>(CatCOM.class); static { Catcom.put(CatCOM.COM_UNKN, new S57enum(0, ""));
+		Catcom.put(CatCOM.COM_VTSC, new S57enum(1, "vts_centre")); Catcom.put(CatCOM.COM_VTSS, new S57enum(2, "vts_sector")); Catcom.put(CatCOM.COM_IVSP, new S57enum(3, "ivs_point"));
+		Catcom.put(CatCOM.COM_MID, new S57enum(4, "mib")); Catcom.put(CatCOM.COM_LOCK, new S57enum(5, "lock")); Catcom.put(CatCOM.COM_BRDG, new S57enum(6, "bridge"));
+		Catcom.put(CatCOM.COM_CSTM, new S57enum(7, "customs")); Catcom.put(CatCOM.COM_HRBR, new S57enum(8, "harbour"));
+	}
+	public enum CatHBR { HBR_UNKN, HBR_CSTM, HBR_REFG, HBR_MRNA, HBR_FISH, HBR_PRIV, HBR_ }
+	private static final EnumMap<CatHBR, S57enum> Cathbr = new EnumMap<CatHBR, S57enum>(CatHBR.class); static { Cathbr.put(CatHBR.HBR_UNKN, new S57enum(0, ""));
+		Cathbr.put(CatHBR.HBR_CSTM, new S57enum(1, "customs")); Cathbr.put(CatHBR.HBR_REFG, new S57enum(2, "refuge")); Cathbr.put(CatHBR.HBR_MRNA, new S57enum(3, "marina"));
+		Cathbr.put(CatHBR.HBR_FISH, new S57enum(4, "fishing")); Cathbr.put(CatHBR.HBR_PRIV, new S57enum(5, "private"));
+	}
+	public enum CatRFD { RFD_UNKN, RFD_CRSD, RFD_WOIL, RFD_GBWT, RFD_DREF } 
+	private static final EnumMap<CatRFD, S57enum> Catrfd = new EnumMap<CatRFD, S57enum>(CatRFD.class); static { Catrfd.put(CatRFD.RFD_UNKN, new S57enum(0, ""));
+		Catrfd.put(CatRFD.RFD_CRSD, new S57enum(1, "cargo_residue")); Catrfd.put(CatRFD.RFD_WOIL, new S57enum(2, "waste_oil")); Catrfd.put(CatRFD.RFD_GBWT, new S57enum(3, "grey_black_water"));
+		Catrfd.put(CatRFD.RFD_DREF, new S57enum(4, "domestic_refuse"));
+	}
+	public enum CatTML { TML_UNKN, TML_PSGR, TML_FERY, TML_TSPT, TML_RORO }
+	private static final EnumMap<CatTML, S57enum> Cattml = new EnumMap<CatTML, S57enum>(CatTML.class); static { Cattml.put(CatTML.TML_UNKN, new S57enum(0, ""));
+		Cattml.put(CatTML.TML_PSGR, new S57enum(1, "passenger")); Cattml.put(CatTML.TML_FERY, new S57enum(2, "ferry")); Cattml.put(CatTML.TML_TSPT, new S57enum(3, "transhipment"));
+		Cattml.put(CatTML.TML_RORO, new S57enum(4, "roro"));
+	}
+	public enum TrsTGD { TGD_UNKN, TGD_CONT, TGD_BULK, TGD_OIL, TGD_FUEL, TGD_CHEM, TGD_LIQD, TGD_EXPL, TGD_FISH, TGD_CARS, TGD_GNRL } 
+	private static final EnumMap<TrsTGD, S57enum> Trshgd = new EnumMap<TrsTGD, S57enum>(TrsTGD.class); static { Trshgd.put(TrsTGD.TGD_UNKN, new S57enum(0, ""));
+		Trshgd.put(TrsTGD.TGD_CONT, new S57enum(1, "containers")); Trshgd.put(TrsTGD.TGD_BULK, new S57enum(2, "bulk")); Trshgd.put(TrsTGD.TGD_OIL, new S57enum(3, "oil"));
+		Trshgd.put(TrsTGD.TGD_FUEL, new S57enum(4, "fuel")); Trshgd.put(TrsTGD.TGD_CHEM, new S57enum(5, "chemicals")); Trshgd.put(TrsTGD.TGD_LIQD, new S57enum(6, "liquid"));
+		Trshgd.put(TrsTGD.TGD_EXPL, new S57enum(7, "explosive")); Trshgd.put(TrsTGD.TGD_FISH, new S57enum(8, "fish")); Trshgd.put(TrsTGD.TGD_CARS, new S57enum(9, "cars"));
+		Trshgd.put(TrsTGD.TGD_GNRL, new S57enum(10, "general"));
+	}
+	public enum CatGAG { GAG_UNKN, GAG_STAF, GAG_RCRD, GAG_RCRA, GAG_RCEI, GAG_RRAI } 
+	private static final EnumMap<CatGAG, S57enum> Catgag = new EnumMap<CatGAG, S57enum>(CatGAG.class); static { Catgag.put(CatGAG.GAG_UNKN, new S57enum(0, ""));
+		Catgag.put(CatGAG.GAG_STAF, new S57enum(1, "staff")); Catgag.put(CatGAG.GAG_RCRD, new S57enum(2, "recording")); Catgag.put(CatGAG.GAG_RCRA, new S57enum(3, "recording_remote_access"));
+		Catgag.put(CatGAG.GAG_RCEI, new S57enum(4, "recording_external_indicator")); Catgag.put(CatGAG.GAG_RRAI, new S57enum(5, "recording_remote_access_indicator"));
+	}
+	public enum RefLEV { LEV_UNKN, LEV_BALT, LEV_ADRC, LEV_AMSD, LEV_MSL, LEV_OTHR, LEV_NG29, LEV_NA88, LEV_1912, LEV_1929 } 
+	private static final EnumMap<RefLEV, S57enum> Reflev = new EnumMap<RefLEV, S57enum>(RefLEV.class); static { Reflev.put(RefLEV.LEV_UNKN, new S57enum(0, ""));
+		Reflev.put(RefLEV.LEV_BALT, new S57enum(1, "baltic")); Reflev.put(RefLEV.LEV_ADRC, new S57enum(2, "adriatic")); Reflev.put(RefLEV.LEV_AMSD, new S57enum(3, "amsterdam"));
+		Reflev.put(RefLEV.LEV_MSL, new S57enum(4, "msl")); Reflev.put(RefLEV.LEV_OTHR, new S57enum(5, "other")); Reflev.put(RefLEV.LEV_NG29, new S57enum(6, "ngvd29"));
+		Reflev.put(RefLEV.LEV_NA88, new S57enum(7, "navd88")); Reflev.put(RefLEV.LEV_1912, new S57enum(8, "msl1912")); Reflev.put(RefLEV.LEV_1929, new S57enum(9, "msl1929"));
+	}
+	public enum CatVTR { VTR_UNKN, VTR_OFFL, VTR_PRIV, VTR_CARC, VTR_CARP, VTR_PREQ, VTR_LGAT }
+	private static final EnumMap<CatVTR, S57enum> Catvtr = new EnumMap<CatVTR, S57enum>(CatVTR.class); static { Catvtr.put(CatVTR.VTR_UNKN, new S57enum(0, ""));
+		Catvtr.put(CatVTR.VTR_OFFL, new S57enum(1, "official")); Catvtr.put(CatVTR.VTR_PRIV, new S57enum(2, "private")); Catvtr.put(CatVTR.VTR_CARC, new S57enum(3, "car_cranes"));
+		Catvtr.put(CatVTR.VTR_CARP, new S57enum(4, "car_planks")); Catvtr.put(CatVTR.VTR_PREQ, new S57enum(5, "permission_required")); Catvtr.put(CatVTR.VTR_LGAT, new S57enum(6, "locked_gate"));
+	}
+	public enum CatTAB { TAB_UNKN, TAB_OPPD, TAB_NOPP }
+	private static final EnumMap<CatTAB, S57enum> Cattab = new EnumMap<CatTAB, S57enum>(CatTAB.class); static { Cattab.put(CatTAB.TAB_UNKN, new S57enum(0, ""));
+		Cattab.put(CatTAB.TAB_OPPD, new S57enum(1, "operational_period")); Cattab.put(CatTAB.TAB_NOPP, new S57enum(2, "non-operational_period"));
+	}
+	public enum UseSHP { SHP_UNKN, SHP_LINT, SHP_OCSH, SHP_LESR }
+	private static final EnumMap<UseSHP, S57enum> Useshp = new EnumMap<UseSHP, S57enum>(UseSHP.class); static { Useshp.put(UseSHP.SHP_UNKN, new S57enum(0, ""));
+		Useshp.put(UseSHP.SHP_LINT, new S57enum(1, "liner_trade")); Useshp.put(UseSHP.SHP_OCSH, new S57enum(2, "occasional_professional_shipping")); Useshp.put(UseSHP.SHP_LESR, new S57enum(3, "leisure"));
+	}
+	public enum CatEXS { EXS_UNKN, EXS_LLOK, EXS_AQDT, EXS_SPLK, EXS_WSLK, EXS_OTHR } 
+	private static final EnumMap<CatEXS, S57enum> Catexs = new EnumMap<CatEXS, S57enum>(CatEXS.class); static { Catexs.put(CatEXS.EXS_UNKN, new S57enum(0, ""));
+		Catexs.put(CatEXS.EXS_LLOK, new S57enum(1, "lift-lock")); Catexs.put(CatEXS.EXS_AQDT, new S57enum(2, "aqueduct")); Catexs.put(CatEXS.EXS_SPLK, new S57enum(3, "sloping_plane_lock"));
+		Catexs.put(CatEXS.EXS_WSLK, new S57enum(4, "water_slope_lock")); Catexs.put(CatEXS.EXS_OTHR, new S57enum(5, "other"));
+	}
+	public enum CatWWM { WWM_UNKN, WWM_WWRT, WWM_WWLT, WWM_WWSP, WWM_CHRT, WWM_CHLT, WWM_CHSP, WWM_CHRB, WWM_CHLB, WWM_CORT, WWM_COLT, WWM_DGRT, WWM_DGLT,
+		WWM_TORT, WWM_TOLT, WWM_JNRT, WWM_JNLT, WWM_HBRT, WWM_HBLT, WWM_BRPR } 
+	private static final EnumMap<CatWWM, S57enum> Catwwm = new EnumMap<CatWWM, S57enum>(CatWWM.class); static { Catwwm.put(CatWWM.WWM_UNKN, new S57enum(0, ""));
+		Catwwm.put(CatWWM.WWM_WWRT, new S57enum(1, "waterway_right")); Catwwm.put(CatWWM.WWM_WWLT, new S57enum(2, "waterway_left")); Catwwm.put(CatWWM.WWM_WWSP, new S57enum(3, "waterway_separation"));
+		Catwwm.put(CatWWM.WWM_CHRT, new S57enum(4, "channel_right")); Catwwm.put(CatWWM.WWM_CHLT, new S57enum(5, "channel_left")); Catwwm.put(CatWWM.WWM_CHSP, new S57enum(6, "channel_separation"));
+		Catwwm.put(CatWWM.WWM_CHRB, new S57enum(7, "channel_right_bank")); Catwwm.put(CatWWM.WWM_CHLB, new S57enum(8, "channel_left_bank")); Catwwm.put(CatWWM.WWM_CORT, new S57enum(9, "crossover_right"));
+		Catwwm.put(CatWWM.WWM_COLT, new S57enum(10, "crossover_left")); Catwwm.put(CatWWM.WWM_DGRT, new S57enum(11, "danger_right")); Catwwm.put(CatWWM.WWM_DGLT, new S57enum(12, "danger_left"));
+		Catwwm.put(CatWWM.WWM_TORT, new S57enum(13, "turnoff_right")); Catwwm.put(CatWWM.WWM_TOLT, new S57enum(14, "turnoff_left")); Catwwm.put(CatWWM.WWM_JNRT, new S57enum(15, "junction_right"));
+		Catwwm.put(CatWWM.WWM_JNLT, new S57enum(16, "junction_left")); Catwwm.put(CatWWM.WWM_HBRT, new S57enum(17, "harbour_right")); Catwwm.put(CatWWM.WWM_HBLT, new S57enum(18, "harbour_left"));
+		Catwwm.put(CatWWM.WWM_BRPR, new S57enum(19, "bridge_pier"));
+	}
+	public enum Lg_SPR { SPR_UNKN, SPR_OTHR, SPR_SPOG, SPR_SPTW }
+	private static final EnumMap<Lg_SPR, S57enum> Lg_spr = new EnumMap<Lg_SPR, S57enum>(Lg_SPR.class); static { Lg_spr.put(Lg_SPR.SPR_UNKN, new S57enum(0, ""));
+		Lg_spr.put(Lg_SPR.SPR_OTHR, new S57enum(1, "other")); Lg_spr.put(Lg_SPR.SPR_SPOG, new S57enum(2, "speed_over_ground")); Lg_spr.put(Lg_SPR.SPR_SPTW, new S57enum(3, "speed_through_water"));
+	}
+	public enum Lg_WDU { WDU_UNKN, WDU_OTHR, WDU_CUMT, WDU_TONS }
+	private static final EnumMap<Lg_WDU, S57enum> Lg_wdu = new EnumMap<Lg_WDU, S57enum>(Lg_WDU.class); static { Lg_wdu.put(Lg_WDU.WDU_UNKN, new S57enum(0, ""));
+		Lg_wdu.put(Lg_WDU.WDU_OTHR, new S57enum(1, "other")); Lg_wdu.put(Lg_WDU.WDU_CUMT, new S57enum(2, "cubic_metres")); Lg_wdu.put(Lg_WDU.WDU_TONS, new S57enum(3, "tonnes"));
+	}
+	public enum Lg_REL { REL_UNKN, REL_OTHR, REL_USWW, REL_CREQ, REL_TKOP }
+	private static final EnumMap<Lg_REL, S57enum> Lg_rel = new EnumMap<Lg_REL, S57enum>(Lg_REL.class); static { Lg_rel.put(Lg_REL.REL_UNKN, new S57enum(0, ""));
+		Lg_rel.put(Lg_REL.REL_OTHR, new S57enum(1, "other")); Lg_rel.put(Lg_REL.REL_USWW, new S57enum(2, "usage_of_waterway")); Lg_rel.put(Lg_REL.REL_CREQ, new S57enum(3, "carriage_of_equipment"));
+		Lg_rel.put(Lg_REL.REL_TKOP, new S57enum(4, "task_operation"));
+	}
+	public enum Lg_FNC { FNC_UNKN, FNC_OTHR, FNC_PRHB, FNC_PRHE, FNC_PERM, FNC_PERE, FNC_RCMD, FNC_NRCD } 
+	private static final EnumMap<Lg_FNC, S57enum> Lg_fnc = new EnumMap<Lg_FNC, S57enum>(Lg_FNC.class); static { Lg_fnc.put(Lg_FNC.FNC_UNKN, new S57enum(0, ""));
+		Lg_fnc.put(Lg_FNC.FNC_OTHR, new S57enum(1, "other")); Lg_fnc.put(Lg_FNC.FNC_PRHB, new S57enum(2, "prohibited")); Lg_fnc.put(Lg_FNC.FNC_PRHE, new S57enum(3, "prohibited_with_exceptions"));
+		Lg_fnc.put(Lg_FNC.FNC_PERM, new S57enum(4, "permitted")); Lg_fnc.put(Lg_FNC.FNC_PERE, new S57enum(5, "permitted_with_exceptions")); Lg_fnc.put(Lg_FNC.FNC_RCMD, new S57enum(6, "recommended"));
+		Lg_fnc.put(Lg_FNC.FNC_NRCD, new S57enum(7, "not_recommended"));
+	}
+	public enum Lc_CSX { CSX_UNKN, CSX_ALL, CSX_OTHR, CSX_NMOT, CSX_CRFT, CSX_VSSL, CSX_ILWW, CSX_SEAG, CSX_MOTR, CSX_MTNK, CSX_MCGO, CSX_CBRG, CSX_TUG, CSX_PSHR, CSX_BARG, CSX_TNKB, 
+		CSX_DMBB, CSX_LGTR, CSX_TNKL, CSX_CGOL, CSX_SBLR, CSX_PSGR, CSX_PSGS, CSX_DAYT, CSX_CABN, CSX_HSPD, CSX_FLEQ, CSX_WSIT, CSX_RCNL, CSX_DNGY, CSX_FEST, CSX_FOBJ }
+	private static final EnumMap<Lc_CSX, S57enum> Lc_csi = new EnumMap<Lc_CSX, S57enum>(Lc_CSX.class); static { Lc_csi.put(Lc_CSX.CSX_UNKN, new S57enum(0, ""));
+		Lc_csi.put(Lc_CSX.CSX_ALL, new S57enum(1, "all")); Lc_csi.put(Lc_CSX.CSX_OTHR, new S57enum(2, "other")); Lc_csi.put(Lc_CSX.CSX_NMOT, new S57enum(3, "non-motorized"));
+		Lc_csi.put(Lc_CSX.CSX_CRFT, new S57enum(5, "craft")); Lc_csi.put(Lc_CSX.CSX_VSSL, new S57enum(6, "vessel")); Lc_csi.put(Lc_CSX.CSX_ILWW, new S57enum(7, "inland_waterway"));
+		Lc_csi.put(Lc_CSX.CSX_SEAG, new S57enum(8, "sea-going")); Lc_csi.put(Lc_CSX.CSX_MOTR, new S57enum(9, "motor")); Lc_csi.put(Lc_CSX.CSX_MTNK, new S57enum(10, "motor_tanker"));
+		Lc_csi.put(Lc_CSX.CSX_MCGO, new S57enum(11, "motor_cargo")); Lc_csi.put(Lc_CSX.CSX_CBRG, new S57enum(12, "canal_barge")); Lc_csi.put(Lc_CSX.CSX_TUG, new S57enum(13, "tug"));
+		Lc_csi.put(Lc_CSX.CSX_PSHR, new S57enum(14, "pusher")); Lc_csi.put(Lc_CSX.CSX_BARG, new S57enum(15, "barge")); Lc_csi.put(Lc_CSX.CSX_TNKB, new S57enum(16, "tank_barge"));
+		Lc_csi.put(Lc_CSX.CSX_DMBB, new S57enum(17, "dumb_barge")); Lc_csi.put(Lc_CSX.CSX_LGTR, new S57enum(18, "lighter")); Lc_csi.put(Lc_CSX.CSX_TNKL, new S57enum(19, "tank_lighter"));
+		Lc_csi.put(Lc_CSX.CSX_CGOL, new S57enum(20, "cargo_lighter")); Lc_csi.put(Lc_CSX.CSX_SBLR, new S57enum(21, "ship_borne_lighter")); Lc_csi.put(Lc_CSX.CSX_PSGR, new S57enum(22, "passenger"));
+		Lc_csi.put(Lc_CSX.CSX_PSGS, new S57enum(23, "passenger_sailing")); Lc_csi.put(Lc_CSX.CSX_DAYT, new S57enum(24, "day_trip")); Lc_csi.put(Lc_CSX.CSX_CABN, new S57enum(25, "cabin"));
+		Lc_csi.put(Lc_CSX.CSX_HSPD, new S57enum(26, "high-speed")); Lc_csi.put(Lc_CSX.CSX_FLEQ, new S57enum(27, "floating_equipment")); Lc_csi.put(Lc_CSX.CSX_WSIT, new S57enum(28, "worksite"));
+		Lc_csi.put(Lc_CSX.CSX_RCNL, new S57enum(29, "recreational")); Lc_csi.put(Lc_CSX.CSX_DNGY, new S57enum(30, "dinghy")); Lc_csi.put(Lc_CSX.CSX_FEST, new S57enum(31, "floating_establishment"));
+		Lc_csi.put(Lc_CSX.CSX_FOBJ, new S57enum(32, "floating_object"));
+	}
+	private static final EnumMap<Lc_CSX, S57enum> Lc_cse = new EnumMap<Lc_CSX, S57enum>(Lc_CSX.class); static { Lc_cse.put(Lc_CSX.CSX_UNKN, new S57enum(0, ""));
+		Lc_cse.put(Lc_CSX.CSX_ALL, new S57enum(1, "all")); Lc_cse.put(Lc_CSX.CSX_OTHR, new S57enum(2, "other")); Lc_cse.put(Lc_CSX.CSX_NMOT, new S57enum(3, "non-motorized"));
+		Lc_cse.put(Lc_CSX.CSX_CRFT, new S57enum(5, "craft")); Lc_cse.put(Lc_CSX.CSX_VSSL, new S57enum(6, "vessel")); Lc_cse.put(Lc_CSX.CSX_ILWW, new S57enum(7, "inland_waterway"));
+		Lc_cse.put(Lc_CSX.CSX_SEAG, new S57enum(8, "sea-going")); Lc_cse.put(Lc_CSX.CSX_MOTR, new S57enum(9, "motor")); Lc_cse.put(Lc_CSX.CSX_MTNK, new S57enum(10, "motor_tanker"));
+		Lc_cse.put(Lc_CSX.CSX_MCGO, new S57enum(11, "motor_cargo")); Lc_cse.put(Lc_CSX.CSX_CBRG, new S57enum(12, "canal_barge")); Lc_cse.put(Lc_CSX.CSX_TUG, new S57enum(13, "tug"));
+		Lc_cse.put(Lc_CSX.CSX_PSHR, new S57enum(14, "pusher")); Lc_cse.put(Lc_CSX.CSX_BARG, new S57enum(15, "barge")); Lc_cse.put(Lc_CSX.CSX_TNKB, new S57enum(16, "tank_barge"));
+		Lc_cse.put(Lc_CSX.CSX_DMBB, new S57enum(17, "dumb_barge")); Lc_cse.put(Lc_CSX.CSX_LGTR, new S57enum(18, "lighter")); Lc_cse.put(Lc_CSX.CSX_TNKL, new S57enum(19, "tank_lighter"));
+		Lc_cse.put(Lc_CSX.CSX_CGOL, new S57enum(20, "cargo_lighter")); Lc_cse.put(Lc_CSX.CSX_SBLR, new S57enum(21, "ship_borne_lighter")); Lc_cse.put(Lc_CSX.CSX_PSGR, new S57enum(22, "passenger"));
+		Lc_cse.put(Lc_CSX.CSX_PSGS, new S57enum(23, "passenger_sailing")); Lc_cse.put(Lc_CSX.CSX_DAYT, new S57enum(24, "day_trip")); Lc_cse.put(Lc_CSX.CSX_CABN, new S57enum(25, "cabin"));
+		Lc_cse.put(Lc_CSX.CSX_HSPD, new S57enum(26, "high-speed")); Lc_cse.put(Lc_CSX.CSX_FLEQ, new S57enum(27, "floating_equipment")); Lc_cse.put(Lc_CSX.CSX_WSIT, new S57enum(28, "worksite"));
+		Lc_cse.put(Lc_CSX.CSX_RCNL, new S57enum(29, "recreational")); Lc_cse.put(Lc_CSX.CSX_DNGY, new S57enum(30, "dinghy")); Lc_cse.put(Lc_CSX.CSX_FEST, new S57enum(31, "floating_establishment"));
+		Lc_cse.put(Lc_CSX.CSX_FOBJ, new S57enum(32, "floating_object"));
+	}
+	public enum Lc_ASX { ASX_UNKN, ASX_ALL, ASX_OTHR, ASX_SNGL, ASX_CONV, ASX_FMTN, ASX_RCNV, ASX_PCNV, ASX_BSTD, ASX_TCNV } 
+	private static final EnumMap<Lc_ASX, S57enum> Lc_asi = new EnumMap<Lc_ASX, S57enum>(Lc_ASX.class); static { Lc_asi.put(Lc_ASX.ASX_UNKN, new S57enum(0, ""));
+		Lc_asi.put(Lc_ASX.ASX_ALL, new S57enum(1, "all")); Lc_asi.put(Lc_ASX.ASX_OTHR, new S57enum(2, "other")); Lc_asi.put(Lc_ASX.ASX_SNGL, new S57enum(3, "single"));
+		Lc_asi.put(Lc_ASX.ASX_CONV, new S57enum(5, "convoy")); Lc_asi.put(Lc_ASX.ASX_FMTN, new S57enum(6, "formation")); Lc_asi.put(Lc_ASX.ASX_RCNV, new S57enum(7, "rigid_convoy"));
+		Lc_asi.put(Lc_ASX.ASX_PCNV, new S57enum(8, "pushed_convoy")); Lc_asi.put(Lc_ASX.ASX_BSTD, new S57enum(9, "breasted")); Lc_asi.put(Lc_ASX.ASX_TCNV, new S57enum(10, "towed_convoy"));
+	}
+	private static final EnumMap<Lc_ASX, S57enum> Lc_ase = new EnumMap<Lc_ASX, S57enum>(Lc_ASX.class); static { Lc_ase.put(Lc_ASX.ASX_UNKN, new S57enum(0, ""));
+		Lc_ase.put(Lc_ASX.ASX_ALL, new S57enum(1, "all")); Lc_ase.put(Lc_ASX.ASX_OTHR, new S57enum(2, "other")); Lc_ase.put(Lc_ASX.ASX_SNGL, new S57enum(3, "single"));
+		Lc_ase.put(Lc_ASX.ASX_CONV, new S57enum(5, "convoy")); Lc_ase.put(Lc_ASX.ASX_FMTN, new S57enum(6, "formation")); Lc_ase.put(Lc_ASX.ASX_RCNV, new S57enum(7, "rigid_convoy"));
+		Lc_ase.put(Lc_ASX.ASX_PCNV, new S57enum(8, "pushed_convoy")); Lc_ase.put(Lc_ASX.ASX_BSTD, new S57enum(9, "breasted")); Lc_ase.put(Lc_ASX.ASX_TCNV, new S57enum(10, "towed_convoy"));
+	}
+	public enum Lc_CCX { CCX_UNKN, CCX_ALL, CCX_OTHR, CCX_BULK, CCX_DRY, CCX_LIQD, CCX_LQDN, CCX_LQDC, CCX_GAS } 
+	private static final EnumMap<Lc_CCX, S57enum> Lc_cci = new EnumMap<Lc_CCX, S57enum>(Lc_CCX.class); static { Lc_cci.put(Lc_CCX.CCX_UNKN, new S57enum(0, ""));
+		Lc_cci.put(Lc_CCX.CCX_ALL, new S57enum(1, "all")); Lc_cci.put(Lc_CCX.CCX_OTHR, new S57enum(2, "other")); Lc_cci.put(Lc_CCX.CCX_BULK, new S57enum(4, "bulk"));
+		Lc_cci.put(Lc_CCX.CCX_DRY, new S57enum(5, "dry")); Lc_cci.put(Lc_CCX.CCX_LIQD, new S57enum(6, "liquid")); Lc_cci.put(Lc_CCX.CCX_LQDN, new S57enum(7, "liquid_n"));
+		Lc_cci.put(Lc_CCX.CCX_LQDC, new S57enum(8, "liquid_c")); Lc_cci.put(Lc_CCX.CCX_GAS, new S57enum(9, "gas"));
+	}
+	private static final EnumMap<Lc_CCX, S57enum> Lc_cce = new EnumMap<Lc_CCX, S57enum>(Lc_CCX.class); static { Lc_cce.put(Lc_CCX.CCX_UNKN, new S57enum(0, ""));
+		Lc_cce.put(Lc_CCX.CCX_ALL, new S57enum(1, "all")); Lc_cce.put(Lc_CCX.CCX_OTHR, new S57enum(2, "other")); Lc_cce.put(Lc_CCX.CCX_BULK, new S57enum(4, "bulk"));
+		Lc_cce.put(Lc_CCX.CCX_DRY, new S57enum(5, "dry")); Lc_cce.put(Lc_CCX.CCX_LIQD, new S57enum(6, "liquid")); Lc_cce.put(Lc_CCX.CCX_LQDN, new S57enum(7, "liquid_n"));
+		Lc_cce.put(Lc_CCX.CCX_LQDC, new S57enum(8, "liquid_c")); Lc_cce.put(Lc_CCX.CCX_GAS, new S57enum(9, "gas"));
+	}
+
+	public enum ShpTYP { TYP_UNKN, TYP_CRGO, TYP_CONT, TYP_TNKR, TYP_SAIL, TYP_FISH, TYP_SPPS, TYP_MOWR, TYP_SUBM, TYP_HSPD, TYP_BCAR, TYP_SPLN, TYP_TUGB, TYP_PSGR, TYP_FERY, TYP_BOAT }
+	private static final EnumMap<ShpTYP, S57enum> Shptyp = new EnumMap<ShpTYP, S57enum>(ShpTYP.class); static { Shptyp.put(ShpTYP.TYP_UNKN, new S57enum(0, ""));
+		Shptyp.put(ShpTYP.TYP_CRGO, new S57enum(1, "cargo")); Shptyp.put(ShpTYP.TYP_CONT, new S57enum(2, "container")); Shptyp.put(ShpTYP.TYP_TNKR, new S57enum(3, "tanker"));
+		Shptyp.put(ShpTYP.TYP_SAIL, new S57enum(4, "sailing")); Shptyp.put(ShpTYP.TYP_FISH, new S57enum(5, "fishing")); Shptyp.put(ShpTYP.TYP_SPPS, new S57enum(6, "special_purpose."));
+		Shptyp.put(ShpTYP.TYP_MOWR, new S57enum(7, "man_of_war")); Shptyp.put(ShpTYP.TYP_SUBM, new S57enum(8, "submarine")); Shptyp.put(ShpTYP.TYP_HSPD, new S57enum(9, "high-speed"));
+		Shptyp.put(ShpTYP.TYP_BCAR, new S57enum(10, "bulk_carrier")); Shptyp.put(ShpTYP.TYP_SPLN, new S57enum(11, "seaplane")); Shptyp.put(ShpTYP.TYP_TUGB, new S57enum(12, "tugboat"));
+		Shptyp.put(ShpTYP.TYP_PSGR, new S57enum(13, "passenger")); Shptyp.put(ShpTYP.TYP_FERY, new S57enum(14, "ferry")); Shptyp.put(ShpTYP.TYP_BOAT, new S57enum(15, "boat"));
+	}
+
+	public enum CatCVR { CVR_UNKN, CVR_COVR, CVR_NCVR }
+	private static final EnumMap<CatCVR, S57enum> Catcvr = new EnumMap<CatCVR, S57enum>(CatCVR.class); static { Catcvr.put(CatCVR.CVR_UNKN, new S57enum(0, ""));
+	Catcvr.put(CatCVR.CVR_COVR, new S57enum(1, "coverage")); Catcvr.put(CatCVR.CVR_NCVR, new S57enum(2, "no_coverage"));
+	}
+
+	private static final EnumMap<Att, S57key> keys = new EnumMap<Att, S57key>(Att.class);
+	static {
+		keys.put(Att.UNKATT, new S57key(Conv.A, null)); keys.put(Att.AGENCY, new S57key(Conv.A, null)); keys.put(Att.BCNSHP, new S57key(Conv.E, Bcnshp));
+		keys.put(Att.BUISHP, new S57key(Conv.E, Buishp)); keys.put(Att.BOYSHP, new S57key(Conv.E, Boyshp)); keys.put(Att.BURDEP, new S57key(Conv.F, null));
+		keys.put(Att.CALSGN, new S57key(Conv.S, null)); keys.put(Att.CATAIR, new S57key(Conv.L, Catair)); keys.put(Att.CATACH, new S57key(Conv.L, Catach));
+		keys.put(Att.CATBRG, new S57key(Conv.L, Catbrg)); keys.put(Att.CATBUA, new S57key(Conv.E, Catbua)); keys.put(Att.CATCBL, new S57key(Conv.E, Catcbl));
+		keys.put(Att.CATCAN, new S57key(Conv.E, Catcan)); keys.put(Att.CATCAM, new S57key(Conv.E, Catcam)); keys.put(Att.CATCHP, new S57key(Conv.E, Catchp));
+		keys.put(Att.CATCOA, new S57key(Conv.E, Catcoa)); keys.put(Att.CATCTR, new S57key(Conv.E, Catctr)); keys.put(Att.CATCON, new S57key(Conv.E, Catcon));
+		keys.put(Att.CATCRN, new S57key(Conv.E, Catcrn)); keys.put(Att.CATDAM, new S57key(Conv.E, Catdam));	keys.put(Att.CATDIS, new S57key(Conv.E, Catdis));
+		keys.put(Att.CATDOC, new S57key(Conv.E, Catdoc)); keys.put(Att.CATDPG, new S57key(Conv.L, Catdpg));	keys.put(Att.CATFNC, new S57key(Conv.E, Catfnc));
+		keys.put(Att.CATFRY, new S57key(Conv.E, Catfry)); keys.put(Att.CATFIF, new S57key(Conv.E, Catfif));	keys.put(Att.CATFOG, new S57key(Conv.E, Catfog));
+		keys.put(Att.CATFOR, new S57key(Conv.E, Catfor)); keys.put(Att.CATGAT, new S57key(Conv.E, Catgat));	keys.put(Att.CATHAF, new S57key(Conv.L, Cathaf));
+		keys.put(Att.CATHLK, new S57key(Conv.L, Cathlk)); keys.put(Att.CATICE, new S57key(Conv.E, Catice));	keys.put(Att.CATINB, new S57key(Conv.E, Catinb));
+		keys.put(Att.CATLND, new S57key(Conv.L, Catlnd)); keys.put(Att.CATLMK, new S57key(Conv.L, Catlmk));	keys.put(Att.CATLAM, new S57key(Conv.E, Catlam));
+		keys.put(Att.CATLIT, new S57key(Conv.L, Catlit)); keys.put(Att.CATMFA, new S57key(Conv.E, Catmfa));	keys.put(Att.CATMPA, new S57key(Conv.L, Catmpa));
+		keys.put(Att.CATMOR, new S57key(Conv.E, Catmor)); keys.put(Att.CATNAV, new S57key(Conv.E, Catnav));	keys.put(Att.CATOBS, new S57key(Conv.E, Catobs));
+		keys.put(Att.CATOFP, new S57key(Conv.L, Catofp)); keys.put(Att.CATOLB, new S57key(Conv.E, Catolb));	keys.put(Att.CATPLE, new S57key(Conv.E, Catple));
+		keys.put(Att.CATPIL, new S57key(Conv.E, Catpil)); keys.put(Att.CATPIP, new S57key(Conv.L, Catpip));	keys.put(Att.CATPRA, new S57key(Conv.E, Catpra));
+		keys.put(Att.CATPYL, new S57key(Conv.E, Catpyl)); keys.put(Att.CATRAS, new S57key(Conv.E, Catras)); keys.put(Att.CATRTB, new S57key(Conv.E, Catrtb));
+		keys.put(Att.CATROS, new S57key(Conv.L, Catros));	keys.put(Att.CATTRK, new S57key(Conv.E, Cattrk)); keys.put(Att.CATRSC, new S57key(Conv.L, Catrsc));
+		keys.put(Att.CATREA, new S57key(Conv.L, Catrea));	keys.put(Att.CATROD, new S57key(Conv.E, Catrod)); keys.put(Att.CATRUN, new S57key(Conv.E, Catrun));
+		keys.put(Att.CATSEA, new S57key(Conv.E, Catsea));	keys.put(Att.CATSIL, new S57key(Conv.E, Catsil)); keys.put(Att.CATSLO, new S57key(Conv.E, Catslo));
+		keys.put(Att.CATSCF, new S57key(Conv.L, Catscf));	keys.put(Att.CATSLC, new S57key(Conv.E, Catslc)); keys.put(Att.CATSIT, new S57key(Conv.L, Catsit));
+		keys.put(Att.CATSIW, new S57key(Conv.L, Catsiw));	keys.put(Att.CATSPM, new S57key(Conv.L, Catspm)); keys.put(Att.CATTSS, new S57key(Conv.E, Cattss));
+		keys.put(Att.CATVEG, new S57key(Conv.L, Catveg));	keys.put(Att.CATWAT, new S57key(Conv.E, Catwat)); keys.put(Att.CATWED, new S57key(Conv.E, Catwed));
+		keys.put(Att.CATWRK, new S57key(Conv.E, Catwrk));	keys.put(Att.COLOUR, new S57key(Conv.L, Colour));
+		keys.put(Att.COLPAT, new S57key(Conv.L, Colpat));	keys.put(Att.COMCHA, new S57key(Conv.A, null)); keys.put(Att.CPDATE, new S57key(Conv.A, null));
+		keys.put(Att.CSCALE, new S57key(Conv.I, null));	keys.put(Att.CONDTN, new S57key(Conv.E, Condtn)); keys.put(Att.CONRAD, new S57key(Conv.E, Conrad));
+		keys.put(Att.CONVIS, new S57key(Conv.E, Convis));	keys.put(Att.CURVEL, new S57key(Conv.F, null)); keys.put(Att.DATEND, new S57key(Conv.A, null));
+		keys.put(Att.DATSTA, new S57key(Conv.A, null));	keys.put(Att.DRVAL1, new S57key(Conv.F, null)); keys.put(Att.DRVAL2, new S57key(Conv.F, null));
+		keys.put(Att.DUNITS, new S57key(Conv.E, Dunits));	keys.put(Att.ELEVAT, new S57key(Conv.F, null)); keys.put(Att.ESTRNG, new S57key(Conv.F, null));
+		keys.put(Att.EXCLIT, new S57key(Conv.E, Exclit));	keys.put(Att.EXPSOU, new S57key(Conv.E, Expsou)); keys.put(Att.FUNCTN, new S57key(Conv.L, Functn));
+		keys.put(Att.HEIGHT, new S57key(Conv.F, null));	keys.put(Att.HUNITS, new S57key(Conv.E, Hunits)); keys.put(Att.HORACC, new S57key(Conv.F, null));
+		keys.put(Att.HORCLR, new S57key(Conv.F, null));	keys.put(Att.HORLEN, new S57key(Conv.F, null)); keys.put(Att.HORWID, new S57key(Conv.F, null));
+		keys.put(Att.ICEFAC, new S57key(Conv.F, null));	keys.put(Att.INFORM, new S57key(Conv.S, null)); keys.put(Att.JRSDTN, new S57key(Conv.E, Jrsdtn));
+		keys.put(Att.LIFCAP, new S57key(Conv.F, null));	keys.put(Att.LITCHR, new S57key(Conv.E, Litchr));	keys.put(Att.LITVIS, new S57key(Conv.L, Litvis));
+		keys.put(Att.MARSYS, new S57key(Conv.E, Marsys));	keys.put(Att.MLTYLT, new S57key(Conv.I, null));	keys.put(Att.NATION, new S57key(Conv.A, null));
+		keys.put(Att.NATCON, new S57key(Conv.L, Natcon));	keys.put(Att.NATSUR, new S57key(Conv.L, Natsur));	keys.put(Att.NATQUA, new S57key(Conv.L, Natqua));
+		keys.put(Att.NMDATE, new S57key(Conv.A, null));	keys.put(Att.OBJNAM, new S57key(Conv.S, null));	keys.put(Att.ORIENT, new S57key(Conv.F, null));
+		keys.put(Att.PEREND, new S57key(Conv.A, null));	keys.put(Att.PERSTA, new S57key(Conv.A, null));	keys.put(Att.PICREP, new S57key(Conv.S, null));
+		keys.put(Att.PILDST, new S57key(Conv.S, null));	keys.put(Att.PRCTRY, new S57key(Conv.A, null));	keys.put(Att.PRODCT, new S57key(Conv.L, Prodct));
+		keys.put(Att.PUBREF, new S57key(Conv.S, null));	keys.put(Att.QUASOU, new S57key(Conv.L, Quasou));	keys.put(Att.RADWAL, new S57key(Conv.A, null));
+		keys.put(Att.RADIUS, new S57key(Conv.F, null));	keys.put(Att.RECDAT, new S57key(Conv.A, null));	keys.put(Att.RECIND, new S57key(Conv.A, null));
+		keys.put(Att.RYRMGV, new S57key(Conv.A, null));	keys.put(Att.RESTRN, new S57key(Conv.L, Restrn));	keys.put(Att.SCAMAX, new S57key(Conv.I, null));
+		keys.put(Att.SCAMIN, new S57key(Conv.I, null));	keys.put(Att.SCVAL1, new S57key(Conv.I, null));	keys.put(Att.SCVAL2, new S57key(Conv.I, null));
+		keys.put(Att.SECTR1, new S57key(Conv.F, null));	keys.put(Att.SECTR2, new S57key(Conv.F, null));	keys.put(Att.SHIPAM, new S57key(Conv.A, null));
+		keys.put(Att.SIGFRQ, new S57key(Conv.I, null));	keys.put(Att.SIGGEN, new S57key(Conv.E, Siggen));	keys.put(Att.SIGGRP, new S57key(Conv.A, null));
+		keys.put(Att.SIGPER, new S57key(Conv.F, null));	keys.put(Att.SIGSEQ, new S57key(Conv.A, null));	keys.put(Att.SOUACC, new S57key(Conv.F, null));
+		keys.put(Att.SDISMX, new S57key(Conv.I, null));	keys.put(Att.SDISMN, new S57key(Conv.I, null));	keys.put(Att.SORDAT, new S57key(Conv.A, null));
+		keys.put(Att.SORIND, new S57key(Conv.A, null));	keys.put(Att.STATUS, new S57key(Conv.L, Status));	keys.put(Att.SURATH, new S57key(Conv.S, null));
+		keys.put(Att.SUREND, new S57key(Conv.A, null));	keys.put(Att.SURSTA, new S57key(Conv.A, null));	keys.put(Att.SURTYP, new S57key(Conv.L, Surtyp));
+		keys.put(Att.TECSOU, new S57key(Conv.L, Tecsou));	keys.put(Att.TXTDSC, new S57key(Conv.S, null));	keys.put(Att.TS_TSP, new S57key(Conv.A, null));
+		keys.put(Att.TS_TSV, new S57key(Conv.A, null));	keys.put(Att.T_ACWL, new S57key(Conv.E, null));	keys.put(Att.T_HWLW, new S57key(Conv.A, null));
+		keys.put(Att.T_MTOD, new S57key(Conv.E, null));	keys.put(Att.T_THDF, new S57key(Conv.A, null));	keys.put(Att.T_TINT, new S57key(Conv.I, null));
+		keys.put(Att.T_TSVL, new S57key(Conv.A, null));	keys.put(Att.T_VAHC, new S57key(Conv.A, null));	keys.put(Att.TIMEND, new S57key(Conv.A, null));
+		keys.put(Att.TIMSTA, new S57key(Conv.A, null));	keys.put(Att.TOPSHP, new S57key(Conv.E, Topshp)); keys.put(Att.TRAFIC, new S57key(Conv.E, Trafic));
+		keys.put(Att.VALACM, new S57key(Conv.F, null));	keys.put(Att.VALDCO, new S57key(Conv.F, null)); keys.put(Att.VALLMA, new S57key(Conv.F, null));
+		keys.put(Att.VALMAG, new S57key(Conv.F, null));	keys.put(Att.VALMXR, new S57key(Conv.F, null)); keys.put(Att.VALNMR, new S57key(Conv.F, null));
+		keys.put(Att.VALSOU, new S57key(Conv.F, null));	keys.put(Att.VERACC, new S57key(Conv.F, null)); keys.put(Att.VERCLR, new S57key(Conv.F, null));
+		keys.put(Att.VERCCL, new S57key(Conv.F, null));	keys.put(Att.VERCOP, new S57key(Conv.F, null)); keys.put(Att.VERCSA, new S57key(Conv.F, null));
+		keys.put(Att.VERDAT, new S57key(Conv.E, Verdat));	keys.put(Att.VERLEN, new S57key(Conv.F, null)); keys.put(Att.WATLEV, new S57key(Conv.E, Watlev));
+		keys.put(Att.CAT_TS, new S57key(Conv.E, Cat_ts));	keys.put(Att.PUNITS, new S57key(Conv.E, Punits)); keys.put(Att.NINFOM, new S57key(Conv.S, null));
+		keys.put(Att.NOBJNM, new S57key(Conv.S, null));	keys.put(Att.NPLDST, new S57key(Conv.S, null)); keys.put(Att.NTXTDS, new S57key(Conv.S, null));
+		keys.put(Att.HORDAT, new S57key(Conv.E, null));	keys.put(Att.POSACC, new S57key(Conv.F, null)); keys.put(Att.QUAPOS, new S57key(Conv.E, Quapos));
+		keys.put(Att.CLSDNG, new S57key(Conv.E, Clsdng));	keys.put(Att.DIRIMP, new S57key(Conv.L, Dirimp)); keys.put(Att.DISBK1, new S57key(Conv.F, null));
+		keys.put(Att.DISBK2, new S57key(Conv.F, null));	keys.put(Att.DISIPU, new S57key(Conv.F, null)); keys.put(Att.DISIPD, new S57key(Conv.F, null));
+		keys.put(Att.ELEVA1, new S57key(Conv.F, null));	keys.put(Att.ELEVA2, new S57key(Conv.F, null)); keys.put(Att.FNCTNM, new S57key(Conv.E, Fnctnm));
+		keys.put(Att.WTWDIS, new S57key(Conv.F, null));	keys.put(Att.BUNVES, new S57key(Conv.E, Bunves)); keys.put(Att.COMCTN, new S57key(Conv.S, null));
+		keys.put(Att.HORCLL, new S57key(Conv.F, null));	keys.put(Att.HORCLW, new S57key(Conv.F, null)); keys.put(Att.TRSHGD, new S57key(Conv.L, Trshgd));
+		keys.put(Att.UNLOCD, new S57key(Conv.S, null));	keys.put(Att.HIGWAT, new S57key(Conv.F, null)); keys.put(Att.HIGNAM, new S57key(Conv.S, null));
+		keys.put(Att.LOWWAT, new S57key(Conv.F, null));	keys.put(Att.LOWNAM, new S57key(Conv.S, null)); keys.put(Att.MEAWAT, new S57key(Conv.F, null));
+		keys.put(Att.MEANAM, new S57key(Conv.S, null));	keys.put(Att.OTHWAT, new S57key(Conv.F, null)); keys.put(Att.OTHNAM, new S57key(Conv.S, null));
+		keys.put(Att.REFLEV, new S57key(Conv.E, Reflev));	keys.put(Att.SDRLEV, new S57key(Conv.S, null)); keys.put(Att.VCRLEV, new S57key(Conv.S, null));
+		keys.put(Att.SCHREF, new S57key(Conv.S, null));	keys.put(Att.USESHP, new S57key(Conv.E, Useshp)); keys.put(Att.CURVHW, new S57key(Conv.F, null));
+		keys.put(Att.CURVLW, new S57key(Conv.F, null));	keys.put(Att.CURVMW, new S57key(Conv.F, null)); keys.put(Att.CURVOW, new S57key(Conv.F, null));
+		keys.put(Att.APTREF, new S57key(Conv.S, null));	keys.put(Att.SHPTYP, new S57key(Conv.E, Shptyp)); keys.put(Att.UPDMSG, new S57key(Conv.S, null));
+		keys.put(Att.ADDMRK, new S57key(Conv.L, Addmrk));	keys.put(Att.BNKWTW, new S57key(Conv.E, Bnkwtw)); keys.put(Att.CATBNK, new S57key(Conv.E, Catbnk));
+		keys.put(Att.CATNMK, new S57key(Conv.E, Catnmk));	keys.put(Att.CATBRT, new S57key(Conv.L, Catbrt)); keys.put(Att.CATBUN, new S57key(Conv.L, Catbun));
+		keys.put(Att.CATCCL, new S57key(Conv.L, Catccl));	keys.put(Att.CATCOM, new S57key(Conv.L, Catcom)); keys.put(Att.CATHBR, new S57key(Conv.L, Cathbr));
+		keys.put(Att.CATRFD, new S57key(Conv.L, Catrfd));	keys.put(Att.CATTML, new S57key(Conv.L, Cattml)); keys.put(Att.CATGAG, new S57key(Conv.L, Catgag));
+		keys.put(Att.CATVTR, new S57key(Conv.L, Catvtr));	keys.put(Att.CATTAB, new S57key(Conv.E, Cattab)); keys.put(Att.CATEXS, new S57key(Conv.E, Catexs));
+		keys.put(Att.CATWWM, new S57key(Conv.E, Catwwm));	keys.put(Att.LG_SPD, new S57key(Conv.F, null)); keys.put(Att.LG_SPR, new S57key(Conv.L, Lg_spr));
+		keys.put(Att.LG_BME, new S57key(Conv.F, null));	keys.put(Att.LG_LGS, new S57key(Conv.F, null)); keys.put(Att.LG_DRT, new S57key(Conv.F, null));
+		keys.put(Att.LG_WDP, new S57key(Conv.F, null));	keys.put(Att.LG_WDU, new S57key(Conv.E, Lg_wdu)); keys.put(Att.LG_REL, new S57key(Conv.L, Lg_rel));
+		keys.put(Att.LG_FNC, new S57key(Conv.L, Lg_fnc));	keys.put(Att.LG_DES, new S57key(Conv.S, null)); keys.put(Att.LG_PBR, new S57key(Conv.S, null));
+		keys.put(Att.LC_CSI, new S57key(Conv.L, Lc_csi));	keys.put(Att.LC_CSE, new S57key(Conv.L, Lc_cse)); keys.put(Att.LC_ASI, new S57key(Conv.L, Lc_asi));
+		keys.put(Att.LC_ASE, new S57key(Conv.L, Lc_ase));	keys.put(Att.LC_CCI, new S57key(Conv.L, Lc_cci)); keys.put(Att.LC_CCE, new S57key(Conv.L, Lc_cce));
+		keys.put(Att.LC_BM1, new S57key(Conv.F, null));	keys.put(Att.LC_BM2, new S57key(Conv.F, null)); keys.put(Att.LC_LG1, new S57key(Conv.F, null));
+		keys.put(Att.LC_LG2, new S57key(Conv.F, null));	keys.put(Att.LC_DR1, new S57key(Conv.F, null)); keys.put(Att.LC_DR2, new S57key(Conv.F, null));
+		keys.put(Att.LC_SP1, new S57key(Conv.F, null));	keys.put(Att.LC_SP2, new S57key(Conv.F, null)); keys.put(Att.LC_WD1, new S57key(Conv.F, null));
+		keys.put(Att.LC_WD2, new S57key(Conv.F, null));	keys.put(Att.LITRAD, new S57key(Conv.A, null));	keys.put(Att.CATCVR, new S57key(Conv.E, Catcvr));
+	}
+	
+	public static Enum<?> s57Enum(String val, Att att) { // Convert S57 attribute value string to OSeaM enumeration
+		EnumMap<?, ?> map = keys.get(att).map;
+		Enum<?> unkn = null;
+		int i = 0;
+		try {
+			i = Integer.parseInt(val);
+		} catch (Exception e) {
+			return unkn;
+		}
+		if (map != null) {
+			for (Object item : map.keySet()) {
+				if (unkn == null)
+					unkn = (Enum<?>) item;
+				if (((S57enum) map.get(item)).atvl.equals(i))
+					return (Enum<?>) item;
+			}
+		}
+		return unkn;
+	}
+
+	public static AttVal<?> decodeValue(String val, Att att) {          // Convert S57 attribute value string to OSeaM attribute value
+		Conv conv = keys.get(att).conv;
+		switch (conv) {
+		case A:
+		case S:
+			return new AttVal<String>(att, conv, val);
+		case E:
+			return new AttVal<Enum<?>>(att, Conv.E, s57Enum(val, att));
+		case L:
+			ArrayList<Enum<?>> list = new ArrayList<Enum<?>>();
+			for (String item : val.split(",")) {
+				list.add(s57Enum(item, att));
+			}
+			return new AttVal<ArrayList<?>>(att, Conv.L, list);
+		case I:
+			try {
+				return new AttVal<Long>(att, Conv.I, Long.parseLong(val));
+			} catch (Exception e) {
+				break;
+			}
+		case F:
+			try {
+				return new AttVal<Double>(att, Conv.F, Double.parseDouble(val));
+			} catch (Exception e) {
+				break;
+			}
+		}
+		return null;
+	}
+
+	public static Integer encodeValue(String val, Att att) {        // Convert OSeaM attribute value string to S57 attribute value
+		EnumMap<?, ?> map = keys.get(att).map;
+		for (Object item : map.keySet()) {
+			if (((S57enum)map.get(item)).val.equals(val))
+				return ((S57enum)map.get(item)).atvl;
+		}
+		return 0;
+	}
+
+	
+	public static String stringValue(AttVal<?> attval) {                  // Convert OSeaM value object to OSeaM attribute value string
+		if (attval != null) {
+			switch (attval.conv) {
+			case A:
+			case S:
+				return (String) attval.val;
+			case E:
+				EnumMap<?, ?> map = keys.get(attval.att).map;
+				return ((S57enum) map.get(attval.val)).val;
+			case L:
+				String str = "";
+				map = keys.get(attval.att).map;
+				for (Object item : (ArrayList<?>) attval.val) {
+					if (!str.isEmpty())
+						str += ";";
+					str += ((S57enum) map.get(item)).val;
+				}
+				return str;
+			case I:
+				return ((Long) attval.val).toString();
+			case F:
+				return ((Double) attval.val).toString();
+			}
+		}
+		return "";
+	}
+
+	public static Enum<?> osmEnum(String val, Att att) { // Convert OSeaM attribute value string to OSeaM enumeration
+		EnumMap<?, ?> map = keys.get(att).map;
+		Enum<?> unkn = null;
+		if (map != null) {
+			for (Object item : map.keySet()) {
+				if (unkn == null)
+					unkn = (Enum<?>) item;
+				if (((S57enum) map.get(item)).val.equals(val))
+					return (Enum<?>) item;
+			}
+		}
+		return unkn;
+	}
+
+	public static AttVal<?> convertValue(String val, Att att) { 				// Convert OSeaM attribute value string to OSeaM value object
+		switch (keys.get(att).conv) {
+		case A:
+		case S:
+			return new AttVal<String>(att, Conv.S, val);
+		case E:
+			return new AttVal<Enum<?>>(att, Conv.E, osmEnum(val, att));
+		case L:
+			ArrayList<Enum<?>> list = new ArrayList<Enum<?>>();
+			for (String item : val.split(";")) {
+				list.add(osmEnum(item, att));
+			}
+			return new AttVal<ArrayList<?>>(att, Conv.L, list);
+		case I:
+			try {
+				return new AttVal<Long>(att, Conv.I, Long.parseLong(val));
+			} catch (Exception e) {
+				break;
+			}
+		case F:
+			try {
+				return new AttVal<Double>(att, Conv.F, Double.parseDouble(val));
+			} catch (Exception e) {
+				break;
+			}
+		}
+		return new AttVal<Object>(att, keys.get(att).conv, null);
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/src/seachart/ChartImage.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/seachart/ChartImage.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/seachart/ChartImage.java	(revision 30894)
@@ -0,0 +1,96 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package seachart;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Point2D;
+import java.awt.geom.Point2D.Double;
+
+import javax.swing.Action;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.imagery.ImageryInfo;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener;
+import org.openstreetmap.josm.gui.layer.ImageryLayer;
+
+import render.ChartContext;
+import render.Renderer;
+import s57.S57map.*;
+
+public class ChartImage extends ImageryLayer implements ZoomChangeListener, ChartContext {
+
+	double top;
+	double bottom;
+	double left;
+	double right;
+	double width;
+	double height;
+	int zoom;
+	
+	public ChartImage(ImageryInfo info) {
+		super(info);
+		MapView.addZoomChangeListener(this);
+		zoomChanged();
+	}
+	
+	@Override
+	public Action[] getMenuEntries() {
+		return null;
+	}
+
+	@Override
+	public String getToolTipText() {
+		return null;
+	}
+
+	@Override
+	public void visitBoundingBox(BoundingXYVisitor arg0) {
+	}
+
+	@Override
+	public void paint(Graphics2D g2, MapView mv, Bounds bb) {
+		Rectangle rect = Main.map.mapView.getBounds();
+		g2.setBackground(new Color(0xb5d0d0));
+		g2.clearRect(rect.x, rect.y, rect.width, rect.height);
+		g2.setPaint(Color.black);
+		g2.setFont(new Font("Arial", Font.BOLD, 20));
+		g2.drawString(("Z" + zoom), (rect.x + rect.width - 40), (rect.y + rect.height - 10));
+		Renderer.reRender(g2, zoom, Math.pow(2, (zoom-12)), SeachartAction.map, this);
+	}
+
+	@Override
+	public void zoomChanged() {
+		if ((Main.map != null) && (Main.map.mapView != null)) {
+			Bounds bounds = Main.map.mapView.getRealBounds();
+			top = bounds.getMax().lat();
+			bottom = bounds.getMin().lat();
+			left = bounds.getMin().lon();
+			right = bounds.getMax().lon();
+			width = Main.map.mapView.getBounds().getWidth();
+			height = Main.map.mapView.getBounds().getHeight();
+			zoom = ((int) Math.min(18, Math.max(9, Math.round(Math.floor(Math.log(1024 / bounds.asRect().height) / Math.log(2))))));
+		}
+	}
+
+	public Point2D.Double getPoint(Snode coord) {
+		return (Double) Main.map.mapView.getPoint2D(new LatLon(Math.toDegrees(coord.lat), Math.toDegrees(coord.lon)));
+	}
+
+	public double mile(Feature feature) {
+		return 185000 / Main.map.mapView.getDist100Pixel();
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/seachart/Seachart.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/seachart/Seachart.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/seachart/Seachart.java	(revision 30894)
@@ -0,0 +1,23 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package seachart;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MainMenu;
+import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
+
+public class Seachart extends Plugin {
+
+	public Seachart(PluginInformation info) {
+        super(info);
+        MainMenu.add(Main.main.menu.imageryMenu, new SeachartAction());
+    }
+}
Index: /applications/editors/josm/plugins/seachart/src/seachart/SeachartAction.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/seachart/SeachartAction.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/seachart/SeachartAction.java	(revision 30894)
@@ -0,0 +1,182 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package seachart;
+
+import java.awt.event.*;
+import javax.swing.*;
+
+import java.util.Map.Entry;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
+import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.layer.*;
+import org.openstreetmap.josm.data.imagery.ImageryInfo;
+import org.openstreetmap.josm.data.osm.*;
+import org.openstreetmap.josm.data.osm.event.*;
+import org.openstreetmap.josm.Main;
+
+import s57.S57map;
+
+public class SeachartAction extends JosmAction implements EditLayerChangeListener, LayerChangeListener {
+	private static String title = "SeaChart";
+	private boolean isOpen = false;
+	public static ChartImage rendering;
+	public static S57map map = null;
+	public DataSet data = null;
+
+	private final DataSetListener dataSetListener = new DataSetListener() {
+
+		@Override
+		public void dataChanged(DataChangedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void nodeMoved(NodeMovedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void otherDatasetChange(AbstractDatasetChangedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void primitivesAdded(PrimitivesAddedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void primitivesRemoved(PrimitivesRemovedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void relationMembersChanged(RelationMembersChangedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void tagsChanged(TagsChangedEvent e) {
+			makeChart();
+		}
+
+		@Override
+		public void wayNodesChanged(WayNodesChangedEvent e) {
+			makeChart();
+		}
+	};
+
+	public SeachartAction() {
+		super(title, "SC", title, null, true);
+	}
+
+	@Override
+	public void activeLayerChange(Layer arg0, Layer arg1) {
+	}
+
+	@Override
+	public void layerAdded(Layer arg0) {
+	}
+
+	@Override
+	public void layerRemoved(Layer arg0) {
+		if (arg0.getName().equals("SeaChart")) {
+			closeChartLayer();
+		}
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				if (!isOpen)
+					createChartLayer();
+				isOpen = true;
+			}
+		});
+	}
+
+	protected void createChartLayer() {
+		// System.out.println("hello");
+		rendering = new ChartImage(new ImageryInfo("SeaChart"));
+		rendering.setBackgroundLayer(true);
+		Main.main.addLayer(rendering);
+		MapView.addEditLayerChangeListener(this);
+		MapView.addLayerChangeListener(this);
+		editLayerChanged(Main.main.getEditLayer(), Main.main.getEditLayer());
+	}
+
+	public void closeChartLayer() {
+		if (isOpen) {
+			MapView.removeEditLayerChangeListener(this);
+			MapView.removeLayerChangeListener(this);
+			Main.main.removeLayer(rendering);
+		}
+		isOpen = false;
+	}
+
+	@Override
+	public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+		if (oldLayer != null) {
+			oldLayer.data.removeDataSetListener(dataSetListener);
+		}
+		if (newLayer != null) {
+			newLayer.data.addDataSetListener(dataSetListener);
+			data = newLayer.data;
+			makeChart();
+		} else {
+			data = null;
+			map = null;
+		}
+	}
+
+	void makeChart() {
+		map = new S57map();
+		if (data != null) {
+			for (Node node : data.getNodes()) {
+				map.addNode(node.getUniqueId(), node.getCoor().lat(), node.getCoor().lon());
+				for (Entry<String, String> entry : node.getKeys().entrySet()) {
+					map.addTag(entry.getKey(), entry.getValue());
+				}
+				map.tagsDone(node.getUniqueId());
+			}
+			for (Way way : data.getWays()) {
+				if (way.getNodesCount() > 0) {
+					map.addEdge(way.getUniqueId());
+					for (Node node : way.getNodes()) {
+						map.addToEdge((node.getUniqueId()));
+					}
+					for (Entry<String, String> entry : way.getKeys().entrySet()) {
+						map.addTag(entry.getKey(), entry.getValue());
+					}
+					map.tagsDone(way.getUniqueId());
+				}
+			}
+			for (Relation rel : data.getRelations()) {
+				if (rel.isMultipolygon() && (rel.getMembersCount() > 0)) {
+					map.addArea(rel.getUniqueId());
+					for (RelationMember mem : rel.getMembers()) {
+						if (mem.getType() == OsmPrimitiveType.WAY)
+							map.addToArea(mem.getUniqueId(), (mem.getRole().equals("outer")));
+					}
+					for (Entry<String, String> entry : rel.getKeys().entrySet()) {
+						map.addTag(entry.getKey(), entry.getValue());
+					}
+					map.tagsDone(rel.getUniqueId());
+				}
+			}
+			if (rendering != null) rendering.zoomChanged();
+		}
+	}
+
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Areas.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Areas.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Areas.java	(revision 30894)
@@ -0,0 +1,206 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+
+import symbols.Symbols.*;
+
+public class Areas {
+	public static final Symbol Plane = new Symbol();
+	static {
+		Plane.add(new Instr(Form.BBOX, new Rectangle2D.Double(-60,-60,120,120)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(40,20); p.lineTo(50,10); p.lineTo(27.0,13.3); p.lineTo(23.7,6.8); p.lineTo(40.0,5.0); p.curveTo(55,4,55,-9,40,-10);
+		p.quadTo(31,-11,30,-15); p.lineTo(-30,2); p.quadTo(-35,-12,-45,-15); p.quadTo(-56,-3,-50,15); p.lineTo(18.4,7.3); p.lineTo(21.7,14); p.lineTo(-20,20); p.closePath();
+		Plane.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Cable = new Symbol();
+	static {
+		Cable.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,60)));
+		Cable.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Cable.add(new Instr(Form.FILL, new Color(0xc480ff)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0,0); p.curveTo(-13,-13,-13,-17,0,-30); p.curveTo(13,-43,13,-47,0,-60);
+		Cable.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol CableDot = new Symbol();
+	static {
+		CableDot.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,60)));
+		CableDot.add(new Instr(Form.RSHP, new Ellipse2D.Double(-10,-40,20,20)));
+	}
+	public static final Symbol CableDash = new Symbol();
+	static {
+		CableDash.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,60)));
+		CableDash.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		CableDash.add(new Instr(Form.LINE, new Line2D.Double(0,-15,0,-45)));
+	}
+	public static final Symbol CableFlash = new Symbol();
+	static {
+		CableFlash.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,60)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-30,-25); p.lineTo(-10,-40); p.lineTo(10,-26); p.lineTo(30,-35); p.lineTo(10,-20); p.lineTo(-10,-34); p.closePath();
+		CableFlash.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol LaneArrow = new Symbol();
+	static {
+		LaneArrow.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-240,40,240)));
+		LaneArrow.add(new Instr(Form.STRK, new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		LaneArrow.add(new Instr(Form.FILL, new Color(0x80c480ff, true)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(15,0); p.lineTo(15,-195); p.lineTo(40,-195);
+		p.lineTo(0,-240); p.lineTo(-40,-195); p.lineTo(-15,-195); p.lineTo(-15,0); p.closePath();
+		LaneArrow.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol LineAnchor = new Symbol();
+	static {
+		LineAnchor.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,90)));
+		LineAnchor.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 0.5, 0, 0, null, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(-90.0))))));
+	}
+	public static final Symbol LinePlane = new Symbol();
+	static {
+		LinePlane.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-60,60,90)));
+		LinePlane.add(new Instr(Form.FILL, new Color(0xc480ff)));
+		LinePlane.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.Plane, 0.5, 0, 0, null, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(-90.0))))));
+	}
+	public static final Symbol MarineFarm = new Symbol();
+	static {
+		MarineFarm.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-23,12); p.lineTo(-23,23); p.lineTo(23,23); p.lineTo(23,12); p.moveTo(-8,15); p.lineTo(-8,23); p.moveTo(8,15); p.lineTo(8,23);
+		p.moveTo(-23,-12); p.lineTo(-23,-23); p.lineTo(23,-23); p.lineTo(23,-12); p.moveTo(-8,-15); p.lineTo(-8,-23); p.moveTo(8,-15); p.lineTo(8,-23);
+		p.moveTo(-21,8); p.quadTo(-1,-14,21,0); p.quadTo(-1,14,-21,-8); p.moveTo(7,6); p.quadTo(2,0,7,-6);
+		MarineFarm.add(new Instr(Form.PLIN, p));
+		MarineFarm.add(new Instr(Form.RSHP, new Ellipse2D.Double(9,-2,4,4)));
+	}
+	public static final Symbol NoWake = new Symbol();
+	static {
+		NoWake.add(new Instr(Form.STRK, new BasicStroke(12, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoWake.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-60,20); p.curveTo(-28,20,-32,0,0,0); p.curveTo(32,0,28,20,60,20); p.moveTo(-60,0); p.curveTo(-28,0,-32,-20,0,-20); p.curveTo(32,-20,28,0,60,0);
+		NoWake.add(new Instr(Form.PLIN, p));
+		NoWake.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoWake.add(new Instr(Form.LINE, new Line2D.Double(-60,60,60,-60)));
+		NoWake.add(new Instr(Form.LINE, new Line2D.Double(-60,-60,60,60)));
+	}
+	public static final Symbol Pipeline = new Symbol();
+	static {
+		Pipeline.add(new Instr(Form.BBOX, new Rectangle2D.Double(-15,-60,30,60)));
+		Pipeline.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Pipeline.add(new Instr(Form.FILL, new Color(0xc480ff)));
+		Pipeline.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-50)));
+		Pipeline.add(new Instr(Form.RSHP, new Ellipse2D.Double(-10,-60,20,20)));
+	}
+	public static final Symbol Restricted = new Symbol();
+	static {
+		Restricted.add(new Instr(Form.BBOX, new Rectangle2D.Double(-15,-30,30,30)));
+		Restricted.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Restricted.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-30)));
+		Restricted.add(new Instr(Form.LINE, new Line2D.Double(0,-15,17,-15)));
+	}
+	public static final Symbol Rock = new Symbol();
+	static {
+		Rock.add(new Instr(Form.FILL, new Color(0x80c0ff)));
+		Rock.add(new Instr(Form.RSHP, new Ellipse2D.Double(-30,-30,60,60)));
+		Rock.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{5,5}, 0)));
+		Rock.add(new Instr(Form.FILL, Color.black));
+		Rock.add(new Instr(Form.ELPS, new Ellipse2D.Double(-30,-30,60,60)));
+		Rock.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Rock.add(new Instr(Form.LINE, new Line2D.Double(-20,0,20,0)));
+		Rock.add(new Instr(Form.LINE, new Line2D.Double(0,-20,0,20)));
+	}
+	public static final Symbol RockA = new Symbol();
+	static {
+		RockA.add(new Instr(Form.FILL, new Color(0x80c0ff)));
+		RockA.add(new Instr(Form.RSHP, new Ellipse2D.Double(-30,-30,60,60)));
+		RockA.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{5,5}, 0)));
+		RockA.add(new Instr(Form.FILL, Color.black));
+		RockA.add(new Instr(Form.ELPS, new Ellipse2D.Double(-30,-30,60,60)));
+		RockA.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		RockA.add(new Instr(Form.LINE, new Line2D.Double(-20,0,20,0)));
+		RockA.add(new Instr(Form.LINE, new Line2D.Double(0,-20,0,20)));
+		RockA.add(new Instr(Form.RSHP, new Ellipse2D.Double(-17,-17,8,8)));
+		RockA.add(new Instr(Form.RSHP, new Ellipse2D.Double(-17,9,8,8)));
+		RockA.add(new Instr(Form.RSHP, new Ellipse2D.Double(9,-17,8,8)));
+		RockA.add(new Instr(Form.RSHP, new Ellipse2D.Double(9,9,8,8)));
+	}
+	public static final Symbol RockC = new Symbol();
+	static {
+		RockC.add(new Instr(Form.FILL, new Color(0x80c0ff)));
+		RockC.add(new Instr(Form.RSHP, new Ellipse2D.Double(-30,-30,60,60)));
+		RockC.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{5,5}, 0)));
+		RockC.add(new Instr(Form.FILL, Color.black));
+		RockC.add(new Instr(Form.ELPS, new Ellipse2D.Double(-30,-30,60,60)));
+		RockC.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		RockC.add(new Instr(Form.LINE, new Line2D.Double(-20,0,20,0)));
+		RockC.add(new Instr(Form.LINE, new Line2D.Double(-10,17.3,10,-17.3)));
+		RockC.add(new Instr(Form.LINE, new Line2D.Double(10,17.3,-10,-17.3)));
+	}
+	public static final Symbol Seaplane = new Symbol();
+	static {
+		Seaplane.add(new Instr(Form.BBOX, new Rectangle2D.Double(-60,-60,120,120)));
+		Seaplane.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Seaplane.add(new Instr(Form.ELPS, new Ellipse2D.Double(-58,-58,116,116)));
+		Seaplane.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Areas.Plane, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol WindFarm = new Symbol();
+	static {
+		WindFarm.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		WindFarm.add(new Instr(Form.ELPS, new Ellipse2D.Double(-100,-100,200,200)));
+		WindFarm.add(new Instr(Form.LINE, new Line2D.Double(-35,50,35,50)));
+		WindFarm.add(new Instr(Form.LINE, new Line2D.Double(0,50,0,-27.5)));
+		WindFarm.add(new Instr(Form.LINE, new Line2D.Double(0,-27.5,30,-27.5)));
+		WindFarm.add(new Instr(Form.LINE, new Line2D.Double(0,-27.5,-13.8,-3.8)));
+		WindFarm.add(new Instr(Form.LINE, new Line2D.Double(0,-27.5,-13.8,-53.6)));
+	}
+	public static final Symbol WreckD = new Symbol();
+	static {
+		WreckD.add(new Instr(Form.FILL, new Color(0x80c0ff)));
+		WreckD.add(new Instr(Form.RSHP, new Ellipse2D.Double(-50,-40,100,80)));
+		WreckD.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{5,5}, 0)));
+		WreckD.add(new Instr(Form.FILL, Color.black));
+		WreckD.add(new Instr(Form.ELPS, new Ellipse2D.Double(-50,-40,100,80)));
+		WreckD.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		WreckD.add(new Instr(Form.LINE, new Line2D.Double(-40,0,40,0)));
+		WreckD.add(new Instr(Form.LINE, new Line2D.Double(0,-30,0,30)));
+		WreckD.add(new Instr(Form.LINE, new Line2D.Double(-20,-15,-20,15)));
+		WreckD.add(new Instr(Form.LINE, new Line2D.Double(20,-15,20,15)));
+	}
+	public static final Symbol WreckND = new Symbol();
+	static {
+		WreckND.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		WreckND.add(new Instr(Form.LINE, new Line2D.Double(-40,0,40,0)));
+		WreckND.add(new Instr(Form.LINE, new Line2D.Double(0,-30,0,30)));
+		WreckND.add(new Instr(Form.LINE, new Line2D.Double(-20,-15,-20,15)));
+		WreckND.add(new Instr(Form.LINE, new Line2D.Double(20,-15,20,15)));
+	}
+	public static final Symbol WreckS = new Symbol();
+	static {
+		WreckS.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		WreckS.add(new Instr(Form.ELPS, new Ellipse2D.Double(-6,-6,12,12)));
+		WreckS.add(new Instr(Form.LINE, new Line2D.Double(-40,0,-6,0)));
+		WreckS.add(new Instr(Form.LINE, new Line2D.Double(40,0,6,0)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-30,0); p.lineTo(-40,-25); p.lineTo(-0.3,-12.6); p.lineTo(13.7,-37.7); p.lineTo(16.3,-36.3);
+		p.lineTo(2.7,-11.6); p.lineTo(37.5,0); p.lineTo(6,0); p.curveTo(5.6,-8,-5.6,-8,-6,0); p.closePath();
+		WreckS.add(new Instr(Form.PGON, p));
+	}
+	public static final BufferedImage Sandwaves = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+	static {
+		Graphics2D g2 = Sandwaves.createGraphics();
+		g2.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+		g2.setBackground(new Color(0, true));
+		g2.clearRect(0,  0, 100, 100);
+		g2.setPaint(new Color(0xffd400));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,34.5); p.lineTo(03.3,30.8); p.lineTo(09.9,19.3); p.lineTo(13.2,16.0); p.lineTo(16.5,16.1); p.lineTo(18.2,19.5);
+		p.lineTo(19.9,25.0); p.lineTo(21.6,30.3); p.lineTo(23.3,33.4); p.lineTo(25.0,33.3); p.lineTo(28.3,30.1); p.lineTo(31.6,25.0); p.lineTo(34.9,20.1); p.lineTo(38.2,17.2);
+		p.lineTo(41.5,17.3); p.lineTo(43.2,20.3); p.lineTo(44.9,25); p.lineTo(46.6,29.6); p.lineTo(48.3,32.2); p.lineTo(50.0,32.1);
+		p.moveTo(50.0,84.5); p.lineTo(53.3,80.8); p.lineTo(56.6,75.0); p.lineTo(59.9,69.3); p.lineTo(63.2,66.0); p.lineTo(66.5,66.1); p.lineTo(68.2,69.5); p.lineTo(69.9,75.0);
+		p.lineTo(71.6,80.3); p.lineTo(73.3,83.4); p.lineTo(75.0,83.3); p.lineTo(78.3,80.1); p.lineTo(81.6,75.0); p.lineTo(84.9,70.1); p.lineTo(88.2,67.2); p.lineTo(91.5,67.3);
+		p.lineTo(93.2,70.3); p.lineTo(94.9,75.0); p.lineTo(96.6,79.6); p.lineTo(98.3,82.2); p.lineTo(100.0,82.1);
+		g2.draw(p);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Beacons.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Beacons.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Beacons.java	(revision 30894)
@@ -0,0 +1,191 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.*;
+import java.util.EnumMap;
+
+import symbols.Symbols.*;
+import s57.S57val.*;
+
+public class Beacons {
+	
+	public static final Symbol Beacon = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-6.0,-8.5); p.lineTo(-6.0,-70.0); p.lineTo(6.0,-70.0); p.lineTo(6.0,-8.5); p.curveTo(6.0,-10.0,-6.0,-10.0,-6.0,-8.5); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-6.0,-8.5); p.lineTo(-6.0,-40.0); p.lineTo(6.0,-40.0); p.lineTo(6.0,-8.5); p.curveTo(6.0,-10.0,-6.0,-10.0,-6.0,-8.5); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-6.0,-30.0); p.lineTo(-6.0,-50.0); p.lineTo(6.0,-50.0); p.lineTo(6.0,-30.0); p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-6.0,-40.0); p.lineTo(-6.0,-55.0); p.lineTo(6.0,-55.0); p.lineTo(6.0,-40.0); p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-6.0,-25.0); p.lineTo(-6.0,-40.0); p.lineTo(6.0,-40.0); p.lineTo(6.0,-25.0); p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-70.0); p.lineTo(6.0,-70.0); p.lineTo(6.0,-8.5); p.quadTo(3.0,-9.3,0.0,-10.0); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+    Beacon.add(new Instr(Form.COLR, colours));
+    Beacon.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    Beacon.add(new Instr(Form.FILL, Color.black));
+    Beacon.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    Beacon.add(new Instr(Form.LINE, new Line2D.Double(-20,0,-10,0)));
+    Beacon.add(new Instr(Form.LINE, new Line2D.Double(10,0,20,0)));
+		p = new Path2D.Double(); p.moveTo(-6.0,-8.5); p.lineTo(-6.0,-70.0); p.lineTo(6.0,-70.0); p.lineTo(6.0,-8.5);
+		Beacon.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Cairn = new Symbol();
+	static {
+		Cairn.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Cairn.add(new Instr(Form.FILL, Color.black));
+		Cairn.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Cairn.add(new Instr(Form.LINE, new Line2D.Double(-40,0,-10,0)));
+		Cairn.add(new Instr(Form.LINE, new Line2D.Double(10,0,40,0)));
+		Cairn.add(new Instr(Form.ELPS, new Ellipse2D.Double(3,-40,40,40)));
+		Cairn.add(new Instr(Form.ELPS, new Ellipse2D.Double(-43,-40,40,40)));
+		Cairn.add(new Instr(Form.ELPS, new Ellipse2D.Double(-18,-70,36,36)));
+	}
+	public static final Symbol FogSignal = new Symbol();
+	static {
+		FogSignal.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		FogSignal.add(new Instr(Form.FILL, Color.black));
+		FogSignal.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		FogSignal.add(new Instr(Form.STRK, new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		FogSignal.add(new Instr(Form.FILL, new Color(0xd400d4)));
+		FogSignal.add(new Instr(Form.EARC, new Arc2D.Double(-120.0,-120.0,240.0,240.0,190.0,50.0,Arc2D.OPEN)));
+		FogSignal.add(new Instr(Form.EARC, new Arc2D.Double(-92.5,-92.5,185.0,185.0,190.0,50.0,Arc2D.OPEN)));
+		FogSignal.add(new Instr(Form.EARC, new Arc2D.Double(-65.0,-65.0,130.0,130.0,190.0,50.0,Arc2D.OPEN)));
+	}
+	public static final Symbol LightFlare = new Symbol();
+	static {
+		LightFlare.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-100,40,100)));
+		LightFlare.add(new Instr(Form.RSHP, new Ellipse2D.Double(-3,-3,6,6)));
+		Path2D.Double p = new Path2D.Double();
+		p.moveTo(0.0,-25.0); p.lineTo(15.0,-95.0); p.curveTo(20.0,-123.0,-20.0,-123.0,-15.0,-95.0);
+		p.closePath();
+		LightFlare.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol LightMajor = new Symbol();
+	static {
+		LightMajor.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_NON_ZERO);
+		p.moveTo(0.0,-7.0); p.curveTo(-9.3,-6.5,-9.3,6.5,0.0,7.0); p.curveTo(9.3,6.5,9.3,-6.5,0.0,-7.0); p.closePath();
+		p.moveTo(0.0,-35.5); p.lineTo(8.0,-11.2); p.lineTo(33.5,-11.2); p.lineTo(12.8,4.0);
+		p.lineTo(20.5,28.5); p.lineTo(0.0,13.0); p.lineTo(-20.5,28.5); p.lineTo(-12.8,4.0); p.lineTo(-33.5,-11.2); p.lineTo(-8.0,-11.2); p.closePath();
+		LightMajor.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol LightMinor = new Symbol();
+	static {
+		LightMinor.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-26.5); p.lineTo(6.0,-8.4); p.lineTo(25.1,-8.4); p.lineTo(9.6,3.0);
+		p.lineTo(15.4,21.4); p.lineTo(0.0,9.8); p.lineTo(-15.4,21.4); p.lineTo(-9.6,3.0); p.lineTo(-25.1,-8.4); p.lineTo(-6.0,-8.4); p.closePath();
+		LightMinor.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol PerchPort = new Symbol();
+	static {
+		PerchPort.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		PerchPort.add(new Instr(Form.FILL, Color.black));
+		PerchPort.add(new Instr(Form.LINE, new Line2D.Double(-10,0,10,0)));
+		PerchPort.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-40)));
+		PerchPort.add(new Instr(Form.LINE, new Line2D.Double(25,-70,0,-40)));
+		PerchPort.add(new Instr(Form.LINE, new Line2D.Double(-25,-70,0,-40)));
+	}
+	public static final Symbol PerchStarboard = new Symbol();
+	static {
+		PerchStarboard.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		PerchStarboard.add(new Instr(Form.FILL, Color.black));
+		PerchStarboard.add(new Instr(Form.LINE, new Line2D.Double(-10,0,10,0)));
+		PerchStarboard.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-70)));
+		PerchStarboard.add(new Instr(Form.LINE, new Line2D.Double(25,-40,0,-68.7)));
+		PerchStarboard.add(new Instr(Form.LINE, new Line2D.Double(-25,-40,0,-68.7)));
+	}
+	public static final Symbol RadarStation = new Symbol();
+	static {
+		RadarStation.add(new Instr(Form.STRK, new BasicStroke(2.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		RadarStation.add(new Instr(Form.FILL, new Color(0xd400d4)));
+		RadarStation.add(new Instr(Form.ELPS, new Ellipse2D.Double(-125,-125,250,250)));
+	}
+	public static final Symbol Stake = new Symbol();
+	static {
+		Stake.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Stake.add(new Instr(Form.FILL, Color.black));
+		Stake.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-70)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-2.0,0.0); p.lineTo(-2.0,-70.0); p.lineTo(2.0,-70.0); p.lineTo(2.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-2.0,0.0); p.lineTo(-2.0,-35.0); p.lineTo(2.0,-35.0); p.lineTo(2.0,0.0); p.closePath();
+		colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-2.0,-23.3); p.lineTo(-2.0,-46.7); p.lineTo(2.0,-46.7); p.lineTo(2.0,-23.3); p.closePath();
+		colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-2.0,-35.0); p.lineTo(-2.0,-52.5); p.lineTo(2.0,-52.5); p.lineTo(2.0,-35.0); p.closePath();
+		colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-2.0,-17.5); p.lineTo(-2.0,-35.0); p.lineTo(2.0,-35.0); p.lineTo(2.0,-17.5); p.closePath();
+		colours.add(new Instr(Form.H5, p));
+		Stake.add(new Instr(Form.COLR, colours));
+		Stake.add(new Instr(Form.FILL, Color.black));
+		Stake.add(new Instr(Form.LINE, new Line2D.Double(-10,0,10,0)));
+	}
+	public static final Symbol Tower = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-25.0,0.0); p.lineTo(-20.0,-70.0); p.lineTo(20.0,-70.0); p.lineTo(25.0,0.0); p.lineTo(10.0,0.0); p.curveTo(10.0,-13.3,-10.0,-13.3,-10.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-25.0,0.0); p.lineTo(-22.5,-35.0); p.lineTo(22.5,-35.0); p.lineTo(25.0,0.0); p.lineTo(10.0,0.0); p.curveTo(10.0,-13.3,-10.0,-13.3,-10.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-23.3,-23.3); p.lineTo(-21.7,-46.7); p.lineTo(21.7,-46.7); p.lineTo(23.3,-23.3); p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-22.5,-35.0); p.lineTo(-21.0,-52.5); p.lineTo(21.0,-52.5); p.lineTo(22.5,-35.0); p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-23.6,-17.5); p.lineTo(-22.5,-35.0); p.lineTo(22.5,-35.0); p.lineTo(23.6,-17.5); p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-70.0); p.lineTo(20.0,-70.0); p.lineTo(25.0,0.0); p.lineTo(10.0,0.0); p.quadTo(10.0,-10.0,0.0,-10.0); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+    Tower.add(new Instr(Form.COLR, colours));
+    Tower.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    Tower.add(new Instr(Form.FILL, Color.black));
+    Tower.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    Tower.add(new Instr(Form.LINE, new Line2D.Double(-35,0,-10,0)));
+    Tower.add(new Instr(Form.LINE, new Line2D.Double(10,0,35,0)));
+		p = new Path2D.Double(); p.moveTo(-25.0,0.0); p.lineTo(-20.0,-70.0); p.lineTo(20.0,-70.0); p.lineTo(25.0,0.0);
+		Tower.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol WithyPort = new Symbol();
+	static {
+		WithyPort.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		WithyPort.add(new Instr(Form.FILL, Color.black));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(-10,0,10,0)));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-70)));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(20,-60,0,-50)));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(-20,-60,0,-50)));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(30,-35,0,-21)));
+		WithyPort.add(new Instr(Form.LINE, new Line2D.Double(-30,-35,0,-21)));
+	}
+	public static final Symbol WithyStarboard = new Symbol();
+	static {
+		WithyStarboard.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		WithyStarboard.add(new Instr(Form.FILL, Color.black));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(-10,0,10,0)));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-70)));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(20,-50,0,-60)));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(-20,-50,0,-60)));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(30,-21,0,-35)));
+		WithyStarboard.add(new Instr(Form.LINE, new Line2D.Double(-30,-21,0,-35)));
+	}
+	
+	public static final EnumMap<BcnSHP, Symbol> Shapes = new EnumMap<BcnSHP, Symbol>(BcnSHP.class);
+	static {
+		Shapes.put(BcnSHP.BCN_UNKN, Beacons.Beacon); Shapes.put(BcnSHP.BCN_STAK, Beacons.Stake); Shapes.put(BcnSHP.BCN_TOWR, Beacons.Tower);
+		Shapes.put(BcnSHP.BCN_LATT, Beacons.Beacon); Shapes.put(BcnSHP.BCN_PILE, Beacons.Beacon); Shapes.put(BcnSHP.BCN_POLE, Beacons.Stake);
+		Shapes.put(BcnSHP.BCN_CARN, Beacons.Cairn); Shapes.put(BcnSHP.BCN_BUOY, Beacons.Beacon); Shapes.put(BcnSHP.BCN_POST, Beacons.Stake);
+		Shapes.put(BcnSHP.BCN_PRCH, Beacons.Stake);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Buoys.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Buoys.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Buoys.java	(revision 30894)
@@ -0,0 +1,257 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.*;
+import java.util.EnumMap;
+
+import s57.S57val.BoySHP;
+import symbols.Symbols.*;
+
+public class Buoys {
+
+	public static final Symbol Barrel = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-50.0,0); p.curveTo(-50.0,-11.0,-45.0,-32.0,-32.0,-36.0);
+		p.curveTo(-18.0,-40.0,12.0,-40.0,25.0,-36.0); p.curveTo(38.0,-32.0,43.0,-11.0,43.0,0);
+		p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		Barrel.add(new Instr(Form.COLR, colours));
+    Barrel.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Barrel.add(new Instr(Form.FILL, Color.black));
+		Barrel.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Barrel.add(new Instr(Form.LINE, new Line2D.Double(-57,0,-10,0)));
+		Barrel.add(new Instr(Form.LINE, new Line2D.Double(10,0,50,0)));
+		p = new Path2D.Double(); p.moveTo(-50.0,0); p.curveTo(-50.0,-11.0,-45.0,-32.0,-32.0,-36.0); p.curveTo(-18.0,-40.0,12.0,-40.0,25.0,-36.0);
+		p.curveTo(38.0,-32.0,43.0,-11.0,43.0,0); p.moveTo(-32.0,-36.0); p.curveTo(-23.0,-25.0,-21.0,-12.0,-21.0,0.0);
+    Barrel.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Can = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-31.6, 0); p.lineTo(-15.7,-47.4); p.lineTo(41.1,-28.4); p.lineTo(31.6,0);
+		p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-31.6,0); p.lineTo(-22.0,-28.4); p.lineTo(34.8,-9.4); p.lineTo(31.6,0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-24.2,-22.1); p.lineTo(-19.9,-34.8); p.lineTo(36.9,-15.8); p.lineTo(32.6,-3.1);	p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-22.0,-28.4); p.lineTo(-18.9,-37.9); p.lineTo(37.9,-18.9); p.lineTo(34.8,-9.4);	p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-25.2,-19.0); p.lineTo(-22.0,-28.4); p.lineTo(34.8,-9.4); p.lineTo(31.6,0.0);	p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(12.7,-37.9); p.lineTo(41.1,-28.4); p.lineTo(31.6,0);	p.lineTo(8.0,0.0); p.quadTo(8.0,-6.0,2.5,-7.6); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Can.add(new Instr(Form.COLR, colours));
+    Can.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Can.add(new Instr(Form.FILL, Color.black));
+		Can.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Can.add(new Instr(Form.LINE, new Line2D.Double(-40,0,-10,0)));
+		Can.add(new Instr(Form.LINE, new Line2D.Double(10,0,40,0)));
+		p = new Path2D.Double(); p.moveTo(-31.6, 0); p.lineTo(-15.7,-47.4); p.lineTo(41.1,-28.4); p.lineTo(31.6,0);
+    Can.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Cone = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-31.6,0); p.curveTo(-24.9,-32.2, 1.4,-38.7,12.7,-37.9); p.curveTo(21.9,-30.5,32.8,-18.4,32.1,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-31.6,0); p.quadTo(-29.0,-15.5,-17.3,-26.9); p.lineTo(31.5,-10.5); p.quadTo(33.0,-5.0,32.1,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0, -11.0, -8.0, -11.0, -8.0, 0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-22.3,-21.4); p.quadTo(-15.2,-29.8,-10.8,-31.8); p.lineTo(28.8,-18.5); p.quadTo(31.8,-12.5,32.6,-3.1); p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-17.3,-27.0); p.quadTo(-13.0,-31.4,-6.9,-33.8); p.lineTo(26.4,-22.7); p.quadTo(30.0,-17.0,31.7,-10.3); p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-24.4,-18.7); p.quadTo(-20.3,-25.0,-17.3,-27.0); p.lineTo(31.7,-10.3); p.quadTo(32.7,-4.5,32.1,0.0); p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(12.7,-37.9); p.curveTo(21.9,-30.5,32.8,-18.4,32.1,0.0);	p.lineTo(8.0,0.0); p.quadTo(8.0,-6.0,2.5,-7.6); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Cone.add(new Instr(Form.COLR, colours));
+    Cone.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Cone.add(new Instr(Form.FILL, Color.black));
+		Cone.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Cone.add(new Instr(Form.LINE, new Line2D.Double(-40,0,-10,0)));
+		Cone.add(new Instr(Form.LINE, new Line2D.Double(10,0,40,0)));
+		p = new Path2D.Double(); p.moveTo(-31.6, 0); p.curveTo(-24.9,-32.2,1.4,-38.7,12.7,-37.9); p.curveTo(21.9,-30.5,32.8,-18.4,32.1,0.0);
+    Cone.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Float = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-36.0,0); p.lineTo(-47.0,-33.0); p.quadTo(-30.0, -25.0, -19.0,-23.0);
+		p.lineTo(-12.0,-42.0); p.lineTo(12.0,-42.0); p.lineTo(19.0,-23.0); p.quadTo(30.0,-25.0,47.0,-33.0); p.lineTo(36.0,0);
+		p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-36.0,0); p.lineTo(-43.0,-21.0); p.lineTo(43.0,-21.0); p.lineTo(36.0,0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-40.8,-14.0); p.lineTo(-45.4,-28.0); p.lineTo(-35.5,-28.0); p.quadTo(-28.0,-25.0,-19.0,-23.0); p.lineTo(-17.2,-28.0);
+		p.lineTo(17.2,-28.0); p.lineTo(19.0,-23.0); p.quadTo(28.0,-25.0,35.5,-28.0); p.lineTo(45.4,-28.0); p.lineTo(40.8,-14.0); p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-43.0,-21.0); p.lineTo(-47.0,-33.0); p.quadTo(-29.7,-24.8,-19.0,-23.0); p.lineTo(-15.8,-31.5); p.lineTo(15.8,-31.5);
+		p.lineTo(19.0,-23.0); p.quadTo(28.4,-24.3,47.0,-33.0); p.lineTo(43.0,-21.0);	p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-39.8,-11.5); p.lineTo(-43.0,-21.0); p.lineTo(43.0,-21.0); p.lineTo(39.8,-11.5);	p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-42.0); p.lineTo(12.0,-42.0); p.lineTo(19.0,-23.0); p.quadTo(28.4,-24.3,47.0,-33.0); p.lineTo(36.0,0.0);
+		p.lineTo(8.0,0.0); p.quadTo(7.7,-7.7,0.0,-8.0); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Float.add(new Instr(Form.COLR, colours));
+    Float.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Float.add(new Instr(Form.FILL, Color.black));
+		Float.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Float.add(new Instr(Form.LINE, new Line2D.Double(-54,0,-10,0)));
+		Float.add(new Instr(Form.LINE, new Line2D.Double(10,0,54,0)));
+		p = new Path2D.Double(); p.moveTo(-36.0,0); p.lineTo(-47.0,-33.0); p.curveTo(-15.0, -17.0, 15.0, -17.0, 47.0,-33.0); p.lineTo(36.0,0);
+		p.moveTo(-19.0, -23.0); p.lineTo(-12.0,-42.0); p.lineTo(12.0,-42.0); p.lineTo(19.0,-23.0);
+    Float.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Ice = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,0); p.quadTo(-30.0,0.0,-30.0,-15.0); p.lineTo(-30.0,-25.0); p.lineTo(30.0,-25.0); p.lineTo(30.0,-15); p.quadTo(30.0,0.0,15.0,0.0);
+		p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+    Ice.add(new Instr(Form.COLR, colours));
+    Ice.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    Ice.add(new Instr(Form.FILL, Color.black));
+    Ice.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    Ice.add(new Instr(Form.LINE, new Line2D.Double(-35,0,-10,0)));
+    Ice.add(new Instr(Form.LINE, new Line2D.Double(10,0,35,0)));
+		p = new Path2D.Double(); p.moveTo(-15.0,0); p.quadTo(-30.0,0.0,-30.0,-15.0); p.lineTo(-30.0,-25.0); p.lineTo(30.0,-25.0); p.lineTo(30.0,-15); p.quadTo(30.0,0.0,15.0,0.0);
+		Ice.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(-6.0,8.0); p.lineTo(-6.0,40.0); p.lineTo(6.0,40.0); p.lineTo(6.0,8.0);
+		Ice.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Pillar = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-32.0,0.0); p.lineTo(-2.8,-32.5); p.lineTo(25.6,-96.7); p.lineTo(37.0,-92.9); p.lineTo(21.8,-24.3);
+		p.lineTo(25.0,0.0); p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-32.0,0); p.lineTo(-2.8,-32.5); p.lineTo(5.3,-51.0); p.lineTo(26.3,-43.9); p.lineTo(21.8,-24.3); p.lineTo(25.0,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-0.9,-37.1); p.lineTo(11.3,-64.6); p.lineTo(29.6,-58.7); p.lineTo(23.1,-29.3);	p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(5.3,-51.0); p.lineTo(14.5,-71.5); p.lineTo(31.2,-65.9); p.lineTo(26.3,-43.9);	p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-5.2,-29.7); p.lineTo(-2.8,-32.5); p.lineTo(5.3,-51.0); p.lineTo(26.3,-43.9); p.lineTo(21.8,-24.3); p.lineTo(22.2,-21.5);	p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(12.7,-37.9); p.lineTo(31.3,-94.8); p.lineTo(37.0,-92.9); p.lineTo(21.8,-24.3);
+		p.lineTo(25.0,0.0); p.lineTo(8.0,0.0); p.quadTo(8.0,-6.0,2.5,-7.6); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Pillar.add(new Instr(Form.COLR, colours));
+		Pillar.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Pillar.add(new Instr(Form.FILL, Color.black));
+		Pillar.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Pillar.add(new Instr(Form.LINE, new Line2D.Double(-42,0,-10,0)));
+		Pillar.add(new Instr(Form.LINE, new Line2D.Double(10,0,36,0)));
+		p = new Path2D.Double(); p.moveTo(-32.0,0.0); p.lineTo(-2.8,-32.5); p.lineTo(25.6,-96.7); p.lineTo(37.0,-92.9); p.lineTo(21.8,-24.3); p.lineTo(25.0,0.0);
+		Pillar.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Spar = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-3.2,-9.5); p.lineTo(25.6,-96.7); p.lineTo(37.0,-92.9); p.lineTo(8.2,-5.7); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-3.2,-9.5); p.lineTo(11.2,-53.1); p.lineTo(22.6,-49.3); p.lineTo(8.2,-5.7); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(6.4,-38.6); p.lineTo(16.0,-67.6); p.lineTo(27.4,-63.8); p.lineTo(17.8,-34.8);	p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(11.2,-53.1); p.lineTo(18.4,-74.9); p.lineTo(29.8,-71.1); p.lineTo(22.6,-49.3);	p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(4.0,-31.3); p.lineTo(11.2,-53.1); p.lineTo(22.6,-49.3); p.lineTo(15.4,-27.5); p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(2.5,-7.6); p.lineTo(31.3,-94.8); p.lineTo(37.0,-92.9); p.lineTo(8.2,-5.7); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Spar.add(new Instr(Form.COLR, colours));
+		Spar.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Spar.add(new Instr(Form.FILL, Color.black));
+		Spar.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Spar.add(new Instr(Form.LINE, new Line2D.Double(-20,0,-10,0)));
+		Spar.add(new Instr(Form.LINE, new Line2D.Double(10,0,20,0)));
+		p = new Path2D.Double(); p.moveTo(-3.2,-9.5); p.lineTo(25.6,-96.7); p.lineTo(37.0,-92.9); p.lineTo(8.2,-5.7);
+		Spar.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Sphere = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-25.0,0); p.curveTo(-32.0,-21.0,-14.0,-45.5,12.7,-37.9); p.curveTo(27.5,-33.8,37.8,-15.5,32.0,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-25.0,0); p.quadTo(-30.0,-15.0,-20.5,-28.0); p.lineTo(33.8,-10.0); p.quadTo(33.7,-4.0,32.0,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-24.2,-22.1); p.quadTo(-21.0,-28.5,-15.2,-33.3); p.lineTo(32.8,-17.2); p.quadTo(34.6,-10.0,33.0,-2.9); p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-20.5,-28.0); p.quadTo(-16.5,-33.0,-12.0,-35.5); p.lineTo(31.5,-21.0); p.quadTo(33.5,-17.0,34.0,-9.5); p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-25.2,-19.0); p.quadTo(-23.5,-24.0,-20.5,-28.0); p.lineTo(34.0,-9.5); p.quadTo(34.0,-3.0,32.0,0.0);	p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(12.7,-37.9); p.curveTo(27.5,-33.8,37.8,-15.5,32.0,0.0);	p.lineTo(8.0,0.0); p.quadTo(8.0,-6.0,2.5,-7.6); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+    Sphere.add(new Instr(Form.COLR, colours));
+    Sphere.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    Sphere.add(new Instr(Form.FILL, Color.black));
+    Sphere.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    Sphere.add(new Instr(Form.LINE, new Line2D.Double(-33,0,-10,0)));
+    Sphere.add(new Instr(Form.LINE, new Line2D.Double(10,0,40,0)));
+    Sphere.add(new Instr(Form.EARC, new Arc2D.Double(-26.5,-39.4,60.0,60.0,-18.0,216.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Storage = new Symbol();
+	static {
+		Storage.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Storage.add(new Instr(Form.FILL, Color.black));
+		Storage.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    Path2D.Double p = new Path2D.Double(); p.moveTo(-50.0,0.0); p.lineTo(-40.0,-20.0); p.lineTo(40.0,-20.0); p.lineTo(40.0,-20.0);
+    p.lineTo(50.0,0.0); p.lineTo(40.0,20.0); p.lineTo(-40.0,20.0); p.closePath();
+    Storage.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Super = new Symbol();
+	static {
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-48.0,0); p.lineTo(-28.0,-42.0); p.lineTo(28.0,-42.0); p.lineTo(48.0,0);
+		p.lineTo(8.0, 0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-48.0,0); p.lineTo(-38.0,-21.0); p.lineTo(38.0,-21.0); p.lineTo(48.0,0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+    colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-41.3,-14.0); p.lineTo(-34.7,-28.0); p.lineTo(34.7,-28.0); p.lineTo(41.3,-14.0);	p.closePath();
+    colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(-38.0,-21.0); p.lineTo(-33.0,-31.5); p.lineTo(33.0,-31.5); p.lineTo(38.0,-21.0);	p.closePath();
+    colours.add(new Instr(Form.H4, p));
+		p = new Path2D.Double(); p.moveTo(-43.0,-11.5); p.lineTo(-38.0,-21.0); p.lineTo(38.0,-21.0); p.lineTo(43.0,-11.5);	p.closePath();
+    colours.add(new Instr(Form.H5, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-42.0); p.lineTo(28.0,-42.0); p.lineTo(48.0,0.0); p.lineTo(8.0,0.0); p.quadTo(7.7,-7.7,0.0,-8.0); p.closePath();
+    colours.add(new Instr(Form.V2, p));
+		Super.add(new Instr(Form.COLR, colours));
+    Super.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Super.add(new Instr(Form.FILL, Color.black));
+		Super.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Super.add(new Instr(Form.LINE, new Line2D.Double(-54,0,-10,0)));
+		Super.add(new Instr(Form.LINE, new Line2D.Double(10,0,54,0)));
+		p = new Path2D.Double(); p.moveTo(-48.0,0); p.lineTo(-28.0,-42.0); p.lineTo(28.0,-42.0); p.lineTo(48.0,0);
+    Super.add(new Instr(Form.PLIN, p));
+	}
+	
+	public static final EnumMap<BoySHP, Symbol> Shapes = new EnumMap<BoySHP, Symbol>(BoySHP.class);
+	static {
+		Shapes.put(BoySHP.BOY_UNKN, Buoys.Pillar); Shapes.put(BoySHP.BOY_CONE, Buoys.Cone); Shapes.put(BoySHP.BOY_CAN, Buoys.Can);
+		Shapes.put(BoySHP.BOY_SPHR, Buoys.Sphere); Shapes.put(BoySHP.BOY_PILR, Buoys.Pillar); Shapes.put(BoySHP.BOY_SPAR, Buoys.Spar);
+		Shapes.put(BoySHP.BOY_BARL, Buoys.Barrel); Shapes.put(BoySHP.BOY_SUPR, Buoys.Super); Shapes.put(BoySHP.BOY_ICE, Buoys.Ice);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Facilities.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Facilities.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Facilities.java	(revision 30894)
@@ -0,0 +1,199 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.*;
+import java.util.EnumMap;
+
+import s57.S57val.*;
+import symbols.Symbols.*;
+
+public class Facilities {
+	private static final Symbol Facility = new Symbol();
+	static {
+		Facility.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Facility.add(new Instr(Form.FILL, new Color(0x80ffffff, true)));
+		RoundRectangle2D.Double s = new RoundRectangle2D.Double(-29,-29,58,58,15,15);
+		Facility.add(new Instr(Form.RSHP, s));
+		Facility.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Facility.add(new Instr(Form.RRCT, s));
+	}
+	public static final Symbol Boatlift = new Symbol();//was Crane
+	static {
+		Boatlift.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Boatlift.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Boatlift.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Boatlift.add(new Instr(Form.ELPS, new Ellipse2D.Double(-3.7,-19.7,12,12)));
+		Boatlift.add(new Instr(Form.LINE, new Line2D.Double(2.3,-7.7,2.3,-2.0)));
+		Boatlift.add(new Instr(Form.EARC, new Arc2D.Double(-10.0,-1.5,20,20,75.0,-260.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Boatyard = new Symbol();
+	static {
+		Boatyard.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Boatyard.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Boatyard.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Boatyard.add(new Instr(Form.LINE, new Line2D.Double(19,19,-8,-8)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-11.3,-11.3); p.lineTo(-10.5,-17.5); p.lineTo(-14.8,-21.9); p.lineTo(-11.3,-25.4); p.lineTo(-7.4,-21.5);
+		p.curveTo(1.0,-11.5,-11.5,1.0,-21.5,-7.4); p.lineTo(-25.4,-11.3); p.lineTo(-21.9,-14.8); p.lineTo(-17.5,-10.5); p.closePath();
+		Boatyard.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Chandler = new Symbol();
+	static {
+		Chandler.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Chandler.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Chandler.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Chandler.add(new Instr(Form.ELPS, new Ellipse2D.Double(14,7,10,10)));
+		Chandler.add(new Instr(Form.LINE, new Line2D.Double(-23.0,12.0,14.0,12.0)));
+		Chandler.add(new Instr(Form.LINE, new Line2D.Double(8.0,21.0,8.0,-8.6)));
+		Chandler.add(new Instr(Form.LINE, new Line2D.Double(-16.0,21.0,-16.0,-8.6)));
+		Chandler.add(new Instr(Form.EARC, new Arc2D.Double(-16.0,-20.5,24,24,0.0,180.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Fuel = new Symbol();
+	static {
+		Fuel.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Fuel.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Fuel.add(new Instr(Form.STRK, new BasicStroke(2.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Fuel.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-15.6,22.1); p.lineTo(-15.6,-19.4); p.quadTo(-15.5,-22.7,-12.2,-22.8); p.lineTo(0.2,-22.8); p.quadTo(3.3,-22.7,3.4,-19.4); p.lineTo(3.4,22.1); p.closePath(); 
+		p.moveTo(-12.8,-19.0); p.quadTo(-12.7,-19.9,-11.8,-20.0); p.lineTo(-0.4,-20.0); p.quadTo(0.5,-19.9,0.6,-19.0); p.lineTo(0.6,-9.4);
+		p.quadTo(0.5,-8.5,-0.4,-8.4); p.lineTo(-11.8,-8.4); p.quadTo(-12.7,-8.3,-12.8,-9.4); p.closePath();
+		Fuel.add(new Instr(Form.PGON, p));
+		p = new Path2D.Double(); p.moveTo(3.0,-3.0); p.lineTo(7.0,-3.0); p.quadTo(9.4,-2.8,9.6,-0.4); p.lineTo(9.6,18.0); p.curveTo(10.1,23.2,18.4,21.5,17.4,17.2);
+		p.lineTo(14.9,3.5); p.lineTo(15.1,-10.3); p.quadTo(14.9,-11.9,13.9,-13.1); p.lineTo(7.4,-19.6); p.moveTo(15.1,-7.4); p.lineTo(12.6,-7.4); p.quadTo(11.1,-7.4,11.1,-8.9); p.lineTo(11.1,-16.0);
+		Fuel.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Laundrette = new Symbol();
+	static {
+		Laundrette.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Laundrette.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Laundrette.add(new Instr(Form.STRK, new BasicStroke(1.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Laundrette.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Laundrette.add(new Instr(Form.RECT, new Rectangle2D.Double(-15,-15,30,30)));
+		Laundrette.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15,-15); p.lineTo(-15,-20); p.lineTo(15,-20); p.lineTo(15,-15);
+		p.moveTo(-10,15); p.lineTo(-10,20); p.lineTo(10,20); p.lineTo(10,15);
+		Laundrette.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol PumpOut = new Symbol();
+	static {
+		PumpOut.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		PumpOut.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		PumpOut.add(new Instr(Form.STRK, new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		PumpOut.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(3.9,-3.7); p.lineTo(-7.4,-3.7); p.lineTo(-12.0,2.0); p.lineTo(-22.7,2.0);
+		p.lineTo(-11.8,14.9); p.lineTo(15.1,14.9); p.lineTo(21.9,10.2); p.lineTo(21.9,3.1); p.lineTo(13.5,3.1);
+		PumpOut.add(new Instr(Form.PLIN, p));
+		PumpOut.add(new Instr(Form.STRK, new BasicStroke(3.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(-2.5,3.0); p.lineTo(-2.5,-13.8); p.lineTo(6.9,-13.8); p.lineTo(6.9,-6.7); p.lineTo(14.5,-6.7);
+		PumpOut.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(9.7,2.3); p.lineTo(9.7,10.3); p.lineTo(-4.1,10.3); p.lineTo(-4.1,2.3); p.closePath();
+		PumpOut.add(new Instr(Form.PGON, p));
+		p = new Path2D.Double(); p.moveTo(14.1,-10.6); p.lineTo(23.1,-6.7); p.lineTo(14.1,-2.8); p.closePath();
+		PumpOut.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol SailingClub = new Symbol();
+	static {
+		SailingClub.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		SailingClub.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		SailingClub.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		SailingClub.add(new Instr(Form.FILL, new Color(0xa30075)));
+		SailingClub.add(new Instr(Form.LINE, new Line2D.Double(-5,20,-5,-20)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-5,0); p.lineTo(20,-10); p.lineTo(-5,-20); p.closePath();
+		SailingClub.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Shower = new Symbol();
+	static {
+		Shower.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Shower.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Shower.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Shower.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Shower.add(new Instr(Form.LINE, new Line2D.Double(-4.8,-24.5,6.2,-13.5)));
+		Shower.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Shower.add(new Instr(Form.LINE, new Line2D.Double(-18.1,-17.9,-6.1,-21.3)));
+		Shower.add(new Instr(Form.LINE, new Line2D.Double(-13.9,-10.2,-3.9,-17.7)));
+		Shower.add(new Instr(Form.LINE, new Line2D.Double(-7.8,-4.4,-0.5,-14.3)));
+		Shower.add(new Instr(Form.LINE, new Line2D.Double(-0.2,-0.2,3.1,-12.1)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(11.1,24.6); p.lineTo(11.1,-16.0); p.curveTo(11.1,-22.7,3.4,-23.6,0.8,-19.3);
+		Shower.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Slipway = new Symbol();
+	static {
+		Slipway.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Slipway.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Slipway.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Slipway.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-24.8,0.1); p.lineTo(-24.8,18.0); p.curveTo(-21.2,18.0,-22.2,16.7,-18.6,16.7); p.curveTo(-15.0,16.7,-16.0,18.0,-12.4,18.0);
+		p.curveTo(-8.8,18.0,-9.8,16.7,-6.2,16.7); p.curveTo(-2.6,16.7,-3.6,18.0,0.0,18.0); p.curveTo(3.6,18.0,2.6,16.7,6.2,16.7); p.curveTo(9.8,16.7,8.8,18.0,12.4,18.0);
+		p.curveTo(16.0,18.0,15.0,16.7,18.6,16.7); p.curveTo(22.2,16.7,21.2,18.0,24.8,18.0);	p.lineTo(24.8,13.6); p.closePath();
+		Slipway.add(new Instr(Form.PGON, p));
+		Slipway.add(new Instr(Form.ELPS, new Ellipse2D.Double(-1.65,-1.9,8,8)));
+		Slipway.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Slipway.add(new Instr(Form.LINE, new Line2D.Double(-24.5,-8.3,-3.1,-2.4)));
+		Slipway.add(new Instr(Form.LINE, new Line2D.Double(9.3,1.1,22.2,4.6)));
+		p = new Path2D.Double(); p.moveTo(22.9,0.6); p.lineTo(25.0,-7.4); p.lineTo(-5.1,-15.8); p.lineTo(0.3,-19.6); p.lineTo(-1.6,-20.1); p.lineTo(-7.2,-16.2);
+		p.lineTo(-17.1,-18.9); p.quadTo(-16.8,-11.4,-7.7,-7.7); p.closePath();
+		Slipway.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Toilet = new Symbol();
+	static {
+		Toilet.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Toilet.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Facilities.Facility, 1.0, 0, 0, null, null)));
+		Toilet.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		Toilet.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Toilet.add(new Instr(Form.LINE, new Line2D.Double(0,20,0,-20)));
+		Toilet.add(new Instr(Form.RSHP, new Ellipse2D.Double(-18.5,-22.5,7.4,7.4)));
+		Toilet.add(new Instr(Form.RSHP, new Ellipse2D.Double(11,-22.5,7.4,7.4)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-9.8,-12.2); p.lineTo(-4.8,2.7); p.lineTo(-7.3,3.9); p.lineTo(-10.6,-7.0); p.lineTo(-11.7,-6.4); p.lineTo(-7.6,9.0);
+		p.lineTo(-11.3,9.0); p.lineTo(-11.6,22.1); p.lineTo(-13.9,22.1); p.lineTo(-14.2,9.0); p.lineTo(-15.8,9.0); p.lineTo(-16.2,22.1); p.lineTo(-18.4,22.1);
+		p.lineTo(-18.8,9.0); p.lineTo(-22.3,9.0); p.lineTo(-18.2,-6.4); p.lineTo(-19.1,-7.0); p.lineTo(-22.9,3.9); p.lineTo(-25.1,2.7); p.lineTo(-19.9,-12.2); p.closePath();
+		Toilet.add(new Instr(Form.PGON, p));
+		p = new Path2D.Double(); p.moveTo(19.2,-12.2); p.lineTo(22.3,-10.1); p.lineTo(22.3,4.4); p.lineTo(20.2,4.4); p.lineTo(20.2,-7.3); p.lineTo(18.3,-7.3); p.lineTo(18.3,22.1);
+		p.lineTo(15.8,22.1); p.lineTo(15.8,4.6); p.lineTo(13.8,4.6); p.lineTo(13.4,22.1); p.lineTo(11.0,22.1); p.lineTo(11.0,-7.3); p.lineTo(9.5,-7.3); p.lineTo(9.5,4.4); p.lineTo(6.8,4.4);
+		p.lineTo(6.8,-10.1); p.lineTo(9.4,-12.2); p.closePath();
+		Toilet.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol VisitorBerth = new Symbol();
+	static {
+		VisitorBerth.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		VisitorBerth.add(new Instr(Form.FILL, new Color(0xa30075)));
+		VisitorBerth.add(new Instr(Form.RSHP, new Ellipse2D.Double(-25,-25,50,50)));
+		VisitorBerth.add(new Instr(Form.FILL, Color.white));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(7.9,-13.6); p.lineTo(14.0,-13.6); p.lineTo(3.4,13.6); p.lineTo(-3.4,13.6);
+		p.lineTo(-14.0,-13.6); p.lineTo(-7.9,-13.6); p.lineTo(0.0,8.7); p.closePath();
+		VisitorBerth.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol VisitorMooring = new Symbol();
+	static {
+		VisitorMooring.add(new Instr(Form.FILL, new Color(0xa30075)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-25.0,0); p.curveTo(-32.0,-21.0,-14.0,-45.5,12.7,-37.9); p.curveTo(27.5,-33.8,37.8,-15.5,32.0,0.0);
+		p.lineTo(8.0,0.0); p.curveTo(8.0,-11.0,-8.0,-11.0,-8.0,0.0); p.closePath();
+		VisitorMooring.add(new Instr(Form.PGON, p));
+    VisitorMooring.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    VisitorMooring.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+    VisitorMooring.add(new Instr(Form.LINE, new Line2D.Double(-33,0,-10,0)));
+    VisitorMooring.add(new Instr(Form.LINE, new Line2D.Double(10,0,40,0)));
+    VisitorMooring.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+    VisitorMooring.add(new Instr(Form.ELPS, new Ellipse2D.Double(6.5,-49.5,12,12)));
+    VisitorMooring.add(new Instr(Form.FILL, Color.white));
+		p = new Path2D.Double(); p.moveTo(8.3,-32.8); p.lineTo(12.5,-32.8); p.lineTo(5.4,-12.9); p.lineTo(1.0,-12.9); p.lineTo(-6.1,-32.8);
+		p.lineTo(-1.9,-32.8); p.lineTo(3.2,-18.1); p.closePath();
+		VisitorMooring.add(new Instr(Form.PGON, p));
+	}
+
+	public static final EnumMap<CatSCF, Symbol> Cats = new EnumMap<CatSCF, Symbol>(CatSCF.class);
+	static {
+		Cats.put(CatSCF.SCF_BHST, Boatlift); Cats.put(CatSCF.SCF_BTYD, Boatyard); Cats.put(CatSCF.SCF_CHDR, Chandler); Cats.put(CatSCF.SCF_FUEL, Fuel); Cats.put(CatSCF.SCF_LAUN, Laundrette);
+		Cats.put(CatSCF.SCF_PMPO, PumpOut); Cats.put(CatSCF.SCF_CLUB, SailingClub); Cats.put(CatSCF.SCF_SHWR, Shower); Cats.put(CatSCF.SCF_SLPW, Slipway); Cats.put(CatSCF.SCF_WC, Toilet);
+		Cats.put(CatSCF.SCF_VBTH, VisitorBerth); Cats.put(CatSCF.SCF_VMOR, VisitorMooring);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Harbours.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Harbours.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Harbours.java	(revision 30894)
@@ -0,0 +1,203 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.*;
+
+import render.Rules;
+import symbols.Symbols.*;
+
+public class Harbours {
+	public static final Symbol Anchor = new Symbol();
+	static {
+		Anchor.add(new Instr(Form.BBOX, new Rectangle2D.Double(-60,-60,120,120)));
+		Anchor.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Anchor.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-59,20,20)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(23.0,-40.0); p.lineTo(23.0,-30.0); p.lineTo(6.0,-30.0); p.lineTo(7.0,31.0); p.quadTo(21.0,29.0,31.0,22.0);
+		p.lineTo(27.0,18.0); p.lineTo(52.0,0.0); p.lineTo(45.0,35.0); p.lineTo(37.0,28.0);	p.quadTo(25.0,39.0,7.0,43.0); p.lineTo(6.0,51.0);
+		p.lineTo(-6.0,51.0); p.lineTo(-7.0,43.0);	p.quadTo(-25.0,39.0,-37.0,28.0); p.lineTo(-45.0,35.0); p.lineTo(-52.0,0.0); p.lineTo(-27.0,18.0);
+		p.lineTo(-31.0,22.0); p.quadTo(-21.0,29.0,-7.0,31.0); p.lineTo(-6.0,-30.0); p.lineTo(-23.0,-30.0); p.lineTo(-23.0,-40.0); p.closePath();
+		Anchor.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Yacht = new Symbol();
+	static {
+		Yacht.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-65.0,50.0); p.curveTo(-36.0,97.0,36.0,97.0,65.0,50.0); p.lineTo(3.0,50.0); p.lineTo(3.0,40.0); p.lineTo(55.0,30.0);
+		p.curveTo(32.0,4.0,25.0,-15.0,26.0,-52.0); p.lineTo(1.5,-40.0); p.lineTo(1.0,-64.0); p.lineTo(-2.0,-64.0); p.lineTo(-4.0,50.0); p.closePath();
+		p.moveTo(-50.0,45.0); p.curveTo(-55.0,3.0,-37.0,-28.5,-7.0,-46.0); p.curveTo(-28.0,-15.0,-26.0,11.0,-20.5,30.0); p.closePath();
+		Yacht.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Anchorage = new Symbol();
+	static {
+		Anchorage.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 1.0, 0, 0, new Scheme(Rules.Msymb), null)));
+	}
+	public static final Symbol Bollard = new Symbol();
+	static {
+		Bollard.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Bollard.add(new Instr(Form.FILL, Color.white));
+		Ellipse2D.Double s = new Ellipse2D.Double(-10,-10,20,20);
+		Bollard.add(new Instr(Form.RSHP, s));
+		Bollard.add(new Instr(Form.FILL, Color.black));
+		Bollard.add(new Instr(Form.ELPS, s));
+	}
+	public static final Symbol ContainerCrane = new Symbol();
+	static {
+		ContainerCrane.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		ContainerCrane.add(new Instr(Form.RSHP, new Rectangle2D.Double(-15,-65,30,100)));
+		ContainerCrane.add(new Instr(Form.RECT, new Rectangle2D.Double(-40,-12.5,80,25)));
+	}
+	public static final Symbol Customs = new Symbol();
+	static {
+		Customs.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Customs.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Customs.add(new Instr(Form.ELPS, new Ellipse2D.Double(-28,-28,56,56)));
+		Customs.add(new Instr(Form.LINE, new Line2D.Double(-25,5,25,5)));
+		Customs.add(new Instr(Form.LINE, new Line2D.Double(-25,-5,25,-5)));
+	}
+	public static final Symbol DeviationDolphin = new Symbol();
+	static {
+		DeviationDolphin.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-30.0,0.0); p.lineTo(30.0,0.0); p.moveTo(0.0,0.0); p.lineTo(0.0,-40.0);
+		p.moveTo(-20.0,0.0); p.lineTo(-15.0,-32.0); p.lineTo(15.0,-32.0); p.lineTo(20.0,0.0);
+		DeviationDolphin.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol DistanceI = new Symbol();
+	static {
+		DistanceI.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		DistanceI.add(new Instr(Form.ELPS, new Ellipse2D.Double(-11,-11,22,22)));
+	}
+	public static final Symbol DistanceU = new Symbol();
+	static {
+		DistanceU.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		DistanceU.add(new Instr(Form.FILL, Rules.Msymb));
+		DistanceU.add(new Instr(Form.ELPS, new Ellipse2D.Double(-11,-11,22,22)));
+	}
+	public static final Symbol Dolphin = new Symbol();
+	static {
+		Dolphin.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Dolphin.add(new Instr(Form.FILL, new Color(0xffd400)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(3.8,-9.2); p.lineTo(9.2,-3.8); p.lineTo(9.2,3.8); p.lineTo(3.8,9.2);
+		p.lineTo(-3.8,9.2); p.lineTo(-9.2,3.8); p.lineTo(-9.2,-3.8); p.lineTo(-3.8,-9.2); p.closePath();
+		Dolphin.add(new Instr(Form.PGON, p));
+		Dolphin.add(new Instr(Form.FILL, Color.black));
+		Dolphin.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Explosives = new Symbol();
+	static {
+		Explosives.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Explosives.add(new Instr(Form.RSHP, new Ellipse2D.Double(-5,25,10,10)));
+		Explosives.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-10,20); p.lineTo(-13,17); p.lineTo(-13,8);
+		p.moveTo(0,10); p.lineTo(0,0); p.lineTo(-8,-10);
+		p.moveTo(10,17); p.lineTo(18,-10); p.lineTo(10,-20);
+		Explosives.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Fishing = new Symbol();
+	static {
+		Fishing.add(new Instr(Form.STRK, new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Fishing.add(new Instr(Form.FILL, Rules.Msymb));
+		Fishing.add(new Instr(Form.EARC, new Arc2D.Double(-50,-50,100,100,15,140,Arc2D.OPEN)));
+		Fishing.add(new Instr(Form.EARC, new Arc2D.Double(-50,-50,100,100,-15,-140,Arc2D.OPEN)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-24,3); p.curveTo(12,24,30,15,48,0); p.curveTo(30,-15,12,-24,-24,-3);
+		p.lineTo(-45,-15); p.quadTo(-48, 0, -45, 15); p.closePath();
+		p.moveTo(25, 0); p.curveTo(25, 6, 34, 6, 34, 0); p.curveTo(34, -6, 25, -6, 25, 0); p.closePath();
+		Fishing.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Harbour = new Symbol();
+	static {
+		Harbour.add(new Instr(Form.STRK, new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Harbour.add(new Instr(Form.FILL, Rules.Msymb));
+		Harbour.add(new Instr(Form.ELPS, new Ellipse2D.Double(-50,-50,100,100)));
+		Harbour.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 0.6, 0, 0, new Scheme(Rules.Msymb), null)));
+	}
+	public static final Symbol HarbourMaster = new Symbol();
+	static {
+		HarbourMaster.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		HarbourMaster.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		HarbourMaster.add(new Instr(Form.ELPS, new Ellipse2D.Double(-24,-28,48,56)));
+		HarbourMaster.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 0.4, 0, 0, null, null)));
+	}
+	public static final Symbol Hospital = new Symbol();
+	static {
+		Hospital.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Hospital.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Hospital.add(new Instr(Form.ELPS, new Ellipse2D.Double(-28,-28,56,56)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-26,-5); p.lineTo(-5,-5); p.lineTo(-5,-25); p.moveTo(5,-25); p.lineTo(5,-5); p.lineTo(25,-5);
+		p.moveTo(-25,5); p.lineTo(-5,5); p.lineTo(-5,25); p.moveTo(5,25); p.lineTo(5,5); p.lineTo(25,5);
+		Hospital.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol LandingSteps = new Symbol();
+	static {
+		LandingSteps.add(new Instr(Form.FILL, Rules.Msymb));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-20,-10); p.lineTo(10,20); p.lineTo(20,20); p.lineTo(20,10);
+		p.lineTo(10,10); p.lineTo(10,0); p.lineTo(0,0); p.lineTo(0,-10); p.lineTo(-10,-10); p.lineTo(-10,-20); p.lineTo(-20,-20); p.closePath();
+		LandingSteps.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol Lock_Gate = new Symbol();
+	public static final Symbol Lock = new Symbol();
+	public static final Symbol Marina = new Symbol();
+	static {
+		Marina.add(new Instr(Form.STRK, new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Marina.add(new Instr(Form.FILL, Rules.Msymb));
+		Marina.add(new Instr(Form.EARC, new Arc2D.Double(-50.0,-50.0,100.0,100.0,215.0,-250.0,Arc2D.OPEN)));
+		Marina.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Yacht, 0.6, 0, 0, new Scheme(Rules.Msymb), null)));
+	}
+	public static final Symbol MarinaNF = new Symbol();
+	static {
+		MarinaNF.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Yacht, 0.6, 0, 0, new Scheme(Rules.Msymb), null)));
+	}
+	public static final Symbol Pilot = new Symbol();
+	static{
+		Pilot.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Pilot.add(new Instr(Form.FILL, new Color(0xd400d4)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15,0); p.lineTo(0,-56); p.lineTo(15,0); p.lineTo(0,56); p.closePath();
+		Pilot.add(new Instr(Form.PGON, p));
+		Pilot.add(new Instr(Form.ELPS, new Ellipse2D.Double(-58,-58,116,116)));
+	}
+	public static final Symbol PortCrane = new Symbol();
+	static {
+		PortCrane.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		PortCrane.add(new Instr(Form.EARC, new Arc2D.Double(-36.0,-36.0,72.0,72.0,70.0,-320.0,Arc2D.OPEN)));
+		PortCrane.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-60)));
+	}
+	public static final Symbol Post = new Symbol();
+	static {
+		Post.add(new Instr(Form.RSHP, new Ellipse2D.Double(-10,-10,20,20)));
+	}
+	public static final Symbol Rescue = new Symbol();
+	static{
+		Rescue.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-50,40,100)));
+		Rescue.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-11,0); p.lineTo(0,-43); p.lineTo(11,0); p.lineTo(0,43); p.closePath();
+		Rescue.add(new Instr(Form.PGON, p));
+		Rescue.add(new Instr(Form.LINE, new Line2D.Double(-15,0,15,0)));
+	}
+	public static final Symbol SignalStation = new Symbol();
+	static {
+		SignalStation.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		SignalStation.add(new Instr(Form.ELPS, new Ellipse2D.Double(-25,-25,50,50)));
+		SignalStation.add(new Instr(Form.RSHP, new Ellipse2D.Double(-4,-4,8,8)));
+	}
+	public static final Symbol TideGauge = new Symbol();
+	static {
+		TideGauge.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TideGauge.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(-10,0,-30,0)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(10,0,30,0)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(0,-10,0,-80)));
+		TideGauge.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(-15,-25,15,-25)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(-25,-45,25,-45)));
+		TideGauge.add(new Instr(Form.LINE, new Line2D.Double(-15,-65,15,-65)));
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Landmarks.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Landmarks.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Landmarks.java	(revision 30894)
@@ -0,0 +1,210 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.geom.*;
+import java.util.EnumMap;
+
+import s57.S57val.*;
+import symbols.Symbols.*;
+
+
+public class Landmarks {
+	private static final Symbol Base = new Symbol();
+	static {
+		Base.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Base.add(new Instr(Form.ELPS, new Ellipse2D.Double(-10,-10,20,20)));
+		Base.add(new Instr(Form.LINE, new Line2D.Double(-35,0,-10,0)));
+		Base.add(new Instr(Form.LINE, new Line2D.Double(10,0,35,0)));
+	}
+	
+	public static final Symbol Chimney = new Symbol();
+	static {
+		Chimney.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Chimney.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-25.0,0.0); p.lineTo(-10.0,-120.0); p.lineTo(10.0,-120.0); p.lineTo(25.0,0.0);
+		p.moveTo(-10.0,-128.0); p.curveTo(-13.0,-147.0,15.0,-159.0,20.0,-148.0);
+		p.moveTo(16.0,-152.3); p.curveTo(58.0,-194.0,98.0,-87.0,16.0,-132.0);
+		p.moveTo(11.0,-128.0); p.curveTo(13.4,-132.0,20.0,-132.0,20.0,-136.0);
+		Chimney.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Church = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(10.0,-10.0); p.lineTo(37.0,-10.0); p.quadTo(48.0,-10.0,48.0,-21.0); p.lineTo(50.0,-21.0); p.lineTo(50.0,21.0);
+		p.lineTo(48.0,21.0); p.quadTo(48.0,10.0,37.0,10.0); p.lineTo(10.0,10.0); p.lineTo(10.0,37.0); p.quadTo(10.0,48.0,21.0,48.0); p.lineTo(21.0,50.0);
+		p.lineTo(-21.0,50.0); p.lineTo(-21.0,48.0); p.quadTo(-10.0,48.0,-10.0,37.0); p.lineTo(-10.0,10.0); p.lineTo(-37.0,10.0); p.quadTo(-48.0,10.0,-48.0,21.0);
+		p.lineTo(-50.0,21.0); p.lineTo(-50.0,-21.0); p.lineTo(-48.0,-21.0); p.quadTo(-48.0,-10.0,-37.0,-10.0); p.lineTo(-10.0,-10.0); p.lineTo(-10.0,-37.0);
+		p.quadTo(-10.0,-48.0,-21.0,-48.0); p.lineTo(-21.0,-50.0); p.lineTo(21.0,-50.0); p.lineTo(21.0,-48.0); p.quadTo(10.0,-48.0,10.0,-37.0); p.closePath();
+		Church.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol ChurchTower = new Symbol();
+	static {
+		ChurchTower.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		ChurchTower.add(new Instr(Form.RECT, new Rectangle2D.Double(-36,-36,72,72)));
+		ChurchTower.add(new Instr(Form.ELPS, new Ellipse2D.Double(-2,-2,4,4)));
+	}
+	public static final Symbol Cross = new Symbol();
+	static {
+		Cross.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Cross.add(new Instr(Form.STRK, new BasicStroke(6, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Cross.add(new Instr(Form.LINE, new Line2D.Double(0,-10,0,-150)));
+		Cross.add(new Instr(Form.LINE, new Line2D.Double(-30,-115,30,-115)));
+	}
+	public static final Symbol DishAerial = new Symbol();
+	static {
+		DishAerial.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		DishAerial.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-7.8,-6.0); p.lineTo(0.0,-62.0); p.lineTo(7.8,-6.0); p.moveTo(18.0,-109.0); p.lineTo(25.0,-113.0);
+		p.moveTo(-9.5,-157.0); p.curveTo(-60.7,-125.5,-16.5,-33.9,44.9,-61.7); p.closePath();
+		DishAerial.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Dome = new Symbol();
+	static {
+		Dome.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Dome.add(new Instr(Form.ELPS, new Ellipse2D.Double(-36,-36,72,72)));
+		Dome.add(new Instr(Form.RSHP, new Ellipse2D.Double(-4,-4,8,8)));
+	}
+	public static final Symbol Flagstaff = new Symbol();
+	static {
+		Flagstaff.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Flagstaff.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(0.0,-150.0); p.moveTo(0.0,-140.0); p.lineTo(40.0,-140.0); p.lineTo(40.0,-100.0); p.lineTo(0.0,-100.0);
+		Flagstaff.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol FlareStack = new Symbol();
+	static {
+		FlareStack.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		FlareStack.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-7.8,-6.0); p.lineTo(-7.8,-100.0); p.lineTo(7.8,-100.0); p.lineTo(7.8,-6.0);
+		FlareStack.add(new Instr(Form.PLIN, p));
+		FlareStack.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(21.6,-169.6); p.curveTo(-22.0,-132.4,-27.4,-103.5,3.0,-100.0); p.curveTo(39.0,-118.0,-4.0,-141.0,21.6,-169.6);
+		FlareStack.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol LandTower = new Symbol();
+	static {
+		LandTower.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		LandTower.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		LandTower.add(new Instr(Form.LINE, new Line2D.Double(-25,0,-15,-120)));
+		LandTower.add(new Instr(Form.LINE, new Line2D.Double(25,0,15,-120)));
+		LandTower.add(new Instr(Form.RECT, new Rectangle2D.Double(-15,-150,30,30)));
+	}
+	public static final Symbol Mast = new Symbol();
+	static {
+		Mast.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Mast.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-25.0,0.0); p.lineTo(0.0,-150.0); p.lineTo(25.0,0.0);
+		Mast.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol Monument = new Symbol();
+	static {
+		Monument.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Monument.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Monument.add(new Instr(Form.LINE, new Line2D.Double(-25,0,-15,-105)));
+		Monument.add(new Instr(Form.LINE, new Line2D.Double(25,0,15,-105)));
+		Monument.add(new Instr(Form.EARC, new Arc2D.Double(-25.0,-150.0,50.0,50.0,233.0,-285.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Platform = new Symbol();
+	static {
+		Platform.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Platform.add(new Instr(Form.RECT, new Rectangle2D.Double(-48,-48,96,96)));
+		Platform.add(new Instr(Form.RSHP, new Ellipse2D.Double(-4,-4,8,8)));
+	}
+	public static final Symbol RadioTV = new Symbol();
+	static {
+		RadioTV.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL)));
+		RadioTV.add(new Instr(Form.EARC, new Arc2D.Double(-30.0,-180.0,60.0,60.0,45.0,-90.0,Arc2D.OPEN)));
+		RadioTV.add(new Instr(Form.EARC, new Arc2D.Double(-45.0,-195.0,90.0,90.0,45.0,-90.0,Arc2D.OPEN)));
+		RadioTV.add(new Instr(Form.EARC, new Arc2D.Double(-30.0,-180.0,60.0,60.0,225.0,-90.0,Arc2D.OPEN)));
+		RadioTV.add(new Instr(Form.EARC, new Arc2D.Double(-45.0,-195.0,90.0,90.0,225.0,-90.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Spire = new Symbol();
+	static {
+		Spire.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Spire.add(new Instr(Form.ELPS, new Ellipse2D.Double(-25,-25,50,50)));
+		Spire.add(new Instr(Form.RSHP, new Ellipse2D.Double(-4,-4,8,8)));
+	}
+	public static final Symbol Minaret = new Symbol();
+	static {
+		Minaret.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Spire, 1.0, 0, 0, null, null)));
+		Minaret.add(new Instr(Form.STRK, new BasicStroke(6, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Minaret.add(new Instr(Form.LINE, new Line2D.Double(0,-25,0,-50)));
+		Minaret.add(new Instr(Form.STRK, new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Minaret.add(new Instr(Form.EARC, new Arc2D.Double(-40.0,-110.0,80.0,60.0,180.0,180.0,Arc2D.OPEN)));
+	}
+	public static final Symbol Temple = new Symbol();
+	static {
+		Temple.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Temple.add(new Instr(Form.RECT, new Rectangle2D.Double(-25,-15,50,30)));
+		Temple.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Temple.add(new Instr(Form.LINE, new Line2D.Double(-35,-21,35,21)));
+		Temple.add(new Instr(Form.LINE, new Line2D.Double(-35,21,35,-21)));
+	}
+	public static final Symbol WaterTower = new Symbol();
+	static {
+		WaterTower.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		WaterTower.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		WaterTower.add(new Instr(Form.LINE, new Line2D.Double(-25,0,-15,-120)));
+		WaterTower.add(new Instr(Form.LINE, new Line2D.Double(25,0,15,-120)));
+		WaterTower.add(new Instr(Form.RECT, new Rectangle2D.Double(-25,-150,50,30)));
+	}
+	public static final Symbol WindMotor = new Symbol();
+	static {
+		WindMotor.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		WindMotor.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		WindMotor.add(new Instr(Form.LINE, new Line2D.Double(0,-10,0,-90)));
+		WindMotor.add(new Instr(Form.LINE, new Line2D.Double(0,-90,30,-90)));
+		WindMotor.add(new Instr(Form.LINE, new Line2D.Double(0,-90,-14,-116.6)));
+		WindMotor.add(new Instr(Form.LINE, new Line2D.Double(0,-90,-14.3,-66.7)));
+	}
+	public static final Symbol Windmill = new Symbol();
+	static {
+		Windmill.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Windmill.add(new Instr(Form.ELPS, new Ellipse2D.Double(-12,-12,24,24)));
+		Windmill.add(new Instr(Form.LINE, new Line2D.Double(-30,-42,30,10)));
+		Windmill.add(new Instr(Form.LINE, new Line2D.Double(-30,10,30,-42)));
+	}
+	public static final Symbol Windsock = new Symbol();
+	static {
+		Windsock.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Landmarks.Base, 1.0, 0, 0, null, null)));
+		Windsock.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Windsock.add(new Instr(Form.LINE, new Line2D.Double(0,-10,0,-100)));
+		Windsock.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		Windsock.add(new Instr(Form.LINE, new Line2D.Double(0,-100,0,-150)));
+		Windsock.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-100.0); p.lineTo(10.0,-100.0); p.lineTo(10.0,-150.0); p.lineTo(0.0,-150.0);
+		p.moveTo(10.0,-150.0); p.lineTo(50.0,-145.0); p.lineTo(120.0,-70.0); p.quadTo(120.0,-55.0,105.0,-55.0);
+		p.lineTo(55,-95); p.lineTo(40,-102); p.lineTo(10,-100); p.moveTo(40,-102); p.lineTo(50,-120); p.moveTo(55,-95); p.lineTo(75,-97);
+		Windsock.add(new Instr(Form.PLIN, p));
+	}
+	
+	public static final EnumMap<CatLMK, Symbol> Shapes = new EnumMap<CatLMK, Symbol>(CatLMK.class);
+	static {
+		Shapes.put(CatLMK.LMK_CARN, Beacons.Cairn); Shapes.put(CatLMK.LMK_CHMY, Landmarks.Chimney);
+		Shapes.put(CatLMK.LMK_DISH, Landmarks.DishAerial); Shapes.put(CatLMK.LMK_FLAG, Landmarks.Flagstaff); Shapes.put(CatLMK.LMK_FLAR, Landmarks.FlareStack);
+		Shapes.put(CatLMK.LMK_MAST, Landmarks.Mast); Shapes.put(CatLMK.LMK_WNDS, Landmarks.Windsock); Shapes.put(CatLMK.LMK_MNMT, Landmarks.Monument);
+		Shapes.put(CatLMK.LMK_CLMN, Landmarks.Monument); Shapes.put(CatLMK.LMK_MEML, Landmarks.Monument); Shapes.put(CatLMK.LMK_OBLK, Landmarks.Monument);
+		Shapes.put(CatLMK.LMK_STAT, Landmarks.Monument); Shapes.put(CatLMK.LMK_CROS, Landmarks.Cross); Shapes.put(CatLMK.LMK_DOME, Landmarks.Dome);
+		Shapes.put(CatLMK.LMK_RADR, Landmarks.Mast); Shapes.put(CatLMK.LMK_TOWR, Landmarks.LandTower); Shapes.put(CatLMK.LMK_WNDM, Landmarks.Windmill);
+		Shapes.put(CatLMK.LMK_WNDG, Landmarks.WindMotor); Shapes.put(CatLMK.LMK_SPIR, Landmarks.Spire); Shapes.put(CatLMK.LMK_BLDR, Beacons.Cairn);
+		Shapes.put(CatLMK.LMK_MNRT, Landmarks.Minaret); Shapes.put(CatLMK.LMK_WTRT, Landmarks.WaterTower);
+	}
+
+	public static final EnumMap<FncFNC, Symbol> Funcs = new EnumMap<FncFNC, Symbol>(FncFNC.class);
+	static {
+		Funcs.put(FncFNC.FNC_CHCH, Landmarks.Church); Funcs.put(FncFNC.FNC_CHPL, Landmarks.Church); Funcs.put(FncFNC.FNC_TMPL, Landmarks.Temple);
+		Funcs.put(FncFNC.FNC_PGDA, Landmarks.Temple); Funcs.put(FncFNC.FNC_SHSH, Landmarks.Temple); Funcs.put(FncFNC.FNC_BTMP, Landmarks.Temple);
+		Funcs.put(FncFNC.FNC_MOSQ, Landmarks.Minaret); Funcs.put(FncFNC.FNC_MRBT, Landmarks.Spire); Funcs.put(FncFNC.FNC_COMM, Landmarks.RadioTV);
+		Funcs.put(FncFNC.FNC_TV, Landmarks.RadioTV); Funcs.put(FncFNC.FNC_RADO, Landmarks.RadioTV); Funcs.put(FncFNC.FNC_RADR, Landmarks.RadioTV);
+		Funcs.put(FncFNC.FNC_LGHT, Beacons.LightMajor); Funcs.put(FncFNC.FNC_MCWV, Landmarks.RadioTV); Funcs.put(FncFNC.FNC_HBRM, Harbours.HarbourMaster);
+		Funcs.put(FncFNC.FNC_CSTM, Harbours.Customs); Funcs.put(FncFNC.FNC_HLTH, Harbours.Hospital); Funcs.put(FncFNC.FNC_HOSP, Harbours.Hospital);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Notices.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Notices.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Notices.java	(revision 30894)
@@ -0,0 +1,1164 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.*;
+import java.util.ArrayList;
+import java.util.EnumMap;
+
+import s57.S57val.*;
+import symbols.Symbols.*;
+
+public class Notices {
+	private static final Symbol Bollard = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(20,21); p.lineTo(20,16.5); p.lineTo(11.6,16.5); p.quadTo(9.1,9.6,8.3,2.0); p.lineTo(-8.0,-0.3); p.quadTo(-8.6,9.0,-11.3,16.5);
+		p.lineTo(-23.5,16.5); p.lineTo(-23.5,21.0); p.closePath(); p.moveTo(23.8,3.0); p.lineTo(-10.7,-1.8); p.curveTo(-13.1,-2.2,-12.8,-6.0,-10.2,-5.8); p.lineTo(23.8,-1.1);
+		p.closePath(); p.moveTo(8.4,-4.3); p.curveTo(9.0,-9.3,9.0,-11.4,11.2,-13.0); p.curveTo(12.8,-15.0,12.8,-16.7,11.0,-18.6); p.curveTo(4.0,-22.2,-4.0,-22.2,-11.0,-18.6);
+		p.curveTo(-12.8,-16.7,-12.8,-15.0,-11.2,-13.0); p.curveTo(-9.0,-11.3,-8.7,-9.5,-8.4,-6.5); p.closePath();
+		Bollard.add(new Instr(Form.PGON, p));
+	}
+	private static final Symbol Motor = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-5.0,4.3); p.curveTo(-3.7,5.5,-1.8,5.7,-0.2,4.9); p.curveTo(1.3,8.7,4.6,10.9,8.4,10.9); p.curveTo(14.0,10.9,17.5,6.3,17.5,2.0);
+		p.curveTo(17.5,-0.7,16.1,-3.2,14.5,-3.2); p.curveTo(12.5,-3.2,11.7,0.8,2.5,1.1); p.curveTo(2.5,-1.2,1.6,-2.2,0.6,-3.0); p.curveTo(3.2,-5.6,4.0,-12.6,-1.0,-16.1);
+		p.curveTo(-5.3,-19.2,-11.6,-18.3,-13.7,-13.7); p.curveTo(-14.3,-12.2,-14.0,-11.2,-12.5,-10.6); p.curveTo(-8.6,-9.6,-5.3,-6.0,-4.0,-3.4); p.curveTo(-5.4,-2.6,-6.2,-2.0,-6.2,0.2);
+		p.curveTo(-12.8,-1.0,-17.5,3.7,-17.5,9.3); p.curveTo(-17.5,14.7,-12.6,18.8,-8.0,17.6); p.curveTo(-7.0,17.2,-6.6,16.2,-7.2,14.6); p.curveTo(-7.7,12.4,-7.0,7.7,-5.0,4.3); p.closePath();
+		Motor.add(new Instr(Form.PGON, p));
+	}
+	private static final Symbol Rowboat = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-17.5,-2.0); p.lineTo(17.5,-2.0); p.lineTo(15.0,6.0); p.lineTo(-11.0,6.0); p.closePath();
+		Rowboat.add(new Instr(Form.PGON, p));
+		Rowboat.add(new Instr(Form.RSHP, new Ellipse2D.Double(-6,-17.5,6,6)));
+		Rowboat.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Rowboat.add(new Instr(Form.LINE, new Line2D.Double(-5.5,-9,-8,0)));
+		Rowboat.add(new Instr(Form.LINE, new Line2D.Double(-5.0,10.0,-7.5,14.0)));
+		Rowboat.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Rowboat.add(new Instr(Form.LINE, new Line2D.Double(-5.5,-9,7,-6.5)));
+		Rowboat.add(new Instr(Form.LINE, new Line2D.Double(7.3,-7.8,-5.0,10.0)));
+	}
+	private static final Symbol Sailboard = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-6.0,19.0); p.quadTo(-4.0,-5,1.5,-20.0); p.quadTo(14,-7,15.5,6.5); p.quadTo(7,17,-6.0,19.0); p.closePath();
+		Sailboard.add(new Instr(Form.PGON, p));
+		Sailboard.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Sailboard.add(new Instr(Form.LINE, new Line2D.Double(-2,20,-10,20)));
+		Sailboard.add(new Instr(Form.LINE, new Line2D.Double(-13,2.5,-3,2.5)));
+		Sailboard.add(new Instr(Form.RSHP, new Ellipse2D.Double(-15,-4,5,5)));
+		Sailboard.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(-13,2.5); p.lineTo(-12,6.0); p.lineTo(-12,9.5);
+		Sailboard.add(new Instr(Form.PLIN, p));
+		Sailboard.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(-12,9.5); p.lineTo(-7.5,13.0); p.lineTo(-6.0,19.0);
+		Sailboard.add(new Instr(Form.PLIN, p));
+	}
+	private static final Symbol Sailboat = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(3.75,-20.5); p.lineTo(3.75,8.5); p.lineTo(-19.5,8.5); p.closePath();
+		Sailboat.add(new Instr(Form.PGON, p));
+		p = new Path2D.Double(); p.moveTo(-19.5,12.0); p.lineTo(19.5,12.0); p.lineTo(13.0,20.5); p.lineTo(-16.0,20.5); p.closePath();
+		Sailboat.add(new Instr(Form.PGON, p));
+	}
+	private static final Symbol Slipway = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-17,-5.5); p.lineTo(-13.5,0); p.lineTo(4,-1.5); p.quadTo(18,-5,20,-13.5); p.closePath();
+		p.moveTo(-14,7); p.lineTo(-14,11); p.lineTo(20,11); p.lineTo(20,2); p.closePath();
+		Slipway.add(new Instr(Form.PGON, p));
+		Slipway.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Slipway.add(new Instr(Form.LINE, new Line2D.Double(-14,3,20,-2.5)));
+		Slipway.add(new Instr(Form.STRK, new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Slipway.add(new Instr(Form.ELPS, new Ellipse2D.Double(1,1.5,3,3)));
+		p = new Path2D.Double(); p.moveTo(-21,8.5); p.curveTo(-17.5, 5, -17.5, 12, -13, 7.2);
+		Slipway.add(new Instr(Form.PLIN, p));
+	}
+	private static final Symbol Speedboat = new Symbol();
+	static {
+		Speedboat.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Speedboat.add(new Instr(Form.LINE, new Line2D.Double(-21,0,-17,-1)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-17.5,8.5); p.curveTo(-10.5,13,-2.5,2,4,6); p.curveTo(12,2,11.5,9.5,20,6);
+		Speedboat.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(-18.5,1.5); p.lineTo(-16,6); p.curveTo(-9, 9.0, -3.5, -2.0, 4.5, 3.5); p.lineTo(14.5,0); p.quadTo(19, -3, 19.5, -9);
+		p.lineTo(9.5,-6); p.lineTo(6.5,-8); p.lineTo(2.5,-4); p.closePath();
+		Speedboat.add(new Instr(Form.PGON, p));
+		Speedboat.add(new Instr(Form.RSHP, new Ellipse2D.Double(-1.5,-13,5,5)));
+		Speedboat.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Speedboat.add(new Instr(Form.LINE, new Line2D.Double(-2,-7,-5,0)));
+		Speedboat.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Speedboat.add(new Instr(Form.LINE, new Line2D.Double(-2,-7,5,-5)));
+	}
+	private static final Symbol Turn = new Symbol();
+	static {
+		Turn.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Turn.add(new Instr(Form.EARC, new Arc2D.Double(-9.0,-9.0,18.0,18.0,270.0,230.0,Arc2D.OPEN)));
+		Turn.add(new Instr(Form.EARC, new Arc2D.Double(-20.0,-20.0,40.0,40.0,315.0,-280.0,Arc2D.OPEN)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(21.8,-7.0); p.lineTo(18.8,-18.2); p.lineTo(10.5,-10.0); p.closePath();
+		p.moveTo(-12.9,0.7); p.lineTo(-1.7,-2.3); p.lineTo(-9.9,-10.5); p.closePath();
+		Turn.add(new Instr(Form.PGON, p));
+	}
+	private static final Symbol Waterbike = new Symbol();
+	static {
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-17.5,13); p.curveTo(-10.5,17.5,-2.5,6.5,4,10.5); p.curveTo(12,6.5,11.5,14,20,10.5);
+		Waterbike.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(-16.5,9.5); p.lineTo(-16,10.5); p.curveTo(-9, 13.5, -3.5, 2.5, 4.5, 8); p.quadTo(15, 4, 19.5, -4); p.closePath();
+		p.moveTo(19.5,-5); p.lineTo(1, -5); p.lineTo(-4.5, -10); p.lineTo(-5.5, -10); p.lineTo(2, -2); p.lineTo(-15, 4); p.lineTo(-16, 8); p.closePath();
+		Waterbike.add(new Instr(Form.PGON, p));
+		Waterbike.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(-7,1); p.lineTo(-7.5,-1.5); p.lineTo(-12.5,-3.5); p.lineTo(-11.5,-10.5);
+		Waterbike.add(new Instr(Form.PLIN, p));
+		Waterbike.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Waterbike.add(new Instr(Form.LINE, new Line2D.Double(-11.5,-10.5,-3,-8.5)));
+		Waterbike.add(new Instr(Form.RSHP, new Ellipse2D.Double(-11.5,-18,5,5)));
+	}
+	private static final Symbol Waterski = new Symbol();
+	static {
+		Waterski.add(new Instr(Form.RSHP, new Ellipse2D.Double(12,-18,6,6)));
+		Waterski.add(new Instr(Form.STRK, new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Waterski.add(new Instr(Form.LINE, new Line2D.Double(-18,-6,0,-6)));
+		Waterski.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(6.5,17.5); p.lineTo(-13,14.5); p.curveTo(-15,14.25,-16.0,13.6,-17.5,12.0);
+		Waterski.add(new Instr(Form.PLIN, p));
+		Waterski.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)));
+		p = new Path2D.Double(); p.moveTo(-1.5,-4.0); p.lineTo(14,-7.5); p.lineTo(9.5,3.5); p.lineTo(2.0,6.0); p.lineTo(-4.4,15.8);
+		Waterski.add(new Instr(Form.PLIN, p));
+	}
+	private static final Symbol NoticeA = new Symbol();
+	static {
+		NoticeA.add(new Instr(Form.FILL, new Color(0xe80000)));
+		NoticeA.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeA.add(new Instr(Form.FILL, Color.white));
+		NoticeA.add(new Instr(Form.RSHP, new Rectangle2D.Double(-21,-21,42,42)));
+		NoticeA.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		NoticeA.add(new Instr(Form.FILL, new Color(0xe80000)));
+		NoticeA.add(new Instr(Form.LINE, new Line2D.Double(-25,-25,25,25)));
+		NoticeA.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeA.add(new Instr(Form.FILL, Color.black));
+		NoticeA.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+	}
+	private static final Symbol NoticeB = new Symbol();
+	static {
+		NoticeB.add(new Instr(Form.FILL, new Color(0xe80000)));
+		NoticeB.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeB.add(new Instr(Form.FILL, Color.white));
+		NoticeB.add(new Instr(Form.RSHP, new Rectangle2D.Double(-21,-21,42,42)));
+		NoticeB.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB.add(new Instr(Form.FILL, Color.black));
+		NoticeB.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+	}
+	private static final Symbol NoticeE = new Symbol();
+	static {
+		NoticeE.add(new Instr(Form.FILL, new Color(0x0000a0)));
+		NoticeE.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeE.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE.add(new Instr(Form.FILL, Color.black));
+		NoticeE.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeE.add(new Instr(Form.FILL, Color.white));
+	}
+	public static final Symbol Notice = new Symbol();
+	static {
+		Notice.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Notice.add(new Instr(Form.FILL, new Color(0xe80000)));
+		Notice.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		Notice.add(new Instr(Form.FILL, new Color(0x0000a0)));
+		Notice.add(new Instr(Form.RSHP, new Rectangle2D.Double(-21,-21,42,42)));
+		Notice.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Notice.add(new Instr(Form.FILL, Color.black));
+		Notice.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+	}
+	public static final Symbol NoticeA1 = new Symbol();
+	static {
+		NoticeA1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA1.add(new Instr(Form.FILL, new Color(0xe80000)));
+		NoticeA1.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeA1.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeA1.add(new Instr(Form.FILL, Color.white));
+		NoticeA1.add(new Instr(Form.RSHP, new Rectangle2D.Double(-30,-10,60,20)));
+		NoticeA1.add(new Instr(Form.FILL, Color.black));
+		NoticeA1.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+	}
+	public static final Symbol NoticeA1a = new Symbol();
+	static {
+		NoticeA1a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA1a.add(new Instr(Form.FILL, new Color(0xe80000)));
+		NoticeA1a.add(new Instr(Form.RSHP, new Ellipse2D.Double(-30,-30,60,60)));
+		NoticeA1a.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeA1a.add(new Instr(Form.FILL, Color.white));
+		NoticeA1a.add(new Instr(Form.RSHP, new Rectangle2D.Double(-29,-10,58,20)));
+		NoticeA1a.add(new Instr(Form.FILL, Color.black));
+		NoticeA1a.add(new Instr(Form.ELPS, new Ellipse2D.Double(-30,-30,60,60)));
+	}
+	public static final Symbol NoticeA2 = new Symbol();
+	static {
+		NoticeA2.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA2.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA2.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-10,23); p.lineTo(-10,0); p.lineTo(-6,0); p.lineTo(-12.5,-8); p.lineTo(-19,0); p.lineTo(-15,0); p.lineTo(-15,23);
+		p.closePath(); p.moveTo(10,8); p.lineTo(10,-15); p.lineTo(6,-15); p.lineTo(12.5,-23); p.lineTo(19,-15); p.lineTo(15,-15); p.lineTo(15,8); p.closePath();
+		NoticeA2.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeA3 = new Symbol();
+	static {
+		NoticeA3.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA3.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA2, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-10,12); p.lineTo(-6,12); p.lineTo(-12.5,4); p.lineTo(-19,12);
+		p.closePath(); p.moveTo(10,-3); p.lineTo(6,-3); p.lineTo(12.5,-11); p.lineTo(19,-3); p.closePath();
+		NoticeA3.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeA4 = new Symbol();
+	static {
+		NoticeA4.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA4.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA4.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-10,-15); p.lineTo(-10,8); p.lineTo(-6,8); p.lineTo(-12.5,16); p.lineTo(-19,8); p.lineTo(-15,8); p.lineTo(-15,-15);
+		p.closePath(); p.moveTo(10,15); p.lineTo(10,-8); p.lineTo(6,-8); p.lineTo(12.5,-16); p.lineTo(19,-8); p.lineTo(15,-8); p.lineTo(15,15); p.closePath();
+		NoticeA4.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeA4_1 = new Symbol();
+	static {
+		NoticeA4_1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA4_1.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA4, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-10,-4); p.lineTo(-6,-4); p.lineTo(-12.5,4); p.lineTo(-19,-4);
+		p.closePath(); p.moveTo(10,5); p.lineTo(6,5); p.lineTo(12.5,-3); p.lineTo(19,5); p.closePath();
+		NoticeA4_1.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeA5 = new Symbol();
+	static {
+		NoticeA5.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA5.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD); p.moveTo(-5.3,14.6); p.lineTo(-5.3,4.0); p.lineTo(0.0,4.0); p.curveTo(4.2,4.0,7.4,3.5,9.4,0.0);
+		p.curveTo(11.4,-2.8,11.4,-7.2,9.4,-10.5); p.curveTo(7.4,-13.6,4.2,-14.0,0.0,-14.0); p.lineTo(-11.0,-14.0); p.lineTo(-11.0,14.6); p.closePath();
+		p.moveTo(-5.3,-1.0); p.lineTo(0.0,-1.0); p.curveTo(6.5,-1.0,6.5,-9.0,0.0,-9.0); p.lineTo(-5.3,-9.0); p.closePath();
+		NoticeA5.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeA5_1 = new Symbol();
+	static {
+		NoticeA5_1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA5_1.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeA6 = new Symbol();
+	static {
+		NoticeA6.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 0.4, 0, 0, new Scheme(Color.black), new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(180.0))))));
+	}
+	public static final Symbol NoticeA7 = new Symbol();
+	static {
+		NoticeA7.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Bollard, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA8 = new Symbol();
+	static {
+		NoticeA8.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Turn, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA9 = new Symbol();
+	static {
+		NoticeA9.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA9.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA9.add(new Instr(Form.STRK, new BasicStroke(7, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeA9.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-23,10); p.curveTo(-11,10,-12,4,0,4); p.curveTo(12,4,11,10,23,10);
+		p.moveTo(-23,-3); p.curveTo(-11,-3,-12,-9,0,-9); p.curveTo(12,-9,11,-3,23,-3);
+		NoticeA9.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol NoticeA10a = new Symbol();
+	static {
+		NoticeA10a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA10a.add(new Instr(Form.FILL, Color.white));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(30,0); p.lineTo(0,30); p.closePath();
+		NoticeA10a.add(new Instr(Form.PGON, p));
+		NoticeA10a.add(new Instr(Form.FILL, new Color(0xe80000)));
+		p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(-30,0); p.lineTo(0,30); p.closePath();
+		NoticeA10a.add(new Instr(Form.PGON, p));
+		NoticeA10a.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeA10a.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(-30,0); p.lineTo(0,30); p.lineTo(30,0); p.closePath();
+		NoticeA10a.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol NoticeA10b = new Symbol();
+	static {
+		NoticeA10b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA10b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA10a, 1.0, 0, 0, null, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(180.0))))));
+	}
+	public static final Symbol NoticeA12 = new Symbol();
+	static {
+		NoticeA12.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA12.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA12.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Motor, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA13 = new Symbol();
+	static {
+		NoticeA13.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA13.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA13.add(new Instr(Form.TEXT, new Caption("SPORT", new Font("Arial", Font.BOLD, 15), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 5)))));
+	}
+	public static final Symbol NoticeA14 = new Symbol();
+	static {
+		NoticeA14.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA14.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA14.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Waterski, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA15 = new Symbol();
+	static {
+		NoticeA15.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA15.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA15.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Sailboat, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA16 = new Symbol();
+	static {
+		NoticeA16.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA16.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA16.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Rowboat, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA17 = new Symbol();
+	static {
+		NoticeA17.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA17.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA17.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Sailboard, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA18 = new Symbol();
+	static {
+		NoticeA18.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA18.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA18.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Speedboat, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA19 = new Symbol();
+	static {
+		NoticeA19.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA19.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA19.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Slipway, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeA20 = new Symbol();
+	static {
+		NoticeA20.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeA20.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeA, 1.0, 0, 0, null, null)));
+		NoticeA20.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Waterbike, 1.0, 0, 0, new Scheme(Color.black), null)));
+	}
+	public static final Symbol NoticeB1a = new Symbol();
+	static {
+		NoticeB1a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB1a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(21,8); p.lineTo(-8,8); p.lineTo(-8,18); p.lineTo(-21,0);
+		p.lineTo(-8,-18); p.lineTo(-8,-8); p.lineTo(21,-8); p.closePath();
+		NoticeB1a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB1b = new Symbol();
+	static {
+		NoticeB1b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB1b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-21,8); p.lineTo(8,8); p.lineTo(8,18); p.lineTo(21,0);
+		p.lineTo(8,-18); p.lineTo(8,-8); p.lineTo(-21,-8); p.closePath();
+		NoticeB1b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB2a = new Symbol();
+	static {
+		NoticeB2a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB2a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB2a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(18,21); p.lineTo(18,10); p.lineTo(-15,-10); p.lineTo(-15,-15);
+		NoticeB2a.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(-15,-21); p.lineTo(-21,-15); p.lineTo(-9,-15); p.closePath();
+		NoticeB2a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB2b = new Symbol();
+	static {
+		NoticeB2b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB2b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB2b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB2b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-18,21); p.lineTo(-18,10); p.lineTo(15,-10); p.lineTo(15,-15);
+		NoticeB2b.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(15,-21); p.lineTo(21,-15); p.lineTo(9,-15); p.closePath();
+		NoticeB2b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB3a = new Symbol();
+	static {
+		NoticeB3a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB3a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB3a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB3a.add(new Instr(Form.LINE, new Line2D.Double(-15,21,-15,-15)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15,-21); p.lineTo(-21,-15); p.lineTo(-9,-15); p.closePath();
+		NoticeB3a.add(new Instr(Form.PGON, p));
+		NoticeB3a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[] { 5.5f, 2.4f }, 0.0f)));
+		NoticeB3a.add(new Instr(Form.LINE, new Line2D.Double(15,-21,15,15)));
+		p = new Path2D.Double(); p.moveTo(15,21); p.lineTo(21,15); p.lineTo(9,15); p.closePath();
+		NoticeB3a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB3b = new Symbol();
+	static {
+		NoticeB3b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB3b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB3b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB3b.add(new Instr(Form.LINE, new Line2D.Double(15,21,15,-15)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(15,-21); p.lineTo(21,-15); p.lineTo(9,-15); p.closePath();
+		NoticeB3b.add(new Instr(Form.PGON, p));
+		NoticeB3b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[] { 5.5f, 2.4f }, 0.0f)));
+		NoticeB3b.add(new Instr(Form.LINE, new Line2D.Double(-15,-21,-15,15)));
+		p = new Path2D.Double(); p.moveTo(-15,21); p.lineTo(-21,15); p.lineTo(-9,15); p.closePath();
+		NoticeB3b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB4a = new Symbol();
+	static {
+		NoticeB4a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB4a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB2a, 1.0, 0, 0, null, null)));
+		NoticeB4a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[] { 5.5f, 2.4f }, 0.0f)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(18,-21); p.lineTo(18,-10); p.lineTo(-15,10); p.lineTo(-15,15);
+		NoticeB4a.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(-15,21); p.lineTo(-21,15); p.lineTo(-9,15); p.closePath();
+		NoticeB4a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB4b = new Symbol();
+	static {
+		NoticeB4b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB4b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB2b, 1.0, 0, 0, null, null)));
+		NoticeB4b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[] { 5.5f, 2.4f }, 0.0f)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-18,-21); p.lineTo(-18,-10); p.lineTo(15,10); p.lineTo(15,15);
+		NoticeB4b.add(new Instr(Form.PLIN, p));
+		p = new Path2D.Double(); p.moveTo(15,21); p.lineTo(21,15); p.lineTo(9,15); p.closePath();
+		NoticeB4b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeB5 = new Symbol();
+	static {
+		NoticeB5.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB5.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB5.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		NoticeB5.add(new Instr(Form.LINE, new Line2D.Double(15,0,-15,0)));
+	}
+	public static final Symbol NoticeB6 = new Symbol();
+	static {
+		NoticeB6.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeB7 = new Symbol();
+	static {
+		NoticeB7.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB7.add(new Instr(Form.RSHP, new Ellipse2D.Double(-10,-10,20,20)));
+	}
+	public static final Symbol NoticeB8 = new Symbol();
+	static {
+		NoticeB8.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB8.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)));
+		NoticeB8.add(new Instr(Form.LINE, new Line2D.Double(0,15,0,-15)));
+	}
+	public static final Symbol NoticeB9a = new Symbol();
+	static {
+		NoticeB9a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB9a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB9a.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB9a.add(new Instr(Form.LINE, new Line2D.Double(-21,0,21,0)));
+		NoticeB9a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB9a.add(new Instr(Form.LINE, new Line2D.Double(0,21,0,0)));
+	}
+	public static final Symbol NoticeB9b = new Symbol();
+	static {
+		NoticeB9b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB9b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB9b.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB9b.add(new Instr(Form.LINE, new Line2D.Double(-21,0,21,0)));
+		NoticeB9b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeB9b.add(new Instr(Form.LINE, new Line2D.Double(0,21,0,-21)));
+	}
+	public static final Symbol NoticeB11 = new Symbol();
+	static {
+		NoticeB11.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeB11.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		NoticeB11.add(new Instr(Form.TEXT, new Caption("VHF", new Font("Arial", Font.BOLD, 20), Color.black, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 0)))));
+	}
+	public static final Symbol NoticeC1 = new Symbol();
+	static {
+		NoticeC1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC1.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15,21); p.lineTo(0,12); p.lineTo(15,21); p.closePath();
+		NoticeC1.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeC2 = new Symbol();
+	static {
+		NoticeC2.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC2.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15,-21); p.lineTo(0,-12); p.lineTo(15,-21); p.closePath();
+		NoticeC2.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeC3 = new Symbol();
+	static {
+		NoticeC3.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC3.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(21,-15); p.lineTo(12,0); p.lineTo(21,15); p.closePath();
+		p.moveTo(-21,-15); p.lineTo(-12,0); p.lineTo(-21,15); p.closePath();
+		NoticeC3.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeC4 = new Symbol();
+	static {
+		NoticeC4.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC4.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeC5a = new Symbol();
+	static {
+		NoticeC5a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC5a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-21,-21); p.lineTo(10,-21); p.lineTo(21,0);	p.lineTo(10,21);	p.lineTo(-21,21); p.closePath();
+		NoticeC5a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeC5b = new Symbol();
+	static {
+		NoticeC5b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeC5b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeB, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(21,-21); p.lineTo(-10,-21); p.lineTo(-21,0);	p.lineTo(-10,21);	p.lineTo(21,21); p.closePath();
+		NoticeC5b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeD1a = new Symbol();
+	static {
+		NoticeD1a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD1a.add(new Instr(Form.FILL, Color.yellow));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(-30,0); p.lineTo(0,30); p.lineTo(30,0); p.closePath();
+		NoticeD1a.add(new Instr(Form.PGON, p));
+		NoticeD1a.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeD1a.add(new Instr(Form.FILL, Color.black));
+		NoticeD1a.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol NoticeD1b = new Symbol();
+	static {
+		NoticeD1b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD1b.add(new Instr(Form.FILL, Color.yellow));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-30,0); p.lineTo(-15,25); p.lineTo(15,-25); p.lineTo(30,0);	p.lineTo(15,25); p.lineTo(-15,-25); p.closePath();
+		NoticeD1b.add(new Instr(Form.PGON, p));
+		NoticeD1b.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeD1b.add(new Instr(Form.FILL, Color.black));
+		NoticeD1b.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol NoticeD2a = new Symbol();
+	static {
+		NoticeD2a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD2a.add(new Instr(Form.FILL, Color.white));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(-30,0); p.lineTo(0,30); p.closePath();
+		NoticeD2a.add(new Instr(Form.PGON, p));
+		NoticeD2a.add(new Instr(Form.FILL, new Color(0x00e800)));
+		p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(30,0); p.lineTo(0,30); p.closePath();
+		NoticeD2a.add(new Instr(Form.PGON, p));
+		NoticeD2a.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeD2a.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(0,-30); p.lineTo(-30,0); p.lineTo(0,30); p.lineTo(30,0); p.closePath();
+		NoticeD2a.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol NoticeD2b = new Symbol();
+	static {
+		NoticeD2b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD2b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeD2a, 1.0, 0, 0, null, new Delta(Handle.CC, AffineTransform.getRotateInstance(Math.toRadians(180.0))))));
+	}
+	public static final Symbol NoticeD3a = new Symbol();
+	static {
+		NoticeD3a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD3a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(28,10); p.lineTo(-10,10); p.lineTo(-10,20); p.lineTo(-28,0);
+		p.lineTo(-10,-20); p.lineTo(-10,-10); p.lineTo(28,-10); p.closePath();
+		NoticeD3a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeD3b = new Symbol();
+	static {
+		NoticeD3b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeD3b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-28,10); p.lineTo(10,10); p.lineTo(10,20); p.lineTo(28,0);
+		p.lineTo(10,-20); p.lineTo(10,-10); p.lineTo(-28,-10); p.closePath();
+		NoticeD3b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE1 = new Symbol();
+	static {
+		NoticeE1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE1.add(new Instr(Form.FILL, new Color(0x00e800)));
+		NoticeE1.add(new Instr(Form.RSHP, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+		NoticeE1.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE1.add(new Instr(Form.FILL, Color.white));
+		NoticeE1.add(new Instr(Form.RSHP, new Rectangle2D.Double(-10,-30,20,60)));
+		NoticeE1.add(new Instr(Form.FILL, Color.black));
+		NoticeE1.add(new Instr(Form.RRCT, new RoundRectangle2D.Double(-30,-30,60,60,4,4)));
+	}
+	public static final Symbol NoticeE2 = new Symbol();
+	static {
+		NoticeE2.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE2.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(5,-25); p.lineTo(-10,-1); p.lineTo(10,-1); p.lineTo(-10,20);
+		p.lineTo(-7,20); p.lineTo(-12,25); p.lineTo(-16,20); p.lineTo(-13,20); p.lineTo(4,1); p.lineTo(-14,1);
+		p.lineTo(2,-25); p.closePath();
+		NoticeE2.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE3 = new Symbol();
+	static {
+		NoticeE3.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE3.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE3.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(25,-20,25,20)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(-25,-20,-25,20)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(-15,-15,-15,20)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(-5,-15,-5,20)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(5,-15,5,20)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(15,-15,15,20)));
+		NoticeE3.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(-26,18.5,26,18.5)));
+		NoticeE3.add(new Instr(Form.LINE, new Line2D.Double(-26,-15,26,-15)));
+	}
+	public static final Symbol NoticeE4a = new Symbol();
+	static {
+		NoticeE4a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE4a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-20,-10); p.lineTo(-5,-10); p.lineTo(-5,-20); p.lineTo(5,-20); p.lineTo(5,-10);
+		p.lineTo(20,-10); p.lineTo(15,0); p.lineTo(-15,0); p.closePath();
+		p.moveTo(-25,5); p.lineTo(25,5); p.lineTo(25,10); p.lineTo(-25,10); p.closePath();
+		NoticeE4a.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE4b = new Symbol();
+	static {
+		NoticeE4b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE4b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-20,0); p.lineTo(-5,0); p.lineTo(-5,-10); p.lineTo(5,-10); p.lineTo(5,0);
+		p.lineTo(20,0); p.lineTo(15,10); p.lineTo(-15,10); p.closePath();
+		NoticeE4b.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5 = new Symbol();
+	static {
+		NoticeE5.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD); p.moveTo(-5.3,14.6); p.lineTo(-5.3,4.0); p.lineTo(0.0,4.0); p.curveTo(4.2,4.0,7.4,3.5,9.4,0.0);
+		p.curveTo(11.4,-2.8,11.4,-7.2,9.4,-10.5); p.curveTo(7.4,-13.6,4.2,-14.0,0.0,-14.0); p.lineTo(-11.0,-14.0); p.lineTo(-11.0,14.6); p.closePath();
+		p.moveTo(-5.3,-1.0); p.lineTo(0.0,-1.0); p.curveTo(6.5,-1.0,6.5,-9.0,0.0,-9.0); p.lineTo(-5.3,-9.0); p.closePath();
+		NoticeE5.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_1 = new Symbol();
+	static {
+		NoticeE5_1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_1.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeE5_2 = new Symbol();
+	static {
+		NoticeE5_2.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_2.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeE5_3 = new Symbol();
+	static {
+		NoticeE5_3.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_3.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+	}
+	public static final Symbol NoticeE5_4 = new Symbol();
+	static {
+		NoticeE5_4.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_4.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,25); p.lineTo(0,-28); p.lineTo(28,25); p.closePath();
+		NoticeE5_4.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_5 = new Symbol();
+	static {
+		NoticeE5_5.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_5.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,25); p.lineTo(0,-28); p.lineTo(28,25); p.closePath();
+		p.moveTo(0,24); p.lineTo(-15,2); p.lineTo(15,2); p.closePath();
+		NoticeE5_5.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_6 = new Symbol();
+	static {
+		NoticeE5_6.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,25); p.lineTo(0,-28); p.lineTo(28,25); p.closePath();
+		p.moveTo(0,7); p.lineTo(-10,-8); p.lineTo(10,-8); p.closePath();
+		p.moveTo(0,24); p.lineTo(-10,9); p.lineTo(10,9); p.closePath();
+		NoticeE5_6.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_7 = new Symbol();
+	static {
+		NoticeE5_7.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,25); p.lineTo(0,-28); p.lineTo(28,25); p.closePath();
+		p.moveTo(0,-1); p.lineTo(-8,-11); p.lineTo(8,-11); p.closePath();
+		p.moveTo(0,11); p.lineTo(-8,1); p.lineTo(8,1); p.closePath();
+		p.moveTo(0,23); p.lineTo(-8,13); p.lineTo(8,13); p.closePath();
+		NoticeE5_7.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_8 = new Symbol();
+	static {
+		NoticeE5_8.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,-25); p.lineTo(0,28); p.lineTo(28,-25); p.closePath();
+		NoticeE5_8.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_9 = new Symbol();
+	static {
+		NoticeE5_9.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_9.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,-25); p.lineTo(0,28); p.lineTo(28,-25); p.closePath();
+		p.moveTo(0,8); p.lineTo(-15,-14); p.lineTo(15,-14); p.closePath();
+		NoticeE5_9.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_10 = new Symbol();
+	static {
+		NoticeE5_10.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_10.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,-25); p.lineTo(0,28); p.lineTo(28,-25); p.closePath();
+		p.moveTo(0,-5); p.lineTo(-10,-20); p.lineTo(10,-20); p.closePath();
+		p.moveTo(0,15); p.lineTo(-10,0); p.lineTo(10,0); p.closePath();
+		NoticeE5_10.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_11 = new Symbol();
+	static {
+		NoticeE5_11.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_11.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,-25); p.lineTo(0,28); p.lineTo(28,-25); p.closePath();
+		p.moveTo(0,-12); p.lineTo(-8,-22); p.lineTo(8,-22); p.closePath();
+		p.moveTo(0,3); p.lineTo(-8,-7); p.lineTo(8,-7); p.closePath();
+		p.moveTo(0,18); p.lineTo(-8,8); p.lineTo(8,8); p.closePath();
+		NoticeE5_11.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_12 = new Symbol();
+	static {
+		NoticeE5_12.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_12.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,0); p.lineTo(0,28); p.lineTo(28,0); p.lineTo(0,-28); p.closePath();
+		NoticeE5_12.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_13 = new Symbol();
+	static {
+		NoticeE5_13.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_13.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,0); p.lineTo(0,28); p.lineTo(28,0); p.lineTo(0,-28); p.closePath();
+		p.moveTo(0,15); p.lineTo(-15,-7); p.lineTo(15,-7); p.closePath();
+		NoticeE5_13.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_14 = new Symbol();
+	static {
+		NoticeE5_14.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_14.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,0); p.lineTo(0,28); p.lineTo(28,0); p.lineTo(0,-28); p.closePath();
+		p.moveTo(0,0); p.lineTo(-10,-15); p.lineTo(10,-15); p.closePath();
+		p.moveTo(0,20); p.lineTo(-10,5); p.lineTo(10,5); p.closePath();
+		NoticeE5_14.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE5_15 = new Symbol();
+	static {
+		NoticeE5_15.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE5_15.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-28,0); p.lineTo(0,28); p.lineTo(28,0); p.lineTo(0,-28); p.closePath();
+		p.moveTo(0,-7); p.lineTo(-8,-17); p.lineTo(8,-17); p.closePath();
+		p.moveTo(0,8); p.lineTo(-8,-2); p.lineTo(8,-2); p.closePath();
+		p.moveTo(0,23); p.lineTo(-8,13); p.lineTo(8,13); p.closePath();
+		NoticeE5_15.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE6 = new Symbol();
+	static {
+		NoticeE6.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE6.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Harbours.Anchor, 0.4, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE7 = new Symbol();
+	static {
+		NoticeE7.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE7.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Bollard, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE7_1 = new Symbol();
+	static {
+		NoticeE7_1.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE7_1.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE7_1.add(new Instr(Form.STRK, new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE7_1.add(new Instr(Form.LINE, new Line2D.Double(20,25,20,-10)));
+		NoticeE7_1.add(new Instr(Form.LINE, new Line2D.Double(22,-8,-15,-20)));
+		NoticeE7_1.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE7_1.add(new Instr(Form.LINE, new Line2D.Double(20,8,0,-15)));
+		Path2D.Double p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-17,2); p.quadTo(-5,0,7,2); p.lineTo(9,12); p.lineTo(7,20); p.lineTo(6,20); p.lineTo(6,23); p.lineTo(3,23); p.lineTo(3,20);
+		p.quadTo(-5,22,-13,20); p.lineTo(-13,23); p.lineTo(-16,23); p.lineTo(-16,20); p.lineTo(-17,20); p.lineTo(-19,12); p.closePath();
+		p.moveTo(-15,4); p.quadTo(-3,2,5,4); p.lineTo(6,11); p.quadTo(-5,9,-16,11); p.closePath();
+		NoticeE7_1.add(new Instr(Form.PGON, p));
+		NoticeE7_1.add(new Instr(Form.FILL, new Color(0x0000a0)));
+		NoticeE7_1.add(new Instr(Form.RSHP, new Ellipse2D.Double(-16,13,4,4)));
+		NoticeE7_1.add(new Instr(Form.RSHP, new Ellipse2D.Double(2,13,4,4)));
+	}
+	public static final Symbol NoticeE8 = new Symbol();
+	static {
+		NoticeE8.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE8.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Turn, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE9a = new Symbol();
+	static {
+		NoticeE9a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9a.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9a.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-29)));
+		NoticeE9a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9a.add(new Instr(Form.LINE, new Line2D.Double(-29,0,29,0)));
+	}
+	public static final Symbol NoticeE9b = new Symbol();
+	static {
+		NoticeE9b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9b.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9b.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-29)));
+		NoticeE9b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9b.add(new Instr(Form.LINE, new Line2D.Double(-2,0,29,0)));
+	}
+	public static final Symbol NoticeE9c = new Symbol();
+	static {
+		NoticeE9c.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9c.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9c.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9c.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-29)));
+		NoticeE9c.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9c.add(new Instr(Form.LINE, new Line2D.Double(2,0,-29,0)));
+	}
+	public static final Symbol NoticeE9d = new Symbol();
+	static {
+		NoticeE9d.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9d.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9d.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9d.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9d.add(new Instr(Form.LINE, new Line2D.Double(-4,0,29,0)));
+		NoticeE9d.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9d.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,2)));
+	}
+	public static final Symbol NoticeE9e = new Symbol();
+	static {
+		NoticeE9e.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9e.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9e.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9e.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9e.add(new Instr(Form.LINE, new Line2D.Double(4,0,-29,0)));
+		NoticeE9e.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9e.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,2)));
+	}
+	public static final Symbol NoticeE9f = new Symbol();
+	static {
+		NoticeE9f.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9f.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9f.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9f.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9f.add(new Instr(Form.LINE, new Line2D.Double(-4,0,29,0)));
+		NoticeE9f.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9f.add(new Instr(Form.LINE, new Line2D.Double(2,0,-29,0)));
+	}
+	public static final Symbol NoticeE9g = new Symbol();
+	static {
+		NoticeE9g.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9g.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9g.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9g.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9g.add(new Instr(Form.LINE, new Line2D.Double(4,0,-29,0)));
+		NoticeE9g.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9g.add(new Instr(Form.LINE, new Line2D.Double(-2,0,29,0)));
+	}
+	public static final Symbol NoticeE9h = new Symbol();
+	static {
+		NoticeE9h.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9h.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9h.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9h.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9h.add(new Instr(Form.LINE, new Line2D.Double(-4,0,29,0)));
+		NoticeE9h.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9h.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,2)));
+		NoticeE9h.add(new Instr(Form.LINE, new Line2D.Double(2,0,-29,0)));
+	}
+	public static final Symbol NoticeE9i = new Symbol();
+	static {
+		NoticeE9i.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE9i.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE9i.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9i.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-4)));
+		NoticeE9i.add(new Instr(Form.LINE, new Line2D.Double(4,0,-29,0)));
+		NoticeE9i.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE9i.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,2)));
+		NoticeE9i.add(new Instr(Form.LINE, new Line2D.Double(-2,0,29,0)));
+	}
+	public static final Symbol NoticeE10a = new Symbol();
+	static {
+		NoticeE10a.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE10a.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE10a.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10a.add(new Instr(Form.LINE, new Line2D.Double(-29,0,29,0)));
+		NoticeE10a.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10a.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-29)));
+	}
+	public static final Symbol NoticeE10b = new Symbol();
+	static {
+		NoticeE10b.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE10b.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE10b.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10b.add(new Instr(Form.LINE, new Line2D.Double(-29,0,29,0)));
+		NoticeE10b.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10b.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-2)));
+	}
+	public static final Symbol NoticeE10c = new Symbol();
+	static {
+		NoticeE10c.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE10c.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE10c.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10c.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,4)));
+		NoticeE10c.add(new Instr(Form.LINE, new Line2D.Double(-4,0,29,0)));
+		NoticeE10c.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10c.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-2)));
+	}
+	public static final Symbol NoticeE10d = new Symbol();
+	static {
+		NoticeE10d.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE10d.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE10d.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10d.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,4)));
+		NoticeE10d.add(new Instr(Form.LINE, new Line2D.Double(4,0,-29,0)));
+		NoticeE10d.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10d.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-2)));
+	}
+	public static final Symbol NoticeE10e = new Symbol();
+	static {
+	NoticeE10e.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+	NoticeE10e.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+	NoticeE10e.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+	NoticeE10e.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,4)));
+	NoticeE10e.add(new Instr(Form.LINE, new Line2D.Double(-4,0,29,0)));
+	NoticeE10e.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+	NoticeE10e.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-2)));
+	NoticeE10e.add(new Instr(Form.LINE, new Line2D.Double(2,0,-29,0)));
+	}
+	public static final Symbol NoticeE10f = new Symbol();
+	static {
+		NoticeE10f.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE10f.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE10f.add(new Instr(Form.STRK, new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10f.add(new Instr(Form.LINE, new Line2D.Double(0,-29,0,4)));
+		NoticeE10f.add(new Instr(Form.LINE, new Line2D.Double(4,0,-29,0)));
+		NoticeE10f.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		NoticeE10f.add(new Instr(Form.LINE, new Line2D.Double(0,29,0,-2)));
+		NoticeE10f.add(new Instr(Form.LINE, new Line2D.Double(-2,0,29,0)));
+	}
+	public static final Symbol NoticeE11 = new Symbol();
+	static {
+		NoticeE11.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE11.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE11.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)));
+		NoticeE11.add(new Instr(Form.LINE, new Line2D.Double(-27,-27,27,27)));
+	}
+	public static final Symbol NoticeE13 = new Symbol();
+	static {
+		NoticeE13.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE13.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-4,-16); p.lineTo(9,-16); p.lineTo(9,-14); p.lineTo(3.5,-14); p.lineTo(3.5,-7); p.lineTo(5,-7);
+		p.lineTo(5,1); p.lineTo(6.5,1); p.lineTo(6.5,5); p.lineTo(17.5,5); p.lineTo(17.5,1); p.lineTo(19,1); p.lineTo(19,15); p.lineTo(17.5,15);
+		p.lineTo(17.5,10); p.lineTo(17.5,10); p.lineTo(6.5,10); p.lineTo(6.5,13); p.lineTo(-2,13); p.lineTo(-2,10); p.lineTo(-9,10);
+		p.quadTo(-13.5,10,-13.5,16); p.lineTo(-19,16); p.quadTo(-19,5,-9,5); p.lineTo(-2,5); p.lineTo(-2,1); p.lineTo(0,1); p.lineTo(0,-7);
+		p.lineTo(1.5,-7); p.lineTo(1.5,-14); p.lineTo(-4,-14); p.closePath();
+		NoticeE13.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE14 = new Symbol();
+	static {
+		NoticeE14.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE14.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-18,-18); p.lineTo(-11,-7); p.lineTo(-9,-10); p.lineTo(-14,-18); p.closePath();
+		p.moveTo(9.5,7); p.lineTo(22.5,9); p.lineTo(21.5,5.5); p.lineTo(12,4); p.closePath();
+		p.moveTo(-19,-16.5); p.lineTo(-13,-6.5); p.quadTo(-15.5,-2,-12.5,0); p.lineTo(4,11); p.quadTo(7,13,10,9); p.lineTo(21.5,11);
+		p.curveTo(15.5,23,1,18.5,-9,12); p.curveTo(-18,6,-28.5,-7,-19,-16.5); p.closePath();
+		NoticeE14.add(new Instr(Form.PGON, p));
+	}
+	public static final Symbol NoticeE15 = new Symbol();
+	static {
+		NoticeE15.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE15.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE15.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Motor, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE16 = new Symbol();
+	static {
+		NoticeE16.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE16.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE16.add(new Instr(Form.TEXT, new Caption("SPORT", new Font("Arial", Font.BOLD, 15), Color.white, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 5)))));
+	}
+	public static final Symbol NoticeE17 = new Symbol();
+	static {
+		NoticeE17.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE17.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE17.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Waterski, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE18 = new Symbol();
+	static {
+		NoticeE18.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE18.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE18.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Sailboat, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE19 = new Symbol();
+	static {
+		NoticeE19.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE19.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE19.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Rowboat, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE20 = new Symbol();
+	static {
+		NoticeE20.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE20.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE20.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Sailboard, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE21 = new Symbol();
+	static {
+		NoticeE21.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE21.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE21.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Speedboat, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE22 = new Symbol();
+	static {
+		NoticeE22.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE22.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE22.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Slipway, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+	public static final Symbol NoticeE23 = new Symbol();
+	static {
+		NoticeE23.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE23.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE23.add(new Instr(Form.TEXT, new Caption("VHF", new Font("Arial", Font.BOLD, 20), Color.white, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0, 0)))));
+	}
+	public static final Symbol NoticeE24 = new Symbol();
+	static {
+		NoticeE24.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		NoticeE24.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.NoticeE, 1.0, 0, 0, null, null)));
+		NoticeE24.add(new Instr(Form.SYMB, new Symbols.SubSymbol(Notices.Waterbike, 1.0, 0, 0, new Scheme(Color.white), null)));
+	}
+
+	public static final EnumMap<CatNMK, Symbol> NmkCevni = new EnumMap<CatNMK, Symbol>(CatNMK.class);
+	static {
+		NmkCevni.put(CatNMK.NMK_UNKN, Notice); NmkCevni.put(CatNMK.NMK_NENT, NoticeA1); NmkCevni.put(CatNMK.NMK_CLSA, NoticeA1a); NmkCevni.put(CatNMK.NMK_NOVK, NoticeA2);
+		NmkCevni.put(CatNMK.NMK_NCOV, NoticeA3); NmkCevni.put(CatNMK.NMK_NPAS, NoticeA4); NmkCevni.put(CatNMK.NMK_NCPS, NoticeA4_1); NmkCevni.put(CatNMK.NMK_NBRT, NoticeA5);
+		NmkCevni.put(CatNMK.NMK_NBLL, NoticeA5_1); NmkCevni.put(CatNMK.NMK_NANK, NoticeA6); NmkCevni.put(CatNMK.NMK_NMOR, NoticeA7); NmkCevni.put(CatNMK.NMK_NTRN, NoticeA8);
+		NmkCevni.put(CatNMK.NMK_NWSH, NoticeA9); NmkCevni.put(CatNMK.NMK_NPSL, NoticeA10a); NmkCevni.put(CatNMK.NMK_NPSR, NoticeA10b); NmkCevni.put(CatNMK.NMK_NMTC, NoticeA12);
+		NmkCevni.put(CatNMK.NMK_NSPC, NoticeA13); NmkCevni.put(CatNMK.NMK_NWSK, NoticeA14); NmkCevni.put(CatNMK.NMK_NSLC, NoticeA15); NmkCevni.put(CatNMK.NMK_NUPC, NoticeA16);
+		NmkCevni.put(CatNMK.NMK_NSLB, NoticeA17); NmkCevni.put(CatNMK.NMK_NWBK, NoticeA20); NmkCevni.put(CatNMK.NMK_NHSC, NoticeA18); NmkCevni.put(CatNMK.NMK_NLBG, NoticeA19);
+		NmkCevni.put(CatNMK.NMK_MVTL, NoticeB1a); NmkCevni.put(CatNMK.NMK_MVTR, NoticeB1b); NmkCevni.put(CatNMK.NMK_MVTP, NoticeB2a); NmkCevni.put(CatNMK.NMK_MVTS, NoticeB2b);
+		NmkCevni.put(CatNMK.NMK_KPTP, NoticeB3a); NmkCevni.put(CatNMK.NMK_KPTS, NoticeB3b); NmkCevni.put(CatNMK.NMK_CSTP, NoticeB4a); NmkCevni.put(CatNMK.NMK_CSTS, NoticeB4b);
+		NmkCevni.put(CatNMK.NMK_STOP, NoticeB5); NmkCevni.put(CatNMK.NMK_SPDL, NoticeB6); NmkCevni.put(CatNMK.NMK_SHRN, NoticeB7); NmkCevni.put(CatNMK.NMK_KPLO, NoticeB8);
+		NmkCevni.put(CatNMK.NMK_GWJN, NoticeB9a); NmkCevni.put(CatNMK.NMK_GWCS, NoticeB9b); NmkCevni.put(CatNMK.NMK_MKRC, NoticeB11);
+		NmkCevni.put(CatNMK.NMK_LMDP, NoticeC1); NmkCevni.put(CatNMK.NMK_LMHR, NoticeC2);	NmkCevni.put(CatNMK.NMK_LMWD, NoticeC3); NmkCevni.put(CatNMK.NMK_NAVR, NoticeC4);
+		NmkCevni.put(CatNMK.NMK_CHDL, NoticeC5a); NmkCevni.put(CatNMK.NMK_CHDR, NoticeC5b);
+		NmkCevni.put(CatNMK.NMK_CHTW, NoticeD1a); NmkCevni.put(CatNMK.NMK_CHOW, NoticeD1b); NmkCevni.put(CatNMK.NMK_OPTR, NoticeD2a); NmkCevni.put(CatNMK.NMK_OPTL, NoticeD2b);
+		NmkCevni.put(CatNMK.NMK_PRTL, NoticeD3a); NmkCevni.put(CatNMK.NMK_PRTR, NoticeD3b);
+		NmkCevni.put(CatNMK.NMK_ENTP, NoticeE1); NmkCevni.put(CatNMK.NMK_OVHC, NoticeE2);	NmkCevni.put(CatNMK.NMK_WEIR, NoticeE3); NmkCevni.put(CatNMK.NMK_FERN, NoticeE4a);
+		NmkCevni.put(CatNMK.NMK_FERI, NoticeE4b); NmkCevni.put(CatNMK.NMK_BRTP, NoticeE5);	NmkCevni.put(CatNMK.NMK_BTLL, NoticeE5_1); NmkCevni.put(CatNMK.NMK_BTLS, NoticeE5_2);
+		NmkCevni.put(CatNMK.NMK_BTRL, NoticeE5_3); NmkCevni.put(CatNMK.NMK_BTUP, NoticeE5_4);	NmkCevni.put(CatNMK.NMK_BTP1, NoticeE5_5); NmkCevni.put(CatNMK.NMK_BTP2, NoticeE5_6);
+		NmkCevni.put(CatNMK.NMK_BTP3, NoticeE5_7); NmkCevni.put(CatNMK.NMK_BTUN, NoticeE5_8);	NmkCevni.put(CatNMK.NMK_BTN1, NoticeE5_9); NmkCevni.put(CatNMK.NMK_BTN2, NoticeE5_10);
+		NmkCevni.put(CatNMK.NMK_BTN3, NoticeE5_11); NmkCevni.put(CatNMK.NMK_BTUM, NoticeE5_12);	NmkCevni.put(CatNMK.NMK_BTU1, NoticeE5_13); NmkCevni.put(CatNMK.NMK_BTU2, NoticeE5_14);
+		NmkCevni.put(CatNMK.NMK_BTU3, NoticeE5_15); NmkCevni.put(CatNMK.NMK_ANKP, NoticeE6);	NmkCevni.put(CatNMK.NMK_MORP, NoticeE7); NmkCevni.put(CatNMK.NMK_VLBT, NoticeE7_1);
+		NmkCevni.put(CatNMK.NMK_TRNA, NoticeE8); NmkCevni.put(CatNMK.NMK_SWWC, NoticeE9a);	NmkCevni.put(CatNMK.NMK_SWWR, NoticeE9b); NmkCevni.put(CatNMK.NMK_SWWL, NoticeE9c);
+		NmkCevni.put(CatNMK.NMK_WRSA, NoticeE9d); NmkCevni.put(CatNMK.NMK_WLSA, NoticeE9e);	NmkCevni.put(CatNMK.NMK_WRSL, NoticeE9f); NmkCevni.put(CatNMK.NMK_WLSR, NoticeE9g);
+		NmkCevni.put(CatNMK.NMK_WRAL, NoticeE9h); NmkCevni.put(CatNMK.NMK_WLAR, NoticeE9i);	NmkCevni.put(CatNMK.NMK_MWWC, NoticeE10a); NmkCevni.put(CatNMK.NMK_MWWJ, NoticeE10b);
+		NmkCevni.put(CatNMK.NMK_MWAR, NoticeE10c); NmkCevni.put(CatNMK.NMK_MWAL, NoticeE10d);	NmkCevni.put(CatNMK.NMK_WARL, NoticeE10e); NmkCevni.put(CatNMK.NMK_WALR, NoticeE10f);
+		NmkCevni.put(CatNMK.NMK_PEND, NoticeE11); NmkCevni.put(CatNMK.NMK_DWTR, NoticeE13);	NmkCevni.put(CatNMK.NMK_TELE, NoticeE14); NmkCevni.put(CatNMK.NMK_MTCP, NoticeE15);
+		NmkCevni.put(CatNMK.NMK_SPCP, NoticeE16); NmkCevni.put(CatNMK.NMK_WSKP, NoticeE17);	NmkCevni.put(CatNMK.NMK_SLCP, NoticeE18); NmkCevni.put(CatNMK.NMK_UPCP, NoticeE19);
+		NmkCevni.put(CatNMK.NMK_SLBP, NoticeE20); NmkCevni.put(CatNMK.NMK_RADI, NoticeE23);	NmkCevni.put(CatNMK.NMK_WTBP, NoticeE24); NmkCevni.put(CatNMK.NMK_HSCP, NoticeE21);
+		NmkCevni.put(CatNMK.NMK_LBGP, NoticeE22);
+  };
+
+	public static final Symbol NoticeBnank = new Symbol();
+	static {
+		NoticeBnank.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-30,60,60)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-80.0); p.lineTo(-15.0,-47.0); p.lineTo(15.0,-47.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(-15.0,-43.0); p.lineTo(15.0,-43.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		NoticeBnank.add(new Instr(Form.COLR, colours));
+	}
+	public static final Symbol NoticeBlmhr = new Symbol();
+	public static final Symbol NoticeBwral = new Symbol();
+	public static final Symbol NoticeBwrar = new Symbol();
+	public static final Symbol NoticeBktpm = new Symbol();
+	public static final Symbol NoticeBktsm = new Symbol();
+	public static final Symbol NoticeBktmr = new Symbol();
+	public static final Symbol NoticeBcrtp = new Symbol();
+	public static final Symbol NoticeBcrts = new Symbol();
+	public static final Symbol NoticeBtrbm = new Symbol();
+	public static final Symbol NoticeBrspd = new Symbol();
+	public static final EnumMap<CatNMK, Symbol> NmkBniwr = new EnumMap<CatNMK, Symbol>(CatNMK.class);
+	static {
+		NmkBniwr.put(CatNMK.NMK_NANK, NoticeBnank); NmkBniwr.put(CatNMK.NMK_LMHR, NoticeBlmhr); NmkBniwr.put(CatNMK.NMK_OPTR, NoticeD2a); NmkBniwr.put(CatNMK.NMK_OPTL, NoticeD2b);
+		NmkBniwr.put(CatNMK.NMK_WRAL, NoticeBwral); NmkBniwr.put(CatNMK.NMK_WLAR, NoticeBwrar); NmkBniwr.put(CatNMK.NMK_KTPM, NoticeBktpm); NmkBniwr.put(CatNMK.NMK_KTSM, NoticeBktsm);
+		NmkBniwr.put(CatNMK.NMK_KTMR, NoticeBktmr); NmkBniwr.put(CatNMK.NMK_CRTP, NoticeBcrtp); NmkBniwr.put(CatNMK.NMK_CRTS, NoticeBcrts); NmkBniwr.put(CatNMK.NMK_TRBM, NoticeBtrbm);
+		NmkBniwr.put(CatNMK.NMK_RSPD, NoticeBrspd);
+	}
+
+	public static final EnumMap<CatNMK, Symbol> NmkPpwbc = new EnumMap<CatNMK, Symbol>(CatNMK.class);
+	static {
+		NmkPpwbc.put(CatNMK.NMK_WRAL, Notice); NmkPpwbc.put(CatNMK.NMK_WLAR, Notice); NmkPpwbc.put(CatNMK.NMK_KTPM, Notice); NmkPpwbc.put(CatNMK.NMK_KTSM, Notice);
+		NmkPpwbc.put(CatNMK.NMK_KTMR, Notice); NmkPpwbc.put(CatNMK.NMK_CRTP, Notice); NmkPpwbc.put(CatNMK.NMK_CRTS, Notice);
+	}
+	
+	public static Scheme getScheme(MarSYS sys, BnkWTW bank) {
+		ArrayList<Color> colours = new ArrayList<Color>();
+		Scheme scheme = new Scheme(null, colours);
+		switch (sys) {
+		case SYS_BNWR:
+			switch (bank) {
+			case BWW_LEFT:
+				colours.add(Color.white);
+				colours.add(new Color(0xf00000));
+				break;
+			case BWW_RGHT:
+				colours.add(Color.white);
+				colours.add(new Color(0x00a000));
+				break;
+			default:
+				colours.add(new Color(0xff8040));
+				colours.add(Color.black);
+				break;
+			}
+			break;
+		case SYS_PPWB:
+			switch (bank) {
+			case BWW_LEFT:
+				colours.add(Color.white);
+				colours.add(new Color(0xd40000));
+				break;
+			case BWW_RGHT:
+				colours.add(Color.white);
+				colours.add(new Color(0x00d400));
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+		return scheme;
+	}
+	
+	public static Symbol getNotice(CatNMK cat, MarSYS sys) {
+		Symbol symbol = null;
+		switch (sys) {
+		case SYS_CEVN:
+			symbol = NmkCevni.get(cat);
+			break;
+		case SYS_BNWR:
+			symbol = NmkBniwr.get(cat);
+			break;
+		case SYS_PPWB:
+			symbol = NmkPpwbc.get(cat);
+			break;
+		default:
+			break;
+		}
+		return symbol;
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Symbols.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Symbols.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Symbols.java	(revision 30894)
@@ -0,0 +1,377 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.font.TextLayout;
+import java.awt.geom.*;
+import java.util.ArrayList;
+
+public class Symbols {
+
+	public enum Form {
+		BBOX, STRK, COLR, FILL, LINE, RECT, RRCT, ELPS, EARC, PLIN, PGON, RSHP, TEXT, SYMB, P1, P2, H2, H3, H4, H5, V2, V3, D2, D3, D4, B1, S2, S3, S4, C2, X2
+	}
+
+	public enum Patt {
+		Z, H, V, D, B, S, C, X
+	}
+
+	public enum Handle {
+		CC, TL, TR, TC, LC, RC, BL, BR, BC
+	}
+
+	public static class Instr {
+		public Form type;
+		public Object params;
+
+		public Instr(Form itype, Object iparams) {
+			type = itype;
+			params = iparams;
+		}
+	}
+
+	public static class Delta {
+		public Handle h;
+		public AffineTransform t;
+
+		public Delta(Handle ih, AffineTransform it) {
+			h = ih;
+			t = it;
+		}
+		public Delta(Handle ih) {
+			h = ih;
+			t = new AffineTransform();
+		}
+	}
+
+	public static class Scheme {
+		public ArrayList<Patt> pat;
+		public ArrayList<Color> col;
+
+		public Scheme(ArrayList<Patt> ipat, ArrayList<Color> icol) {
+			pat = ipat;
+			col = icol;
+		}
+		public Scheme(Color icol) {
+			pat = new ArrayList<Patt>();
+			col = new ArrayList<Color>();
+			col.add(icol);
+		}
+		public Scheme() {
+			pat = new ArrayList<Patt>();
+			col = new ArrayList<Color>();
+		}
+	}
+
+	public static class Caption {
+		public String string;
+		public Font font;
+		public Color colour;
+		public Delta dd;
+
+		public Caption(String istr, Font ifont, Color icolour, Delta idd) {
+			string = istr;
+			font = ifont;
+			colour = icolour;
+			dd = idd;
+		}
+	}
+
+	public static class LineStyle {
+		public Color line;
+		public float width;
+		public float[] dash;
+		public Color fill;
+
+		public LineStyle(Color iline, float iwidth) {
+			line = iline;
+			width = iwidth;
+			dash = null;
+			fill = null;
+		}
+		public LineStyle(Color iline, float iwidth, float[] idash) {
+			line = iline;
+			width = iwidth;
+			dash = idash;
+			fill = null;
+		}
+		public LineStyle(Color iline, float iwidth, Color ifill) {
+			line = iline;
+			width = iwidth;
+			dash = null;
+			fill = ifill;
+		}
+		public LineStyle(Color iline, float iwidth, float[] idash, Color ifill) {
+			line = iline;
+			width = iwidth;
+			dash = idash;
+			fill = ifill;
+		}
+	}
+
+	public static class Symbol extends ArrayList<Instr> {
+
+		public Symbol() {
+			super();
+		}
+	}
+	
+	public static class SubSymbol {
+		public Symbol instr;
+		public double scale;
+		public double x;
+		public double y;
+		public Delta delta;
+		public Scheme scheme;
+
+		public SubSymbol(Symbol iinstr, double iscale, double ix, double iy, Scheme ischeme, Delta idelta) {
+			instr = iinstr;
+			scale = iscale;
+			x = ix;
+			y = iy;
+			delta = idelta;
+			scheme = ischeme;
+		}
+	}
+
+	public static void drawSymbol(Graphics2D g2, Symbol symbol, double scale, double x, double y, Scheme cs, Delta dd) {
+		int pn = 0;
+		int cn = 0;
+		Patt bpat = Patt.Z;
+		Color bcol = null;
+		g2.setPaint(Color.black);
+		if (cs != null) {
+			if ((cs.pat.size() > 0) && (cs.col.size() > 0) && (cs.pat.get(0) == Patt.B)) {
+				bpat = (cs.pat.remove(0));
+				bcol = (cs.col.remove(0));
+			}
+			pn = cs.pat.size();
+			cn = cs.col.size() - ((pn != 0) ? pn - 1 : 0);
+			if ((pn == 0) && (cs.col.size() == 1)) {
+				g2.setPaint(cs.col.get(0));
+			}
+		}
+		AffineTransform savetr = g2.getTransform();
+		g2.translate(x, y);
+		g2.scale(scale, scale);
+		if (symbol != null) {
+			for (Instr item : symbol) {
+				switch (item.type) {
+				case BBOX:
+					Rectangle2D.Double bbox = (Rectangle2D.Double) item.params;
+					double dx = 0.0;
+					double dy = 0.0;
+					if (dd != null) {
+						g2.transform(dd.t);
+						switch (dd.h) {
+						case CC:
+							dx -= bbox.x + (bbox.width / 2.0);
+							dy -= bbox.y + (bbox.height / 2.0);
+							break;
+						case TL:
+							dx -= bbox.x;
+							dy -= bbox.y;
+							break;
+						case TR:
+							dx -= bbox.x + bbox.width;
+							dy -= bbox.y;
+							break;
+						case TC:
+							dx -= bbox.x + (bbox.width / 2.0);
+							dy -= bbox.y;
+							break;
+						case LC:
+							dx -= bbox.x;
+							dy -= bbox.y + (bbox.height / 2.0);
+							break;
+						case RC:
+							dx -= bbox.x + bbox.width;
+							dy -= bbox.y + (bbox.height / 2.0);
+							break;
+						case BL:
+							dx -= bbox.x;
+							dy -= bbox.y + bbox.height;
+							break;
+						case BR:
+							dx -= bbox.x + bbox.width;
+							dy -= bbox.y + bbox.height;
+							break;
+						case BC:
+							dx -= bbox.x + (bbox.width / 2.0);
+							dy -= bbox.y + bbox.height;
+							break;
+						}
+						g2.translate(dx, dy);
+					}
+					break;
+				case COLR:
+					if ((cs != null) && (cs.col != null)) {
+						for (Instr patch : (Symbol) item.params) {
+							switch (patch.type) {
+							case P1:
+								if (cn > 0) {
+									g2.setPaint(cs.col.get(0));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case P2:
+								if (cn > 0) {
+									if (cn > 1) {
+										g2.setPaint(cs.col.get(1));
+									} else {
+										g2.setPaint(cs.col.get(0));
+									}
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case H2:
+								if ((cn > 1) && (pn > 0) && (cs.pat.get(0) == Patt.H)) {
+									g2.setPaint(cs.col.get(cs.col.size() - pn));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case H3:
+								if ((cn == 3) && (pn > 0) && (cs.pat.get(0) == Patt.H)) {
+									g2.setPaint(cs.col.get(1));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case H4:
+								if ((cn == 4) && (pn > 0) && (cs.pat.get(0) == Patt.H)) {
+									g2.setPaint(cs.col.get(1));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case H5:
+								if ((cn == 4) && (pn > 0) && (cs.pat.get(0) == Patt.H)) {
+									g2.setPaint(cs.col.get(2));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case V2:
+								if ((cn > 1) && (pn > 0) && (cs.pat.get(0) == Patt.V)) {
+									g2.setPaint(cs.col.get(cs.col.size() - pn));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case V3:
+								if ((cn == 3) && (pn > 0) && (cs.pat.get(0) == Patt.V)) {
+									g2.setPaint(cs.col.get(1));
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							case B1:
+								if (bpat == Patt.B) {
+									g2.setPaint(bcol);
+									g2.fill((Path2D.Double) patch.params);
+								}
+								break;
+							default:
+								break;
+							}
+						}
+					}
+					break;
+				case STRK:
+					g2.setStroke((BasicStroke) item.params);
+					break;
+				case FILL:
+					g2.setPaint((Color) item.params);
+					break;
+				case LINE:
+					g2.draw((Line2D.Double) item.params);
+					break;
+				case RECT:
+					g2.draw((Rectangle2D.Double) item.params);
+					break;
+				case RRCT:
+					g2.draw((RoundRectangle2D.Double) item.params);
+					break;
+				case ELPS:
+					g2.draw((Ellipse2D.Double) item.params);
+					break;
+				case EARC:
+					g2.draw((Arc2D.Double) item.params);
+					break;
+				case PLIN:
+					g2.draw((Path2D.Double) item.params);
+					break;
+				case PGON:
+					g2.fill((Path2D.Double) item.params);
+					break;
+				case RSHP:
+					g2.fill((RectangularShape) item.params);
+					break;
+				case SYMB:
+					SubSymbol s = (SubSymbol) item.params;
+					drawSymbol(g2, s.instr, s.scale, s.x, s.y, (s.scheme != null ? s.scheme : cs), s.delta);
+					break;
+				case TEXT:
+					Caption c = (Caption) item.params;
+					g2.setPaint(c.colour);
+					TextLayout layout = new TextLayout(c.string, c.font, g2.getFontRenderContext());
+					Rectangle2D bb = layout.getBounds();
+					dx = 0;
+					dy = 0;
+					if (c.dd != null) {
+						if (c.dd.t != null) g2.transform(c.dd.t);
+						switch (c.dd.h) {
+						case CC:
+							dx -= bb.getX() + (bb.getWidth() / 2.0);
+							dy -= bb.getY() + (bb.getHeight() / 2.0);
+							break;
+						case TL:
+							dx -= bb.getX();
+							dy -= bb.getY();
+							break;
+						case TR:
+							dx -= bb.getX() + bb.getWidth();
+							dy -= bb.getY();
+							break;
+						case TC:
+							dx -= bb.getX() + (bb.getWidth() / 2.0);
+							dy -= bb.getY();
+							break;
+						case LC:
+							dx -= bb.getX();
+							dy -= bb.getY() + (bb.getHeight() / 2.0);
+							break;
+						case RC:
+							dx -= bb.getX() + bb.getWidth();
+							dy -= bb.getY() + (bb.getHeight() / 2.0);
+							break;
+						case BL:
+							dx -= bb.getX();
+							dy -= bb.getY() + bb.getHeight();
+							break;
+						case BR:
+							dx -= bb.getX() + bb.getWidth();
+							dy -= bb.getY() + bb.getHeight();
+							break;
+						case BC:
+							dx -= bb.getX() + (bb.getWidth() / 2.0);
+							dy -= bb.getY() + bb.getHeight();
+							break;
+						}
+					}
+					layout.draw(g2, (float)dx, (float)dy);
+					break;
+				default:
+					break;
+				}
+			}
+		}
+		g2.setTransform(savetr);
+	}
+}
Index: /applications/editors/josm/plugins/seachart/src/symbols/Topmarks.java
===================================================================
--- /applications/editors/josm/plugins/seachart/src/symbols/Topmarks.java	(revision 30894)
+++ /applications/editors/josm/plugins/seachart/src/symbols/Topmarks.java	(revision 30894)
@@ -0,0 +1,331 @@
+/* Copyright 2014 Malcolm Herring
+ *
+ * This 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, version 3 of the License.
+ *
+ * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
+ */
+
+package symbols;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.geom.*;
+import java.util.EnumMap;
+
+import s57.S57val.*;
+import symbols.Symbols.*;
+
+public class Topmarks {
+	
+	public static final Symbol TopBesom = new Symbol();
+	static {
+		TopBesom.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		TopBesom.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopBesom.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,0.0); p.lineTo(0.0,-30.0); p.lineTo(15.0,0.0); p.moveTo(0.0,0.0); p.lineTo(0.0,-28.0);
+		TopBesom.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopIBesom = new Symbol();
+	static {
+		TopIBesom.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		TopIBesom.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopIBesom.add(new Instr(Form.FILL, Color.black));
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-30.0); p.lineTo(0.0,0.0); p.lineTo(15.0,-30.0);
+		TopIBesom.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopBoard = new Symbol();
+	static {
+		TopBoard.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-19.0,-2.0); p.lineTo(-19.0,-39.0); p.lineTo(19.0,-39.0); p.lineTo(19.0,-2.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopBoard.add(new Instr(Form.COLR, colours));
+		TopBoard.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopBoard.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(-19.0,-2.0); p.lineTo(-19.0,-39.0); p.lineTo(19.0,-39.0); p.lineTo(19.0,-2.0); p.closePath();
+		TopBoard.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopCan = new Symbol();
+	static {
+		TopCan.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-12.0,-15.0); p.lineTo(-12.0,-48.0); p.lineTo(12.0,-48.0); p.lineTo(12.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopCan.add(new Instr(Form.COLR, colours));
+		TopCan.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopCan.add(new Instr(Form.FILL, Color.black));
+		TopCan.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		p = new Path2D.Double(); p.moveTo(-12.0,-15.0); p.lineTo(-12.0,-48.0); p.lineTo(12.0,-48.0); p.lineTo(12.0,-15.0); p.closePath();
+		TopCan.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopCone = new Symbol();
+	static {
+		TopCone.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-15.0); p.lineTo(0.0,-45.0); p.lineTo(15.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopCone.add(new Instr(Form.COLR, colours));
+		TopCone.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopCone.add(new Instr(Form.FILL, Color.black));
+		TopCone.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		p = new Path2D.Double(); p.moveTo(-15.0,-15.0); p.lineTo(0.0,-45.0); p.lineTo(15.0,-15.0); p.closePath();
+		TopCone.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopCross = new Symbol();
+	static {
+		TopCross.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-5.0,-15.0); p.lineTo(-5.0,-32.5); p.lineTo(-22.5,-32.5);	p.lineTo(-22.5,-42.5); p.lineTo(-5.0,-42.5);
+		p.lineTo(-5.0,-60.0); p.lineTo(5.0,-60.0); p.lineTo(5.0,-42.5); p.lineTo(22.5,-42.5);	p.lineTo(22.5,-32.5); p.lineTo(5.0,-32.5); p.lineTo(5.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopCross.add(new Instr(Form.COLR, colours));
+		TopCross.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopCross.add(new Instr(Form.FILL, Color.black));
+		TopCross.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		TopCross.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(-5.0,-15.0); p.lineTo(-5.0,-32.5); p.lineTo(-22.5,-32.5); p.lineTo(-22.5,-42.5); p.lineTo(-5.0,-42.5); p.lineTo(-5.0,-60.0);
+		p.lineTo(5.0,-60.0); p.lineTo(5.0,-42.5); p.lineTo(22.5,-42.5); p.lineTo(22.5,-32.5); p.lineTo(5.0,-32.5); p.lineTo(5.0,-15.0); p.closePath();
+		TopCross.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopEast = new Symbol();
+	static {
+		TopEast.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-80.0); p.lineTo(-15.0,-47.0); p.lineTo(15.0,-47.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(-15.0,-43.0); p.lineTo(15.0,-43.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		TopEast.add(new Instr(Form.COLR, colours));
+		TopEast.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopEast.add(new Instr(Form.FILL, Color.black));
+		TopEast.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-10)));
+		TopEast.add(new Instr(Form.LINE, new Line2D.Double(0,-43,0,-47)));
+		TopEast.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(-15.0,-43.0); p.lineTo(15.0,-43.0); p.closePath();
+		p.moveTo(0.0,-80.0); p.lineTo(-15.0,-47.0);  p.lineTo(15.0,-47.0); p.closePath();
+		TopEast.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopIcone = new Symbol();
+	static {
+		TopIcone.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-45.0); p.lineTo(0.0,-15.0); p.lineTo(15.0,-45.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopIcone.add(new Instr(Form.COLR, colours));
+		TopIcone.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopIcone.add(new Instr(Form.FILL, Color.black));
+		TopIcone.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		p = new Path2D.Double(); p.moveTo(-15.0,-45.0); p.lineTo(0.0,-15.0); p.lineTo(15.0,-45.0); p.closePath();
+		TopIcone.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopIsol = new Symbol();
+	static {
+		TopIsol.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-13.0,-55.0); p.curveTo(-13.0, -72.3, 13.0, -72.3, 13.0,-55.0); p.curveTo(13.0, -37.7, -13.0, -37.7, -13.0,-55.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-13.0,-28.0); p.curveTo(-13.0, -45.3, 13.0, -45.3, 13.0,-28.0); p.curveTo(13.0, -10.7, -13.0, -10.7, -13.0,-28.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		TopIsol.add(new Instr(Form.COLR, colours));
+		TopIsol.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopIsol.add(new Instr(Form.FILL, Color.black));
+		TopIsol.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		TopIsol.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopIsol.add(new Instr(Form.ELPS, new Ellipse2D.Double(-13,-41,26,26)));
+		TopIsol.add(new Instr(Form.ELPS, new Ellipse2D.Double(-13,-68,26,26)));
+	}
+	public static final Symbol TopMooring = new Symbol();
+	static {
+		TopMooring.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		TopMooring.add(new Instr(Form.STRK, new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopMooring.add(new Instr(Form.FILL, Color.black));
+		TopMooring.add(new Instr(Form.ELPS, new Ellipse2D.Double(-1.5,-6,3,3)));
+		TopMooring.add(new Instr(Form.ELPS, new Ellipse2D.Double(-8.5,-25,17,17)));
+	}
+	public static final Symbol TopNorth = new Symbol();
+	static {
+		TopNorth.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-78.0); p.lineTo(-15.0,-45.0); p.lineTo(15.0,-45.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-15.0,-10.0); p.lineTo(0.0,-43.0); p.lineTo(15.0,-10.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		TopNorth.add(new Instr(Form.COLR, colours));
+		TopNorth.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopNorth.add(new Instr(Form.FILL, Color.black));
+		TopNorth.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-10)));
+		TopNorth.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(-15.0,-10.0); p.lineTo(0.0,-43.0); p.lineTo(15.0,-10.0); p.closePath();
+		p.moveTo(0.0,-78.0); p.lineTo(-15.0,-45.0);  p.lineTo(15.0,-45.0); p.closePath();
+		TopNorth.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopSouth = new Symbol();
+	static {
+		TopSouth.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-78.0); p.lineTo(0.0,-45.0);  p.lineTo(15.0,-78.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(-15.0,-43.0); p.lineTo(15.0,-43.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		TopSouth.add(new Instr(Form.COLR, colours));
+		TopSouth.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopSouth.add(new Instr(Form.FILL, Color.black));
+		TopSouth.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-10)));
+		TopSouth.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(0.0,-10.0); p.lineTo(-15.0,-43.0); p.lineTo(15.0,-43.0); p.closePath();
+		p.moveTo(-15.0,-78.0); p.lineTo(0.0,-45.0);  p.lineTo(15.0,-78.0); p.closePath();
+		TopSouth.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopSphere = new Symbol();
+	static {
+		TopSphere.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-14.0,-28.0); p.curveTo(-14.0,-46.7,14.0,-46.7,14.0,-28.0); p.curveTo(14.0,-9.3,-14.0,-9.3,-14.0,-28.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopSphere.add(new Instr(Form.COLR, colours));
+		TopSphere.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopSphere.add(new Instr(Form.FILL, Color.black));
+		TopSphere.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-15)));
+		TopSphere.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopSphere.add(new Instr(Form.ELPS, new Ellipse2D.Double(-14,-42,28,28)));
+	}
+	public static final Symbol TopSquare = new Symbol();
+	static {
+		TopSquare.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-13.0,-1.0); p.lineTo(-13.0,-27.0); p.lineTo(13.0,-27.0); p.lineTo(13.0,-1.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-13.0,-15.0); p.lineTo(-13.0,-1.0); p.lineTo(13.0,-1.0); p.lineTo(13.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-13.0,-19.3); p.lineTo(-13.0,-10.7); p.lineTo(13.0,-10.7); p.lineTo(13.0,-19.3); p.closePath();
+		colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-1.0); p.lineTo(0.0,-27.0); p.lineTo(13.0,-27.0); p.lineTo(13.0,-1.0); p.closePath();
+		colours.add(new Instr(Form.V2, p));
+		p = new Path2D.Double(); p.moveTo(-4.3,-1.0); p.lineTo(-4.3,-27.0); p.lineTo(4.3,-27.0); p.lineTo(4.3,-1.0); p.closePath();
+		colours.add(new Instr(Form.V3, p));
+		p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-13.0,-1.0); p.lineTo(-13.0,-27.0); p.lineTo(13.0,-27.0); p.lineTo(13.0,-1.0); p.closePath();
+		p.moveTo(-8.0,-6.0); p.lineTo(-8.0,-22.0); p.lineTo(8.0,-22.0); p.lineTo(8.0,-6.0); p.closePath();
+		colours.add(new Instr(Form.B1, p));
+		TopSquare.add(new Instr(Form.COLR, colours));
+		TopSquare.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopSquare.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(-13.0,-1.0); p.lineTo(-13.0,-27.0); p.lineTo(13.0,-27.0); p.lineTo(13.0,-1.0); p.closePath();
+		TopSquare.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopRhombus = new Symbol();
+	static {
+		TopRhombus.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-29.0); p.lineTo(-15.0,-15.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-15.0,-15.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.H2, p));
+		p = new Path2D.Double(); p.moveTo(-10.0,-19.7); p.lineTo(-15.0,-15.0); p.lineTo(-10.0,-10.3); p.lineTo(10.0,-10.3); p.lineTo(15.0,-15.0); p.lineTo(10.0,-19.7); p.closePath();
+		colours.add(new Instr(Form.H3, p));
+		p = new Path2D.Double();  p.moveTo(0.0,-29.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.V2, p));
+		p = new Path2D.Double(); p.moveTo(0.0,-29.0); p.lineTo(-5.0,-24.3); p.lineTo(-5.0,-5.7); p.lineTo(0.0,-1.0); p.lineTo(5.0,-5.7); p.lineTo(5.0,-24.3); p.closePath();
+		colours.add(new Instr(Form.V3, p));
+		p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(0.0,-29.0); p.lineTo(-15.0,-15.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-15.0); p.closePath();
+		p.moveTo(0.0,-23.0); p.lineTo(-9.0,-15.0); p.lineTo(0.0,-7.0); p.lineTo(9.0,-15.0); p.closePath();
+		colours.add(new Instr(Form.B1, p));
+		TopRhombus.add(new Instr(Form.COLR, colours));
+		TopRhombus.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopRhombus.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(0.0,-29.0); p.lineTo(-15.0,-15.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-15.0); p.closePath();
+		TopRhombus.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopTriangle = new Symbol();
+	static {
+		TopTriangle.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-1.0); p.lineTo(0.0,-29.0); p.lineTo(15.0,-1.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-15.0,-1.0); p.lineTo(0.0,-29.0); p.lineTo(15.0,-1.0); p.closePath();
+		p.moveTo(-10.0,-6.0); p.lineTo(0.0,-24.0); p.lineTo(10.0,-6.0); p.closePath();
+		colours.add(new Instr(Form.B1, p));
+		TopTriangle.add(new Instr(Form.COLR, colours));
+		TopTriangle.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopTriangle.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(-15.0,-1.0); p.lineTo(0.0,-29.0); p.lineTo(15.0,-1.0); p.closePath();
+		TopTriangle.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopItriangle = new Symbol();
+	static {
+		TopItriangle.add(new Instr(Form.BBOX, new Rectangle2D.Double(-20,-80,40,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-29.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-29.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
+		p.moveTo(-15.0,-29.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-29.0); p.closePath();
+		p.moveTo(-10.0,-24.0); p.lineTo(0.0,-6.0); p.lineTo(10.0,-24.0); p.closePath();
+		colours.add(new Instr(Form.B1, p));
+		TopItriangle.add(new Instr(Form.COLR, colours));
+		TopItriangle.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopItriangle.add(new Instr(Form.FILL, Color.black));
+		p = new Path2D.Double(); p.moveTo(-15.0,-29.0); p.lineTo(0.0,-1.0); p.lineTo(15.0,-29.0); p.closePath();
+		TopItriangle.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopWest = new Symbol();
+	static {
+		TopWest.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(-15.0,-78.0); p.lineTo(0.0,-45.0);  p.lineTo(15.0,-78.0); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		p = new Path2D.Double(); p.moveTo(-15.0,-10.0); p.lineTo(0.0,-43.0); p.lineTo(15.0,-10.0); p.closePath();
+		colours.add(new Instr(Form.P2, p));
+		TopWest.add(new Instr(Form.COLR, colours));
+		TopWest.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopWest.add(new Instr(Form.FILL, Color.black));
+		TopWest.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-10)));
+		TopWest.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(-15.0,-10.0); p.lineTo(0.0,-43.0); p.lineTo(15.0,-10.0); p.closePath();
+		p.moveTo(-15.0,-78.0); p.lineTo(0.0,-45.0);  p.lineTo(15.0,-78.0); p.closePath();
+		TopWest.add(new Instr(Form.PLIN, p));
+	}
+	public static final Symbol TopX = new Symbol();
+	static {
+		TopX.add(new Instr(Form.BBOX, new Rectangle2D.Double(-30,-80,60,80)));
+		Symbol colours = new Symbol();
+		Path2D.Double p = new Path2D.Double(); p.moveTo(0.0,-27.7); p.lineTo(-12.4,-15.7); p.lineTo(-19.3,-22.6); p.lineTo(-7.3,-35.0); p.lineTo(-19.3,-47.3);
+		p.lineTo(-12.4,-54.2); p.lineTo(0.0,-42.4); p.lineTo(12.4,-54.2); p.lineTo(19.3,-47.3); p.lineTo(7.3,-35.0); p.lineTo(19.3,-22.6); p.lineTo(12.4,-15.7); p.closePath();
+		colours.add(new Instr(Form.P1, p));
+		TopX.add(new Instr(Form.COLR, colours));
+		TopX.add(new Instr(Form.STRK, new BasicStroke(4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		TopX.add(new Instr(Form.FILL, Color.black));
+		TopX.add(new Instr(Form.LINE, new Line2D.Double(0,0,0,-27)));
+		TopX.add(new Instr(Form.STRK, new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)));
+		p = new Path2D.Double(); p.moveTo(0.0,-27.7); p.lineTo(-12.4,-15.7); p.lineTo(-19.3,-22.6); p.lineTo(-7.3,-35.0); p.lineTo(-19.3,-47.3); p.lineTo(-12.4,-54.2); p.lineTo(0.0,-42.4);
+		p.lineTo(12.4,-54.2); p.lineTo(19.3,-47.3); p.lineTo(7.3,-35.0); p.lineTo(19.3,-22.6); p.lineTo(12.4,-15.7); p.closePath();
+		TopX.add(new Instr(Form.PLIN, p));
+	}
+	
+	public static final EnumMap<TopSHP, Symbol> Shapes = new EnumMap<TopSHP, Symbol>(TopSHP.class);
+	static {
+		Shapes.put(TopSHP.TOP_BESM, TopBesom); Shapes.put(TopSHP.TOP_IBESM, TopIBesom); Shapes.put(TopSHP.TOP_BORD, TopBoard); Shapes.put(TopSHP.TOP_CAN, TopCan);
+		Shapes.put(TopSHP.TOP_CONE, TopCone); Shapes.put(TopSHP.TOP_CROS, TopCross); Shapes.put(TopSHP.TOP_EAST, TopEast); Shapes.put(TopSHP.TOP_ICONE, TopIcone);
+		Shapes.put(TopSHP.TOP_ISD, TopIsol); Shapes.put(TopSHP.TOP_NORTH, TopNorth); Shapes.put(TopSHP.TOP_SOUTH, TopSouth); Shapes.put(TopSHP.TOP_SPHR, TopSphere);
+		Shapes.put(TopSHP.TOP_SQUR, TopSquare); Shapes.put(TopSHP.TOP_TRI, TopTriangle); Shapes.put(TopSHP.TOP_ITRI, TopItriangle); Shapes.put(TopSHP.TOP_WEST, TopWest);
+		Shapes.put(TopSHP.TOP_SALT, TopX); Shapes.put(TopSHP.TOP_RHOM, TopRhombus);
+	}
+	public static final EnumMap<BoySHP, Delta> BuoyDeltas = new EnumMap<BoySHP, Delta>(BoySHP.class);
+	static {
+		BuoyDeltas.put(BoySHP.BOY_PILR, new Delta(Handle.BC, new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 31.5, -95.0))); 
+		BuoyDeltas.put(BoySHP.BOY_SPAR, new Delta(Handle.BC, new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 31.5, -95.0))); 
+		BuoyDeltas.put(BoySHP.BOY_CAN, new Delta(Handle.BC,  new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 12.7, -37.9))); 
+		BuoyDeltas.put(BoySHP.BOY_CONE, new Delta(Handle.BC, new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 12.7, -37.9))); 
+		BuoyDeltas.put(BoySHP.BOY_SPHR, new Delta(Handle.BC, new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 12.7, -37.9))); 
+		BuoyDeltas.put(BoySHP.BOY_BARL, new Delta(Handle.BC, new AffineTransform(0.948324, 0.317305, -0.3173047, 0.948324, 12.7, -37.9))); 
+		BuoyDeltas.put(BoySHP.BOY_SUPR, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0.0, -42.0))); 
+		BuoyDeltas.put(BoySHP.BOY_ICE, new Delta(Handle.BC, AffineTransform.getTranslateInstance(0.0, -25.0))); 
+	}
+	public static final Delta FloatDelta = new Delta(Handle.BC, AffineTransform.getTranslateInstance(0.0, -42.0));
+	public static final Delta BeaconDelta = new Delta(Handle.BC, AffineTransform.getTranslateInstance(0.0, -70.0));
+	public static final Delta LightDelta = new Delta(Handle.BC, AffineTransform.getTranslateInstance(0.0, -20.0));
+
+}
