[Pkg-octave-commit] [octave-octclip] 01/03: Imported Upstream version 1.0.8
Rafael Laboissière
rlaboiss-guest at moszumanska.debian.org
Sun Feb 7 14:05:27 UTC 2016
This is an automated email from the git hooks/post-receive script.
rlaboiss-guest pushed a commit to branch master
in repository octave-octclip.
commit ba2211591577cbb78f4067fe426287a37aeb1f2c
Author: Rafael Laboissiere <rafael at laboissiere.net>
Date: Sun Feb 7 08:47:38 2016 -0200
Imported Upstream version 1.0.8
---
COPYING | 674 +++++++++++++++++
DESCRIPTION | 13 +
INDEX | 5 +
NEWS | 32 +
doc/octclip.pdf | Bin 0 -> 206232 bytes
doc/octclip.tex | 247 +++++++
inst/oc_polybool.m | 265 +++++++
src/Makefile | 44 ++
src/_oc_polybool.cc | 241 ++++++
src/calctopo.c | 71 ++
src/compilador.c | 82 +++
src/dpeucker.c | 472 ++++++++++++
src/errores.c | 119 +++
src/eucli.c | 238 ++++++
src/fgeneral.c | 880 ++++++++++++++++++++++
src/geocnan.c | 184 +++++
src/geocomp.c | 129 ++++
src/greiner.c | 1840 ++++++++++++++++++++++++++++++++++++++++++++++
src/libgeoc/calctopo.h | 81 ++
src/libgeoc/compilador.h | 96 +++
src/libgeoc/constantes.h | 264 +++++++
src/libgeoc/dpeucker.h | 261 +++++++
src/libgeoc/errores.h | 1058 ++++++++++++++++++++++++++
src/libgeoc/eucli.h | 237 ++++++
src/libgeoc/fgeneral.h | 646 ++++++++++++++++
src/libgeoc/general.h | 61 ++
src/libgeoc/geocnan.h | 233 ++++++
src/libgeoc/geocomp.h | 208 ++++++
src/libgeoc/geom.h | 64 ++
src/libgeoc/greiner.h | 827 +++++++++++++++++++++
src/libgeoc/polig.h | 1101 +++++++++++++++++++++++++++
src/libgeoc/polil.h | 799 ++++++++++++++++++++
src/libgeoc/ptopol.h | 947 ++++++++++++++++++++++++
src/libgeoc/recpolil.h | 439 +++++++++++
src/libgeoc/segmento.h | 299 ++++++++
src/libgeoc/ventorno.h | 100 +++
src/octclip.h | 31 +
src/polig.c | 1815 +++++++++++++++++++++++++++++++++++++++++++++
src/polil.c | 1463 ++++++++++++++++++++++++++++++++++++
src/ptopol.c | 1007 +++++++++++++++++++++++++
src/recpolil.c | 1402 +++++++++++++++++++++++++++++++++++
src/segmento.c | 292 ++++++++
src/ventorno.c | 86 +++
43 files changed, 19353 insertions(+)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -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>.
diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..28b5ad2
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,13 @@
+Name: OctCLIP
+Version: 1.0.8
+Date: 2015-06-16
+Author: José Luis García Pallero <jgpallero at gmail.com>
+Maintainer: José Luis García Pallero <jgpallero at gmail.com>
+Title: GNU Octave clipping polygons tool
+Description: This package allows to do boolean operations with polygons using
+ the Greiner-Hormann algorithm.
+Depends: Octave (>= 2.9.7)
+Url: http://davis.wpi.edu/~matt/courses/clipping/
+ https://bitbucket.org/jgpallero/octclip
+Autoload: no
+License: GPLv3+, modified BSD
diff --git a/INDEX b/INDEX
new file mode 100644
index 0000000..23fe7c2
--- /dev/null
+++ b/INDEX
@@ -0,0 +1,5 @@
+toolbox >> OctCLIP
+Category Kernel functions
+ _oc_polybool
+Category Driver functions
+ oc_polybool
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..25596af
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,32 @@
+Summary of important user-visible changes for version 1.0.8:
+------------------------------------------------------------
+
+** Minor changes in src/Makefile
+
+Summary of important user-visible changes for version 1.0.7:
+------------------------------------------------------------
+
+** Minor changes and corrections in help strings
+
+Summary of important user-visible changes for version 1.0.6:
+------------------------------------------------------------
+
+** All calls to ismatrix() are changed by isnumeric()
+
+Summary of important user-visible changes for version 1.0.5:
+------------------------------------------------------------
+
+** Only minor changes in Mercurial repository managment
+
+Summary of important user-visible changes for version 1.0.3:
+------------------------------------------------------------
+
+** Change 'autoload' option to 'no' by default
+
+** Correct the way of calculation of the minumum perturbation number
+
+** Add number of polygons output argument
+
+** Fix number of input arguments control
+
+** Documentation updates
diff --git a/doc/octclip.pdf b/doc/octclip.pdf
new file mode 100644
index 0000000..7059395
Binary files /dev/null and b/doc/octclip.pdf differ
diff --git a/doc/octclip.tex b/doc/octclip.tex
new file mode 100644
index 0000000..5b0247c
--- /dev/null
+++ b/doc/octclip.tex
@@ -0,0 +1,247 @@
+\documentclass[10pt,a4paper]{article}
+\usepackage{tocbibind}
+\usepackage{hyperref}
+\hypersetup{colorlinks,citecolor=red,linkcolor=red,urlcolor=red}
+
+\newcommand{\octclip}{\texttt{OctCLIP}}
+\newcommand{\octave}{GNU Octave}
+
+\title{Clipping polygons from \octave\footnote{This document is distributed
+ under the terms of the GNU Free Documentation License. Please, see
+ \url{http://www.gnu.org/licenses/}}}
+\author{Jos\'e Luis Garc\'ia Pallero\footnote{ETSI en Topograf\'ia, Geodesia y
+ Cartograf\'ia, Universidad Polit\'ecnica de Madrid.
+ \texttt{jlg.pallero at upm.es}, \texttt{jgpallero at gmail.com}}}
+\date{February 13, 2015 (version 1.0.6)\\
+ June 20, 2013 (version 1.0.5)\\
+ October 1, 2012 (version 1.0.2)\\
+ November 21, 2011 (version 1.0.1)\\
+ May 24, 2011 (version 1.0.0)}
+
+\begin{document}
+\maketitle
+% \tableofcontents
+
+\nocite{eat-om}
+\nocite{kim2006a}
+
+\begin{abstract}
+This is a small introduction to using the \octclip{} package. In this text, you
+can overview the basic usage of the functions in
+\octave\footnote{\url{http://www.octave.org}}. If you need a detailed
+description about the Greiner-Hormann implemented algorithm, please read
+\cite{greiner1998} and visit \url{http://davis.wpi.edu/~matt/courses/clipping/}.
+\end{abstract}
+
+\section{Overview}
+
+The \octclip{} package allows you to perform boolean operations (intersection,
+union, difference and exclusive or) between two polygons in \octave{} using the
+Greiner-Hormann algorithm\footnote{\cite{greiner1998} and
+\url{http://davis.wpi.edu/~matt/courses/clipping/}}.
+
+Greiner-Hormann is an efficient algorithm for clipping arbitrary 2D polygons.
+The algorithm can handle arbitrary closed polygons, specifically where the
+subject and clip polygons may self-intersect.
+
+\section{Installation}
+
+As most of \octave{} packages, \octclip{} installation consists in compiling the
+C++ kernel sources, link them against \octave{} library to generate
+\texttt{*.oct} functions and copy this \texttt{*.oct} executables and other
+\texttt{*.m} functions into a working directory.
+
+The automagic procedure can be easily done by running the command:
+
+\begin{verbatim}
+octave:1> pkg install octclip-x.x.x.tar.gz
+\end{verbatim}
+where \texttt{x.x.x} is the version number.
+
+After that, the functions and documentation are installed in your machine and
+you are ready for use the package.
+
+\section{\octave{} functions}
+
+Two types of functions are programmed for \octave: one \texttt{*.oct} function
+and one \texttt{*.m} function.
+
+\subsection{\texttt{*.oct} function}
+\label{op-of}
+
+This function are linked with the C code that actually make the computations.
+You can use it, but is no recommended because the input arguments are more
+strict than \texttt{*.m} functions and don't check for some errors.
+
+The function is:
+\begin{itemize}
+\item \texttt{\_oc\_polybool}: Performs boolean operation between two polygons.
+\end{itemize}
+
+\subsection{\texttt{*.m} function}
+
+This function makes the computations by calling the \texttt{*.oct} function. You
+must call this function because you can use different number of input arguments
+and checking of input arguments is performed.
+
+The function is the same as in section \ref{op-of} (without the \texttt{\_} at
+the beginning of the name):
+\begin{itemize}
+\item \texttt{oc\_polybool}: Performs boolean operation between two polygons
+ by calling the \texttt{\_oc\_polybool}.
+\end{itemize}
+
+\texttt{oc\_polybool} includes too some demonstration code in order to test the
+functionality of the functions. The demo code can be executed as:
+\begin{verbatim}
+octave:1> demo oc_polybool
+\end{verbatim}
+
+\subsection{Error handling}
+
+\texttt{*.oct} and \texttt{*.m} functions can emit errors, some due to errors
+with input arguments and other due to errors in functions from the
+C\footnote{The algorithm is internally implemented in C (C99 standard).} code.
+
+Errors due to wrong input arguments (data types, dimensions, etc.) can be only
+given for \texttt{*.m} function and this is the reason because the use of this
+function is recommended. In this case, the execution is aborted and nothing is
+stored in output arguments.
+
+The \texttt{*.oct} function can emit errors due to wrong number of input
+arguments, wrong value of the operation identifier and internal errors of memory
+allocation.
+
+\section{Caveats of Greiner-Hormann algorithm}
+
+To do.
+
+\section{Examples}
+
+To do.
+
+\section{Notes}
+
+Apart from \url{http://octave.sourceforge.net/octclip/index.html}, an up to date
+version of \octclip{} can be downloaded from
+\url{https://bitbucket.org/jgpallero/octclip/}.
+
+% \subsection{Geodetic to geocentric and vice versa}
+%
+% \begin{verbatim}
+% lon=-6*pi/180;lat=43*pi/180;h=1000;
+% [x,y,z]=op_geod2geoc(lon,lat,h,6378388,1/297)
+% x = 4647300.72326257
+% y = -488450.988568138
+% z = 4328259.36425774
+%
+% [lon,lat,h]=op_geoc2geod(x,y,z,6378388,1/297);
+% lon*=180/pi,lat*=180/pi,h
+% lon = -6
+% lat = 43
+% h = 1000.00000000074
+% \end{verbatim}
+%
+% \subsection{Forward and inverse projection}
+%
+% \begin{verbatim}
+% lon=-6*pi/180;lat=43*pi/180;
+% [x,y]=op_fwd(lon,lat,'+proj=utm +lon_0=3w +ellps=GRS80')
+% x = 255466.980547577
+% y = 4765182.93268401
+%
+% [lon,lat]=op_inv(x,y,'+proj=utm +lon_0=3w +ellps=GRS80');
+% lon*=180/pi,lat*=180/pi
+% lon = -6.00000000003597
+% lat = 42.9999999999424
+% \end{verbatim}
+%
+% \subsection{Forward and inverse projection: \texttt{op\_transform}}
+%
+% \subsubsection{With altitude}
+%
+% \begin{verbatim}
+% lon=-6*pi/180;lat=43*pi/180;h=1000;
+% [x,y,h]=op_transform(lon,lat,h,'+proj=latlong +ellps=GRS80',...
+% '+proj=utm +lon_0=3w +ellps=GRS80')
+% x = 255466.980547577
+% y = 4765182.93268401
+% h = 1000
+%
+% [lon,lat,h]=op_transform(x,y,h,...
+% '+proj=utm +lon_0=3w +ellps=GRS80',...
+% '+proj=latlong +ellps=GRS80');
+% lon*=180/pi,lat*=180/pi,h
+% lon = -6.00000000003597
+% lat = 42.9999999999424
+% h = 1000
+% \end{verbatim}
+%
+% \subsubsection{Without altitude}
+%
+% \begin{verbatim}
+% lon=-6*pi/180;lat=43*pi/180;
+% [x,y]=op_transform(lon,lat,'+proj=latlong +ellps=GRS80',...
+% '+proj=utm +lon_0=3w +ellps=GRS80')
+% x = 255466.980547577
+% y = 4765182.93268401
+%
+% [lon,lat]=op_transform(x,y,'+proj=utm +lon_0=3w +ellps=GRS80',...
+% '+proj=latlong +ellps=GRS80');
+% lon*=180/pi,lat*=180/pi
+% lon = -6.00000000003597
+% lat = 42.9999999999424
+% \end{verbatim}
+%
+% \subsection{Error due to an erroneous parameter}
+%
+% \begin{verbatim}
+% lon=-6*pi/180;lat=43*pi/180;
+% [x,y]=op_fwd(lon,lat,'+proj=utm +lon_0=3w +ellps=GRS8')
+% error:
+% In function op_fwd:
+% In function _op_fwd:
+% Projection parameters
+% unknown elliptical parameter name
+% +proj=utm +lon_0=3w +ellps=GRS8
+% \end{verbatim}
+%
+% \subsection{Error due to latitude too big}
+%
+% \begin{verbatim}
+% lon=[-6*pi/180;-6*pi/180];lat=[43*pi/180;43];
+% [x,y]=op_fwd(lon,lat,'+proj=utm +lon_0=3w +ellps=GRS80')
+% warning: _op_fwd:
+%
+% warning: Projection error in point 2 (index starts at 1)
+% x =
+%
+% 255466.980547577
+% Inf
+%
+% y =
+%
+% 4765182.93268401
+% Inf
+% \end{verbatim}
+
+\begin{thebibliography}{99}
+\bibitem{eat-om} \textsc{Eaton}, John W.; \textsc{Bateman}, David, and
+ \textsc{Hauberg}, S\o{}ren; \textit{GNU Octave. A high-level
+ interactive language for numerical computations}; Edition 3 for
+ Octave version 3.2.3; July 2007; Permanently updated at
+ \url{http://www.gnu.org/software/octave/docs.html}.
+\bibitem{greiner1998} \textsc{Greiner}, G\"unter, and \textsc{Hormann}, Kai;
+ \textit{Efficient clipping of arbitrary polygons};
+ ACM Transactions on Graphics; Volume 17(2), April 1998;
+ Pages 71--83.
+ There is a web link with some example code at
+ \url{http://davis.wpi.edu/~matt/courses/clipping/}.
+\bibitem{kim2006a} \textsc{Kim}, Dae Hyun, and \textsc{Kim}, Myoung-Jun;
+ \textit{An Extension of Polygon Clipping To Resolve
+ Degenerate Cases};
+ Computer-Aided Design \& Applications; Vol. 3; Numbers 1--4,
+ 2006; Pages 447--456.
+\end{thebibliography}
+
+\end{document}
diff --git a/inst/oc_polybool.m b/inst/oc_polybool.m
new file mode 100644
index 0000000..2ed1608
--- /dev/null
+++ b/inst/oc_polybool.m
@@ -0,0 +1,265 @@
+## Copyright (C) 2011-2015, José Luis García Pallero, <jgpallero at gmail.com>
+##
+## This file is part of OctCLIP.
+##
+## OctCLIP 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 Octave; see the file COPYING. If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn{Function File}{[@var{X}, at var{Y}, at var{nPol}, at var{nInt}, at var{nPert}] =}oc_polybool(@var{sub}, at var{clip}, at var{op})
+## @deftypefnx{Function File}{[@var{X}, at var{Y}, at var{nPol}, at var{nInt}, at var{nPert}] =}oc_polybool(@var{sub}, at var{clip})
+##
+## This function performs boolean operations between two polygons using the
+## Greiner-Hormann algorithm (http://davis.wpi.edu/~matt/courses/clipping/).
+##
+## @var{sub} is a two column matrix containing the X and Y coordinates of the
+## vertices for the subject polygon.
+##
+## @var{clip} is a two column matrix containing the X and Y coordinates of the
+## vertices for the clipper polygon.
+##
+## @var{op} is a text string containing the operation to perform between
+## @var{sub} and @var{clip}. Possible values are:
+##
+## @itemize @bullet
+## @item @var{'AND'}
+## Intersection of @var{sub} and @var{clip} (value by default).
+## @item @var{'OR'}
+## Union of @var{subt} and @var{clip}.
+## @item @var{'AB'}
+## Operation @var{sub} - @var{clip}.
+## @item @var{'BA'}
+## Operation of @var{clip} - @var{sub}.
+## @end itemize
+##
+## For the matrices @var{sub} and @var{clip}, the first point is not needed to
+## be repeated at the end (but is permitted). Pairs of (NaN,NaN) coordinates in
+## @var{sub} and/or @var{clip} are omitted, so they are treated as if each one
+## stored a single polygon.
+##
+## @var{X} is a column vector containing the X coordinates of the vertices of
+## the resultant polygon(s).
+##
+## @var{Y} is a column vector containing the Y coordinates of the vertices of
+## the resultant polygon(s).
+##
+## @var{nPol} is the number of output polygons.
+##
+## @var{nInt} is the number of intersections between @var{sub} and @var{clip}.
+##
+## @var{nPert} is the number of perturbed points of the @var{clip} polygon in
+## any particular case (points in the oborder of the other polygon) occurs see
+## http://davis.wpi.edu/~matt/courses/clipping/ for details.
+## @end deftypefn
+
+
+
+
+function [X,Y,nPol,nInt,nPert] = oc_polybool(sub,clip,op)
+
+try
+ functionName = 'oc_polybool';
+ minArg = 2;
+ maxArg = 3;
+
+%*******************************************************************************
+%NUMBER OF INPUT ARGUMENTS CHECKING
+%*******************************************************************************
+
+ %number of input arguments checking
+ if (nargin<minArg)||(nargin>maxArg)
+ error(['Incorrect number of input arguments (%d)\n\t ',...
+ 'Correct number of input arguments = %d or %d'],...
+ nargin,minArg,maxArg);
+ end
+ %check if we omit the op argument
+ if nargin==minArg
+ %by default, use AND
+ op = 'AND';
+ end
+
+%*******************************************************************************
+%INPUT ARGUMENTS CHECKING
+%*******************************************************************************
+
+ %checking input arguments
+ [op] = checkInputArguments(sub,clip,op);
+catch
+ %error message
+ error('\n\tIn function %s:\n\t -%s ',functionName,lasterr);
+end
+
+%*******************************************************************************
+%COMPUTATION
+%*******************************************************************************
+
+try
+ %calling oct function
+ [X,Y,nPol,nInt,nPert] = _oc_polybool(sub,clip,op);
+catch
+ %error message
+ error('\n\tIn function %s:\n\tIn function %s ',functionName,lasterr);
+end
+
+
+
+
+%*******************************************************************************
+%AUXILIARY FUNCTION
+%*******************************************************************************
+
+
+
+
+function [outOp] = checkInputArguments(sub,clip,inOp)
+
+%sub must be matrix type
+if isnumeric(sub)
+ %a dimensions
+ [rowSub,colSub] = size(sub);
+else
+ error('The first input argument is not numeric');
+end
+%clip must be matrix type
+if isnumeric(clip)
+ %b dimensions
+ [rowClip,colClip] = size(clip);
+else
+ error('The second input argument is not numeric');
+end
+%checking dimensions
+if (colSub~=2)||(colClip~=2)
+ error('The columns of input arguments must be 2');
+end
+%operation must be a text string
+if ~ischar(inOp)
+ error('The third input argument is not a text string');
+else
+ %upper case
+ outOp = toupper(inOp);
+ %check values
+ if (~strcmp(outOp,'AND'))&&(~strcmp(outOp,'OR'))&& ...
+ (~strcmp(outOp,'AB'))&&(~strcmp(outOp,'BA'))
+ error('The third input argument is not correct');
+ end
+end
+
+
+
+
+%*****END OF FUNCIONS*****
+
+
+
+
+%*****FUNCTION TESTS*****
+
+
+
+
+%tests for input arguments
+%!error(oc_polybool)
+%!error(oc_polybool(1,2,3,4))
+%!error(oc_polybool('string',2,3))
+%!error(oc_polybool(1,'string',3))
+%!error(oc_polybool(1,2,3))
+%demo program
+%!demo
+%! %subject polygon
+%! clSub = [9.0 7.5
+%! 9.0 3.0
+%! 2.0 3.0
+%! 2.0 4.0
+%! 8.0 4.0
+%! 8.0 5.0
+%! 2.0 5.0
+%! 2.0 6.0
+%! 8.0 6.0
+%! 8.0 7.0
+%! 2.0 7.0
+%! 2.0 7.5
+%! 9.0 7.5];
+%! %clipper polygon
+%! clClip = [2.5 1.0
+%! 7.0 1.0
+%! 7.0 8.0
+%! 6.0 8.0
+%! 6.0 2.0
+%! 5.0 2.0
+%! 5.0 8.0
+%! 4.0 8.0
+%! 4.0 2.0
+%! 3.0 2.0
+%! 3.0 8.0
+%! 2.5 8.0
+%! 2.5 1.0];
+%! %limits for the plots
+%! clXLim = [1.5 11.75];
+%! clYLim = [0.5 8.50];
+%! %compute intersection
+%! [clXI,clYI] = oc_polybool(clSub,clClip,'and');
+%! %compute union
+%! [clXU,clYU] = oc_polybool(clSub,clClip,'or');
+%! %compute A-B
+%! [clXA,clYA] = oc_polybool(clSub,clClip,'ab');
+%! %compute B-A
+%! [clXB,clYB] = oc_polybool(clSub,clClip,'ba');
+%! %plot window for intersection
+%! subplot(2,2,1);
+%! plot(clXI,clYI,'r.-','markersize',10,'linewidth',3,clSub(:,1),clSub(:,2),...
+%! clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP intersection');
+%! legend('Intersection','Subject polygon','Clipper polygon',...
+%! 'location','southeast');
+%! %plot window for union
+%! subplot(2,2,2);
+%! plot(clXU,clYU,'r.-','markersize',10,'linewidth',3,clSub(:,1),clSub(:,2),...
+%! clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP union');
+%! legend('Union','Subject polygon','Clipper polygon','location','southeast');
+%! %plot window for A-B
+%! subplot(2,2,3);
+%! plot(clXA,clYA,'r.-','markersize',10,'linewidth',3,clSub(:,1),clSub(:,2),...
+%! clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP A-B');
+%! legend('A-B','Subject polygon','Clipper polygon','location','southeast');
+%! %plot window for B-A
+%! subplot(2,2,4);
+%! plot(clXB,clYB,'r.-','markersize',10,'linewidth',3,clSub(:,1),clSub(:,2),...
+%! clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP B-A');
+%! legend('B-A','Subject polygon','Clipper polygon','location','southeast');
+%! %input message
+%! disp('Press ENTER to continue ...');
+%! pause();
+%! %kill and close the plot window
+%! clf();
+%! close();
+
+
+
+
+%*****END OF TESTS*****
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..454d544
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+#Compiler
+MKOCTFILE=mkoctfile
+#Common warning flags for C and C++
+FLAGSCOMW=-Wall -Wextra -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
+#Common optimization flags for C and C++
+FLAGSCOMO=-O2 -funroll-loops -fno-common -fshort-enums
+#Flags for C
+CFLAGS=-std=c99 -pedantic $(FLAGSCOMW) -Wconversion -Wmissing-prototypes
+CFLAGS+=-Wstrict-prototypes -Wnested-externs $(FLAGSCOMO)
+#Flags for C++
+CXXFLAGS=$(FLAGSCOMW) $(FLAGSCOMO)
+#Export flags for compilers and linker
+export CFLAGS CXXFLAGS
+
+.PHONY: all
+all: compile
+
+.PHONY: compile
+compile:
+ $(MKOCTFILE) -c -I. calctopo.c -o calctopo.o
+ $(MKOCTFILE) -c -I. compilador.c -o compilador.o
+ $(MKOCTFILE) -c -I. dpeucker.c -o dpeucker.o
+ $(MKOCTFILE) -c -I. errores.c -o errores.o
+ $(MKOCTFILE) -c -I. eucli.c -o eucli.o
+ $(MKOCTFILE) -c -I. fgeneral.c -o fgeneral.o
+ $(MKOCTFILE) -c -I. geocnan.c -o geocnan.o
+ $(MKOCTFILE) -c -I. geocomp.c -o geocomp.o
+ $(MKOCTFILE) -c -I. greiner.c -o greiner.o
+ $(MKOCTFILE) -c -I. polig.c -o polig.o
+ $(MKOCTFILE) -c -I. polil.c -o polil.o
+ $(MKOCTFILE) -c -I. ptopol.c -o ptopol.o
+ $(MKOCTFILE) -c -I. recpolil.c -o recpolil.o
+ $(MKOCTFILE) -c -I. segmento.c -o segmento.o
+ $(MKOCTFILE) -c -I. ventorno.c -o ventorno.o
+ $(MKOCTFILE) -s -I. _oc_polybool.cc *.o
+
+.PHONY: clean
+clean:
+ rm -rf *.o *~
+
+.PHONY: cleanall
+cleanall:
+ rm -rf *~ *.o *.oct
diff --git a/src/_oc_polybool.cc b/src/_oc_polybool.cc
new file mode 100644
index 0000000..bcee558
--- /dev/null
+++ b/src/_oc_polybool.cc
@@ -0,0 +1,241 @@
+/* -*- coding: utf-8 -*- */
+/* Copyright (C) 2011-2015 José Luis García Pallero, <jgpallero at gmail.com>
+ *
+ * This file is part of OctCLIP.
+ *
+ * OctCLIP 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 software; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+/******************************************************************************/
+/******************************************************************************/
+#define HELPTEXT "\
+-*- texinfo -*-\n\
+ at deftypefn{Loadable Function}{[@var{X}, at var{Y}, at var{nPol}, at var{nInt},\
+ at var{nPert}] =}_oc_polybool(@var{sub}, at var{clip}, at var{op})\n\
+\n\
+ at cindex Performs boolean operations between two polygons.\n\
+\n\
+This function performs boolean operations between two polygons using the\n\
+Greiner-Hormann algorithm (http://davis.wpi.edu/~matt/courses/clipping/).\n\
+\n\
+ at var{sub} is a two column matrix containing the X and Y coordinates of the\n\
+vertices for the subject polygon.\n\n\
+ at var{clip} is a two column matrix containing the X and Y coordinates of the\n\
+vertices for the clipper polygon.\n\n\
+ at var{op} is a text string containing the operation to perform between\n\
+ at var{sub} and @var{clip}. Possible values are:\n\
+\n\
+ at itemize @bullet\n\
+ at item @var{'AND'}\n\
+Intersection of @var{sub} and @var{clip}.\n\n\
+ at item @var{'OR'}\n\
+Union of @var{subt} and @var{clip}.\n\n\
+ at item @var{'AB'}\n\
+Operation @var{sub} - @var{clip}.\n\n\
+ at item @var{'BA'}\n\
+Operation of @var{clip} - @var{sub}.\n\
+ at end itemize\n\
+\n\
+For the matrices @var{sub} and @var{clip}, the first point is not needed to\n\
+be repeated at the end (but is permitted). Pairs of (NaN,NaN) coordinates in\n\
+ at var{sub} and/or @var{clip} are omitted, so they are treated as if each one\n\
+stored a single polygon.\n\
+\n\
+ at var{X} is a column vector containing the X coordinates of the vertices of\n\
+the resultant polygon(s).\n\n\
+ at var{Y} is a column vector containing the Y coordinates of the vertices of\n\
+the resultant polygon(s).\n\n\
+ at var{nPol} is the number of output polygons.\n\n\
+ at var{nInt} is the number of intersections between @var{sub} and @var{clip}.\n\n\
+ at var{nPert} is the number of perturbed points of the @var{clip} polygon in\n\
+any particular case (points in the oborder of the other polygon) occurs see\n\
+http://davis.wpi.edu/~matt/courses/clipping/ for details.\n\
+\n\
+This function do not check if the dimensions of @var{sub} and @var{clip} are\n\
+correct.\n\
+\n\
+ at end deftypefn"
+/******************************************************************************/
+/******************************************************************************/
+#include<octave/oct.h>
+#include<cstdio>
+#include<cstring>
+#include<cstdlib>
+#include<cmath>
+#include"octclip.h"
+/******************************************************************************/
+/******************************************************************************/
+#define ERRORTEXT 1000
+/******************************************************************************/
+/******************************************************************************/
+DEFUN_DLD(_oc_polybool,args,,HELPTEXT)
+{
+ //error message
+ char errorText[ERRORTEXT+1]="_oc_polybool:\n\t";
+ //output list
+ octave_value_list outputList;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //checking input arguments
+ if(args.length()!=3)
+ {
+ //error text
+ sprintf(&errorText[strlen(errorText)],
+ "Incorrect number of input arguments\n\t"
+ "See help _oc_polybool");
+ //error message
+ error(errorText);
+ }
+ else
+ {
+ //loop index
+ size_t i=0;
+ //polygons and operation
+ ColumnVector xSubj=args(0).matrix_value().column(0);
+ ColumnVector ySubj=args(0).matrix_value().column(1);
+ ColumnVector xClip=args(1).matrix_value().column(0);
+ ColumnVector yClip=args(1).matrix_value().column(1);
+ std::string opchar=args(2).string_value();
+ //computation vectors
+ double* xA=NULL;
+ double* yA=NULL;
+ double* xB=NULL;
+ double* yB=NULL;
+ //double linked lists
+ vertPoliClip* polA=NULL;
+ vertPoliClip* polB=NULL;
+ //operation identifier
+ enum GEOC_OP_BOOL_POLIG op=GeocOpBoolInter;
+ //output struct
+ polig* result=NULL;
+ //number of polygons, intersections and perturbations
+ size_t nPol=0,nInter=0,nPert=0;
+ //number of elements for the output vectors
+ size_t nElem=0;
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //pointers to data
+ xA = xSubj.fortran_vec();
+ yA = ySubj.fortran_vec();
+ xB = xClip.fortran_vec();
+ yB = yClip.fortran_vec();
+ //create double linked lists for subject and clipper polygons
+ polA = CreaPoliClip(xA,yA,static_cast<size_t>(xSubj.length()),1,1);
+ polB = CreaPoliClip(xB,yB,static_cast<size_t>(xClip.length()),1,1);
+ //error checking
+ if((polB==NULL)||(polB==NULL))
+ {
+ //free peviously allocated memory
+ LibMemPoliClip(polA);
+ LibMemPoliClip(polB);
+ //error text
+ sprintf(&errorText[strlen(errorText)],"Error in memory allocation");
+ //error message
+ error(errorText);
+ //exit
+ return outputList;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //select operation
+ if((!strcmp(opchar.c_str(),"AND"))||(!strcmp(opchar.c_str(),"and")))
+ {
+ op = GeocOpBoolInter;
+ }
+ else if((!strcmp(opchar.c_str(),"OR"))||(!strcmp(opchar.c_str(),"or")))
+ {
+ op = GeocOpBoolUnion;
+ }
+ else if((!strcmp(opchar.c_str(),"AB"))||(!strcmp(opchar.c_str(),"ab")))
+ {
+ op = GeocOpBoolAB;
+ }
+ else if((!strcmp(opchar.c_str(),"BA"))||(!strcmp(opchar.c_str(),"ba")))
+ {
+ op = GeocOpBoolBA;
+ }
+ else
+ {
+ //free peviously allocated memory
+ LibMemPoliClip(polA);
+ LibMemPoliClip(polB);
+ //error text
+ sprintf(&errorText[strlen(errorText)],
+ "The third input argument (op=%s) is not correct",
+ opchar.c_str());
+ //error message
+ error(errorText);
+ //exit
+ return outputList;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //clipping
+ result = PoliBoolGreiner(polA,polB,op,GEOC_GREINER_FAC_EPS_PERTURB,
+ &nInter,&nPert);
+ //error checking
+ if(result==NULL)
+ {
+ //free peviously allocated memory
+ LibMemPoliClip(polA);
+ LibMemPoliClip(polB);
+ //error text
+ sprintf(&errorText[strlen(errorText)],"Error in memory allocation");
+ //error message
+ error(errorText);
+ //exit
+ return outputList;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //number or output polygons
+ nPol = result->nPolig;
+ //dimensions for the output vectors
+ if(nPol)
+ {
+ nElem = result->nElem;
+ }
+ else
+ {
+ nElem = 0;
+ }
+ //output vectors
+ ColumnVector xResult(nElem);
+ ColumnVector yResult(nElem);
+ //copy output data
+ for(i=0;i<nElem;i++)
+ {
+ xResult(i) = result->x[i];
+ yResult(i) = result->y[i];
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //output parameters list
+ outputList(0) = xResult;
+ outputList(1) = yResult;
+ outputList(2) = nPol;
+ outputList(3) = nInter;
+ outputList(4) = nPert;
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //free memory
+ LibMemPoliClip(polA);
+ LibMemPoliClip(polB);
+ LibMemPolig(result);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //exit
+ return outputList;
+}
diff --git a/src/calctopo.c b/src/calctopo.c
new file mode 100644
index 0000000..ab3c595
--- /dev/null
+++ b/src/calctopo.c
@@ -0,0 +1,71 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geodesia geom
+@{
+\file calctopo.c
+\brief Definición de funciones para cálculos de topografía.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 05 de julio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/calctopo.h"
+/******************************************************************************/
+/******************************************************************************/
+double AcimutTopografico(const double x1,
+ const double y1,
+ const double x2,
+ const double y2)
+{
+ //acimut calculado
+ double acimut=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el acimut en el dominio [-pi pi]
+ acimut = atan2(x2-x1,y2-y1);
+ //comprobamos si ha salido un valor negativo
+ if(acimut<0.0)
+ {
+ //metemos el valor en dominio
+ acimut += 2.0*GEOC_CONST_PI;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return acimut;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/compilador.c b/src/compilador.c
new file mode 100755
index 0000000..aa35e74
--- /dev/null
+++ b/src/compilador.c
@@ -0,0 +1,82 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup general geopot
+@{
+\file compilador.c
+\brief Definición de funciones para la detección de compiladores.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 28 de abril de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/compilador.h"
+/******************************************************************************/
+/******************************************************************************/
+int EsCompiladorGNU(int* noGnu)
+{
+ //variable de salida
+ int salida=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable noGnu, si ha lugar
+ if(noGnu!=NULL)
+ {
+ //inicializamos la variable a 0
+ *noGnu = 0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //para que sea GCC, la constante __GNUC__ ha de estar definida
+#if defined(__GNUC__)
+ //el compilador es GCC
+ salida = 1;
+ //comprobamos si es el compilador de intel
+#if defined(__INTEL_COMPILER)
+ if(noGnu!=NULL)
+ {
+ //el compilador es de intel
+ *noGnu = 1;
+ }
+#endif
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/dpeucker.c b/src/dpeucker.c
new file mode 100644
index 0000000..f63f53d
--- /dev/null
+++ b/src/dpeucker.c
@@ -0,0 +1,472 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeucker.c
+\brief Definición de funciones para el aligerado de polilíneas basadas en el
+ algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 04 de julio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/dpeucker.h"
+/******************************************************************************/
+/******************************************************************************/
+size_t* AligeraPolilinea(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto,
+ size_t* nPtosSal)
+{
+ //índice para recorrer bucles
+ size_t p=0;
+ //índice de los puntos de trabajo
+ size_t i=0,j=0,k=0;
+ //coordenadas de trabajo
+ double xIni=0.0,yIni=0.0,xFin=0.0,yFin=0.0,xTrab=0.0,yTrab=0.0;
+ //altura del triángulo de trabajo
+ double h=0.0;
+ //variable indicadora de punto a mantener
+ int usado=0;
+ //número de elementos de trabajo internos del vector de salida
+ size_t nElem=0;
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //iniciamos la variable de salida de número de puntos a 0
+ *nPtosSal = 0;
+ //comprobamos casos especiales de nPtos
+ if(nPtos==0)
+ {
+ //salimos de la función con NULL
+ return NULL;
+ }
+ else if(nPtos<=2)
+ {
+ //asignamos el número de puntos usados
+ *nPtosSal = nPtos;
+ //asignamos memoria para el vector de salida
+ sal = (size_t*)malloc((*nPtosSal)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //asignamos valores al vector de salida
+ for(i=0;i<(*nPtosSal);i++)
+ {
+ //asignamos el índice de trabajo
+ sal[i] = i;
+ }
+ //salimos de la función
+ return sal;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el indicador interno de tamaño del vector
+ nElem = GEOC_DPEUCKER_BUFFER_PTOS;
+ //asignamos memoria para el vector de salida
+ sal = (size_t*)malloc(nElem*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //indicamos que el primer punto siempre se usa
+ *nPtosSal = 1;
+ sal[0] = 0;
+ //puntos de trabajo para iniciar los cálculos
+ i = 0;
+ j = 1;
+ k = 2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //entramos en un bucle infinito
+ while(1)
+ {
+ //comprobamos si hay que salir del bucle
+ if(k>(nPtos-1))
+ {
+ //salimos del bucle
+ break;
+ }
+ //coordenadas de la base del triángulo
+ xIni = x[i*incX];
+ yIni = y[i*incY];
+ xFin = x[k*incX];
+ yFin = y[k*incY];
+ //inicializamos a 0 la variable de punto usado
+ usado = 0;
+ //recorremos los puntos a testear
+ for(p=j;p<k;p++)
+ {
+ //coordenadas del vértice del triángulo
+ xTrab = x[p*incX];
+ yTrab = y[p*incY];
+ //calculamos la altura del triángulo
+ h = AlturaTriangulo(xTrab,yTrab,xIni,yIni,xFin,yFin);
+ //comprobamos si la altura supera a la tolerancia
+ if(h>tol)
+ {
+ //indicamos que el punto ha sido usado
+ usado = 1;
+ //comprobamos si se utiliza el algoritmo robusto
+ if(robusto!=GeocDPeuckerRobNo)
+ {
+ //comprobamos si hay que aplicar el algoritmo de
+ //intersección con puntos originales
+ if((robusto==GeocDPeuckerRobSi)||
+ (robusto==GeocDPeuckerRobOrig))
+ {
+ //aplicamos el algoritmo
+ AligPolilRobIntersecOrig(x,y,nPtos,incX,incY,
+ nPtosRobusto,i,&p);
+ }
+ //comprobamos si hay que aplicar el algoritmo de auto
+ //intersección
+ if((robusto==GeocDPeuckerRobSi)||
+ (robusto==GeocDPeuckerRobAuto))
+ {
+ //indicamos un número de puntos para el vector de salida
+ //una unidad menor que el número realmente almacenado
+ //para evitar el segmento inmediatamente anterior al que
+ //vamos a crear
+ AligPolilRobAutoIntersec(x,y,incX,incY,sal,
+ (*nPtosSal)-1,nSegRobusto,i,
+ &p);
+ }
+ }
+ //añadimos al contador este nuevo punto
+ (*nPtosSal)++;
+ //comprobamos si hay que reasignar memoria
+ if((*nPtosSal)>nElem)
+ {
+ //añadimos otro grupo de puntos
+ nElem += GEOC_DPEUCKER_BUFFER_PTOS;
+ //asignamos memoria para el vector de salida
+ sal = (size_t*)realloc(sal,nElem*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //añadimos el nuevo punto usado
+ sal[(*nPtosSal)-1] = p;
+ //actualizamos los índices de los puntos de trabajo
+ i = p;
+ j = i+1;
+ k = j+1;
+ //salimos del bucle
+ break;
+ }
+ }
+ //comprobamos si no se ha utilizado ninguno de los vértices candidatos
+ if(!usado)
+ {
+ //pasamos al siguiente punto como extremo del segmento
+ k++;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el último punto se ha añadido
+ if(sal[(*nPtosSal)-1]!=(nPtos-1))
+ {
+ //añadimos al contador el último punto
+ (*nPtosSal)++;
+ //comprobamos si hay que reasignar memoria
+ if((*nPtosSal)>nElem)
+ {
+ //añadimos otro grupo de puntos
+ nElem += GEOC_DPEUCKER_BUFFER_PTOS;
+ //asignamos memoria para el vector de salida
+ sal = (size_t*)realloc(sal,nElem*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos el último punto
+ sal[(*nPtosSal)-1] = nPtos-1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el vector de salida tiene demasiada memoria asignada
+ if(nElem>(*nPtosSal))
+ {
+ //ajustamos el tamaño del vector de salida
+ sal = (size_t*)realloc(sal,(*nPtosSal)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AligPolilRobIntersecOrig(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const size_t ptosAUsar,
+ const size_t posIni,
+ size_t* posFin)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //coordenadas de trabajo
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0,xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //punto de parada para comprobar la intersección de segmentos
+ size_t parada=0;
+ //identificador de intersección
+ int inter=0;
+ //variables auxiliares
+ size_t aux=0;
+ double xAux=0.0,yAux=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contemplamos una posible salida rápida
+ if((*posFin)<=(posIni+1))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número de puntos que quedan hasta el final de los vectores
+ //de coordenadas desde la posición de fin de segmento (contándola)
+ aux = nPtos-(*posFin);
+ //calculamos el punto de parada para la intersección de segmentos
+ if((aux>ptosAUsar)&&(ptosAUsar!=0))
+ {
+ //paramos en un pnto tal que usemos ptosAUsar puntos
+ parada = *posFin+ptosAUsar-1;
+ }
+ else
+ {
+ //paramos en el penúltimo punto
+ parada = nPtos-2;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //las coordenadas del punto inicial del segmento base no cambian nunca
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ //recorremos los puntos candidatos hasta el anterior al punto base
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //terminamos, porque este punto es el siguiente al punto base en el
+ //listado original
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ else
+ {
+ //coordenadas de los puntos inicial y final del segmento base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //recorremos los puntos posteriores hasta el de parada
+ for(j=i;j<=parada;j++)
+ {
+ //coordenadas de los puntos inicial y final del siguiente
+ //segmento
+ xC = x[j*incX];
+ yC = y[j*incY];
+ xD = x[(j+1)*incX];
+ yD = y[(j+1)*incY];
+ //calculamos la intersección entre los segmentos
+ inter = IntersecSegmentos2D(xA,yA,xB,yB,xC,yC,xD,yD,&xAux,
+ &yAux);
+ //comprobamos si hay intersección entre los segmentos
+ if(inter!=GEOC_SEG_NO_INTERSEC)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(inter==GEOC_SEG_NO_INTERSEC)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AligPolilRobAutoIntersec(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //variables de posición
+ size_t k=0,l=0,pos=0;
+ //coordenadas de trabajo
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0,xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //número de segmentos calculados hasta ahora, excepto el último
+ size_t nSeg=0;
+ //identificador de intersección
+ int inter=0;
+ //variables auxiliares
+ double xAux=0.0,yAux=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contemplamos una posible salida rápida
+ if(((*posFin)<=(posIni+1))||(nPosAlig<2))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número de segmentos calculados hasta ahora, excepto el
+ //anterior al de trabajo
+ nSeg = nPosAlig-1;
+ //comprobamos si se usan todos los segmentos o sólo parte
+ if(segAUsar!=0)
+ {
+ //asignamos el número de segmentos a utilizar
+ nSeg = (nSeg>segAUsar) ? segAUsar : nSeg;
+ }
+ //las coordenadas del punto inicial del segmento base no cambian nunca
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos candidatos hasta el anterior al punto base
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //terminamos, porque este punto es el siguiente al punto inicial
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ else
+ {
+ //coordenadas del punto final del segmento base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //recorremos el número de segmentos de trabajo
+ for(j=0;j<nSeg;j++)
+ {
+ //posición del punto inicial del siguiente segmento anterior
+ pos = nPosAlig-1-j;
+ //índices inicial y final del siguiente segmento anterior
+ k = posAlig[pos];
+ l = posAlig[pos-1];
+ //puntos inicial y final del siguiente segmento
+ xC = x[k*incX];
+ yC = y[k*incY];
+ xD = x[l*incX];
+ yD = y[l*incY];
+ //calculamos la intersección entre los segmentos
+ inter = IntersecSegmentos2D(xA,yA,xB,yB,xC,yC,xD,yD,&xAux,
+ &yAux);
+ //comprobamos si hay intersección entre los segmentos
+ if(inter!=GEOC_SEG_NO_INTERSEC)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(inter==GEOC_SEG_NO_INTERSEC)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/errores.c b/src/errores.c
new file mode 100755
index 0000000..4b7788a
--- /dev/null
+++ b/src/errores.c
@@ -0,0 +1,119 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec errores eop fichero general geodesia geom geopot gshhs marea
+\ingroup matriz mmcc orden snx texto
+@{
+\file errores.c
+\brief Definición de funciones para el tratamiento de errores.
+
+En el momento de la compilación ha de seleccionarse el comportamiento de la
+función \ref GeocError. Para realizar la selección es necesario definir las
+variables para el preprocesador \em ESCRIBE_MENSAJE_ERROR si se quiere que la
+función imprima un mensaje de error y/o \em FIN_PROGRAMA_ERROR si se quiere que
+la función termine la ejecución del programa en curso. Si no se define ninguna
+variable, la función no ejecuta ninguna acción. En \p gcc, las variables para el
+preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
+introducir.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 09 de enero de 2011
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/errores.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocTipoError(void)
+{
+ //variable de salida
+ int valor=GEOC_TIPO_ERR_NADA;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos los posibles casos según las variables del preprocesador
+#if defined(ESCRIBE_MENSAJE_ERROR) && defined(FIN_PROGRAMA_ERROR)
+ //mensaje de error y terminación del programa
+ valor = GEOC_TIPO_ERR_MENS_Y_EXIT;
+#elif defined(ESCRIBE_MENSAJE_ERROR)
+ //mensaje de error
+ valor = GEOC_TIPO_ERR_MENS;
+#elif defined(FIN_PROGRAMA_ERROR)
+ //terminación del programa
+ valor = GEOC_TIPO_ERR_EXIT;
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return valor;
+}
+/******************************************************************************/
+/******************************************************************************/
+void GeocError(const char mensaje[],
+ const char funcion[])
+{
+ //hacemos una copia para que en la compilación no dé warning si sólo se
+ //termina la ejecución del programa o no se hace nada
+ mensaje = mensaje;
+ funcion = funcion;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos los posibles casos según las variables del preprocesador
+#if defined(ESCRIBE_MENSAJE_ERROR) && defined(FIN_PROGRAMA_ERROR)
+ //imprimimos el nombre de la función y el mensaje
+ fprintf(stderr,"En la función '%s'\n",funcion);
+ fprintf(stderr,"%s\n",mensaje);
+ //indicamos que el programa finalizará
+ fprintf(stderr,"El programa finalizará mediante la llamada a la función "
+ "'exit(EXIT_FAILURE)'\n");
+ //detenemos la ejecución del programa
+ exit(EXIT_FAILURE);
+#elif defined(ESCRIBE_MENSAJE_ERROR)
+ //imprimimos el nombre de la función y el mensaje
+ fprintf(stderr,"En la función '%s'\n",funcion);
+ fprintf(stderr,"%s\n",mensaje);
+ //salimos de la función
+ return;
+#elif defined(FIN_PROGRAMA_ERROR)
+ //indicamos que el programa finalizará
+ fprintf(stderr,"El programa finalizará mediante la llamada a la función "
+ "'exit(EXIT_FAILURE)'\n");
+ //detenemos la ejecución del programa
+ exit(EXIT_FAILURE);
+#else
+ //salimos de la función
+ return;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/eucli.c b/src/eucli.c
new file mode 100755
index 0000000..fcd8cd7
--- /dev/null
+++ b/src/eucli.c
@@ -0,0 +1,238 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom interp
+@{
+\file eucli.c
+\brief Definición de funciones para la realización de cálculos de geometría
+ euclídea.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 27 de octubre de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/eucli.h"
+/******************************************************************************/
+/******************************************************************************/
+double Dist2D(const double x1,
+ const double y1,
+ const double x2,
+ const double y2)
+{
+ //calculamos y salimos de la función
+ return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
+}
+/******************************************************************************/
+/******************************************************************************/
+void Dist2DVC(const double x1,
+ const double y1,
+ const double x2,
+ const double y2,
+ const double varx1,
+ const double varx1y1,
+ const double vary1,
+ const double varx2,
+ const double varx2y2,
+ const double vary2,
+ double* dist,
+ double* varDist)
+{
+ //matrices auxiliares
+ double j[4],jvc[4];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la distancia
+ *dist = Dist2D(x1,y1,x2,y2);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //rellenamos la matriz jacobiana
+ j[0] = -(x2-x1)/(*dist);
+ j[1] = -(y2-y1)/(*dist);
+ j[2] = -j[0];
+ j[3] = -j[1];
+ //producto de la matriz jacobiana por la matriz de varianza-covarianza
+ jvc[0] = j[0]*varx1+j[1]*varx1y1;
+ jvc[1] = j[0]*varx1y1+j[1]*vary1;
+ jvc[2] = j[2]*varx2+j[3]*varx2y2;
+ jvc[3] = j[2]*varx2y2+j[3]*vary2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //realizamos la propagación de errores
+ *varDist = jvc[0]*j[0]+jvc[1]*j[1]+jvc[2]*j[2]+jvc[3]*j[3];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Dist3D(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2)
+{
+ //calculamos y salimos de la función
+ return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1));
+}
+/******************************************************************************/
+/******************************************************************************/
+void Dist3DVC(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2,
+ const double varx1,
+ const double varx1y1,
+ const double varx1z1,
+ const double vary1,
+ const double vary1z1,
+ const double varz1,
+ const double varx2,
+ const double varx2y2,
+ const double varx2z2,
+ const double vary2,
+ const double vary2z2,
+ const double varz2,
+ double* dist,
+ double* varDist)
+{
+ //matrices auxiliares
+ double j[6],jvc[6];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la distancia
+ *dist = Dist3D(x1,y1,z1,x2,y2,z2);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //rellenamos la matriz jacobiana
+ j[0] = -(x2-x1)/(*dist);
+ j[1] = -(y2-y1)/(*dist);
+ j[2] = -(z2-z1)/(*dist);
+ j[3] = -j[0];
+ j[4] = -j[1];
+ j[5] = -j[2];
+ //producto de la matriz jacobiana por la matriz de varianza-covarianza
+ jvc[0] = j[0]*varx1+j[1]*varx1y1+j[2]*varx1z1;
+ jvc[1] = j[0]*varx1y1+j[1]*vary1+j[2]*vary1z1;
+ jvc[2] = j[0]*varx1z1+j[1]*vary1z1+j[2]*varz1;
+ jvc[3] = j[3]*varx2+j[4]*varx2y2+j[5]*varx2z2;
+ jvc[4] = j[3]*varx2y2+j[4]*vary2+j[5]*vary2z2;
+ jvc[5] = j[3]*varx2z2+j[4]*vary2z2+j[5]*varz2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //realizamos la propagación de errores
+ *varDist = jvc[0]*j[0]+jvc[1]*j[1]+jvc[2]*j[2]+jvc[3]*j[3]+jvc[4]*j[4]+
+ jvc[5]*j[5];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+double AnguloVecPlano(const double x1,
+ const double y1,
+ const double x2,
+ const double y2)
+{
+ //variables auxiliares
+ double num=0.0,den=0.0;
+ //variable de salida
+ double alfa=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el numerador de la fórmula que da el coseno del ángulo
+ num = x1*x2+y1*y2;
+ //calculamos el denominador de la fórmula que da el coseno del ángulo
+ den = sqrt((x1*x1+y1*y1)*(x2*x2+y2*y2));
+ //calculamos el coseno del ángulo, teniendo en cuenta casos singulares
+ if(den==0.0)
+ {
+ //si el denominador es 0.0, el ángulo es 0.0 y su coseno 1.0
+ alfa = 1.0;
+ }
+ else
+ {
+ //no hay singularidad
+ alfa = num/den;
+ }
+ //calculamos el ángulo
+ alfa = acos(alfa);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return alfa;
+}
+/******************************************************************************/
+/******************************************************************************/
+double AlturaTriangulo(const double xVert,
+ const double yVert,
+ const double xBase1,
+ const double yBase1,
+ const double xBase2,
+ const double yBase2)
+{
+ //ángulo entra la base en el punto 1 y el vértice
+ double alfa=0.0;
+ //longitud del punto 1 de la base al vértice
+ double lon=0.0;
+ //variables auxiliares
+ double dxv=0.0,dyv=0.0,dxb=0.0,dyb=0.0;
+ //variable de salida
+ double h=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos los incrementos de coordenadas auxiliares
+ dxv = xVert-xBase1;
+ dyv = yVert-yBase1;
+ dxb = xBase2-xBase1;
+ dyb = yBase2-yBase1;
+ //calculamos el ángulo entre la base y el segmento que une el punto inicial
+ //de ésta con el vértice
+ alfa = AnguloVecPlano(dxv,dyv,dxb,dyb);
+ //longitud del lado que une la base con el vértice 1 de la base
+ lon = sqrt(dxv*dxv+dyv*dyv);
+ //calculamos la altura
+ h = fabs(lon*sin(alfa));
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return h;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/fgeneral.c b/src/fgeneral.c
new file mode 100755
index 0000000..c048f42
--- /dev/null
+++ b/src/fgeneral.c
@@ -0,0 +1,880 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup eop general geom geopot matriz
+@{
+\file fgeneral.c
+\brief Definición de funciones de utilidad general.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 10 de octubre de 2009
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/fgeneral.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpFgeneral(char version[])
+{
+ //comprobamos si hay paralelización
+#if defined(_OPENMP)
+ //comprobamos si hay que extraer versión
+ if(version!=NULL)
+ {
+ //calculamos la versión
+ VersionOpenMP(_OPENMP,version);
+ }
+ //salimos de la función
+ return 1;
+#else
+ if(version!=NULL)
+ {
+ //utilizamos la variable version para que no dé warming al compilar
+ strcpy(version,"");
+ }
+ //salimos de la función
+ return 0;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+double PonAnguloDominio(const double angulo)
+{
+ //signo del ángulo de trabajo
+ double signo=0.0;
+ //2.0*pi
+ double dosPi=2.0*GEOC_CONST_PI;
+ //variable auxiliar
+ double aux=angulo;
+ //variable de salida
+ double sal=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo trabajamos si el valor de entrada está fuera de los límites
+ if((angulo<=-dosPi)||(angulo>=dosPi))
+ {
+ //extraemos el signo del ángulo pasado
+ signo = GEOC_SIGNO(angulo);
+ //valor absoluto del ángulo pasado
+ aux = fabs(angulo);
+ //metemos el ángulo en dominio eliminando la cantidad que se pase de
+ //2.0*pi
+ sal = signo*(aux-floor(aux/dosPi)*dosPi);
+ }
+ else
+ {
+ //el valor de entrada no cambia
+ sal = angulo;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+void BuscaSegmento1DInc(const double valor,
+ const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posInicio,
+ size_t* posFin)
+{
+ //variable para recorrer bucles
+ size_t i=0;
+ //variable indicadora de búsqueda secuencial
+ int busca=0;
+ //variables para calcular posiciones
+ size_t pos1=0,pos2=0;
+ //posiciones en memoria
+ size_t posm=0,pos1m=0,pos2m=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //CONSIDERAMOS QUE LA LISTA CONTIENE ENTEROS EQUIESPACIADOS UNA UNIDAD
+ //posición del valor anterior al de trabajo
+ pos1 = (size_t)(floor(valor)-lista[0]);
+ //posición del valor posterior al de trabajo
+ pos2 = (size_t)(ceil(valor)-lista[0]);
+ //si pos1==pos2, valor puede ser un extremo de la lista
+ if(pos1==pos2)
+ {
+ if(pos1!=(nDatos-1))
+ {
+ //calculamos el punto final del segmento
+ pos2++;
+ }
+ else
+ {
+ //calculamos el punto inicial del segmento
+ pos1--;
+ }
+ }
+ //calculamos las posiciones en memoria
+ pos1m = pos1*incDatos;
+ pos2m = pos2*incDatos;
+ //comprobamos si el segmento detectado es válido
+ if((lista[pos1m]!=round(lista[pos1m]))||
+ (lista[pos2m]!=round(lista[pos2m]))||
+ ((lista[pos2m]-lista[pos1m])!=1.0)||
+ (valor<lista[pos1m])||(valor>lista[pos2m]))
+ {
+ //indicamos que se ha de hacer una búsqueda secuencial
+ busca = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //LA LISTA CONTIENE REALES NO EQUIESPACIADOS
+ if(busca)
+ {
+ //recorremos todos los elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición en memoria
+ posm = i*incDatos;
+ //comprobamos si estamos ante un límite
+ if(lista[posm]>=valor)
+ {
+ //comprobamos el tipo de límite
+ if(lista[posm]>valor)
+ {
+ //extraemos las posiciones
+ pos1 = i-1;
+ pos2 = i;
+ }
+ else
+ {
+ //comprobamos si estamos trabajando con el último elemento
+ if(i==(nDatos-1))
+ {
+ //extraemos las posiciones
+ pos1 = i-1;
+ pos2 = i;
+ }
+ else
+ {
+ //extraemos las posiciones
+ pos1 = i;
+ pos2 = i+1;
+ }
+ }
+ //salimos del bucle
+ break;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos las variables de salida
+ *posInicio = pos1;
+ *posFin = pos2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void BuscaSegmento1D(const double valor,
+ const double* lista,
+ const size_t nDatos,
+ size_t* posInicio,
+ size_t* posFin)
+{
+ //realizamos la búsqueda con incremento igual a 1
+ BuscaSegmento1DInc(valor,lista,nDatos,1,posInicio,posFin);
+}
+/******************************************************************************/
+/******************************************************************************/
+void BuscaPosNWEnMalla(const double xPto,
+ const double yPto,
+ const double xMin,
+ const double xMax,
+ const double yMin,
+ const double yMax,
+ const double pasoX,
+ const double pasoY,
+ size_t* fil,
+ size_t* col)
+{
+ //dimensiones de la matriz
+ size_t f=0,c=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las dimensiones de la matriz de trabajo
+ f = (size_t)(round((yMax-yMin)/pasoY)+1.0);
+ c = (size_t)(round((xMax-xMin)/pasoX)+1.0);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la fila y comprobamos si es el extremo S
+ *fil = (size_t)(fabs(yPto-yMax)/pasoY);
+ if(*fil==(f-1))
+ {
+ //retrasamos una fila
+ (*fil)--;
+ }
+ //calculamos la columna y comprobamos si es el extremo E
+ *col = (size_t)((xPto-xMin)/pasoX);
+ if(*col==(c-1))
+ {
+ //retrasamos una columna
+ (*col)--;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Minimo(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como el máximo valor para un double
+ double salida=DBL_MAX;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(min:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(min:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(lista[pos]<salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = lista[pos];
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Maximo(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como el mínimo valor para un double
+ double salida=DBL_MIN;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(max:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(max:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(lista[pos]>salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = lista[pos];
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+double MinimoAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como el máximo valor para un double
+ double salida=DBL_MAX;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(min:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(min:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(fabs(lista[pos])<salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = fabs(lista[pos]);
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+double MaximoAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como 0.0 (trabajamos en valor absoluto)
+ double salida=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(max:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(max:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(fabs(lista[pos])>salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = fabs(lista[pos]);
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t MinimoSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como el máximo valor para un size_t
+ size_t salida=SIZE_MAX;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(min:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(min:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(lista[pos]<salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = lista[pos];
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t MaximoSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //variable de salida, inicializada como 0 (size_t es sólo positivo)
+ size_t salida=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP, sólo si la versión es superior a la 3.0
+ //en versiones anteriores no existe la posibilidad de usar reduction(max:)
+#if defined(_OPENMP)&&(_OPENMP>=GEOC_OMP_F_3_1)
+#pragma omp parallel for default(none) \
+ shared(lista) \
+ private(i,pos) \
+ reduction(max:salida)
+#endif
+ //recorremos el resto de elementos de la lista
+ for(i=0;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(lista[pos]>salida)
+ {
+ //asignamos el nuevo valor menor
+ salida = lista[pos];
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+void MinMax(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //consideramos que el primer elemento es el mayor y el menor
+ *posMin = 0;
+ *posMax = 0;
+ //recorremos el resto de elementos de la lista
+ for(i=1;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(lista[pos]<lista[(*posMin)*incDatos])
+ {
+ //asignamos la nueva posición
+ *posMin = i;
+ }
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(lista[pos]>lista[(*posMax)*incDatos])
+ {
+ //asignamos la nueva posición
+ *posMax = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void MinMaxAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //consideramos que el primer elemento es el mayor y el menor
+ *posMin = 0;
+ *posMax = 0;
+ //recorremos el resto de elementos de la lista
+ for(i=1;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(fabs(lista[pos])<fabs(lista[(*posMin)*incDatos]))
+ {
+ //asignamos la nueva posición
+ *posMin = i;
+ }
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(fabs(lista[pos])>fabs(lista[(*posMax)*incDatos]))
+ {
+ //asignamos la nueva posición
+ *posMax = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void MinMaxSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //consideramos que el primer elemento es el mayor y el menor
+ *posMin = 0;
+ *posMax = 0;
+ //recorremos el resto de elementos de la lista
+ for(i=1;i<nDatos;i++)
+ {
+ //posición del elemento a comprobar
+ pos = i*incDatos;
+ //comprobamos si el elemento actual es menor que el considerado menor
+ if(lista[pos]<lista[(*posMin)*incDatos])
+ {
+ //asignamos la nueva posición
+ *posMin = i;
+ }
+ //comprobamos si el elemento actual es mayor que el considerado mayor
+ if(lista[pos]>lista[(*posMax)*incDatos])
+ {
+ //asignamos la nueva posición
+ *posMax = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+double** AsigMemMatrizC(const size_t fil,
+ const size_t col)
+{
+ //índices para recorrer bucles
+ size_t i=0;
+ //matriz de salida
+ double** matriz=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el array principal
+ matriz = (double**)malloc(fil*sizeof(double*));
+ //comprobamos los errores
+ if(matriz==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos toda la memoria al primer puntero
+ matriz[0] = (double*)malloc(fil*col*sizeof(double));
+ //comprobamos los errores
+ if(matriz[0]==NULL)
+ {
+ //liberamos la memoria previamente asignada
+ free(matriz);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //recorremos el resto de filas
+ for(i=1;i<fil;i++)
+ {
+ //vamos asignando las direcciones de inicio de cada fila
+ matriz[i] = &matriz[0][i*col];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return matriz;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LibMemMatrizC(double** matriz)
+{
+ //sólo trabajamos si hay memoria asignada
+ if(matriz!=NULL)
+ {
+ //sólo trabajamos si hay memoria asignada
+ if(matriz[0]!=NULL)
+ {
+ //liberamos la memoria de los datos
+ free(matriz[0]);
+ }
+ //liberamos la memoria del array principal
+ free(matriz);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* PosRepeEnVector(const double* datos,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* nRepe)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de repeticiones encontradas
+ size_t numRep=0;
+ //datos de las posiciones de trabajo
+ double dato=0.0,datoTrab=0.0;
+ //variable de salida
+ size_t* pos=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el vector de salida
+ pos = (size_t*)malloc(nDatos*sizeof(double));
+ //comprobamos los posibles errores
+ if(pos==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la primera posición, extraemos el dato e inicializamos el
+ //contador de repeticiones
+ pos[0] = 0;
+ dato = datos[0];
+ numRep = 1;
+ //recorremos el resto de elementos del vector
+ for(i=1;i<nDatos;i++)
+ {
+ //extraemos el dato de trabajo
+ datoTrab = datos[i*incDatos];
+ //lo comparamos con el dato de referencia
+ if(datoTrab!=dato)
+ {
+ //asignamos la nueva posición
+ pos[numRep] = i;
+ //aumentamos el contador de repeticiones
+ numRep++;
+ //convertimos el nuevo dato en dato de referencia
+ dato = datoTrab;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ajustamos la memoria al número de posiciones repetidas encontradas
+ pos = (size_t*)realloc(pos,numRep*sizeof(double));
+ //comprobamos los posibles errores
+ if(pos==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //indicamos el número de repeticiones
+ *nRepe = numRep;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* NumElemRepeEnVector(const size_t* pos,
+ const size_t nPos,
+ const size_t nElemVecOrig)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de salida
+ size_t* num=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el vector de salida
+ num = (size_t*)malloc(nPos*sizeof(double));
+ //comprobamos los posibles errores
+ if(num==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos el vector de posiciones desde el segundo elemento
+ for(i=1;i<nPos;i++)
+ {
+ //vamos calculando los elementos repetidos
+ num[i-1] = pos[i]-pos[i-1];
+ }
+ //comprobamos si la última posición corresponde al último elemento del
+ //vector original
+ if(pos[nPos-1]==(nElemVecOrig-1))
+ {
+ //el último número es 1
+ num[nPos-1] = 1;
+ }
+ else
+ {
+ //tenemos en cuente que los elementos son el mismo hasta el final
+ num[nPos-1] = nElemVecOrig-pos[nPos-1];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return num;
+}
+/******************************************************************************/
+/******************************************************************************/
+void EscalaYTrasladaVector(double* vector,
+ const size_t nElem,
+ const size_t inc,
+ const double escala,
+ const double traslada)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos entre incremento igual a 1 o mayor
+ if(inc==1)
+ {
+ //recorremos los elementos del vector
+ for(i=0;i<nElem;i++)
+ {
+ //primero factor de escala y luego traslación
+ vector[i] = vector[i]*escala+traslada;
+ }
+ }
+ else
+ {
+ //recorremos los elementos del vector
+ for(i=0;i<nElem;i++)
+ {
+ //posición en el vector de trabajo
+ pos = i*inc;
+ //primero factor de escala y luego traslación
+ vector[pos] = vector[pos]*escala+traslada;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void TrasladaYEscalaVector(double* vector,
+ const size_t nElem,
+ const size_t inc,
+ const double escala,
+ const double traslada)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos entre incremento igual a 1 o mayor
+ if(inc==1)
+ {
+ //recorremos los elementos del vector
+ for(i=0;i<nElem;i++)
+ {
+ //primero traslación y luego factor de escala
+ vector[i] = (vector[i]+traslada)*escala;
+ }
+ }
+ else
+ {
+ //recorremos los elementos del vector
+ for(i=0;i<nElem;i++)
+ {
+ //posición en el vector de trabajo
+ pos = i*inc;
+ //primero traslación y luego factor de escala
+ vector[pos] = (vector[pos]+traslada)*escala;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/geocnan.c b/src/geocnan.c
new file mode 100755
index 0000000..2a2aca5
--- /dev/null
+++ b/src/geocnan.c
@@ -0,0 +1,184 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geocnan geom matriz gshhs
+@{
+\file geocnan.c
+\brief Definición de funciones para el trabajo con constantes Not-a-Number.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 26 de mayo de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2010-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/geocnan.h"
+/******************************************************************************/
+/******************************************************************************/
+double GeocNan(void)
+{
+ //devolvemos el valor de NaN
+ //le calculamos el valor absoluto porque, en algunos sistemas, al imprimir
+ //un valor GEOC_NAN normal, éste sale con un signo negativo delante
+ //aclaración a 22 de septiembre de 2011: parecía que con lo del fabs()
+ //estaba solucionado el asunto del signo negativo, pero no es así
+ //la impresión con signo negativo parece que depende de los flags de
+ //optimización al compilar y de los propios compiladores
+ //no obstante, se mantiene el fabs()
+ return fabs(GEOC_NAN);
+}
+/******************************************************************************/
+/******************************************************************************/
+int EsGeocNan(const double valor)
+{
+ //comparamos y salimos de la función
+ return valor!=valor;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* PosGeocNanEnVector(const double* datos,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* nNan)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //vector de salida
+ size_t* salida=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos a 0 el número de NaN encontrados
+ *nNan = 0;
+ //comprobamos una posible salida rápida
+ if(nDatos==0)
+ {
+ //salimos de la función
+ return salida;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los elementos de los vectores
+ for(i=0;i<nDatos;i++)
+ {
+ //comprobamos si el elemento del vector es NaN
+ if(EsGeocNan(datos[i*incDatos]))
+ {
+ //aumentamos el contador de NaN encontrados
+ (*nNan)++;
+ //reasignamos memoria a la salida
+ salida = (size_t*)realloc(salida,(*nNan)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //indicamos la posición del valor NaN
+ salida[(*nNan)-1] = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t LonFormatoNumSimple(const char formato[])
+{
+ //cadena auxiliar para la impresión
+ char cadena[GEOC_NAN_LON_FORM_NUM_SIMPLE+1];
+ //longitud de la cadena imprimida
+ size_t lon=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //imprimimos en la cadena auxiliar un valor numérico
+ sprintf(cadena,formato,1);
+ //calculamos la longitud de la cadena imprimida
+ lon = strlen(cadena);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return lon;
+}
+/******************************************************************************/
+/******************************************************************************/
+void FormatoNumFormatoTexto(const char formatoNum[],
+ char formatoTexto[])
+{
+ //número de carácteres de los resultados impresos con el formato numérico
+ size_t lon=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número de carácteres de los resultados impresos con el
+ //formato numérico
+ lon = LonFormatoNumSimple(formatoNum);
+ //creamos la cadena de formato para imprimir texto
+ sprintf(formatoTexto,"%s%zu%s","%",lon,"s");
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ImprimeGeocNanTexto(FILE* idFich,
+ const size_t nNan,
+ const char formato[],
+ const int retCarro)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos el número de elementos a imprimir
+ for(i=0;i<nNan;i++)
+ {
+ //imprimimos
+ fprintf(idFich,formato,GEOC_NAN_TXT);
+ }
+ //comprobamos si hay que añadir salto de línea
+ if(retCarro)
+ {
+ fprintf(idFich,"\n");
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/geocomp.c b/src/geocomp.c
new file mode 100644
index 0000000..a004e7a
--- /dev/null
+++ b/src/geocomp.c
@@ -0,0 +1,129 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec general geocomp geodesia geom geopot gravim mmcc
+@{
+\file geocomp.c
+\brief Definición de funciones para la obtención de información de la
+ implementación de OpenMP usada.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 25 de agosto de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+void VersionOpenMP(const int macro_OPENMP,
+ char version[])
+{
+ //vamos comprobando los valores de la macro
+ if(macro_OPENMP==GEOC_OMP_F_1_0)
+ {
+ //versión 1.0
+ strcpy(version,GEOC_OMP_V_1_0);
+ }
+ else if(macro_OPENMP==GEOC_OMP_F_2_0)
+ {
+ //versión 2.0
+ strcpy(version,GEOC_OMP_V_2_0);
+ }
+ else if(macro_OPENMP==GEOC_OMP_F_2_5)
+ {
+ //versión 2.5
+ strcpy(version,GEOC_OMP_V_2_5);
+ }
+ else if(macro_OPENMP==GEOC_OMP_F_3_0)
+ {
+ //versión 3.0
+ strcpy(version,GEOC_OMP_V_3_0);
+ }
+ else if(macro_OPENMP==GEOC_OMP_F_3_1)
+ {
+ //versión 3.1
+ strcpy(version,GEOC_OMP_V_3_1);
+ }
+ else
+ {
+ //versión desconocida
+ strcpy(version,GEOC_OMP_V_DESC);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int FechaVersionOpenMP(const char version[])
+{
+ //variable de salida
+ int fecha=GEOC_OMP_F_DESC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //vamos comprobando los valores de la versión
+ if(!strcmp(version,GEOC_OMP_V_1_0))
+ {
+ //versión 1.0
+ fecha = GEOC_OMP_F_1_0;
+ }
+ else if(!strcmp(version,GEOC_OMP_V_2_0))
+ {
+ //versión 2.0
+ fecha = GEOC_OMP_F_2_0;
+ }
+ else if(!strcmp(version,GEOC_OMP_V_2_5))
+ {
+ //versión 2.5
+ fecha = GEOC_OMP_F_2_5;
+ }
+ else if(!strcmp(version,GEOC_OMP_V_3_0))
+ {
+ //versión 3.0
+ fecha = GEOC_OMP_F_3_0;
+ }
+ else if(!strcmp(version,GEOC_OMP_V_3_1))
+ {
+ //versión 3.1
+ fecha = GEOC_OMP_F_3_1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return fecha;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/greiner.c b/src/greiner.c
new file mode 100755
index 0000000..cbe682c
--- /dev/null
+++ b/src/greiner.c
@@ -0,0 +1,1840 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file greiner.c
+\brief Definición de funciones para el recorte de polígonos mediante el
+ algoritmo de Greiner-Hormann
+ (http://davis.wpi.edu/~matt/courses/clipping/).
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 14 de mayo de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/greiner.h"
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* CreaVertPoliClip(const double x,
+ const double y,
+ vertPoliClip* anterior,
+ vertPoliClip* siguiente,
+ vertPoliClip* vecino,
+ const char ini,
+ const char interseccion,
+ const char entrada,
+ const char visitado,
+ const double alfa)
+{
+ //variable de salida (nuevo vértice)
+ vertPoliClip* nuevoVert=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el nuevo vértice
+ nuevoVert = (vertPoliClip*)malloc(sizeof(vertPoliClip));
+ //comprobamos los posibles errores
+ if(nuevoVert==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos los vértices anterior y posterior
+ nuevoVert->anterior = anterior;
+ nuevoVert->siguiente = siguiente;
+ //si anterior es un vértice bueno
+ if(anterior!=NULL)
+ {
+ //lo apuntamos al vértice creado
+ nuevoVert->anterior->siguiente = nuevoVert;
+ }
+ //si siguiente es un vértice bueno
+ if(siguiente!=NULL)
+ {
+ //indicamos que el vértice creado es el anterior
+ nuevoVert->siguiente->anterior = nuevoVert;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el resto de campos
+ nuevoVert->x = x;
+ nuevoVert->y = y;
+ nuevoVert->xP = x;
+ nuevoVert->yP = y;
+ nuevoVert->vecino = vecino;
+ nuevoVert->ini = ini;
+ nuevoVert->interseccion = interseccion;
+ nuevoVert->entrada = entrada;
+ nuevoVert->visitado = visitado;
+ nuevoVert->alfa = alfa;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return nuevoVert;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* CreaPoliClip(const double* x,
+ const double* y,
+ const size_t nCoor,
+ const size_t incX,
+ const size_t incY)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variables auxiliares de posición
+ size_t posIni=0,posFin=0;
+ //otra variable auxiliar
+ int hayVert=0;
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //variable de salida
+ vertPoliClip* poli=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //buscamos el primer punto que sea distinto de NaN
+ for(i=0;i<nCoor;i++)
+ {
+ //comprobamos si el elemento es distinto de NaN
+ if((!EsGeocNan(x[i*incX]))&&(!EsGeocNan(y[i*incY])))
+ {
+ //indicamos que sí hay vértices de trabajo
+ hayVert = 1;
+ //guardamos la posición de este elemento
+ posIni = i;
+ //salimos del bucle
+ break;
+ }
+ }
+ //si no hay ningún vértice distinto de NaN
+ if(!hayVert)
+ {
+ //salimos de la función
+ return poli;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el primer elemento
+ poli = CreaVertPoliClip(x[posIni*incX],y[posIni*incY],NULL,NULL,NULL,1,0,0,
+ 0,0.0);
+ //comprobamos los posibles errores
+ if(poli==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //asignamos el elemento creado a la variable auxiliar
+ aux = poli;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable posFin
+ posFin = posIni;
+ //recorremos los puntos de trabajo
+ for(i=(posIni+1);i<nCoor;i++)
+ {
+ //comprobamos si el elemento es distinto de NaN
+ if((!EsGeocNan(x[i*incX]))&&(!EsGeocNan(y[i*incY])))
+ {
+ //actualizamos la variable que almacena la posición del último
+ //vértice válido
+ posFin = i;
+ //vamos añadiendo vértices al final
+ aux = CreaVertPoliClip(x[i*incX],y[i*incY],aux,NULL,NULL,0,0,0,0,
+ 0.0);
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPoliClip(poli);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el último vértice no está repetido
+ if((x[posIni*incX]!=x[posFin*incX])||(y[posIni*incY]!=y[posFin*incY]))
+ {
+ //repetimos el primer vértice al final
+ aux = CreaVertPoliClip(x[posIni*incX],y[posIni*incY],aux,NULL,NULL,0,0,
+ 0,0,0.0);
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPoliClip(poli);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return poli;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LibMemPoliClip(vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //trabajamos mientras quede memoria
+ while(poli!=NULL)
+ {
+ //apuntamos con la estructura auxiliar hacia la memoria a liberar
+ aux = poli;
+ //apuntamos con la estructura principal al siguiente vértice
+ poli = poli->siguiente;
+ //liberamos la memoria
+ free(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* ReiniciaPoliClip(vertPoliClip* poli)
+{
+ //estructura que apunta al espacio en memoria a liberar
+ vertPoliClip* borra=NULL;
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //estructura de salida
+ vertPoliClip* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar
+ aux = poli;
+ //comprobamos una posible salida rápida
+ if(aux==NULL)
+ {
+ //salimos de la función
+ return NULL;
+ }
+ //buscamos para la estructura de salida el primer vértice que no sea una
+ //intersección
+ while(aux!=NULL)
+ {
+ //comprobamos si estamos ante un vértice bueno
+ if(aux->interseccion==0)
+ {
+ //asignamos la variable de salida
+ sal = aux;
+ //salimos del bucle
+ break;
+ }
+ //siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //volvemos a inicializar la variable auxiliar
+ aux = poli;
+ //mientras la variable de trabajo no apunte a NULL
+ while(aux!=NULL)
+ {
+ //comprobamos si estamos ante un vértice a borrar
+ if(aux->interseccion)
+ {
+ //lo almacenamos en la estructura de borrado
+ borra = aux;
+ //actualizamos el puntero de vértice siguiente
+ if(aux->anterior!=NULL)
+ {
+ //cuando el vértice a borrar no es el primero de la lista
+ aux->anterior->siguiente = aux->siguiente;
+ }
+ else if(aux->siguiente!=NULL)
+ {
+ //cuando el vértice a borrar es el primero de la lista
+ aux->siguiente->anterior = NULL;
+ }
+ //actualizamos el puntero de vértice anterior
+ if(aux->siguiente!=NULL)
+ {
+ //cuando el vértice a borrar no es el último de la lista
+ aux->siguiente->anterior = aux->anterior;
+ }
+ else if(aux->anterior!=NULL)
+ {
+ //cuando el vértice a borrar es el último de la lista
+ aux->anterior->siguiente = NULL;
+ }
+ //apuntamos al siguiente elemento
+ aux = aux->siguiente;
+ //liberamos la memoria
+ free(borra);
+ }
+ else
+ {
+ //reinicializamos el resto de miembros, menos las coordenadas
+ //originales y el identificador de primer elemento
+ aux->xP = aux->x;
+ aux->yP = aux->y;
+ aux->vecino = NULL;
+ aux->interseccion = 0;
+ aux->entrada = 0;
+ aux->visitado = 0;
+ aux->alfa = 0.0;
+ //siguiente elemento
+ aux = aux->siguiente;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* ReiniciaVerticesPoliClip(vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura de auxiliar con la dirección de entrada
+ aux = poli;
+ //mientras no lleguemos al final
+ while(aux!=NULL)
+ {
+ //vamos poniendo a 0 el campo 'visitado'
+ aux->visitado = 0;
+ //vamos poniendo a 0 el campo 'entrada'
+ aux->entrada = 0;
+ //nos posicionamos en el siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return poli;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* SiguienteVertOrigPoliClip(vertPoliClip* vert)
+{
+ //variable de salida, que inicializamos con la dirección de entrada
+ vertPoliClip* sal=vert;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si estamos ante un vértice original, pasamos al siguiente
+ if((sal!=NULL)&&(sal->interseccion==0))
+ {
+ //apuntamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //vamos rechazando intersecciones (el bucle se para cuando llegamos al final
+ //o a un vértice que no es intersección)
+ while((sal!=NULL)&&(sal->interseccion!=0))
+ {
+ //pasamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //si hemos llegado a un vértice que no es original, apuntamos a NULL
+ if((sal!=NULL)&&(sal->interseccion!=0))
+ {
+ //asignamos NULL
+ sal = NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* SiguienteIntersecNoVisitadaPoliClip(vertPoliClip* vert)
+{
+ //variable de salida, que inicializamos con la dirección de entrada
+ vertPoliClip* sal=vert;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si estamos ante una intersección no visitada o ante el vértice original
+ //del polígono, pasamos al siguiente vértice
+ if((sal!=NULL)&&
+ (((sal->interseccion!=0)&&(sal->visitado==0))||(sal->ini!=0)))
+ {
+ //apuntamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //vamos rechazando vértices originales e intersecciones visitadas: el bucle
+ //se para cuando llegamos al final (si la lista no es circular), cuando
+ //volvamos al principio (si la lista es circular) o cuando lleguemos a una
+ //intersección no visitada
+ while(((sal!=NULL)&&(sal->ini==0))&&
+ ((sal->interseccion==0)||
+ ((sal->interseccion!=0)&&(sal->visitado!=0))))
+ {
+ //pasamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //si hemos llegado a un vértice que no es una intersección no visitada o es
+ //de nuevo el punto inicial (lista circular), apuntamos a NULL
+ if((sal!=NULL)&&
+ (((sal->interseccion!=0)&&(sal->visitado!=0))||(sal->ini!=0)))
+ {
+ //asignamos NULL
+ sal = NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* UltimoVertPoliClip(vertPoliClip* poli)
+{
+ //variable de salida, que inicializamos con la dirección de entrada
+ vertPoliClip* sal=poli;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo trabajamos si la entrada es distinta de NULL
+ if(sal!=NULL)
+ {
+ //mientras el siguiente vértice sea distinto de NULL
+ while(sal->siguiente!=NULL)
+ {
+ //avanzamos un vértice
+ sal = sal->siguiente;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+void InsertaVertPoliClip(vertPoliClip* ins,
+ vertPoliClip* extremoIni,
+ vertPoliClip* extremoFin)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el vértice auxiliar como el extremo inicial pasado
+ aux = extremoIni;
+ //mientras no lleguemos al extremo final y el punto a insertar esté más
+ //lejos del origen que el punto de trabajo
+ while((aux!=extremoFin)&&((aux->alfa)<=(ins->alfa)))
+ {
+ //avanzamos al siguiente vértice
+ aux = aux->siguiente;
+ }
+ //insertamos el punto y ordenamos los punteros de vértices anterior y
+ //posterior
+ ins->siguiente = aux;
+ ins->anterior = aux->anterior;
+ ins->anterior->siguiente = ins;
+ ins->siguiente->anterior = ins;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPoliClip* CierraPoliClip(vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //variable de salida: último vértice de la lista original
+ vertPoliClip* ultimo=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si se ha pasado NULL
+ if(poli==NULL)
+ {
+ //salimos de la función
+ return NULL;
+ }
+ //buscamos el último vértice de la lista original
+ ultimo = UltimoVertPoliClip(poli);
+ //almacenamos el penúltimo vértice en la estructura auxiliar
+ aux = ultimo->anterior;
+ //apuntamos el penúltimo vértice al primero
+ aux->siguiente = poli;
+ //le decimos al primer vértice cuál es el anterior
+ aux->siguiente->anterior = aux;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return ultimo;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AbrePoliClip(vertPoliClip* poli,
+ vertPoliClip* ultimo)
+{
+ //estructuras auxiliares
+ vertPoliClip* aux=poli;
+ vertPoliClip* ult=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //buscamos el vértice inicial
+ while((aux!=NULL)&&(aux->ini==0))
+ {
+ //pasamos al siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //último vértice
+ ult = aux->anterior;
+ //le decimos al falso último vértice cuál es el último verdadero
+ ult->siguiente = ultimo;
+ //ajustamos los parámetros del nuevo último vértice
+ ultimo->anterior = ult;
+ ultimo->siguiente = NULL;
+ //le decimos al primer vértice que el anterior es NULL
+ aux->anterior = NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoliClip(const double x,
+ const double y,
+ vertPoliClip* poli)
+{
+ //estructuras auxiliares
+ vertPoliClip* aux=NULL;
+ vertPoliClip* aux1=NULL;
+ //coordenadas auxiliares
+ double x1=0.0,y1=0.0,x2=0.0,y2=0.0;
+ //variable de salida
+ int c=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //comprobamos si no es un vértice original
+ if(aux->interseccion!=0)
+ {
+ //nos posicionamos en el siguiente vértice original
+ aux = SiguienteVertOrigPoliClip(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //entramos en un bucle infinito
+ while(1)
+ {
+ //nos posicionamos en el siguiente vértice original
+ aux1 = SiguienteVertOrigPoliClip(aux);
+ //sólo continuamos si el siguiente vértice no es NULL
+ if(aux1!=NULL)
+ {
+ //extraemos las coordenadas de trabajo
+ x1 = aux->xP;
+ y1 = aux->yP;
+ x2 = aux1->xP;
+ y2 = aux1->yP;
+ //actalizamos el vértice inicial de trabajo para la siguiente vuelta
+ aux = aux1;
+ //calculamos
+ if(((y1>y)!=(y2>y))&&(x<(x2-x1)*(y-y1)/(y2-y1)+x1))
+ {
+ c = !c;
+ }
+ }
+ else
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ //asignamos el elemento de salida
+ if(c)
+ {
+ //el punto está dentro del polígono
+ c = GEOC_PTO_DENTRO_POLIG;
+ }
+ else
+ {
+ //el punto está fuera del polígono
+ c = GEOC_PTO_FUERA_POLIG;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return c;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoliClipVertice(const double x,
+ const double y,
+ vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //variable de salida, que inicializamos fuera del polígono
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //comprobamos si no es un vértice original
+ if(aux->interseccion!=0)
+ {
+ //nos posicionamos en el siguiente vértice original
+ aux = SiguienteVertOrigPoliClip(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el punto es un vértice
+ while(aux!=NULL)
+ {
+ //comprobamos si las coordenadas coinciden
+ if((aux->xP==x)&&(aux->yP==y))
+ {
+ //indicamos que el punto es un vértice
+ pos = GEOC_PTO_VERTICE_POLIG;
+ //salimos del bucle
+ break;
+ }
+ //nos posicionamos en el siguiente vértice original
+ aux = SiguienteVertOrigPoliClip(aux);
+ }
+ //sólo continuamos si el punto no es un vértice
+ if(pos!=GEOC_PTO_VERTICE_POLIG)
+ {
+ //calculamos la posición sin tener en cuenta el borde
+ pos = PtoEnPoliClip(x,y,poli);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t NumeroVertOrigPoliClip(vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //variable de salida
+ size_t num=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //comprobamos si estamos ante un vértice original
+ if(aux->interseccion!=0)
+ {
+ //si no es un vértice original, nos posicionamos en el siguiente que sí
+ //lo sea
+ aux = SiguienteVertOrigPoliClip(aux);
+ }
+ //mientras no lleguemos al final
+ while(aux!=NULL)
+ {
+ //aumentamos el contador de vértices originales
+ num++;
+ //nos posicionamos en el siguiente vértice original
+ aux = SiguienteVertOrigPoliClip(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return num;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t NumeroVertPoliClip(vertPoliClip* poli)
+{
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //variable de salida
+ size_t num=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //mientras no lleguemos al final
+ while(aux!=NULL)
+ {
+ //aumentamos el contador de vértices
+ num++;
+ //nos posicionamos en el siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return num;
+}
+/******************************************************************************/
+/******************************************************************************/
+double CantPerturbMin(const double x,
+ const double factor)
+{
+ //valor absoluto del argumento de entrada
+ double xAbs=fabs(x);
+ //variable auxiliar
+ double aux=0.0;
+ //variable de salida, que inicializamos como el épsilon para el tipo de dato
+ double sal=fabs(DBL_EPSILON);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //mientras la variable auxiliar sea igual a la de antrada (la primera vuelta
+ //del bucle se ejecuta siempre)
+ do
+ {
+ //escalamos la variable de salida
+ sal *= factor;
+ //sumamos el nuevo valor a la coordenada de entrada
+ //esta suma es necesario realizarla aquí, en lugar de en la propia
+ //comparación del while, para obligar al resultado a almacenarse en una
+ //variable y evitar errores porque las variables intermedias de la
+ //comparación puede que se almacenen en registros de más precisión que
+ //el tipo de dato
+ aux = xAbs+sal;
+ }while(aux==xAbs);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+double PerturbaPuntoMin(const double x,
+ const double factor)
+{
+ //variable para almacenar un número seudoaleatorio
+ int aleat=0;
+ //cantidad perturbadora
+ double perturb=0.0;
+ //signo para multiplicar por la cantidad perturbadora
+ double signo=0.0;
+ //variable de salida
+ double sal=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //plantamos la semilla para la función rand()
+ srand((unsigned int)time(NULL));
+ //generamos el número seudoaleatorio
+ aleat = rand();
+ //calculamos el signo para la multiplicación, basándonos en la paridad del
+ //número seudoaleatorio generado: si es par vale 1 y si es impar -1
+ signo = (aleat%2) ? -1.0 : 1.0;
+ //calculamos la cantidad perturbadora
+ perturb = CantPerturbMin(x,factor);
+ //perturbamos la coordenada
+ sal = x+signo*perturb;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int Paso1Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb)
+{
+ //estructuras auxiliares que apuntan a los polígonos pasados
+ vertPoliClip* auxA=NULL;
+ vertPoliClip* auxC=NULL;
+ //estructuras auxiliares para trabajar con el siguiente vértice
+ vertPoliClip* auxB=NULL;
+ vertPoliClip* auxD=NULL;
+ //vértices de intersección a insertar
+ vertPoliClip* insBas=NULL;
+ vertPoliClip* insRec=NULL;
+ //coordenadas de la intersección de dos segmentos
+ double xI=0.0,yI=0.0;
+ //longitudes de segmentos y parámetros alfa
+ double lonAB=0.0,lonCD=0.0,alfaAB=0.0,alfaCD=0.0;
+ //código de intersección de segmentos
+ int intersec=0;
+ //variable de salida
+ int salida=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el número de intersecciones a 0
+ *nIntersec = 0;
+ //inicializamos el número de puntos perturbados a 0
+ *nPerturb = 0;
+ //EL PRIMER PASO DEL ALGORITMO DE GREINER-HORMANN ES EL CÁLCULO DE TODOS LOS
+ //PUNTOS DE INTERSECCIÓN ENTRE LOS POLÍGONOS
+ //recorremos los vértices del polígono base
+ for(auxA=poliBas;auxA->siguiente!=NULL;auxA=auxA->siguiente)
+ {
+ //sólo trabajamos si el vértice es original
+ if(auxA->interseccion==0)
+ {
+ //recorremos los vértices del polígono de recorte
+ for(auxC=poliRec;auxC->siguiente!=NULL;auxC=auxC->siguiente)
+ {
+ //sólo trabajamos si el vértice es original
+ if(auxC->interseccion==0)
+ {
+ //siguiente vértice de los segmentos
+ auxB = SiguienteVertOrigPoliClip(auxA);
+ auxD = SiguienteVertOrigPoliClip(auxC);
+ //calculamos la intersección de los segmentos
+ intersec = IntersecSegmentos2D(auxA->xP,auxA->yP,auxB->xP,
+ auxB->yP,auxC->xP,auxC->yP,
+ auxD->xP,auxD->yP,&xI,&yI);
+ //perturbamos las coordenadas de los extremos de los
+ //segmentos mientras haya una intersección no limpia
+ while((intersec!=GEOC_SEG_NO_INTERSEC)&&
+ (intersec!=GEOC_SEG_INTERSEC))
+ {
+ //distinguimos entre intersecciones donde sólo se toca
+ //un extremo e intersecciones colineales donde se
+ //comparte más de un punto
+ if((intersec==GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN)||
+ (intersec==GEOC_SEG_INTERSEC_EXTREMO_COLIN))
+ {
+ if((xI==auxC->xP)&&(yI==auxC->yP))
+ {
+ //perturbamos el extremo C
+ auxC->xP = PerturbaPuntoMin(auxC->x,facPer);
+ auxC->yP = PerturbaPuntoMin(auxC->y,facPer);
+ //aumentamos el contador de puntos perturbados
+ (*nPerturb)++;
+ }
+ else if((xI==auxD->xP)&&(yI==auxD->yP))
+ {
+ //perturbamos el extremo D
+ auxD->xP = PerturbaPuntoMin(auxD->x,facPer);
+ auxD->yP = PerturbaPuntoMin(auxD->y,facPer);
+ //aumentamos el contador de puntos perturbados
+ (*nPerturb)++;
+ }
+ else
+ {
+ //si el punto de contacto es un extremo de AB y
+ //los segmentos no son paralelos, perturbamos
+ //todo el segmento CD
+ auxC->xP = PerturbaPuntoMin(auxC->x,facPer);
+ auxC->yP = PerturbaPuntoMin(auxC->y,facPer);
+ auxD->xP = PerturbaPuntoMin(auxD->x,facPer);
+ auxD->yP = PerturbaPuntoMin(auxD->y,facPer);
+ //aumentamos el contador de puntos perturbados
+ (*nPerturb) += 2;
+ }
+ }
+ else if((intersec==GEOC_SEG_INTERSEC_MISMO_SEG)||
+ (intersec==GEOC_SEG_INTERSEC_COLIN))
+ {
+ //perturbamos todo el segmento CD
+ auxC->xP = PerturbaPuntoMin(auxC->x,facPer);
+ auxC->yP = PerturbaPuntoMin(auxC->y,facPer);
+ auxD->xP = PerturbaPuntoMin(auxD->x,facPer);
+ auxD->yP = PerturbaPuntoMin(auxD->y,facPer);
+ //aumentamos el contador de puntos perturbados
+ (*nPerturb) += 2;
+ }
+ //volvemos a calcular la intersección de los segmentos
+ intersec = IntersecSegmentos2D(auxA->xP,auxA->yP,
+ auxB->xP,auxB->yP,
+ auxC->xP,auxC->yP,
+ auxD->xP,auxD->yP,
+ &xI,&yI);
+ }
+ //comprobamos si los segmentos se cortan limpiamente
+ if(intersec==GEOC_SEG_INTERSEC)
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ //calculamos las longitudes de los segmentos
+ lonAB = Dist2D(auxA->xP,auxA->yP,auxB->xP,auxB->yP);
+ lonCD = Dist2D(auxC->xP,auxC->yP,auxD->xP,auxD->yP);
+ //calculamos los parámetros alfa
+ alfaAB = Dist2D(auxA->xP,auxA->yP,xI,yI)/lonAB;
+ alfaCD = Dist2D(auxC->xP,auxC->yP,xI,yI)/lonCD;
+ //creamos los nuevos vértices a insertar
+ insBas = CreaVertPoliClip(xI,yI,NULL,NULL,NULL,0,1,0,0,
+ alfaAB);
+ insRec = CreaVertPoliClip(xI,yI,NULL,NULL,NULL,0,1,0,0,
+ alfaCD);
+ //comprobamos los posibles errores
+ if((insBas==NULL)||(insRec==NULL))
+ {
+ //liberamos la memoria previamente asignada
+ free(insBas);
+ free(insRec);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //asignamos el código de error
+ salida = GEOC_ERR_ASIG_MEMORIA;
+ //salimos de la función
+ return salida;
+ }
+ //enlazamos los vértices mediante el campo 'vecino'
+ insBas->vecino = insRec;
+ insRec->vecino = insBas;
+ //los insertamos en los polígonos
+ InsertaVertPoliClip(insBas,auxA,auxB);
+ InsertaVertPoliClip(insRec,auxC,auxD);
+ }
+ }
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+void Paso2Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op)
+{
+ //estructuras auxiliares que apuntan a los polígonos pasados
+ vertPoliClip* auxA=NULL;
+ vertPoliClip* auxC=NULL;
+ //identificador de si una intersección es de entrada o salida
+ char entrada=0;
+ //variables auxiliares
+ char entA=0,entC=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos los valores iniciales a los identificadores de intersección
+ switch(op)
+ {
+ //distinguimos los tipos de operación
+ case GeocOpBoolInter:
+ //intersección
+ entA = 1;
+ entC = 1;
+ break;
+ case GeocOpBoolUnion:
+ //unión
+ entA = 0;
+ entC = 0;
+ break;
+ case GeocOpBoolAB:
+ //A-B
+ entA = 0;
+ entC = 1;
+ break;
+ case GeocOpBoolBA:
+ //B-A
+ entA = 1;
+ entC = 0;
+ break;
+ default:
+ //por defecto, intersección
+ entA = 1;
+ entC = 1;
+ break;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //EL SEGUNDO PASO DEL ALGORITMO DE GREINER-HORMANN ES LA IDENTIFICACIÓN DE
+ //INTERSECCIONES COMO ENTRADA-SALIDA
+ //comprobamos si el primer punto del polígono base está fuera del polígono
+ //de recorte
+ if(PtoEnPoliClipVertice(poliBas->xP,poliBas->yP,poliRec))
+ {
+ //si el punto está fuera, la siguiente intersección es de entrada
+ entrada = !entA;
+ }
+ else
+ {
+ entrada = entA;
+ }
+ //recorremos los vértices del polígono de recorte
+ for(auxA=poliBas;auxA->siguiente!=NULL;auxA=auxA->siguiente)
+ {
+ //sólo trabajamos si el vértice es intersección
+ if(auxA->interseccion!=0)
+ {
+ //indicamos la dirección
+ auxA->entrada = entrada;
+ //actualizamos la variable de entrada para la siguiente vuelta
+ entrada = !entrada;
+ }
+ }
+ //comprobamos si el primer punto del polígono de recorte está fuera del
+ //polígono base
+ if(PtoEnPoliClipVertice(poliRec->xP,poliRec->yP,poliBas))
+ {
+ //si el punto está fuera, la siguiente intersección es de entrada
+ entrada = !entC;
+ }
+ else
+ {
+ entrada = entC;
+ }
+ //recorremos los vértices del polígono base
+ for(auxC=poliRec;auxC->siguiente!=NULL;auxC=auxC->siguiente)
+ {
+ //sólo trabajamos si el vértice es intersección
+ if(auxC->interseccion!=0)
+ {
+ //indicamos la dirección
+ auxC->entrada = entrada;
+ //actualizamos la variable de entrada para la siguiente vuelta
+ entrada = !entrada;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* Paso3Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec)
+{
+ //vértices colgados al cerrar los polígonos
+ vertPoliClip* ultBas=NULL;
+ vertPoliClip* ultRec=NULL;
+ //estructura auxiliar
+ vertPoliClip* aux=NULL;
+ //vectores de coordenadas de los vértices del resultado
+ double* x=NULL;
+ double* y=NULL;
+ //número de elementos de los vectores x e y
+ size_t nPtos=0;
+ //número de elementos para los que ha sido asignada memoria
+ size_t nElem=0;
+ //variable de estado
+ int estado=GEOC_ERR_NO_ERROR;
+ //polígono de salida
+ polig* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //cerramos los polígonos, convirtiéndolos en listas circulares
+ ultBas = CierraPoliClip(poliBas);
+ ultRec = CierraPoliClip(poliRec);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //mientras queden intersecciones sin visitar
+ while((aux = SiguienteIntersecNoVisitadaPoliClip(poliBas))!=NULL)
+ {
+ //aumentamos el contador de elementos para los vectores x e y en 2
+ //unidades: una para el marcador de inicio de polígono y la otra para
+ //las coordenadas del primer vértice
+ nPtos+=2;
+ //comprobamos si hay que reasignar memoria a los vectores de coordenadas
+ if(nPtos>nElem)
+ {
+ //actualizamos el número de elementos de los vectores de puntos
+ nElem += GEOC_GREINER_BUFFER_PTOS;
+ //reasignamos memoria para los vectores
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos si ha ocurrido algún error
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //reabrimos los polígonos
+ AbrePoliClip(poliBas,ultBas);
+ AbrePoliClip(poliRec,ultRec);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos el marcador NaN como identificador de comienzo de polígono
+ x[nPtos-2] = GeocNan();
+ y[nPtos-2] = GeocNan();
+ //asignamos las coordenadas del punto de intersección
+ x[nPtos-1] = aux->xP;
+ y[nPtos-1] = aux->yP;
+ //EN ESTE NIVEL SIEMPRE ESTAMOS ANTE UN PUNTO DE INTERSECCIÓN
+ //mientras el punto no haya sido visitado con anterioridad
+ do
+ {
+ //lo marcamos como visitado
+ aux->visitado = 1;
+ aux->vecino->visitado = 1;
+ //comprobamos si el punto es de entrada o no
+ if(aux->entrada!=0)
+ {
+ //mientras no encontremos otra intersección
+ do
+ {
+ //caminamos en la lista hacia adelante
+ aux = aux->siguiente;
+ //aumentamos el contador de elementos para x e y
+ nPtos++;
+ //comprobamos si hay que reasignar memoria a los vectores de
+ //coordenadas
+ if(nPtos>nElem)
+ {
+ //actualizamos el número de elementos de los vectores de
+ //puntos
+ nElem += GEOC_GREINER_BUFFER_PTOS;
+ //reasignamos memoria para los vectores
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos si ha ocurrido algún error
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //reabrimos los polígonos
+ AbrePoliClip(poliBas,ultBas);
+ AbrePoliClip(poliRec,ultRec);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos las coordenadas del punto de intersección
+ x[nPtos-1] = aux->xP;
+ y[nPtos-1] = aux->yP;
+ }
+ while(aux->interseccion==0); //mientras no sea intersección
+ }
+ else
+ {
+ ////mientras no encontremos otra intersección
+ do
+ {
+ //caminamos hacia atrás
+ aux = aux->anterior;
+ //aumentamos el contador de elementos para x e y
+ nPtos++;
+ //comprobamos si hay que reasignar memoria a los vectores de
+ //coordenadas
+ if(nPtos>nElem)
+ {
+ //actualizamos el número de elementos de los vectores de
+ //puntos
+ nElem += GEOC_GREINER_BUFFER_PTOS;
+ //reasignamos memoria para los vectores
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos si ha ocurrido algún error
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //reabrimos los polígonos
+ AbrePoliClip(poliBas,ultBas);
+ AbrePoliClip(poliRec,ultRec);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos las coordenadas del punto de intersección
+ x[nPtos-1] = aux->xP;
+ y[nPtos-1] = aux->yP;
+ }
+ while(aux->interseccion==0); //mientras no sea intersección
+ }
+ //saltamos al otro polígono
+ aux = aux->vecino;
+ }while(aux->visitado==0); //mientras el punto no haya sido visitado
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la estructura de salida
+ resultado = CreaPolig(x,y,nPtos,1,1,&estado);
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //liberamos la memoria asignada
+ free(x);
+ free(y);
+ //reabrimos los polígonos
+ AbrePoliClip(poliBas,ultBas);
+ AbrePoliClip(poliRec,ultRec);
+ //comprobamos el error
+ if(estado==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else
+ {
+ //mensaje de error
+ GEOC_ERROR("Error en la llamada a 'CreaPolig()'\nEste error no "
+ "puede producirse aquí porque los NaN deben estar "
+ "bien puestos");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //reabrimos los polígonos
+ AbrePoliClip(poliBas,ultBas);
+ AbrePoliClip(poliRec,ultRec);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria asignada
+ free(x);
+ free(y);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* PoliBoolGreiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb)
+{
+ //factor de perturbación
+ double factor=0.0;
+ //variables de posición
+ int posBas=0,posRec=0;
+ //identificador de error
+ int idError=GEOC_ERR_NO_ERROR;
+ //polígono auxiliar
+ polig* ba=NULL;
+ //polígono de salida
+ polig* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si se ha pasado factor de perturbación
+ if(facPer<=1.0)
+ {
+ //utilizamos el valor por defecto
+ factor = GEOC_GREINER_FAC_EPS_PERTURB;
+ }
+ else
+ {
+ //utilizamos el valor pasado
+ factor = facPer;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //PRIMER PASO DEL ALGORITMO DE GREINER-HORMANN: CÁLCULO DE TODOS LOS PUNTOS
+ //DE INTERSECCIÓN ENTRE LOS POLÍGONOS
+ //calculamos los puntos de intersección
+ idError = Paso1Greiner(poliBas,poliRec,factor,nIntersec,nPerturb);
+ //comprobamos los posibles errores
+ if(idError==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso1Greiner'");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si no hay intersecciones
+ if(!(*nIntersec))
+ {
+ //calculo la situación relativa entre los polígonos
+ posBas = PtoEnPoliClipVertice(poliBas->xP,poliBas->yP,poliRec);
+ posRec = PtoEnPoliClipVertice(poliRec->xP,poliRec->yP,poliBas);
+ //comprobamos las posibles situaciones relativas entre los polígonos que
+ //pueden producir cero intersecciones
+ if((posBas==GEOC_PTO_DENTRO_POLIG)||(posBas==GEOC_PTO_VERTICE_POLIG))
+ {
+ //EL POLÍGONO BASE ESTÁ DENTRO DEL POLÍGONO DE RECORTE
+ //distinguimos las operaciones (por defecto, intersección)
+ if(op==GeocOpBoolUnion)
+ {
+ //el resultado es el polígono de recorte
+ resultado = CreaPoligPoliClip(poliRec,0);
+ }
+ else if(op==GeocOpBoolAB)
+ {
+ //el resultado es un polígono vacío
+ resultado = CreaPoligPoliClip(NULL,0);
+ }
+ else if((op==GeocOpBoolBA)||(op==GeocOpBoolXor))
+ {
+ //el resultado son los dos polígonos
+ //polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ //añadimos el polígono de recorte
+ AnyadePoligClipPolig(resultado,poliRec,0);
+ }
+ else
+ {
+ //el resultado es el polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ }
+ }
+ else if((posRec==GEOC_PTO_DENTRO_POLIG)||
+ (posRec==GEOC_PTO_VERTICE_POLIG))
+ {
+ //EL POLÍGONO DE RECORTE ESTÁ DENTRO DEL POLÍGONO BASE
+ //distinguimos las operaciones (por defecto, intersección)
+ if(op==GeocOpBoolUnion)
+ {
+ //el resultado es el polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ }
+ else if((op==GeocOpBoolAB)||(op==GeocOpBoolXor))
+ {
+ //el resultado son los dos polígonos
+ //polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ //añadimos el polígono de recorte
+ AnyadePoligClipPolig(resultado,poliRec,0);
+ }
+ else if(op==GeocOpBoolBA)
+ {
+ //el resultado es un polígono vacío
+ resultado = CreaPoligPoliClip(NULL,0);
+ }
+ else
+ {
+ //el resultado es el polígono de recorte
+ resultado = CreaPoligPoliClip(poliRec,0);
+ }
+ }
+ else
+ {
+ //NINGÚN POLÍGONO ESTÁ DENTRO DEL OTRO
+ //distinguimos las operaciones (por defecto, intersección)
+ if((op==GeocOpBoolUnion)||(op==GeocOpBoolXor))
+ {
+ //el resultado son los dos polígonos
+ //polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ //añadimos el polígono de recorte
+ AnyadePoligClipPolig(resultado,poliRec,0);
+ }
+ else if(op==GeocOpBoolAB)
+ {
+ //el resultado es el polígono base
+ resultado = CreaPoligPoliClip(poliBas,0);
+ }
+ else if(op==GeocOpBoolBA)
+ {
+ //el resultado es el polígono de recorte
+ resultado = CreaPoligPoliClip(poliRec,0);
+ }
+ else
+ {
+ //el resultado es un polígono vacío
+ resultado = CreaPoligPoliClip(NULL,0);
+ }
+ }
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //salimos de la función
+ return resultado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos entre XOR y el resto de operaciones
+ if(op!=GeocOpBoolXor)
+ {
+ //SEGUNDO PASO DEL ALGORITMO DE GREINER-HORMANN: IDENTIFICACIÓN DE
+ //INTERSECCIONES COMO ENTRADA-SALIDA
+ //marcamos los puntos como entrada o salida
+ Paso2Greiner(poliBas,poliRec,op);
+ //TERCER PASO DEL ALGORITMO DE GREINER-HORMANN: EXTRACCIÓN DE LOS POLÍGONOS
+ //RESULTADO DE LA OPERACIÓN
+ //extraemos los polígonos
+ resultado = Paso3Greiner(poliBas,poliRec);
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso3Greiner'");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ else
+ {
+ //LA OPERCIÓN XOR LA HACEMOS COMO LA UNIÓN DE LA OPERACIÓN A-B CON B-A
+ //marcamos los puntos como entrada o salida para la operación A-B
+ Paso2Greiner(poliBas,poliRec,GeocOpBoolAB);
+ //extraemos los polígonos
+ resultado = Paso3Greiner(poliBas,poliRec);
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso3Greiner'");
+ //salimos de la función
+ return NULL;
+ }
+ //reinicializamos los polígonos, pero manteniendo las intersecciones
+ poliBas = ReiniciaVerticesPoliClip(poliBas);
+ poliRec = ReiniciaVerticesPoliClip(poliRec);
+ //marcamos los puntos como entrada o salida para la operación B-A
+ Paso2Greiner(poliBas,poliRec,GeocOpBoolBA);
+ //extraemos los polígonos
+ ba = Paso3Greiner(poliBas,poliRec);
+ //comprobamos los posibles errores
+ if(ba==NULL)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso3Greiner'");
+ //salimos de la función
+ return NULL;
+ }
+ //añadimos el resultado de la operación B-A al anterior de A-B
+ idError = AnyadePoligPolig(resultado,ba);
+ //comprobamos los posibles errores
+ if(idError==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(resultado);
+ LibMemPolig(ba);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'AnyadePoligPolig' para la operación XOR");
+ //salimos de la función
+ return NULL;
+ }
+ //liberamos la memoria asociada a la estructura auxiliar ba
+ LibMemPolig(ba);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* PoliBoolGreinerMult(const polig* poliBas,
+ const polig* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //variable de posición
+ size_t pos=0;
+ //número de intersecciones y de puntos perturbados auxiliar
+ size_t nInt=0,nPer=0;
+ //posición de un rectángulo con respecto a otro
+ int pr=0;
+ //variables de error
+ int estado1=GEOC_ERR_NO_ERROR,estado2=GEOC_ERR_NO_ERROR;
+ //listas de trabajo
+ vertPoliClip* poligBas=NULL;
+ vertPoliClip* poligRec=NULL;
+ //polígono auxiliar
+ polig* poligAux=NULL;
+ //variable de salida
+ polig* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el número total de intersecciones y de puntos perturbados
+ *nIntersec = 0;
+ *nPerturb = 0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de salida
+ resultado = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los polígonos base
+ for(i=0;i<poliBas->nPolig;i++)
+ {
+ //dirección de inicio de los vértices del polígono base
+ pos = poliBas->posIni[i];
+ //creamos el polígono base de trabajo
+ poligBas = CreaPoliClip(&(poliBas->x[pos]),&(poliBas->y[pos]),
+ poliBas->nVert[i],1,1);
+ //comprobamos los posibles errores
+ if(poligBas==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPolig(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //recorremos los polígonos de recorte
+ for(j=0;j<poliRec->nPolig;j++)
+ {
+ //comprobamos si los polígonos tienen definidos sus límites
+ if((poliBas->hayLim)&&(poliRec->hayLim))
+ {
+ //comprobamos si los restángulos que encierran a los polígonos
+ //son disjuntos o no
+ pr = RectDisjuntos(poliBas->xMin[i],poliBas->xMax[i],
+ poliBas->yMin[i],poliBas->yMax[i],
+ poliRec->xMin[j],poliRec->xMax[j],
+ poliRec->yMin[j],poliRec->yMax[j]);
+ //comprobamos los casos particulares si los rectángulos son
+ //disjuntos
+ if(pr&&(op==GeocOpBoolInter))
+ {
+ //EN CASO DE INTERSECCIÓN, NO SE AÑADE NADA
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ else if(pr&&((op==GeocOpBoolUnion)||(op==GeocOpBoolXor)))
+ {
+ //EN CASO DE UNIÓN O UNIÓN EXCLUSIVA, SE AÑADEN LOS DOS
+ //POLÍGONOS
+ //añadimos el polígono base
+ estado1 = AnyadeDatosPolig(resultado,&(poliBas->x[pos]),
+ &(poliBas->y[pos]),
+ poliBas->nVert[i],1,1);
+ //añadimos el polígono de recorte
+ pos = poliRec->posIni[j];
+ estado2 = AnyadeDatosPolig(resultado,&(poliRec->x[pos]),
+ &(poliRec->y[pos]),
+ poliRec->nVert[j],1,1);
+ //comprobamos los posibles errores, que sólo pueden ser de
+ //asignación de memoria
+ if((estado1!=GEOC_ERR_NO_ERROR)||
+ (estado2!=GEOC_ERR_NO_ERROR))
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPolig(resultado);
+ //lanzamos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ else if(pr&&(op==GeocOpBoolAB))
+ {
+ //EN CASO DE OPERACIÓN A-B, SE AÑADE EL POLÍGONO BASE
+ //añadimos el polígono base
+ estado1 = AnyadeDatosPolig(resultado,&(poliBas->x[pos]),
+ &(poliBas->y[pos]),
+ poliBas->nVert[i],1,1);
+ //comprobamos los posibles errores, que sólo pueden ser de
+ //asignación de memoria
+ if(estado1!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPolig(resultado);
+ //lanzamos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ else if(pr&&(op==GeocOpBoolBA))
+ {
+ //EN CASO DE OPERACIÓN B-A, SE AÑADE EL POLÍGONO DE RECORTE
+ //añadimos el polígono de recorte
+ pos = poliRec->posIni[j];
+ estado1 = AnyadeDatosPolig(resultado,&(poliRec->x[pos]),
+ &(poliRec->y[pos]),
+ poliRec->nVert[j],1,1);
+ //comprobamos los posibles errores, que sólo pueden ser de
+ //asignación de memoria
+ if(estado1!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPolig(resultado);
+ //lanzamos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ }
+ //dirección de inicio de los vértices del polígono de recorte
+ pos = poliRec->posIni[j];
+ //creamos el polígono de recorte de trabajo
+ poligRec = CreaPoliClip(&(poliRec->x[pos]),&(poliRec->y[pos]),
+ poliRec->nVert[j],1,1);
+ //comprobamos los posibles errores
+ if(poligRec==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPolig(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //recortamos
+ poligAux = PoliBoolGreiner(poligBas,poligRec,op,facPer,&nInt,&nPer);
+ //comprobamos los posibles errores
+ if(poligAux==NULL)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPoliClip(poligRec);
+ LibMemPolig(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //sumamos el número de intersecciones y de puntos perturbados
+ (*nIntersec) += nInt;
+ (*nPerturb) += nPer;
+ //añadimos los polígonos recortados a la variable de salida
+ if(AnyadePoligPolig(resultado,poligAux)==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPoliClip(poligBas);
+ LibMemPoliClip(poligRec);
+ LibMemPolig(poligAux);
+ LibMemPolig(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //liberamos la memoria asignada al polígono de esta vuelta del bucle
+ LibMemPoliClip(poligRec);
+ //liberamos la memoria asignada al polígono auxiliar
+ LibMemPolig(poligAux);
+ //reinicializamos el polígono base
+ poligBas = ReiniciaPoliClip(poligBas);
+ }
+ //liberamos la memoria asignada al polígono de esta vuelta del bucle
+ LibMemPoliClip(poligBas);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* CreaPoligPoliClip(vertPoliClip* poli,
+ const int coorOrig)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de elementos
+ size_t nVert=0,nElem=0;
+ //estructura auxiliar
+ vertPoliClip* aux=poli;
+ //variable de salida
+ polig* result=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la estructura vacía
+ result = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(result==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contamos todos los vértices del polígono
+ nVert = NumeroVertPoliClip(poli);
+ //contemplamos una posible salida rápida
+ if(nVert==0)
+ {
+ //devolvemos la estructura vacía
+ return result;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //número de elementos de los vectores de coordenadas
+ nElem = nVert+2;
+ //asignamos memoria para los vectores de coordenadas de la estructura
+ result->x = (double*)malloc(nElem*sizeof(double));
+ result->y = (double*)malloc(nElem*sizeof(double));
+ //asignamos memoria para los vectores de posición
+ result->posIni = (size_t*)malloc(sizeof(size_t));
+ result->nVert = (size_t*)malloc(sizeof(size_t));
+ //comprobamos los posibles errores de asignación de memoria
+ if((result->x==NULL)||(result->y==NULL)||(result->posIni==NULL)||
+ (result->nVert==NULL))
+ {
+ //liberamos la posible memoria asignada
+ LibMemPolig(result);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el número de elementos de los vectores de coordenadas y de
+ //polígonos
+ result->nElem = nElem;
+ result->nPolig = 1;
+ //asignamos la posición de inicio y el número de vértices
+ result->posIni[0] = 1;
+ result->nVert[0] = nVert;
+ //asignamos los separadores de polígono al principio y al final
+ result->x[0] = GeocNan();
+ result->y[0] = GeocNan();
+ result->x[nElem-1] = GeocNan();
+ result->y[nElem-1] = GeocNan();
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los vértices del polígono
+ for(i=1;i<=nVert;i++)
+ {
+ //distinguimos el tipo de coordenadas a copiar
+ if(coorOrig)
+ {
+ //coordenadas originales
+ result->x[i] = aux->x;
+ result->y[i] = aux->y;
+ }
+ else
+ {
+ //coordenadas perturbadas
+ result->x[i] = aux->xP;
+ result->y[i] = aux->yP;
+ }
+ //siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return result;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AnyadePoligClipPolig(polig* poli,
+ vertPoliClip* anyade,
+ const int coorOrig)
+{
+ //número de elementos a añadir
+ size_t nVert=0;
+ //polígono auxiliar
+ polig* aux=NULL;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contamos todos los vértices del polígono a añadir
+ nVert = NumeroVertPoliClip(anyade);
+ //contemplamos una posible salida rápida
+ if(nVert==0)
+ {
+ //devolvemos la estructura vacía
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos un nuevo polígono con los datos a añadir
+ aux = CreaPoligPoliClip(anyade,coorOrig);
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //añadimos la nueva estructura
+ estado = AnyadePoligPolig(poli,aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria utilizada
+ LibMemPolig(aux);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/calctopo.h b/src/libgeoc/calctopo.h
new file mode 100644
index 0000000..899cc8e
--- /dev/null
+++ b/src/libgeoc/calctopo.h
@@ -0,0 +1,81 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geodesia geom
+@{
+\file calctopo.h
+\brief Declaración de funciones para cálculos de topografía.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 05 de julio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _CALCTOPO_H_
+#define _CALCTOPO_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<math.h>
+#include"libgeoc/constantes.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el acimut topográfico entre dos puntos.
+\param[in] x1 Coordenada X del primer punto.
+\param[in] y1 Coordenada y del primer punto.
+\param[in] x2 Coordenada X del segundo punto.
+\param[in] y2 Coordenada y del segundo punto.
+\return Acimut del primer al segundo punto, en radianes.
+\date 05 de julio de 2011: Creación de la función.
+\todo Esta función todavía no ha sido probada.
+*/
+double AcimutTopografico(const double x1,
+ const double y1,
+ const double x2,
+ const double y2);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/compilador.h b/src/libgeoc/compilador.h
new file mode 100755
index 0000000..bdd9684
--- /dev/null
+++ b/src/libgeoc/compilador.h
@@ -0,0 +1,96 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup general geopot
+@{
+\file compilador.h
+\brief Declaración de funciones para la detección de compiladores.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 28 de abril de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _COMPILADOR_H_
+#define _COMPILADOR_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdio.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si el compilador utilizado para compilar este fichero es de la
+ familia GCC.
+\param[out] noGnu Identificador de que estamos ante un compilador que no es de
+ la familia GCC, diga lo que diga la variable devuelta por la función
+ (ver nota al final de la documentación). Este argumento sólo es
+ utilizado si en la entrada su valor es distinto de \p NULL. Dos
+ posibles valores de salida:
+ - 0: El compilador \b *ES* de la familia GCC.
+ - Distinto de 0: El compilador \b *NO* \b *ES* de la familia GCC.
+\return Dos posibilidades:
+ - 0: El compilador no pertenece a la familia GCC.
+ - Distinto de 0: El compilador sí pertenece a la familia GCC (para una
+ validez total de este valor hay que tener en cuenta el argumento
+ \em noGnu).
+\note Esta función realiza la comprobación mediante el chequeo de la existencia
+ de la constante simbólica \p __GNUC__. Este hecho hace que la detección
+ del compilador se lleve a cabo durante la compilación del fichero que
+ contiene a esta función, por lo que hay que tener en cuenta si ésta es
+ llamada desde una función contenida en otro fichero que no fue compilado
+ con un compilador de la familia GCC.
+\note Algunos compiladores, como el Intel C/C++ Compiler (\p icc), definen por
+ defecto la macro \p __GNUC__, por lo que la detección puede ser errónea.
+ Para estos casos ha de tenerse en cuenta el argumento \em noGnu.
+\note En las versiones más recientes de \p icc, el argumento \p -no-gcc suprime
+ la definición de \p __GNUC__.
+\date 11 de octubre de 2009: Creación de la función.
+*/
+int EsCompiladorGNU(int* noGnu);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/constantes.h b/src/libgeoc/constantes.h
new file mode 100755
index 0000000..294f5a6
--- /dev/null
+++ b/src/libgeoc/constantes.h
@@ -0,0 +1,264 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec astro eop general geodesia geom gravim marea
+@{
+\file constantes.h
+\brief Definición de constantes generales.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 02 de marzo de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _CONSTANTES_H_
+#define _CONSTANTES_H_
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\typedef geoc_char
+\brief Nombre del tipo \p char para almacenar números en \p libgeoc.
+
+ Se declara este tipo para dotar de portabilidad a la biblioteca, debido a
+ que en algunas implementaciones de C la declaración \p char a secas
+ corresponde a un tipo \p unsigned \p char en lugar de a un \p signed
+ \p char, que es el que necesita \p libgeoc cuando almacena un número en
+ un \p char. En la implementación de \p gcc para PowerPC, por ejemplo, el
+ tipo por defecto de un \p char es \p unsigned \p char, lo que hace que se
+ produzcan errores al intentar almacenar números negativos.
+\date 02 de marzo de 2009: Creación del tipo.
+*/
+typedef signed char geoc_char;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_PI
+\brief Constante \em PI. Tomada del fichero \p gsl_math.h, de la biblioteca GSL.
+\date 02 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_PI (3.14159265358979323846264338328)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_E
+\brief Constante \em e (base de los logaritmos naturales). Tomada del fichero
+ \p gsl_math.h, de la biblioteca GSL.
+\date 03 de octubre de 2010: Creación de la constante.
+*/
+#define GEOC_CONST_E (2.71828182845904523536028747135)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_GR
+\brief Paso de grados centesimales a radianes.
+*/
+#define GEOC_CONST_GR ((GEOC_CONST_PI)/200.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_RG
+\brief Paso de radianes a grados centesimales.
+\date 02 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_RG (1.0/(GEOC_CONST_GR))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_DR
+\brief Paso de grados sexagesimales en formato decimal a radianes.
+\date 02 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_DR ((GEOC_CONST_PI)/180.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_RD
+\brief Paso de radianes a grados sexagesimales en formato decimal.
+\date 02 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_RD (1.0/(GEOC_CONST_DR))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_SIMUGAL
+\brief Paso de atracción gravitatoria en el SI (m/s^2) a microgales.
+\date 05 de noviembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_SIMUGAL (1.0e8)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_MJD
+\brief Constante a sustraer a una fecha juliana (en días) para convertirla en
+ fecha juliana modificada (MJD).
+\date 04 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_MJD (2400000.5)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_J2000
+\brief Constante a sustraer a una fecha juliana (en días) para convertirla en
+ fecha juliana referida a J2000.
+\date 01 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_J2000 (2451545.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_JISGPS
+\brief Fecha juliana del día de inicio de las semanas GPS: 6 de enero de 1980,
+ 00:00:00 horas.
+\date 02 de marzo de 2010: Creación de la constante.
+*/
+#define GEOC_CONST_JISGPS (2444244.5)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_MIN_HORA
+\brief Número de minutos que contiene una hora.
+\date 19 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_MIN_HORA (60.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_SEG_HORA
+\brief Número de segundos que contiene una hora.
+\date 01 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_SEG_HORA (3600.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_SEG_MIN
+\brief Número de segundos que contiene un minuto
+\date 19 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_SEG_MIN (60.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_SEG_DIA
+\brief Número de segundos que contiene un día.
+\date 24 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_SEG_DIA (86400.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_HORAS_DIA
+\brief Número de horas que contiene un día.
+\date 01 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_HORAS_DIA (24.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_DIAS_SIGLO_JUL
+\brief Número de días que contiene un siglo juliano.
+\date 01 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_DIAS_SIGLO_JUL (36525.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_DIAS_SEMANA
+\brief Número de días que contiene una semana.
+\date 02 de marzo de 2010: Creación de la constante.
+*/
+#define GEOC_CONST_DIAS_SEMANA (7.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_DIAS_ANYO_NORM
+\brief Número de días que contiene un año normal.
+\date 02 de marzo de 2010: Creación de la constante.
+*/
+#define GEOC_CONST_DIAS_ANYO_NORM (365.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_DIAS_ANYO_BIS
+\brief Número de días que contiene un año bisiesto.
+\date 02 de marzo de 2010: Creación de la constante.
+*/
+#define GEOC_CONST_DIAS_ANYO_BIS ((GEOC_CONST_DIAS_ANYO_NORM)+1.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_CPD_RH
+\brief Paso de ciclos por día a radianes por hora.
+\date 20 de diciembre de 2009: Creación de la constante.
+ */
+#define GEOC_CONST_CPD_RH (2.0*(GEOC_CONST_PI)/(GEOC_CONST_HORAS_DIA))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_RH_CPD
+\brief Paso de radianes por hora a ciclos por día.
+\date 20 de diciembre de 2009: Creación de la constante.
+ */
+#define GEOC_CONST_RH_CPD (1.0/(GEOC_CONST_CPD_RH))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_G
+\brief Constante de gravitación universal, en m^3/(kg*s^2).
+\date 04 de noviembre de 2009: Creación de la constante.
+*/
+#define GEOC_CONST_G (6.67428e-11)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_CONST_VRT
+\brief Velocidad de rotación de la Tierra, en radianes/s.
+\date 21 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_CONST_VRT (7.292115e-5)
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/dpeucker.h b/src/libgeoc/dpeucker.h
new file mode 100644
index 0000000..b4fe38a
--- /dev/null
+++ b/src/libgeoc/dpeucker.h
@@ -0,0 +1,261 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeucker.h
+\brief Declaración de funciones para el aligerado de polilíneas basadas en el
+ algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 04 de julio de 2011
+\section Licencia Licencia
+Copyright (c) 2009-2010, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _DPEUCKER_H_
+#define _DPEUCKER_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/calctopo.h"
+#include"libgeoc/constantes.h"
+#include"libgeoc/eucli.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/segmento.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_DPEUCKER_BUFFER_PTOS
+\brief Número de puntos para ir asignando memoria en bloques para el vector de
+ salida en la funcion \ref AligeraPolilinea.
+\date 06 de julio de 2011: Creación de la constante.
+*/
+#define GEOC_DPEUCKER_BUFFER_PTOS 100
+/******************************************************************************/
+/******************************************************************************/
+/** \enum GEOC_DPEUCKER_ROBUSTO
+\brief Aplicación o no del algoritmo robusto de aligerado de polilíneas.
+\date 10 de julio de 2011: Creación del tipo.
+*/
+enum GEOC_DPEUCKER_ROBUSTO
+{
+ /** \brief \b *NO* se realiza aligerado robusto. */
+ GeocDPeuckerRobNo=111,
+ /** \brief \b *SÍ* se realiza aligerado robusto. */
+ GeocDPeuckerRobSi=112,
+ /** \brief Aligerado semi robusto con \ref AligPolilRobIntersecOrig. */
+ GeocDPeuckerRobOrig=113,
+ /** \brief Aligerado semi robusto con \ref AligPolilRobAutoIntersec. */
+ GeocDPeuckerRobAuto=114
+};
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea mediante un algoritmo inspirado en el
+ de Douglas-Peucker.
+
+ Este algoritmo, comenzando por el primer punto de la polilínea, va
+ uniendo puntos en segmentos de tal forma que se eliminan todos aquellos
+ puntos que queden a una distancia perpendicular menor o igual a \em tol
+ del segmento de trabajo. Así aplicado, pueden ocurrir casos singulares en
+ los que la polilínea aligerada tenga casos de auto intersección entre sus
+ lados resultantes. Para evitar esto, se puede aplicar la versión robusta
+ del algoritmo.
+\param[in] x Vector que contiene las coordenadas X de los vértices de la
+ polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de la
+ polilínea de trabajo.
+\param[in] nPtos Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
+ coordenadas de los vértices.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerRobNo: No se aplica el algoritmo robusto.
+ - #GeocDPeuckerRobSi: Se aplica el algoritmo robusto completo, que
+ garantiza la no ocurrencia de auto intersecciones en la polilínea
+ resultante. Internamente, primero se aplica el tratamiento robusto
+ de la opción #GeocDPeuckerRobOrig y luego el de la opción
+ #GeocDPeuckerRobAuto.
+ - #GeocDPeuckerRobOrig: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos de la polilínea aligerada
+ que se van creando no intersectarán con ninguno de los segmentos
+ que forman los vértices que quedan por procesar de la polilínea
+ original. En casos muy especiales, este algoritmo puede seguir
+ dando lugar a auto intersecciones.
+ - #GeocDPeuckerRobAuto: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos de la polilínea aligerada
+ que se van creando no intersectarán con ninguno de los segmentos de
+ la polilínea aligerada creados con anterioridad. En casos muy
+ especiales, este algoritmo puede seguir dando lugar a auto
+ intersecciones.
+\param[in] nPtosRobusto Número de puntos de la polilínea original a utilizar en
+ el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi o
+ #GeocDPeuckerRobOrig. Si se pasa el valor 0, se utilizan todos los
+ puntos hasta el final de la polilínea original.
+\param[in] nSegRobusto Número de segmentos de la polilínea aligerada a utilizar
+ en el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi
+ o #GeocDPeuckerRobAuto. Si se pasa el valor 0, se utilizan todos los
+ segmentos hasta el inicio de la polilínea aligerada.
+\param[out] nPtosSal Número de puntos de la polilínea aligerada.
+\return Vector de \em nPtosSal elementos que contiene los índices en los
+ vectores \em x e \em y de los vértices que formarán la polilínea
+ aligerada. Si ocurre algún error de asignación de memoria se devuelve el
+ valor \p NULL.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con el valor pasado en \em nPtos.
+\note Esta función asume que \em nPtos es mayor que 0. En caso contrario,
+ devuelve \p NULL.
+\date 07 de julio de 2011: Creación de la función.
+\date 10 de julio de 2011: Cambio del tipo del argumento \em robusto al tipo
+ enumerado #GEOC_DPEUCKER_ROBUSTO.
+\todo Esta función todavía no está probada.
+*/
+size_t* AligeraPolilinea(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
+ segmentos creados intersecten con los de la polilínea original a partir
+ del punto de trabajo actual.
+\param[in] x Vector que contiene las coordenadas X de los vértices de la
+ polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de la
+ polilínea de trabajo.
+\param[in] nPtos Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] ptosAUsar Número de puntos a utilizar de la polilínea original. Si se
+ pasa el valor 0 se utilizan todos los puntos que quedan desde el
+ punto de trabajo hasta el final.
+\param[in] posIni Posición inicial del segmento a chequear.
+\param[in,out] posFin Posición final del segmento a chequear. Al término de la
+ ejecución de la función almacena la posición del punto que hace
+ que el segmento de la polilínea aligerada no intersecte con
+ ninguno de los que quedan de la polilínea original.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con el valor pasado en \em nPtos.
+\note Esta función no comprueba si los índices pasados en los argumentos
+ \em posIni y \em posFin son congruentes con el tamaño de los vectores
+ pasado en \em nPtos.
+\note Esta función no comprueba internamente si la variable \em ptosAUsar es
+ congruente con el valor pasado en \em nPtos.
+\date 07 de julio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void AligPolilRobIntersecOrig(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const size_t ptosAUsar,
+ const size_t posIni,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
+ segmentos creados intersecten con los anteriores de la polilínea
+ aligerada.
+\param[in] x Vector que contiene las coordenadas X de los vértices de la
+ polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de la
+ polilínea de trabajo.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] posAlig Vector de posiciones de \em x e \em y utilizadas en la
+ polilínea aligerada.
+\param[in] nPosAlig Número de elementos de \em posAlig menos el último punto
+ añadido. Esto se hace así para evitar chequear el segmento
+ inmediatamente anterior, que siempre tiene un punto en común (su
+ extremo final) con el de trabajo.
+\param[in] segAUsar Número de segmentos a utilizar de la polilínea aligerada. Si
+ se pasa el valor 0 se utilizan todos los segmentos anteriores.
+\param[in] posIni Posición inicial del segmento a chequear.
+\param[in,out] posFin Posición final del segmento a chequear. Al término de la
+ ejecución de la función almacena la posición del punto que hace
+ que el segmento de la polilínea aligerada no intersecte con
+ ninguno de los anteriormente calculados.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con el valor pasado en \em nPtos.
+\note Esta función no comprueba si los índices pasados en los argumentos
+ \em posIni y \em posFin son congruentes con el tamaño de los vectores
+ pasado en \em nPtos.
+\note Esta función trabaja internamente con el valor absoluto del argumento
+ \em tamRect.
+\date 05 de julio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void AligPolilRobAutoIntersec(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/errores.h b/src/libgeoc/errores.h
new file mode 100755
index 0000000..3b91f08
--- /dev/null
+++ b/src/libgeoc/errores.h
@@ -0,0 +1,1058 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup errores Módulo ERRORES
+\ingroup anespec eop fichero geodesia geom general geopot gshhs marea matriz
+\ingroup mmcc orden snx texto
+\brief En este módulo se reúnen los ficheros necesarios para realizar el
+ tratamiento de errores que puedan ocurrir en la biblioteca.
+@{
+\file errores.h
+\brief Declaración de funciones y constantes para el tratamiento de errores.
+
+En el momento de la compilación ha de seleccionarse el comportamiento de la
+función \ref GeocError. Para realizar la selección es necesario definir las
+variables para el preprocesador \em ESCRIBE_MENSAJE_ERROR si se quiere que la
+función imprima un mensaje de error y/o \em FIN_PROGRAMA_ERROR si se quiere que
+la función termine la ejecución del programa en curso. Si no se define ninguna
+variable, la función no ejecuta ninguna acción. En \p gcc, las variables para el
+preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
+introducir.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 06 de marzo de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include<stdio.h>
+#include<stdlib.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _ERRORES_H_
+#define _ERRORES_H_
+/******************************************************************************/
+/******************************************************************************/
+//GENERAL
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PLINEA
+\brief Palabra \em Línea para ser utilizada en el mensaje que imprime la macro
+ #GEOC_ERROR. Esta constante se define porque el preprocesador del
+ compilador \p pgcc no soporta letras con tilde escritas directamente en
+ las órdenes a ejecutar por las macros.
+\date 10 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_PLINEA "Línea"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_TIPO_ERR_NADA
+\brief Indicador de que la función \ref GeocError no hace nada.
+\date 09 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_TIPO_ERR_NADA 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_TIPO_ERR_MENS_Y_EXIT
+\brief Indicador de que la función \ref GeocError imprime un mensaje descriptivo
+ en la salida de error \em stderr y termina la ejecución del programa en
+ curso.
+\date 09 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_TIPO_ERR_MENS_Y_EXIT 1
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_TIPO_ERR_MENS
+\brief Indicador de que la función \ref GeocError imprime un mensaje descriptivo
+ en la salida de error \em stderr y no termina la ejecución del programa
+ en curso.
+\date 09 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_TIPO_ERR_MENS 2
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_TIPO_ERR_EXIT
+\brief Indicador de que la función \ref GeocError termina la ejecución del
+ programa en curso.
+\date 09 de enero de 2011: Creación de la constante.
+*/
+#define GEOC_TIPO_ERR_EXIT 3
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica el tipo de acción que realiza la función \ref GeocError.
+\return Cuatro posibles valores:
+ - #GEOC_TIPO_ERR_NADA: La función \ref GeocError no hace nada.
+ - #GEOC_TIPO_ERR_MENS_Y_EXIT: La función \ref GeocError imprime un
+ mensaje descriptivo en la salida de error \em stderr y termina la
+ ejecución del programa en curso.
+ - #GEOC_TIPO_ERR_MENS: La función \ref GeocError imprime un mensaje
+ descriptivo en la salida de error \em stderr y no detiene la ejecución
+ del programa en curso.
+ - #GEOC_TIPO_ERR_EXIT: La función \ref GeocError detiene la ejecución
+ del programa en curso.
+\date 09 de enero de 2011: Creación de la función.
+*/
+int GeocTipoError(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime un mensaje en la salida de error \em stderr y/o sale del programa
+ en ejecución.
+\param[in] mensaje Cadena de texto a imprimir.
+\param[in] funcion Nombre de la función desde donde se ha invocado a esta
+ función.
+\note Si este fichero se compila con las variables para el preprocesador
+ \em ESCRIBE_MENSAJE_ERROR y \em FIN_PROGRAMA_ERROR, esta función imprime
+ el mensaje de error y termina la ejecución del programa en curso mediante
+ la llamada a la función \em exit(EXIT_FAILURE), de la biblioteca estándar
+ de C.
+\note Si este fichero se compila con la variable para el preprocesador
+ \em ESCRIBE_MENSAJE_ERROR, esta función imprime el mensaje de error.
+\note Si este fichero se compila con la variable para el preprocesador
+ \em FIN_PROGRAMA_ERROR, esta función termina la ejecución del programa en
+ curso mediante la llamada a la función \em exit(EXIT_FAILURE), de la
+ biblioteca estándar de C.
+\note Si este fichero se compila sin variables para el preprocesador, esta
+ función no hace nada.
+\date 10 de enero de 2011: Creación de la función.
+*/
+void GeocError(const char mensaje[],
+ const char funcion[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERROR
+\brief Macro para imprimir un mensaje en la salida de error \em stderr y/o sale
+ del programa en ejecución.
+\param[in] mensaje Cadena de texto a imprimir.
+\note Esta macro llama internamente a la función \ref GeocError.
+\note Esta macro pasa como argumento \em funcion a \ref GeocError la variable
+ del preprocesador \em __func__, de C99.
+\date 10 de enero de 2011: Creación de la macro.
+*/
+#define GEOC_ERROR(mensaje) \
+{ \
+ if(GeocTipoError()!=GEOC_TIPO_ERR_NADA) \
+ { \
+ fprintf(stderr,"\n\n"); \
+ fprintf(stderr,"********************\n********************\n"); \
+ fprintf(stderr,GEOC_PLINEA" %d del fichero '%s'\n",__LINE__,__FILE__); \
+ GeocError(mensaje,(const char*)__func__); \
+ fprintf(stderr,"********************\n********************\n\n"); \
+ } \
+ else \
+ { \
+ GeocError(mensaje,(const char*)__func__); \
+ } \
+}
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//GENERAL
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NO_ERROR
+\brief Indicador de que no ha ocurrido ningun error.
+\date 06 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_NO_ERROR 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_LECTURA_FICHERO
+\brief Indicador de que ha ocurrido un error en la lectura de un fichero.
+\date 06 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_LECTURA_FICHERO 1001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_ESCRITURA_FICHERO
+\brief Indicador de que ha ocurrido un error en escritura de un fichero.
+\date 20 de agosto de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_ESCRITURA_FICHERO 1002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_QUEDAN_DATOS_EN_FICHERO
+\brief Indicador de que quedan datos por leer en un fichero.
+\date 06 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_QUEDAN_DATOS_EN_FICHERO 1003
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NO_QUEDAN_DATOS_EN_FICHERO
+\brief Indicador de que no quedan datos por leer en un fichero.
+\date 25 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_NO_QUEDAN_DATOS_EN_FICHERO 1004
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NO_HAY_DATOS_EN_FICHERO
+\brief Indicador de que no hay datos a leer en un fichero.
+\date 02 de diciembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_NO_HAY_DATOS_EN_FICHERO 1005
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_LINEA_LARGA_EN_FICHERO
+\brief Indicador de que una línea de un fichero es demasiado larga.
+\date 23 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_LINEA_LARGA_EN_FICHERO 1006
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_LINEA_CORTA_EN_FICHERO
+\brief Indicador de que una línea de un fichero es demasiado corta.
+\date 23 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_LINEA_CORTA_EN_FICHERO 1007
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_ARG_ENTRADA_INCORRECTO
+\brief Indicador de que un argumento de entrada de una función es incorrecto.
+\date 06 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_ARG_ENTRADA_INCORRECTO 1008
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_ASIG_MEMORIA
+\brief Indicador de que ha ocurrido un error en la asignación de memoria.
+\date 06 de marzo de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_ASIG_MEMORIA 1009
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_FUERA_DOMINIO
+\brief Indicador de que ha ocurrido un error porque un dato está fuera de
+ dominio.
+\date 04 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_FUERA_DOMINIO 1010
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_FUERA_DOMINIO_MAYOR
+\brief Indicador de que ha ocurrido un error porque un dato está fuera de
+ dominio. En este caso, el dato se sale del dominio por arriba (porque es
+ demasiado grande).
+\date 26 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_FUERA_DOMINIO_MAYOR 1011
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_FUERA_DOMINIO_MENOR
+\brief Indicador de que ha ocurrido un error porque un dato está fuera de
+ dominio. En este caso, el dato se sale del dominio por abajo (porque es
+ demasiado pequeño).
+\date 26 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_FUERA_DOMINIO_MENOR 1012
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_INTERP
+\brief Indicador de que ha ocurrido un error en una interpolación.
+\date 15 de mayo de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_INTERP 1013
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_INTERP_NO_DATO
+\brief Indicador de que no hay datos para realizar una interpolación.
+\date 30 de mayo de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_INTERP_NO_DATO 1014
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_DIV_ENTRE_CERO
+\brief Indicador de que se ha realizado una división entre cero.
+\date 26 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_DIV_ENTRE_CERO 1015
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_DIM_MATRIZ
+\brief Indicador de dimensiones de una matriz erróneas.
+\date 02 de diciembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_DIM_MATRIZ 1016
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_MATRIZ_SINGULAR
+\brief Indicador de matriz singular.
+\date 12 de marzo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_MATRIZ_SINGULAR 1017
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//EOP
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_EOP_ERRORES
+\brief Indicador de que ha ocurrido un error porque una estructura eop no
+ contiene información de errores.
+\date 04 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_EOP_ERRORES 2001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_EOP_DOS_PUNTOS
+\brief Indicador de que ha ocurrido un error porque en una interpolación
+ cuadrática sólo hay dos puntos disponibles.
+\date 12 de octubre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_EOP_DOS_PUNTOS 2002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_EOP_NO_DATOS
+\brief Indicador de que una estructura eop no contiene datos.
+\date 19 de junio de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_EOP_NO_DATOS 2003
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//SINEX
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_LINEA_ILEGAL
+\brief Indicador de que una línea de un fichero SINEX no comienza por una de las
+ cadenas permitidas (#GEOC_SNX_CAD_COMENTARIO, #GEOC_SNX_CAD_INI_CABECERA,
+ #GEOC_SNX_CAD_INI_BLOQUE, #GEOC_SNX_CAD_FIN_BLOQUE o
+ #GEOC_SNX_CAD_INI_DATOS).
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_LINEA_ILEGAL 3001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_LINEA_LARGA
+\brief Indicador de que una línea de un fichero SINEX es demasiado larga (más de
+ #GEOC_SNX_LON_MAX_LIN_FICH carácteres).
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_LINEA_LARGA 3002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_LINEA_CORTA
+\brief Indicador de que una línea de un fichero SINEX es demasiado corta.
+\date 29 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_LINEA_CORTA 3003
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_NO_BLOQUES
+\brief Indicador de que en un fichero SINEX no hay bloques válidos.
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_NO_BLOQUES 3004
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_ID_BLOQUE_DISTINTO
+\brief Indicador de que en un fichero SINEX los identificadores de bloque tras
+ las marcas de inicio y fin son distintos.
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_ID_BLOQUE_DISTINTO 3005
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BLOQUE_NO_INICIO
+\brief Indicador de que en un fichero SINEX un bloque no tiene identificador de
+ inicio.
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BLOQUE_NO_INICIO 3006
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BLOQUE_NO_FIN
+\brief Indicador de que en un fichero SINEX un bloque no tiene identificador de
+ fin.
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BLOQUE_NO_FIN 3007
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_NO_FIN_FICH
+\brief Indicador de que un fichero SINEX no tiene indicador de fin de fichero.
+\date 28 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_NO_FIN_FICH 3008
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_NO_ID_CABECERA
+\brief Indicador de que un fichero SINEX no tiene indicador cabecera.
+\date 29 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_NO_ID_CABECERA 3009
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_FORMATO_CABECERA
+\brief Indicador de que un fichero SINEX tiene una cabecera que no respeta el
+ formato.
+\date 29 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_FORMATO_CABECERA 3010
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_CODFICH_INC
+\brief Indicador de que un fichero SINEX tiene un indicador de código de tipo de
+ fichero incorrecto.
+\date 05 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_CODFICH_INC 3011
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_TIPODOC_INC
+\brief Indicador de que un fichero SINEX tiene un indicador de tipo de documento
+ incorrecto.
+\date 05 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_TIPODOC_INC 3012
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_VERS_INC
+\brief Indicador de que un fichero SINEX tiene un indicador de versión
+ incorrecto.
+\date 30 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_VERS_INC 3013
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_FECHA_INC
+\brief Indicador de que una fecha es incorrecta en un fichero SINEX.
+\date 30 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_FECHA_INC 3014
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_CODOBS_INC
+\brief Indicador de que el código de observación es incorrecto en un fichero
+ SINEX.
+\date 30 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_CODOBS_INC 3015
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_CODCONSTR_INC
+\brief Indicador de que el código de constreñimiento es incorrecto en un fichero
+ SINEX.
+\date 30 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_CODCONSTR_INC 3016
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_SOLCONT_INC
+\brief Indicador de que un código de solución contenida en un fichero SINEX es
+ incorrecto.
+\date 31 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_SOLCONT_INC 3017
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_NSOLCONT_INC
+\brief Indicador de que un código de solución contenida en un fichero SINEX es
+ incorrecto.
+\date 31 de diciembre de 2009: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_NSOLCONT_INC 3018
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_FORM_LINEA_INC
+\brief Indicador de que una línea de un fichero SINEX tiene un formato
+ incorrecto.
+\date 01 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_FORM_LINEA_INC 3019
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BFR_TIPOINF_INC
+\brief Indicador de que el código de tipo de información de un bloque
+ FILE/REFERENCE de un fichero SINEX es incorrecto.
+\date 01 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BFR_TIPOINF_INC 3020
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BND_CODNUT_INC
+\brief Indicador de que el código de modelo de nutación de un bloque
+ NUTATION/DATA de un fichero SINEX es incorrecto.
+\date 03 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BND_CODNUT_INC 3021
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BPD_CODPREC_INC
+\brief Indicador de que el código de modelo de precesión de un bloque
+ PRECESSION/DATA de un fichero SINEX es incorrecto.
+\date 03 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BPD_CODPREC_INC 3022
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSII_GRADLATSEX_INC
+\brief Indicador de que un valor de grados sexagesimales de latitud de un bloque
+ SITE/ID de un fichero SINEX es incorrecto.
+\date 15 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSII_GRADLATSEX_INC 3023
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSII_GRADLONSEX_INC
+\brief Indicador de que un valor de grados sexagesimales de longitud de un bloque
+ SITE/ID de un fichero SINEX es incorrecto.
+\date 15 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSII_GRADLONSEX_INC 3024
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSII_MINSEX_INC
+\brief Indicador de que un valor de minutos sexagesimales de un bloque SITE/ID
+ de un fichero SINEX es incorrecto.
+\date 15 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSII_MINSEX_INC 3025
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSII_SEGSEX_INC
+\brief Indicador de que un valor de segundos sexagesimales de un bloque SITE/ID
+ de un fichero SINEX es incorrecto.
+\date 15 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSII_SEGSEX_INC 3026
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSE_CODSREX_INC
+\brief Indicador de que un código del sistema de referencia utilizado para
+ definir la excentricidad de una antena de un bloque SITE/ECCENTRICITY de
+ un fichero SINEX es incorrecto.
+\date 23 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSE_CODSREX_INC 3027
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_CODGNSS_INC
+\brief Indicador de que un código de constelación GNSS utilizado en un fichero
+ SINEX es incorrecto.
+\date 28 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_CODGNSS_INC 3028
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSAP_CODFREC_INC
+\brief Indicador de que un código frecuencia de satélite GNSS de un bloque
+ SATELLITE/PHASE_CENTER de un fichero SINEX es incorrecto.
+\date 28 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSAP_CODFREC_INC 3029
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSAP_TIPOPCV_INC
+\brief Indicador de que un código indicador de tipo de variación del centro de
+ fase de un bloque SATELLITE/PHASE_CENTER de un fichero SINEX es
+ incorrecto.
+\date 28 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSAP_TIPOPCV_INC 3030
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSAP_MODAPPCV_INC
+\brief Indicador de que un código indicador de modelo de aplicación de las
+ variaciones del centro de fase de un bloque SATELLITE/PHASE_CENTER de un
+ fichero SINEX es incorrecto.
+\date 28 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSAP_MODAPPCV_INC 3031
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_BSOES_IDPARAM_INC
+\brief Indicador de que un identificador de parámetro estadístico de un bloque
+ SOLUTION/STATISTICS de un fichero SINEX es incorrecto.
+\date 28 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_BSOES_IDPARAM_INC 3032
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_IDUNID_INC
+\brief Indicador de que un identificador de unidades utilizado en un fichero
+ SINEX es incorrecto.
+\date 29 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_IDUNID_INC 3033
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_TIPPAR_INC
+\brief Indicador de que un identificador de tipo de parámetro utilizado en un
+ fichero SINEX es incorrecto.
+\date 29 de enero de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_TIPPAR_INC 3034
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_PTRIAN_INC
+\brief Indicador de que un identificador de parte triangular de una matriz
+ simétrica utilizado en un fichero SINEX es incorrecto.
+\date 17 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_PTRIAN_INC 3035
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_TIPOMAT_INC
+\brief Indicador de que un identificador de tipo de matriz utilizado en un
+ fichero SINEX es incorrecto.
+\date 17 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_TIPOMAT_INC 3036
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_SNX_POSMAT_INC
+\brief Indicador de que una posición en una matriz almacenada en un fichero
+ SINEX es incorrecta.
+\date 17 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_SNX_POSMAT_INC 3037
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//GTS
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GTS_VERT_FHULL
+\brief Indicador de que un vértice de una nube de puntos está fuera del
+ \em convex \em hull que la engloba.
+\date 09 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GTS_VERT_FHULL 4001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GTS_VERT_FSUP
+\brief Indicador de que un vértice está fuera de una superficie.
+\date 22 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GTS_VERT_FSUP 4002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GTS_VERT_DUPL
+\brief Indicador de que un vértice de una nube de puntos está duplicado.
+\date 09 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GTS_VERT_DUPL 4003
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GTS_CONF_CONSTR
+\brief Indicador de que ha habido un conflicto con un constreñimiento en un
+ proceso de triangulación.
+\date 09 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GTS_CONF_CONSTR 4004
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//PMAREA
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PMAREA_NO_HAY_BLOQUE
+\brief Indicador de que no existe un bloque buscado en un fichero.
+\date 24 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_PMAREA_NO_HAY_BLOQUE 5001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PMAREA_LIN_FICH_INC
+\brief Indicador de que una línea de fichero de parámetros de marea es
+ incorrecta.
+\date 25 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_PMAREA_LIN_FICH_INC 5002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PMAREA_DEF_BLOQUE_INC
+\brief Indicador de que una definición de bloque de parámetros de marea en un
+ fichero es incorrecta.
+\date 25 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_PMAREA_DEF_BLOQUE_INC 5003
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PMAREA_LIM_FDOM
+\brief Indicador de que alguno de los límites de la malla está fuera de dominio.
+\date 25 de abril de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_PMAREA_LIM_FDOM 5004
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//GEOPOT
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRADO_ORDEN_MAL
+\brief Indicador de que los grados y/u órdenes pasados a una función no son
+ correctos.
+\date 25 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRADO_ORDEN_MAL 6001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRACE_LINFO_NO
+\brief Indicador de que no hay línea (o la que hay no es la primera) de
+ información general de un fichero de un desarrollo del potencial de la
+ Tierra en armónicos esféricos en formato de GRACE.
+\date 16 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRACE_LINFO_NO 6002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRACE_LINFO_REPE
+\brief Indicador de que la línea de información general de un fichero de un
+ desarrollo del potencial de la Tierra en armónicos esféricos en formato
+ de GRACE está repetida.
+\date 16 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRACE_LINFO_REPE 6003
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRACE_CAB_INCOMP
+\brief Indicador de cabecera incompleta en un fichero de un desarrollo del
+ potencial de la Tierra en armónicos esféricos en formato de GRACE está
+ repetida.
+\date 17 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRACE_CAB_INCOMP 6004
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRACE_MEZCLA_TIPO_COEF
+\brief Indicador de que en un fichero de un desarrollo del potencial de la
+ Tierra en armónicos esféricos en formato de GRACE hay definiciones de
+ coeficientes de distintas versiones.
+\date 23 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRACE_MEZCLA_TIPO_COEF 6005
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GEOPOT_GRACE_NLINEAS_DATOS_MAL
+\brief Indicador de que en un fichero de un desarrollo del potencial de la
+ Tierra en armónicos esféricos en formato de GRACE no coinciden el número
+ de líneas de datos leídas en dos pasadas distintas sobre el fichero.
+\date 24 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_GEOPOT_GRACE_NLINEAS_DATOS_MAL 6006
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//NUMLOVE
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NUMLOVE_NO_HAY_BLOQUE
+\brief Indicador de que no existe un bloque buscado en un fichero.
+\date 29 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_NUMLOVE_NO_HAY_BLOQUE 7001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NUMLOVE_DEF_BLOQUE_INC
+\brief Indicador de que una línea de fichero de números de Love es incorrecta.
+\date 29 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_NUMLOVE_DEF_BLOQUE_INC 7002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_NUMLOVE_LIN_FICH_INC
+\brief Indicador de que una definición de bloque de números de Love en un
+ fichero es incorrecta.
+\date 29 de noviembre de 2010: Creación de la constante.
+*/
+#define GEOC_ERR_NUMLOVE_LIN_FICH_INC 7003
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//GSHHS
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GSHHS_VERS_ANTIGUA
+\brief Indicador de que la versión de un fichero de GSHHS es antigua.
+\date 16 de abril de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_GSHHS_VERS_ANTIGUA 8001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_GSHHS_CREA_POLI
+\brief Indicador de que ha ocurrido un error de tipo
+ #GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG o
+ #GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG al crear una estructura \ref polig o
+ \ref polil
+\date 19 de junio de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_GSHHS_CREA_POLI 8002
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//POLIG
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG
+\brief Indicador de que dos vectores de coordenadas no contienen el mismo número
+ de polígonos.
+\date 27 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG 9001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG
+\brief Indicador de que dos vectores de coordenadas no contienen los mismos
+ polígonos.
+\date 27 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG 9002
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//POLIL
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL
+\brief Indicador de que dos vectores de coordenadas no contienen el mismo número
+ de polilíneas.
+\date 03 de junio de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL 10001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL
+\brief Indicador de que dos vectores de coordenadas no contienen las mismas
+ polilíneas.
+\date 03 de junio de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL 10002
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+//PROYEC
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PROYEC_INI_PROJ
+\brief Indicador de que ha ocurrido un error en la inicialización de una
+ proyección de PROJ.4.
+\date 31 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_PROYEC_INI_PROJ 11001
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PROYEC_NO_INV_PROJ
+\brief Indicador de que una proyección cartográfica de PROJ.4 no tiene paso
+ inverso.
+\date 31 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_PROYEC_NO_INV_PROJ 11002
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ERR_PROYEC_PROJ_ERROR
+\brief Indicador de que ha ocurrido un error al proyectar un punto con PROJ.4.
+\date 31 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_ERR_PROYEC_PROJ_ERROR 11003
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/eucli.h b/src/libgeoc/eucli.h
new file mode 100755
index 0000000..1ee7d7c
--- /dev/null
+++ b/src/libgeoc/eucli.h
@@ -0,0 +1,237 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom interp
+@{
+\file eucli.h
+\brief Declaración de funciones para la realización de cálculos de geometría
+ euclídea.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 27 de octubre de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _EUCLI_H_
+#define _EUCLI_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<math.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia euclídea entre dos puntos en el plano.
+\param[in] x1 Coordenada X del punto inicial.
+\param[in] y1 Coordenada Y del punto inicial.
+\param[in] x2 Coordenada X del punto final.
+\param[in] y2 Coordenada Y del punto final.
+\return Distancia euclídea entre los dos puntos.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\date 27 de octubre de 2009: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+double Dist2D(const double x1,
+ const double y1,
+ const double x2,
+ const double y2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia euclídea entre dos puntos en el plano y realiza la
+ propagación de errores correspondiente.
+\param[in] x1 Coordenada X del punto inicial.
+\param[in] y1 Coordenada Y del punto inicial.
+\param[in] x2 Coordenada X del punto final.
+\param[in] y2 Coordenada Y del punto final.
+\param[in] varx1 Varianza de la coordenada X del punto inicial.
+\param[in] varx1y1 Covarianza entre las coordenadas X e Y del punto inicial.
+\param[in] vary1 Varianza de la coordenada Y del punto inicial.
+\param[in] varx2 Varianza de la coordenada X del punto final.
+\param[in] varx2y2 Covarianza entre las coordenadas X e Y del punto final.
+\param[in] vary2 Varianza de la coordenada Y del punto final.
+\param[out] dist Distancia euclídea entre los dos puntos.
+\param[out] varDist Varianza de la distancia calculada.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\note Las unidades de las matrices de varianza-covarianza han de ser congruentes
+ con las de las coordenadas pasadas.
+\date 27 de octubre de 2009: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void Dist2DVC(const double x1,
+ const double y1,
+ const double x2,
+ const double y2,
+ const double varx1,
+ const double varx1y1,
+ const double vary1,
+ const double varx2,
+ const double varx2y2,
+ const double vary2,
+ double* dist,
+ double* varDist);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia euclídea entre dos puntos en el espacio.
+\param[in] x1 Coordenada X del punto inicial.
+\param[in] y1 Coordenada Y del punto inicial.
+\param[in] z1 Coordenada Z del punto inicial.
+\param[in] x2 Coordenada X del punto final.
+\param[in] y2 Coordenada Y del punto final.
+\param[in] z2 Coordenada Z del punto final.
+\return Distancia euclídea entre los dos puntos.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\date 27 de octubre de 2009: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+double Dist3D(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia euclídea entre dos puntos en el espacio y realiza la
+ propagación de errores correspondiente.
+\param[in] x1 Coordenada X del punto inicial.
+\param[in] y1 Coordenada Y del punto inicial.
+\param[in] z1 Coordenada Z del punto inicial.
+\param[in] x2 Coordenada X del punto final.
+\param[in] y2 Coordenada Y del punto final.
+\param[in] z2 Coordenada Z del punto final.
+\param[in] varx1 Varianza de la coordenada X del punto inicial.
+\param[in] varx1y1 Covarianza entre las coordenadas X e Y del punto inicial.
+\param[in] varx1z1 Covarianza entre las coordenadas X y Z del punto inicial.
+\param[in] vary1 Varianza de la coordenada Y del punto inicial.
+\param[in] vary1z1 Covarianza entre las coordenadas Y y Z del punto inicial.
+\param[in] varz1 Varianza de la coordenada Z del punto inicial.
+\param[in] varx2 Varianza de la coordenada X del punto final.
+\param[in] varx2y2 Covarianza entre las coordenadas X e Y del punto final.
+\param[in] varx2z2 Covarianza entre las coordenadas X y Z del punto final.
+\param[in] vary2 Varianza de la coordenada Y del punto final.
+\param[in] vary2z2 Covarianza entre las coordenadas Y y Z del punto final.
+\param[in] varz2 Varianza de la coordenada Z del punto final.
+\param[out] dist Distancia euclídea entre los dos puntos.
+\param[out] varDist Varianza de la distancia calculada.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\note Las unidades de las matrices de varianza-covarianza han de ser congruentes
+ con las de las coordenadas pasadas.
+\date 27 de octubre de 2009: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void Dist3DVC(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2,
+ const double varx1,
+ const double varx1y1,
+ const double varx1z1,
+ const double vary1,
+ const double vary1z1,
+ const double varz1,
+ const double varx2,
+ const double varx2y2,
+ const double varx2z2,
+ const double vary2,
+ const double vary2z2,
+ const double varz2,
+ double* dist,
+ double* varDist);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el ángulo formado por dos vectores en el plano.
+\param[in] x1 Coordenada X del primer vector.
+\param[in] y1 Coordenada Y del primer vector.
+\param[in] x2 Coordenada X del segundo vector.
+\param[in] y2 Coordenada Y del segundo vector.
+\return Ángulo formado por los dos vectores, en radianes.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\date 04 de julio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+double AnguloVecPlano(const double x1,
+ const double y1,
+ const double x2,
+ const double y2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la altura de un triángulo a partir de las coordenadas de sus
+ vértices.
+\param[in] xVert Coordenada X del vértice a partir del cual se calculará la
+ altura.
+\param[in] yVert Coordenada Y del vértice a partir del cual se calculará la
+ altura.
+\param[in] xBase1 Coordenada X del primer punto de la base del triángulo.
+\param[in] yBase1 Coordenada Y del primer punto de la base del triángulo.
+\param[in] xBase2 Coordenada X del segundo punto de la base del triángulo.
+\param[in] yBase2 Coordenada Y del segundo punto de la base del triángulo.
+\return Altura del triángulo, dada como la longitud del segmento que, partiendo
+ del vértice pasado, corta en ángulo recto a la base.
+\note Esta función asume que todas las coordenadas vienen dadas en las mismas
+ unidades.
+\date 04 de julio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+double AlturaTriangulo(const double xVert,
+ const double yVert,
+ const double xBase1,
+ const double yBase1,
+ const double xBase2,
+ const double yBase2);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/fgeneral.h b/src/libgeoc/fgeneral.h
new file mode 100755
index 0000000..2dc3832
--- /dev/null
+++ b/src/libgeoc/fgeneral.h
@@ -0,0 +1,646 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup eop general geom geopot matriz
+@{
+\file fgeneral.h
+\brief Declaración de macros y funciones de utilidad general.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 25 de septiembre de 2009
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _FGENERAL_H_
+#define _FGENERAL_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<stdint.h>
+#include<float.h>
+#include<math.h>
+#include"libgeoc/constantes.h"
+#include"libgeoc/errores.h"
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SIGNO
+\brief Macro para determinar el signo de un escalar.
+\param[in] a Un número.
+\return Signo del dato de entrada. Dos posibilidades:
+ - -1.0: El dato pasado es negativo.
+ - 1.0: El dato pasado es positivo o 0.0.
+\date 10 de junio de 2011: Creación de la macro.
+*/
+#define GEOC_SIGNO(a) ((a)>=0.0 ? 1.0 : -1.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MAX
+\brief Macro para seleccionar el valor máximo entre dos escalares.
+\param[in] a Un número.
+\param[in] b Otro número.
+\return El mayor de los dos argumentos de entrada.
+\date 25 de septiembre de 2009: Creación de la macro.
+*/
+#define GEOC_MAX(a,b) ((a)>(b) ? (a) : (b))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MIN
+\brief Macro para seleccionar el valor mínimo entre dos escalares.
+\param[in] a Un número.
+\param[in] b Otro número.
+\return El menor de los dos argumentos de entrada.
+\date 25 de septiembre de 2009: Creación de la macro.
+*/
+#define GEOC_MIN(a,b) ((a)<(b) ? (a) : (b))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PARI
+\brief Macro para comprobar si un número de tipo entero es par.
+\param[in] a Un número.
+\return Dos posibilidades:
+ - 0: El número es impar.
+ - 1: El número es par.
+\note Esta macro usa el operador \b % de C para calcular el resto de la división
+ del número pasado entre 2, por lo que el argumento de entrada ha de ser de
+ tipo entero: \p char, \p short, \p int, \p long o \p long \p long (con los
+ identificadores \p signed o \p undigned).
+\date 15 de marzo de 2011: Creación de la macro.
+*/
+#define GEOC_PARI(a) ((a)%2 ? 0 : 1)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ES_CERO
+\brief Macro para comprobar si un número puede considerarse cero con una cierta
+ tolerancia.
+\param[in] num Número a comprobar.
+\param[in] tol Tolerancia. Ha de ser un número \b POSITIVO.
+\return Dos posibilidades:
+ - 0: \em num es distinto de 0, tal que \f$num<=-tol\f$ o \f$num>=tol\f$.
+ - 1: \em num es 0, tal que \f$ -tol < num < tol\f$.
+\note Para que esta macro funcione correctamente, \em tol ha de ser un número
+ \b POSITIVO.
+\date 13 de marzo de 2010: Creación de la macro.
+\todo Esta macro todavía no está probada.
+*/
+#define GEOC_ES_CERO(num,tol) (((num)>(-(tol)))&&((num)<(tol)) ? 1 : 0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_DBL
+\brief Macro para realizar una conversión explícita a tipo de dato \p double.
+\param[in] a Un número.
+\return Órdenes para la conversión explícita del dato pasado a \p double.
+\date 19 de junio de 2011: Creación de la macro.
+*/
+#define GEOC_DBL(a) ((double)(a))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref fgeneral.c.
+\param[out] version Cadena identificadora de la versión de OpenMP utilizada.
+ Este argumento sólo se utiliza si su valor de entrada es distinto de
+ \p NULL y si hay alguna función compilada con OpenMP.
+\return Dos posibles valores:
+ - 0: No hay ninguna función compilada en paralelo con OpenMP.
+ - Distinto de 0: Sí hay alguna función compilada en paralelo con OpenMP.
+\note Esta función asume que el argumento \em version tiene suficiente memoria
+ asignada (si es distinto de \p NULL).
+\date 22 de agosto de 2011: Creación de la función.
+\date 25 de agosto de 2011: Adición del argumento de entrada \em version.
+*/
+int GeocParOmpFgeneral(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Mete un ángulo en el dominio \f$]-2*\pi,2*\pi[\f$.
+\param[in] angulo Valor angular, en radianes.
+\return Valor angular de entrada, en el dominio \f$]-2*\pi,2*\pi[\f$, en
+ radianes.
+\note Esta función elimina todas las vueltas completas a la circunferencia que
+ hacen que el posible valor de entrada esté fuera de los límites del
+ dominio de salida.
+\date 10 de junio de 2011: Creación de la función.
+*/
+double PonAnguloDominio(const double angulo);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca en una lista de coordenadas de una polilínea en una dimensión las
+ posiciones de inicio y fin del segmento que encierra a un punto dado.
+\param[in] valor Coordenada del punto de trabajo, contenido en el segmento a
+ buscar.
+\param[in] lista Lista con las coordenadas de la polilínea.
+\param[in] nDatos Número de elementos de la lista de coordenadas pasadas.
+\param[in] incDatos Posiciones de separación entre cada elemento de \em lista.
+ Ha de ser un número positivo.
+\param[out] posInicio Posición en \em lista de la coordenada inicial del
+ segmento buscado.
+\param[out] posFin Posición en \em lista de la coordenada final del segmento
+ buscado.
+\note Para convertir las posiciones devueltas por la función en las posiciones
+ reales del array en memoria, han de ser multiplicadas por el valor
+ \em incDatos.
+\note En las siguientes notas, cuando se habla de la longitud o el número de
+ elementos de \em lista quiere decir el número de datos de trabajo, no
+ todas las posiciones almacenadas en memoria.
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con el valor \em nDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 2.
+\note Esta función supone que los elementos almacenados en \em lista están
+ ordenados de menor a mayor.
+\note Esta función supone que \em lista[0] <= \em valor >= \em lista[nDatos-1].
+\note Si algún elemento de \em lista es igual a \em valor, su posición será el
+ punto de inicio del segmento calculado, excepto si el elemento de
+ \em lista es el último, en cuyo caso será el punto final.
+\date 06 de diciembre de 2010: Creación de la función.
+*/
+void BuscaSegmento1DInc(const double valor,
+ const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posInicio,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca en una lista de coordenadas de una polilínea en una dimensión las
+ posiciones de inicio y fin del segmento que encierra a un punto dado.
+\param[in] valor Coordenada del punto de trabajo, contenido en el segmento a
+ buscar.
+\param[in] lista Lista con las coordenadas de la polilínea.
+\param[in] nDatos Número de elementos de la lista de coordenadas pasadas.
+\param[out] posInicio Posición en \em lista de la coordenada inicial del
+ segmento buscado.
+\param[out] posFin Posición en \em lista de la coordenada final del segmento
+ buscado.
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con el valor \em nDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 2.
+\note Esta función supone que los elementos almacenados en \em lista están
+ ordenados de menor a mayor.
+\note Esta función supone que \em lista[0] <= \em valor >= \em lista[nDatos-1].
+\note Si algún elemento de \em lista es igual a \em valor, su posición será el
+ punto de inicio del segmento calculado, excepto si el elemento de
+ \em lista es el último, en cuyo caso será el punto final.
+\date 11 de octubre de 2009: Creación de la función.
+*/
+void BuscaSegmento1D(const double valor,
+ const double* lista,
+ const size_t nDatos,
+ size_t* posInicio,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca las posiciones fila y columna del elemento de una matriz
+ correspondiente a la esquina NW del cuadrado que encierra a un punto
+ dado.
+\param[in] xPto Coordenada X del punto de trabajo.
+\param[in] yPto Coordenada Y del punto de trabajo.
+\param[in] xMin Coordenada X mínima (esquina W) de los puntos almacenados en la
+ matriz.
+\param[in] xMax Coordenada X máxima (esquina E) de los puntos almacenados en la
+ matriz.
+\param[in] yMin Coordenada Y mínima (esquina S) de los puntos almacenados en la
+ matriz.
+\param[in] yMax Coordenada Y máxima (esquina N) de los puntos almacenados en la
+ matriz.
+\param[in] pasoX Paso de malla (valor absoluto) en la dirección X.
+\param[in] pasoY Paso de malla (valor absoluto) en la dirección Y.
+\param[out] fil Fila del elemento NW del cuadrado que encierra al punto de
+ trabajo.
+\param[out] col Columna del elemento NW del cuadrado que encierra al punto de
+ trabajo.
+\note Esta función no comprueba internamente si las coordenadas del punto de
+ trabajo son congruentes con los límites de la matriz.
+\note Esta función asume que los pasos de malla son congruentes con los límites
+ de la malla (supone que el cálculo del número de nodos es un número
+ entero o del tipo X.9... o X.0...).
+\note Esta función asume que \em xMin < \em xMax y que \em yMin < \em yMax.
+\note Esta función asume que \em pasoX y \em pasoY han sido introducidos en
+ valor absoluto.
+\date 15 de mayo de 2010: Creación de la función.
+\date 25 de septiembre de 2011: Corrección de error que hacía que se calculase
+ una fila de más en determinados casos.
+\todo Esta función no está probada.
+*/
+void BuscaPosNWEnMalla(const double xPto,
+ const double yPto,
+ const double xMin,
+ const double xMax,
+ const double yMin,
+ const double yMax,
+ const double pasoX,
+ const double pasoY,
+ size_t* fil,
+ size_t* col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de mínimo valor en una lista de tipo \p double.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de mínimo valor.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 22 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+double Minimo(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de máximo valor en una lista de tipo \p double.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de máximo valor.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 22 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+double Maximo(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de mínimo valor absoluto en una lista de tipo
+ \p double.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de mínimo valor absoluto.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 22 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+double MinimoAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de máximo valor absoluto en una lista de tipo
+ \p double.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de máximo valor absoluto.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 22 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+double MaximoAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de mínimo valor en una lista de tipo \p size_t.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de mínimo valor.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 24 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+size_t MinimoSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el elemento de máximo valor en una lista de tipo \p size_t.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\return Elemento de máximo valor.
+\note Esta función se puede ejecutar en paralelo con OpenMP, versión 3.1 o
+ superior (se detecta automáticamente en la compilación).
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\date 24 de agosto de 2011: Creación de la función.
+\todo Esta función todavía no está probada con OpenMP.
+*/
+size_t MaximoSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca las posiciones que ocupan en una lista de tipo \p double los
+ elementos de menor y mayor valor.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\param[out] posMin Posición en \em lista del elemento de menor valor.
+\param[out] posMax Posición en \em lista del elemento de mayor valor.
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\note Si hay varios elementos en la lista que se corresponden con el valor menor
+ o mayor, la posición devuelta es la correspondiente al primer elemento a
+ partir del inicio.
+\note Las posiciones devueltas lo son atendiendo al parámetro \em nDatos, por lo
+ que para obtener las posiciones reales del elemento en memoria han de ser
+ multiplicadas por el valor \em incDatos.
+\date 27 de octubre de 2009: Creación de la función.
+\date 29 de mayo de 2011: Adición del argumento de entrada \em incDatos.
+*/
+void MinMax(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca las posiciones que ocupan en una lista los elementos de menor y
+ mayor valor absoluto.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\param[out] posMin Posición en \em lista del elemento de menor valor absoluto.
+\param[out] posMax Posición en \em lista del elemento de mayor valor absoluto.
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\note Si hay varios elementos en la lista que se corresponden con el valor menor
+ o mayor, la posición devuelta es la correspondiente al primer elemento a
+ partir del inicio.
+\note Las posiciones devueltas lo son atendiendo al parámetro \em nDatos, por lo
+ que para obtener las posiciones reales del elemento en memoria han de ser
+ multiplicadas por el valor \em incDatos.
+\date 27 de octubre de 2009: Creación de la función.
+\date 29 de mayo de 2011: Adición del argumento de entrada \em incDatos.
+*/
+void MinMaxAbs(const double* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca las posiciones que ocupan en una lista de tipo \p size_t los
+ elementos de menor y mayor valor.
+\param[in] lista Lista de valores.
+\param[in] nDatos Número de elementos de la lista de valores.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em lista. Este argumento siempre ha de ser un número positivo.
+\param[out] posMin Posición en \em lista del elemento de menor valor.
+\param[out] posMax Posición en \em lista del elemento de mayor valor.
+\note Esta función no comprueba internamente si la longitud de \em lista es
+ congruente con los valores de \em nDatos e \em incDatos.
+\note Esta función supone que \em lista contiene un número de elementos >= 1.
+\note Si hay varios elementos en la lista que se corresponden con el valor menor
+ o mayor, la posición devuelta es la correspondiente al primer elemento a
+ partir del inicio.
+\note Las posiciones devueltas lo son atendiendo al parámetro \em nDatos, por lo
+ que para obtener las posiciones reales del elemento en memoria han de ser
+ multiplicadas por el valor \em incDatos.
+\date 08 de enero de 2010: Creación de la función.
+\date 29 de mayo de 2011: Adición del argumento de entrada \em incDatos.
+*/
+void MinMaxSizeT(const size_t* lista,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* posMin,
+ size_t* posMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Asigna memoria para una matriz bidimensional en estilo C.
+\param[in] fil Número de filas de la matriz.
+\param[in] col Número de columnas de la matriz.
+\return Puntero a la matriz creada. Si ocurre algún error de asignación de
+ memoria, se devuelve NULL.
+\note La memoria asignada no se inicializa a ningún valor.
+\note Los datos se almacenan en ROW MAJOR ORDER de forma contigua en memoria.
+\note Esta función no controla si alguna de las dimensiones pasadas es 0.
+\date 14 de enero de 2010: Creación de la función.
+\date 02 de diciembre de 2010: Reprogramación de la función para que los datos
+ se almacenen en memoria de forma contigua.
+*/
+double** AsigMemMatrizC(const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Libera memoria de una matriz bidimensional en estilo C.
+\param[in] matriz Puntero al espacio de memoria a liberar.
+\date 14 de enero de 2010: Creación de la función.
+\date 27 de febrero de 2010: Corregido bug que hacía que la función diese error
+ si se le pasaba un puntero a NULL.
+*/
+void LibMemMatrizC(double** matriz);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula las posiciones de comienzo de elementos repetidos en un vector.
+
+ - Para un vector de datos [1,2,2,3,4,4] se devuelve el vector de
+ posiciones [0,1,3,4].
+ - Para un vector de datos [1,2,2,3,4] se devuelve el vector de posiciones
+ [0,1,3,4].
+ - Para un vector de datos [1,1,1,1,1] se devuelve el vector de posiciones
+ [0].
+ - Para un vector de datos [1] se devuelve el vector de posiciones [0].
+\param[in] datos Vector de datos.
+\param[in] nDatos Número de elementos de \em datos. No puede ser 0.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em datos. Este argumento siempre ha de ser un número positivo.
+\param[out] nRepe Número de elementos del vector de posiciones de comienzo de
+ elementos repetidos devuelto por la función.
+\return Vector, de \em nRepe elementos, que almacena las posiciones de comienzo
+ de elementos repetidos en el vector \em datos. Las posiciones devueltas
+ no tienen en cuenta el argumento \em incDatos, luego no son posiciones
+ en el array realmente almacenado en memoria. Los índices comienzan en 0.
+ Si ocurre un error de asignación de memoria se devuelve \p NULL.
+\note Esta función no comprueba internamente el vector pasado contiene
+ suficiente memoria.
+\note Esta función no comprueba internamente si las dimensiones del vector
+ pasado son congruentes con el espacio almacenado en memoria.
+\note Esta función no comprueba internamente si el argumento \em nDatos es
+ igual a 0.
+\note Para calcular con los valores de salida las posiciones reales en el vector
+ \em datos es necesario tener en cuenta el argumento \em incDatos.
+\date 02 de febrero de 2011: Creación de la función.
+*/
+size_t* PosRepeEnVector(const double* datos,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* nRepe);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el número de elementos repetidos en un vector a partir de la
+ salida de la función \ref PosRepeEnVector.
+
+ - Para un vector de datos [1,2,2,3,4,4], donde la función
+ \ref PosRepeEnVector devuelve el vector de posiciones [0,1,3,4], esta
+ función devuelve el vector [1,2,1,2].
+ - Para un vector de datos [1,2,2,3,4], donde la función
+ \ref PosRepeEnVector devuelve el vector de posiciones [0,1,3,4], esta
+ función devuelve el vector [1,2,1,1].
+ - Para un vector de datos [1,1,1,1,1], donde la función
+ \ref PosRepeEnVector devuelve el vector de posiciones [0], esta función
+ devuelve el vector [5].
+ - Para un vector de datos [1], donde la función
+ \ref PosRepeEnVector devuelve el vector de posiciones [0], esta función
+ devuelve el vector [1].
+\param[in] pos Vector de posiciones devuelto por la función
+ \ref PosRepeEnVector.
+\param[in] nPos Número de elementos de \em pos. No puede ser 0.
+\param[in] nElemVecOrig Número de elementos del vector de datos original.
+\return Vector, de \em nPos elementos, que almacena el número de elementos
+ repetidos a partir de cada posición (incluida ésta) almacenada en el
+ vector \em pos. Si ocurre un error de asignación de memoria se devuelve
+ \p NULL.
+\note Esta función no comprueba internamente el vector pasado contiene
+ suficiente memoria.
+\note Esta función no comprueba internamente si las dimensiones del vector
+ pasado son congruentes con el espacio almacenado en memoria.
+\note Esta función no comprueba internamente si el argumento \em nPos es igual a
+ 0.
+\date 02 de febrero de 2011: Creación de la función.
+*/
+size_t* NumElemRepeEnVector(const size_t* pos,
+ const size_t nPos,
+ const size_t nElemVecOrig);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica un factor de escala y una traslación (en este orden) a los
+ elementos de un vector.
+\param[in,out] vector Vector de datos. Al término de la ejecución de la función,
+ se ha aplicado un factor de escala y una traslación (en este
+ orden) a los elementos del vector.
+\param[in] nElem Número de elementos de \em vector.
+\param[in] inc Posiciones de separación entre los elementos del vector
+ \em vector. Este argumento siempre ha de ser un número positivo.
+\param[in] escala Factor de escala a aplicar.
+\param[in] traslada Traslación a aplicar.
+\note Primero se aplica el factor de escala y luego la traslación.
+\note Esta función asume que el vector de entrada \em vector tiene memoria
+ asignada.
+\date 18 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void EscalaYTrasladaVector(double* vector,
+ const size_t nElem,
+ const size_t inc,
+ const double escala,
+ const double traslada);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica una traslación y un factor de escala (en este orden) a los
+ elementos de un vector.
+\param[in,out] vector Vector de datos. Al término de la ejecución de la función,
+ se ha aplicado una traslación y un factor de escala (en este
+ orden) a los elementos del vector.
+\param[in] nElem Número de elementos de \em vector.
+\param[in] inc Posiciones de separación entre los elementos del vector
+ \em vector. Este argumento siempre ha de ser un número positivo.
+\param[in] escala Factor de escala a aplicar.
+\param[in] traslada Traslación a aplicar.
+\note Primero se aplica la traslación y luego el factor de escala.
+\note Esta función asume que el vector de entrada \em vector tiene memoria
+ asignada.
+\date 18 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void TrasladaYEscalaVector(double* vector,
+ const size_t nElem,
+ const size_t inc,
+ const double escala,
+ const double traslada);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/general.h b/src/libgeoc/general.h
new file mode 100755
index 0000000..c7d5f0f
--- /dev/null
+++ b/src/libgeoc/general.h
@@ -0,0 +1,61 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup general Módulo GENERAL
+\brief En este módulo se reúnen constantes, macros y funciones de utilidad
+ general.
+@{
+\file general.h
+\brief Inclusión de archivos de cabecera para la utilización de la biblioteca
+ GENERAL.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 16 de febrero de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _GENERAL_H_
+#define _GENERAL_H_
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/compilador.h"
+#include"libgeoc/constantes.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/ventorno.h"
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/geocnan.h b/src/libgeoc/geocnan.h
new file mode 100755
index 0000000..c55c1ef
--- /dev/null
+++ b/src/libgeoc/geocnan.h
@@ -0,0 +1,233 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup geocnan Módulo GEOCNAN
+\ingroup geom matriz gshhs
+\brief En este módulo se reúnen constantes y funciones para el trabajo con
+ valores Not-a-Number.
+@{
+\file geocnan.h
+\brief Declaración de constantes y funciones para el trabajo con valores
+ Not-a-Number.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 26 de mayo de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2010-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _GEOCNAN_H_
+#define _GEOCNAN_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<math.h>
+#include"libgeoc/errores.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_NAN
+\brief Constante \em Not-a-Number (\em NaN). Se define como \em 0.0/0.0.
+\date 21 de diciembre de 2010: Creación de la constante.
+*/
+#define GEOC_NAN (0.0/0.0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_NAN_TXT
+\brief Constante \em Not-a-Number (\em NaN), como cadena de texto.
+\date 22 de septiembre de 2011: Creación de la constante.
+*/
+#define GEOC_NAN_TXT "NaN"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_NAN_LON_FORM_NUM_SIMPLE
+\brief Longitud de una cadena de texto auxiliar para el cálculo de la longitud
+ de una cadena de formato numérico simple.
+\date 22 de septiembre de 2011: Creación de la constante.
+*/
+#define GEOC_NAN_LON_FORM_NUM_SIMPLE 100
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Devuelve el número que representa el valor \em Not-a-Number (\em NaN),
+ que se define como el resultado de la evaluación de la operación
+ \em 0.0/0.0.
+\return Valor NaN.
+\note Esta función devuelve el valor almacenado en la constante #GEOC_NAN.
+\date 21 de diciembre de 2010: Creación de la función.
+\date 24 de mayo de 2011: Ahora la función devuelve el valor absoluto de
+ #GEOC_NAN, calculado con la función <tt>fabs()</tt> de C estándar. Se ha
+ hecho así porque, a veces, al imprimir un valor normal de #GEOC_NAN, éste
+ aparecía con un signo negativo delante.
+\date 22 de septiembre de 2011: Lo del <tt>fabs()</tt> no funciona. Parece que
+ los problemas en la impresión dependen del compilador y los flags de
+ optimización utilizados. No obstante, se mantiene el uso de la función
+ <tt>fabs()</tt> en el código.
+\todo Esta función todavía no está probada.
+*/
+double GeocNan(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un número es \em Not-a-Number (\em NaN).
+\param[in] valor Un número.
+\return Dos posibilidades:
+ - 0: El número pasado no es NaN.
+ - Distinto de 0: El número pasado sí es NaN.
+\note Esta función ha sido adaptada de LAPACK 3.2.1, disnan.f,
+ (http://www.netlib.org/lapack).
+\date 21 de diciembre de 2010: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+int EsGeocNan(const double valor);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca valores #GEOC_NAN es un vector de datos.
+\param[in] datos Vector de trabajo.
+\param[in] nDatos Número de elementos que contiene el vector \em datos.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em datos. Este argumento siempre ha de ser un número positivo.
+\param[out] nNan Número de valores #GEOC_NAN encontrados, que es el número de
+ elementos del vector de salida.
+\return Varias posibilidades:
+ - Si todo ha ido bien, vector que contiene las posiciones en el vector
+ original donde se almacena el valor #GEOC_NAN.
+ - NULL: Pueden haber ocurrido dos cosas:
+ - Si \em nNan vale 0, en los datos de entrada no hay ningún valor
+ #GEOC_NAN.
+ - Si \em nNan es mayor que 0, ha ocurrido un error interno de
+ asignación de memoria.
+\note Esta función no comprueba si el número de elementos del vector \em datos
+ es congruente con los valores pasados en \em nDatos e \em incDatos.
+\note Las posiciones de los elementos #GEOC_NAN encontradas se refieren al
+ número de elementos \em nDatos del vector de trabajo. Para encontrar la
+ posición real en memoria es necesario tener en cuenta la variable
+ \em incDatos.
+\date 26 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t* PosGeocNanEnVector(const double* datos,
+ const size_t nDatos,
+ const size_t incDatos,
+ size_t* nNan);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el número de carácteres que ocupa un valor numérico imprimido con
+ determinado formato.
+\param[in] formato Cadena de formato para imprimir \b *UN \b ÚNICO* valor
+ numérico (de cualquier tipo).
+\return Número de carácteres que ocupa un valor numérico imprimido según el
+ formato pasado.
+\note Esta función no comprueba internamente si la cadena de formato es
+ correcta.
+\note \em formato no puede dar lugar a un texto impreso de más de
+ #GEOC_NAN_LON_FORM_NUM_SIMPLE carácteres.
+\date 22 de septiembre de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+size_t LonFormatoNumSimple(const char formato[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Convierte una cadena de formato para imprimir un \b *ÚNICO* número en una
+ cadena para imprimir texto con el mismo ancho que el que tendría de haber
+ sido imprimida como número.
+\param[in] formatoNum Cadena de formato para imprimir \b *UN \b ÚNICO* valor
+ numérico (de cualquier tipo).
+\param[out] formatoTexto Cadena de texto que almacenará la cadena de formato
+ para la impresión en modo texto.
+\note Esta función no comprueba internamente si la cadena de formato numérico es
+ correcta.
+\note \em formatoNum no puede dar lugar a un texto impreso de más de
+ #GEOC_NAN_LON_FORM_NUM_SIMPLE carácteres.
+\note Esta función asume que \em formatoTexto tiene espacio suficiente para
+ almacenar la cadena de salida.
+\note Si \em formatoNum contiene al final carácteres de retorno de carro y salto
+ de línea, estos no son tenidos en cuenta en la creación de la cadena de
+ salida (no son tenidos en cuenta en el sentido de que no se añaden al
+ formato de salida, pero el espacio que ocupan sí se computa).
+\date 22 de septiembre de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void FormatoNumFormatoTexto(const char formatoNum[],
+ char formatoTexto[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime valores Not-a-Number en modo texto (#GEOC_NAN_TXT) es un fichero.
+\param[in] idFich Identificador del fichero de trabajo, abierto para escribir.
+\param[in] nNan Número de veces que se ha de imprimir el valor #GEOC_NAN_TXT,
+ una a continuación de otra.
+\param[in] formato Cadena de formato para la impresión de cada valor
+ #GEOC_NAN_TXT.
+\param[in] retCarro Identificador para añadir un retorno de carro y cambio de
+ línea al final de la impresión de datos, independientemente del valor
+ pasado en el argumento \em formato. Dos posibilidades:
+ - 0: No se imprime retorno de carro y cambio de línea al final.
+ - Distinto de 0: Sí se imprime retorno de carro y cambio de línea al
+ final.
+\note Esta función no comprueba internamente si el fichero de entrada está
+ abierto correctamente.
+\note Esta función no comprueba internamente si la cadena de formato es
+ correcta.
+\note Si se ha indicado que se imprima salto de línea y retorno de carro al
+ final, este se imprime aunque \em nNan valga 0.
+\date 22 de septiembre de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+void ImprimeGeocNanTexto(FILE* idFich,
+ const size_t nNan,
+ const char formato[],
+ const int retCarro);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/geocomp.h b/src/libgeoc/geocomp.h
new file mode 100644
index 0000000..79768ba
--- /dev/null
+++ b/src/libgeoc/geocomp.h
@@ -0,0 +1,208 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup geocomp Módulo GEOC-OMP
+\ingroup anespec general geodesia geom geopot gravim mmcc
+\brief En este módulo se reúnen constantes y funciones para la obtención de
+ información de la implementación de OpenMP usada.
+@{
+\file geocomp.h
+\brief Declaración de macros y funciones para la obtención de información de la
+ implementación de OpenMP usada.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 25 de agosto de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _GEOCOMP_H_
+#define _GEOCOMP_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<string.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_1_0
+\brief Valor (fecha YYYYMM) de la macro \p _OPENMP para la versión 1.0 de
+ OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_1_0 (199810)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_2_0
+\brief Valor (fecha YYYYMM) de la macro \p _OPENMP para la versión 2.0 de
+ OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_2_0 (200203)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_2_5
+\brief Valor (fecha YYYYMM) de la macro \p _OPENMP para la versión 2.5 de
+ OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_2_5 (200505)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_3_0
+\brief Valor (fecha YYYYMM) de la macro \p _OPENMP para la versión 3.0 de
+ OpenMP.
+\date 22 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_3_0 (200805)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_3_1
+\brief Valor (fecha YYYYMM) de la macro \p _OPENMP para la versión 3.1 de
+ OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_3_1 (201107)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_1_0
+\brief Cadena de texto identificadora de la versión 1.0 de OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_1_0 "1.0"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_2_0
+\brief Cadena de texto identificadora de la versión 2.0 de OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_2_0 "2.0"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_2_5
+\brief Cadena de texto identificadora de la versión 2.5 de OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_2_5 "2.5"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_3_0
+\brief Cadena de texto identificadora de la versión 3.0 de OpenMP.
+\date 22 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_3_0 "3.0"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_3_1
+\brief Cadena de texto identificadora de la versión 3.1 de OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_3_1 "3.1"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_F_DESC
+\brief Fecha de versión de OpenMP desconocida.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_F_DESC (0)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_V_DESC
+\brief Versión de OpenMP correspondiente a un valor desconocido de la macro
+ \p _OPENMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_V_DESC "0.0"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_OMP_LON_CAD_VERS
+\brief Longitud de la cadena de texto que almacena la versión de OpenMP.
+\date 25 de agosto de 2011: Creación de la constante.
+*/
+#define GEOC_OMP_LON_CAD_VERS (10)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la versión de OpenMP a partir del valor de la macro \p _OPENMP.
+\param[in] macro_OPENMP Valor de la macro \p _OPENMP.
+\param[out] version Versión de OpenMP correspondiente al valor de la macro. Si
+ el argumento \em macro_OPENMP almacena un valor desconocido, se
+ devuelve #GEOC_OMP_V_DESC.
+\note Esta función asume que \em version tiene asignada suficiente memoria: como
+ mínimo, espacio para una cadena de #GEOC_OMP_LON_CAD_VERS carácteres.
+\date 25 de agosto de 2011: Creación de la función.
+*/
+void VersionOpenMP(const int macro_OPENMP,
+ char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la fecha (el valor de la macro \p _OPENMP) de una versión de
+ OpenMP dada.
+\param[in] version Cadena de versión de OpenMP, tal como es calculada por la
+ función \ref VersionOpenMP.
+\return Fecha, en el formato YYYYMM, correspondiente a la versión. Este valor
+ debería coincidir con la macro \p _OPENMP de la implementación de OpenMP
+ usada.
+\note En caso de pasar una cadena de versión errónea o desconocida, la función
+ devuelve #GEOC_OMP_F_DESC.
+\date 25 de agosto de 2011: Creación de la función.
+*/
+int FechaVersionOpenMP(const char version[]);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/geom.h b/src/libgeoc/geom.h
new file mode 100755
index 0000000..134cb7b
--- /dev/null
+++ b/src/libgeoc/geom.h
@@ -0,0 +1,64 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup geom Módulo GEOMETRIA
+\brief En este módulo se reúnen las funciones necesarias para el tratamiento de
+ problemas de geometría.
+@{
+\file geom.h
+\brief Inclusión de ficheros de cabecera para el trabajo con la biblioteca
+ GEOMETRIA.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 26 de diciembre de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _GEOM_H_
+#define _GEOM_H_
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/dpeucker.h"
+#include"libgeoc/eucli.h"
+#include"libgeoc/greiner.h"
+#include"libgeoc/polig.h"
+#include"libgeoc/polil.h"
+#include"libgeoc/ptopol.h"
+#include"libgeoc/recpolil.h"
+#include"libgeoc/segmento.h"
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/greiner.h b/src/libgeoc/greiner.h
new file mode 100755
index 0000000..37fe416
--- /dev/null
+++ b/src/libgeoc/greiner.h
@@ -0,0 +1,827 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file greiner.h
+\brief Definición de estructuras y declaración de funciones para el recorte de
+ polígonos mediante el algoritmo de Greiner-Hormann
+ (http://davis.wpi.edu/~matt/courses/clipping/).
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 14 de mayo de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _GREINER_H_
+#define _GREINER_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<math.h>
+#include<float.h>
+#include<time.h>
+#include"libgeoc/errores.h"
+#include"libgeoc/eucli.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/polig.h"
+#include"libgeoc/ptopol.h"
+#include"libgeoc/segmento.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_GREINER_FAC_EPS_PERTURB
+\brief Factor de escala para el cálculo de la cantidad mínima de perturbación
+ para un valor. Esta variable se usa en la función \ref CantPerturbMin.
+
+ A base de hacer pruebas he visto que es desaconsejable un valor por
+ debajo de 10.0.
+\date 22 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_GREINER_FAC_EPS_PERTURB 10.0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_GREINER_BUFFER_PTOS
+\brief Número de puntos para ir asignando memoria en bloques para los polígonos
+ de salida en la funcion \ref Paso3Greiner. Ha de ser un número mayor o
+ igual a 2.
+\date 23 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_GREINER_BUFFER_PTOS 100
+/******************************************************************************/
+/******************************************************************************/
+/** \enum GEOC_OP_BOOL_POLIG
+\brief Operación booleana entre polígonos.
+\date 21 de mayo de 2011: Creación del tipo.
+*/
+enum GEOC_OP_BOOL_POLIG
+{
+ /** \brief Intersección entre polígonos. */
+ GeocOpBoolInter=111,
+ /** \brief Unión de polígonos. */
+ GeocOpBoolUnion=112,
+ /** \brief Unión exclusiva de polígonos. */
+ GeocOpBoolXor=113,
+ /** \brief Operación A-B. */
+ GeocOpBoolAB=114,
+ /** \brief Operación B-A. */
+ GeocOpBoolBA=115
+};
+/******************************************************************************/
+/******************************************************************************/
+/** \struct _vertPoliClip
+\brief Estructura de definición de un vértice de un polígono usado en
+ operaciones de recorte. El polígono se almacena en memoria como una lista
+ doblemente enlazada de vértices.
+\date 14 de mayo de 2011: Creación de la estructura.
+*/
+typedef struct _vertPoliClip
+{
+ /** \brief Coordenada X del vértice. */
+ double x;
+ /** \brief Coordenada Y del vértice. */
+ double y;
+ /** \brief Coordenada X perturbada del vértice. */
+ double xP;
+ /** \brief Coordenada Y perturbada del vértice. */
+ double yP;
+ /** \brief Vértice anterior. */
+ struct _vertPoliClip* anterior;
+ /** \brief Vértice siguiente. */
+ struct _vertPoliClip* siguiente;
+ /**
+ \brief Enlace al mismo nodo, perteneciente a otro polígono.
+
+ Los puntos de intersección pertenecen tanto al polígono de recorte
+ como al recortado.
+ */
+ struct _vertPoliClip* vecino;
+ /**
+ \brief Indicador de primer punto de polígono.
+
+ Dos posibilidades:
+ - 0: No es el primer punto del polígono.
+ - Distinto de 0: Sí es el primer punto del polígono.
+ */
+ char ini;
+ /**
+ \brief Indicador de punto de intersección.
+
+ Dos posibilidades:
+ - 0: No es un punto de intersección.
+ - Distinto de 0: Sí es un punto de intersección.
+ */
+ char interseccion;
+ /**
+ \brief Indicador de punto de entrada al interior del otro polígono.
+
+ Dos posibilidades:
+ - 0: No es un punto de entrada, es de salida.
+ - Distinto de 0: Sí es un punto de entrada.
+ */
+ char entrada;
+ /**
+ \brief Indicador de punto visitado.
+
+ Dos posibilidades:
+ - 0: No ha sido visitado.
+ - Distinto de 0: Sí ha sido visitado.
+ */
+ char visitado;
+ /** \brief Distancia, en tanto por uno, de un nodo de intersección con
+ respecto al primer vértice del segmento que lo contiene. */
+ double alfa;
+}vertPoliClip;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea un vértice de tipo \ref _vertPoliClip y lo inserta entre otros dos.
+\param[in] x Coordenada X del vértice.
+\param[in] y Coordenada Y del vértice.
+\param[in] anterior Vértice anterior (puede ser \p NULL).
+\param[in] siguiente Vértice siguiente (puede ser \p NULL).
+\param[in] vecino Campo _vertPoliClip::vecino (puede ser \p NULL).
+\param[in] ini Campo _vertPoliClip::ini.
+\param[in] interseccion Campo _vertPoliClip::interseccion.
+\param[in] entrada Campo _vertPoliClip::entrada.
+\param[in] visitado Campo _vertPoliClip::visitado.
+\param[in] alfa Campo _vertPoliClip::alfa.
+\return Puntero al nuevo vértice creado. Si se devuelve \p NULL, ha ocurrido un
+ error de asignación de memoria.
+\date 18 de mayo de 2011: Creación de la función.
+\date 21 de mayo de 2011: Eliminación del algumento \em siguientePoli y adición
+ del argumento \em ini.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* CreaVertPoliClip(const double x,
+ const double y,
+ vertPoliClip* anterior,
+ vertPoliClip* siguiente,
+ vertPoliClip* vecino,
+ const char ini,
+ const char interseccion,
+ const char entrada,
+ const char visitado,
+ const double alfa);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea un polígono, como una lista doblemente enlazada de elementos
+ \ref _vertPoliClip.
+\param[in] x Vector de coordenadas X de los nodos del polígono.
+\param[in] y Vector de coordenadas Y de los nodos del polígono.
+\param[in] nCoor Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\return Puntero al primer vértice de la lista. Si se devuelve \p NULL, ha
+ ocurrido un error de asignación de memoria.
+\note Esta función asume que el argumento \em nCoor es mayor que 0.
+\note En la lista de salida que representa al polígono, el primer vértice
+ siempre se repite al final. Si en los vectores \em x e \em y el último
+ elemento no es igual que el primero, igualmente se crea en la lista de
+ salida.
+\note Si en los vectores de coordenadas \em x e \em y hay valores #GEOC_NAN,
+ éstos no se tienen en cuenta a la hora de la creación de la estructura de
+ salida.
+\note Que los vectores de coordenadas \em x e \em y admitan vértices con
+ coordenadas (#GEOC_NAN,#GEOC_NAN) no quiere decir que éstos sean
+ separadores de múltiples polígonos. \em x e \em y \b *SÓLO* deben
+ almacenar un único polígono.
+\date 18 de mayo de 2011: Creación de la función.
+\date 24 de mayo de 2011: Adición del soporte de coordenadas
+ (#GEOC_NAN,#GEOC_NAN) en los vectores de entrada.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* CreaPoliClip(const double* x,
+ const double* y,
+ const size_t nCoor,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Libera la memoria asignada a un polígono almacenado como una lista
+ doblemente enlazada de elementos \ref _vertPoliClip.
+\param[in] poli Puntero al primer elemento del polígono.
+\note Esta función no comprueba si hay vértices del polígono anteriores al
+ vértice de entrada, por lo que si se quiere liberar toda la memoria
+ asignada a un polígono, el vértice pasado ha de ser el primero de la
+ lista.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 18 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void LibMemPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina los vértices no originales de un polígono almacenado como una
+ lista doblemente enlazada de elementos \ref _vertPoliClip.
+\param[in] poli Puntero al primer elemento del polígono.
+\return Puntero al primer elemento del polígono original. Si se devuelve
+ \p NULL, ninguno de los vértices pertenecía al polígono original.
+\note Esta función asume que el primero y el último vértices originales del
+ polígono pasado tienen las mismas coordenadas.
+\note Los vértices eliminados por esta función son todos aquéllos cuyo campo
+ _vertPoliClip::interseccion sea distinto de 0.
+\note Aunque se supone que el primer vértice de un polígono siempre es un
+ vértice original, si no lo es, la variable de entrada queda modificada.
+ Por tanto, siempre es recomendable capturar la variable de salida, que
+ garantiza la posición del primer elemento.
+\note Las coordenadas de todos los vértices originales vuelven a ser la de
+ inicio, es decir, los campos _vertPoliClip::xP e _vertPoliClip::yP se
+ sobreescriben con los valores almacenados en _vertPoliClip::x e
+ _vertPoliClip::y.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 18 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* ReiniciaPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Reinicia los vértices de un polígono almacenado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip para poder volver a calcular
+ otra operación booleana sin tener que recalcular las intersecciones.
+
+ Esta función devuelve todos los campos _vertPoliClip::visitado a 0 y los
+ campos _vertPoliClip::entrada a 0.
+\param[in] poli Puntero al primer elemento del polígono.
+\return Puntero al primer elemento del polígono original. Si se devuelve
+ \p NULL, quiere decir qie el argumento de entrada valía \p NULL.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 30 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* ReiniciaVerticesPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el siguiente vértice original en un polígono.
+\param[in] vert Puntero al vértice a partir del cual se ha de buscar.
+\return Puntero al siguiente vértice original en el polígono. Si se devuelve
+ \p NULL, se ha llegado al final.
+\note Esta función asume que el primero y el último vértices originales del
+ polígono pasado tienen las mismas coordenadas.
+\note Los vértices no originales son todos aquéllos cuyo campo
+ _vertPoliClip::interseccion es distinto de 0.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* SiguienteVertOrigPoliClip(vertPoliClip* vert);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el siguiente vértice que sea una intersección no visitada en un
+ polígono.
+\param[in] vert Puntero al vértice a partir del cual se ha de buscar.
+\return Puntero al siguiente vértice que sea una intersección no visitada en el
+ polígono. Si se devuelve \p NULL, se ha llegado al final.
+\note Esta función asume que el primero y el último vértices originales del
+ polígono pasado tienen las mismas coordenadas.
+\note Los vértices intersección no visitados son todos aquéllos cuyo campo
+ _vertPoliClip::visitado es 0.
+\note Esta función asume que el vértice inicial del polígono, aquél cuyo campo
+ _vertPoliClip::ini vale 1, es un vértice original.
+\note Esta función puede trabajar con listas circulares y no circulares.
+\date 21 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* SiguienteIntersecNoVisitadaPoliClip(vertPoliClip* vert);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el último vértice de un polígono almacenado como una lista
+ doblemente enlazada de vértives \ref _vertPoliClip.
+\param[in] poli Puntero al primer elemento del polígono.
+\return Puntero al último vértice del polígono, que es aquél cuyo campo
+ _vertPoliClip::siguiente apunta a \p NULL. Si se devuelve \p NULL,
+ significa que el argumento pasado en \em poli vale \p NULL.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 21 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* UltimoVertPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Inserta un vértice de tipo \ref _vertPoliClip entre otros dos, atendiendo
+ al campo _vertPoliClip::alfa.
+\param[in] ins Vértice a insertar.
+\param[in] extremoIni Extremo inicial del segmento donde se insertará \em ins.
+\param[in] extremoFin Extremo final del segmento donde se insertará \em ins.
+\note Esta función asume que todos los elementos pasados tienen memoria
+ asignada.
+\note Si entre \em extremoIni y \em extremoFin hay más vértices, \em ins se
+ insertará de tal modo que los campos _vertPoliClip::alfa queden ordenados
+ de menor a mayor.
+\note Si el campo _vertPoliClip::alfa de \em ins tiene el mismo valor que el
+ de \em extremoIni, \em ins se insertará justo a continuación de
+ \em extremoIni.
+\note Si el campo _vertPoliClip::alfa de \em ins tiene el mismo valor que el
+ de \em extremoFin, \em ins se insertará justo antes de \em extremoIni.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void InsertaVertPoliClip(vertPoliClip* ins,
+ vertPoliClip* extremoIni,
+ vertPoliClip* extremoFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Convierte una lista doblemente enlazada de elementos \ref _vertPoliClip
+ en una lista doblemente enlazada circular.
+\param[in,out] poli Vértice inicial del polígono, almacenado como lista
+ doblemente enlazada, pero no cerrada. Al término de la ejecución
+ de la función la lista se ha cerrado, por medio de un enlace del
+ penúltimo elemento (el último es el primero repetido) con el
+ primero.
+\return Puntero al último elemento del polígono original que, al ser el primer
+ elemento repetido, queda almacenado en memoria pero no neferenciado por
+ el polígono. Si el valor devuelto es \p NULL quiere decir que el
+ argumento de entrada era \p NULL.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 21 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPoliClip* CierraPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Convierte una lista doblemente enlazada circular de elementos
+ \ref _vertPoliClip en una lista doblemente enlazada simple.
+\param[in,out] poli Vértice inicial del polígono, almacenado como lista
+ doblemente enlazada circular. Al término de la ejecución de la
+ función la lista ha recuperado su condición de doblemente
+ enlazada sin cerrar.
+\param[in] ultimo Puntero al último elemento de la lista doblemente enlazada
+ original. Este argumento ha de ser el valor devuelto por la
+ función \ref CierraPoliClip.
+\note Esta función asume que los elementos pasados tienen memoria asignada.
+\note Esta función sólo trabaja con listas circulares.
+\date 21 de mayo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void AbrePoliClip(vertPoliClip* poli,
+ vertPoliClip* ultimo);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un polígono de un número
+ arbitrario de lados. Esta función puede no dar resultados correctos para
+ puntos en los bordes y/o los vértices del polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] poli Polígono, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPoliClip. Sólo se tienen en cuenta los vértices
+ originales del polígono, que son todos aquéllos cuyo campo
+ _vertPoliClip::interseccion es distinto de 0.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+\note El código de esta función ha sido adaptado de la función
+ \ref PtoEnPoligono.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función no detecta el caso de que el punto de trabajo esté en el
+ borde o en un vértice del polígono. En este caso, el test puede dar el
+ punto dentro o fuera, indistintamente (el chequeo del mismo punto con el
+ mismo polígono siempre dará el mismo resultado).
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoliClip(const double x,
+ const double y,
+ vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un polígono de un número
+ arbitrario de lados. Esta función puede no dar resultados correctos para
+ puntos en los bordes del polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] poli Polígono, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPoliClip. Sólo se tienen en cuenta los vértices
+ originales del polígono, que son todos aquéllos cuyo campo
+ _vertPoliClip::interseccion es distinto de 0.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice del polígono.
+\note El código de esta función ha sido adaptado de la función
+ \ref PtoEnPoligonoVertice.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función utiliza en uno de sus pasos la función \ref PtoEnPoliClip y
+ se comporta igual que ella en el caso de puntos en el borde.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoliClipVertice(const double x,
+ const double y,
+ vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Cuenta el número de vértices originales que hay en un polígono almacenado
+ como una lista doblemente enlazada de elementos \ref _vertPoliClip.
+\param[in] poli Polígono, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPoliClip. Sólo se tienen en cuenta los vértices
+ originales del polígono, que son todos aquéllos cuyo campo
+ _vertPoliClip::interseccion es distinto de 0.
+\return Número de vértices originales almacenados. El último vértice, que es
+ igual al primero, también se cuenta.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t NumeroVertOrigPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Cuenta el número total de vértices que hay en un polígono almacenado como
+ una lista doblemente enlazada de elementos \ref _vertPoliClip.
+\param[in] poli Polígono, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPoliClip. Se tienen en cuenta todos los vértices.
+\return Número total de vértices almacenados. El último vértice, que debe ser
+ igual al primero, también se cuenta.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función \b *NO* trabaja con listas circulares.
+\date 19 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t NumeroVertPoliClip(vertPoliClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la cantidad mínima a añadir a un número para que el valor de la
+ suma sea distinto del número original.
+\param[in] x Número a perturbar.
+\param[in] factor Factor para ir multiplicando el valor a añadir a \em x
+ mientras no sea suficiente para producir una perturbación detectable.
+ Un buen valor para este argumento es #GEOC_GREINER_FAC_EPS_PERTURB.
+\return Cantidad mínima a añadir a \em x para que el valor de la suma sea
+ distinto de \em x.
+\note Esta función no comprueba internamente si \em factor es menor o igual que
+ 1, lo que daría lugar a que la función entrase en un bucle infinito.
+\note Como valor inicial de la cantidad a añadir se toma el producto de
+ \em factor por la constante \p DBL_EPSILON, perteneciente al fichero
+ \p float.h de C estándar.
+\date 22 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+double CantPerturbMin(const double x,
+ const double factor);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Modifica un número la cantidad mínima para que sea distinto del número
+ original.
+\param[in] x Número a perturbar.
+\param[in] factor Factor para el cálculo de la cantidad perturbadora mínima. Ver
+ la documentación de la función \ref CantPerturbMin para obtener más
+ detalles. Un buen valor para este argumento es
+ #GEOC_GREINER_FAC_EPS_PERTURB.
+\return Número perturbado.
+\note La perturbación de \em x se realiza de la siguiente manera:
+ - Se calcula la cantidad mínima perturbadora \p perturb con la función
+ \ref CantPerturbMin.
+ - Se calcula un número seudoaleatorio con la función de C estándar
+ <tt>rand()</tt> (el generador de números seudoaleatorios se inicializa
+ con la orden <tt>srand((unsigned int)time(NULL));</tt>).
+ - Se comprueba la paridad del número seudoaleatorio generado para obtener
+ la variable \p signo, de tal forma que:
+ - Si el número seudoaleatorio es par: \p signo vale 1.0.
+ - Si el número seudoaleatorio es impar: \p signo vale -1.0.
+ - Se perturba \em x como <tt>xPerturb=x+signo*perturb</tt>.
+\date 22 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+double PerturbaPuntoMin(const double x,
+ const double factor);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza el paso número 1 del algoritmo de Greiner-Hormann, que consiste
+ en el cálculo de los puntos de intersección entre los dos polígonos de
+ trabajo.
+\param[in,out] poliBas Polígono base, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip. Al término de la
+ ejecución de la función se le han añadido los puntos de
+ intersección.
+\param[in,out] poliRec Polígono de recorte, representado como una lista
+ doblemente enlazada de elementos \ref _vertPoliClip. Al término
+ de la ejecución de la función se le han añadido los puntos de
+ intersección.
+\param[in] facPer Factor para el posible cálculo de la perturbación de las
+ coordenadas de algunos vértices. Este valor es usado internamente por
+ la función \ref PerturbaPuntoMin (ver su documentación). Un buen
+ valor para este argumento es #GEOC_GREINER_FAC_EPS_PERTURB.
+\param[out] nIntersec Número de intersecciones calculadas.
+\param[out] nPerturb Número de puntos perturbados en el proceso.
+\return Variable de estado. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si las variables \em poliBas y \em poliRec son
+ polígonos correctamente almacenados.
+\note En el caso de tener que perturbar algún vértice, sólo se modifican los de
+ \em poliRec, dejando las coordenadas del polígono base inalteradas.
+\date 22 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int Paso1Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza el paso número 2 del algoritmo de Greiner-Hormann, que consiste
+ en la asignación de los puntos de intersección como entrada o salida.
+\param[in,out] poliBas Polígono base, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip. Al término de la
+ ejecución de la función los puntos de intersección han sido
+ marcados como entrada o salida.
+\param[in,out] poliRec Polígono de recorte, representado como una lista
+ doblemente enlazada de elementos \ref _vertPoliClip. Al término
+ de la ejecución de la función los puntos de intersección han sido
+ marcados como entrada o salida.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIG, excepto la unión exclusiva
+ \p xor. En el caso de indicar la operación de unión exclusiva \p xor,
+ se realiza una intersección y \b *NO* se avisa del argumento
+ incorrecto.
+\note Esta función no comprueba si las variables \em poliBas y \em poliRec son
+ polígonos correctamente almacenados.
+\date 22 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+void Paso2Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza el paso número 3 del algoritmo de Greiner-Hormann, que consiste
+ en la generación de los polígonos resultado.
+\param[in,out] poliBas Polígono base, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip, tal y como sale de la
+ función \ref Paso2Greiner. Al término de la ejecución de la
+ función los puntos visitados han sido marcados en el campo
+ _vertPoliClip::visitado.
+\param[in,out] poliRec Polígono de recorte, representado como una lista
+ doblemente enlazada de elementos \ref _vertPoliClip, tal y como
+ sale de la función \ref Paso2Greiner. Al término de la ejecución
+ de la función los puntos visitados han sido marcados en el campo
+ _vertPoliClip::visitado.
+\return Estructura \ref polig con los polígonos resultado de la operación. Si se
+ devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si las variables \em poliBas y \em poliRec son
+ polígonos correctamente almacenados.
+\date 22 de mayo de 2011: Creación de la función.
+\date 29 de mayo de 2011: Cambio de la variable de salida por la estructura
+ \ref polig.
+\todo Esta función no está probada.
+*/
+polig* Paso3Greiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza una operación booleana entre dos polígonos mediante el algoritmo
+ de Greiner-Hormann.
+\param[in,out] poliBas Polígono base, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip. Al término de la
+ ejecución de la función se han añadido los puntos de intersección
+ con \em poliRec.
+\param[in,out] poliRec Polígono de recorte, representado como una lista
+ doblemente enlazada de elementos \ref _vertPoliClip. Al término
+ de la ejecución de la función se han añadido los puntos de
+ intersección con \em poliRec.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIG. Varias posibilidades:
+ - #GeocOpBoolInter: Realiza la intersección entre \em poliBas y
+ \em poliRec.
+ - #GeocOpBoolUnion: Realiza la unión entre \em poliBas y \em poliRec.
+ - #GeocOpBoolXor: Realiza la unión exclusiva entre \em poliBas y
+ \em poliRec.
+ - #GeocOpBoolAB: Realiza la sustracción \em poliBas-poliRec.
+ - #GeocOpBoolBA: Realiza la sustracción \em poliRec-poliBas.
+\param[in] facPer Factor para el posible cálculo de la perturbación de las
+ coordenadas de algunos vértices. Este valor es usado internamente por
+ la función \ref Paso1Greiner (ver su documentación). Un buen valor
+ para este argumento es #GEOC_GREINER_FAC_EPS_PERTURB.
+\param[out] nIntersec Número de intersecciones calculadas.
+\param[out] nPerturb Número de puntos perturbados en el proceso.
+\return Estructura \ref polig con los polígonos resultado de la operación. Si se
+ devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si las variables \em poliBas y \em poliRec son
+ polígonos correctamente almacenados.
+\note Esta función no comprueba internamente si \em op pertenece al tipo
+ enumerado #GEOC_OP_BOOL_POLIG. Si se introduce un valor no perteneciente
+ al tipo, se realiza la operación #GeocOpBoolInter.
+\note En el caso de tener que perturbar algún vértice, sólo se modifican los de
+ \em poliRec, dejando las coordenadas de \em poliBase inalteradas.
+\note Si \em facPer es menor o igual que 1, se sustituye internamente su valor
+ por #GEOC_GREINER_FAC_EPS_PERTURB (ver documentación de la función
+ \ref CantPerturbMin).
+\note Esta función realiza la unión exclusiva #GeocOpBoolXor mediante la unión
+ de las operaciones individuales #GeocOpBoolAB y #GeocOpBoolBA. Esta última
+ unión simplemente es el almacenamiento en la estructura de salida de los
+ resultados de #GeocOpBoolAB y #GeocOpBoolBA. En ningún momento se realiza
+ la operación booleana #GeocOpBoolUnion entre los resultados de
+ #GeocOpBoolAB y #GeocOpBoolBA.
+\date 22 de mayo de 2011: Creación de la función.
+\date 29 de mayo de 2011: Cambio de la variable de salida por la estructura
+ \ref polig.
+\date 30 de mayo de 2011: Adición de la capacidad de calcular la operación unión
+ exclusiva \p xor.
+\todo Esta función no está probada.
+*/
+polig* PoliBoolGreiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza una operación booleana entre múltiples polígonos mediante el
+ algoritmo de Greiner-Hormann.
+\param[in] poliBas Estructura \ref polig que almacena los polígonos base.
+\param[in] poliRec Estructura \ref polig que almacena los polígonos de recorte.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIG. Varias posibilidades:
+ - #GeocOpBoolInter: Realiza la intersección entre los polígonos
+ almacenados en \em poliBas y los almacenados en \em poliRec.
+ - #GeocOpBoolUnion: Realiza la unión entre los polígonos almacenados
+ en \em poliBas y los almacenados en \em poliRec.
+ - #GeocOpBoolXor: Realiza la unión exclusiva entre los polígonoa
+ almacenados en \em poliBas y los almacenados en \em poliRec.
+ - #GeocOpBoolAB: Realiza la sustracción entre todos los polígonos
+ \em poliBas-poliRec.
+ - #GeocOpBoolBA: Realiza la sustracción entre todos los polígonos
+ \em poliRec-poliBas.
+\param[in] facPer Factor para el posible cálculo de la perturbación de las
+ coordenadas de algunos vértices. Este valor es usado internamente por
+ la función \ref Paso1Greiner (ver su documentación). Un buen valor
+ para este argumento es #GEOC_GREINER_FAC_EPS_PERTURB.
+\param[out] nIntersec Número total de intersecciones calculadas entre todas los
+ polígonos.
+\param[out] nPerturb Número total de puntos perturbados en el proceso.
+\return Estructura \ref polig con los polígonos resultado de las operaciones. Si
+ se devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función realiza la operación \em op con todas las combinaciones
+ posibles de polígonos. Es decir, se recorren todos los polígonos
+ almacenados en \em poliBas y con cada uno de ellos se realiza la operación
+ \em op con cada polígono almacenado en \em poliRec.
+\note Esta función no comprueba si las variables \em poliBas y \em poliRec son
+ polígonos correctamente almacenados.
+\note Esta función no comprueba internamente si \em op pertenece al tipo
+ enumerado #GEOC_OP_BOOL_POLIG. Si se introduce un valor no perteneciente
+ al tipo, se realiza la operación #GeocOpBoolInter.
+\note En el caso de tener que perturbar algún vértice, sólo se modifican los
+ correspondientes a \em poliRec, dejando las coordenadas de los polígonos
+ de \em poliBase inalteradas.
+\note Si \em facPer es menor o igual que 1, se sustituye internamente su valor
+ por #GEOC_GREINER_FAC_EPS_PERTURB (ver documentación de la función
+ \ref CantPerturbMin).
+\note Esta función realiza la unión exclusiva #GeocOpBoolXor mediante la unión
+ de las operaciones individuales #GeocOpBoolAB y #GeocOpBoolBA. Esta última
+ unión simplemente es el almacenamiento en la estructura de salida de los
+ resultados de #GeocOpBoolAB y #GeocOpBoolBA. En ningún momento se realiza
+ la operación booleana #GeocOpBoolUnion entre los resultados de
+ #GeocOpBoolAB y #GeocOpBoolBA.
+\date 07 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polig* PoliBoolGreinerMult(const polig* poliBas,
+ const polig* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op,
+ const double facPer,
+ size_t* nIntersec,
+ size_t* nPerturb);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polig a partir de todos los vértices de un
+ polígono almacenado como una lista doblemente enlazada de elementos
+ \ref _vertPoliClip.
+\param[in] poli Polígono de trabajo, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip. El puntero pasado ha
+ de apuntar al primer elemento del polígono (no se controla
+ internamente).
+\param[in] coorOrig Identificador para copiar las coordenadas originales o
+ perturbadas. Dos posibilidades:
+ - 0: Se copiarán las coordenadas perturbadas _vertPoliClip::xP e
+ _vertPoliClip::yP.
+ - Distinto de 0: Se copiarán las coordenadas originales
+ _vertPoliClip::x e _vertPoliClip::y.
+\return Estructura \ref polig que representa el polígono. Si se devuelve \p NULL
+ ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función \b *NO* trabaja con listas circulares.
+\note Esta función realiza una copia en memoria de las coordenadas de los
+ vértices de la estructura \em poli a la estructura de salida.
+\date 29 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polig* CreaPoligPoliClip(vertPoliClip* poli,
+ const int coorOrig);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Añade los vértices de un polígono almacenado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip a una estructura \ref polig
+ previamente creada.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se han añadido los
+ polígonos de la estructura \em anyade.
+\param[in] anyade Polígono a añadir, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip. El puntero pasado ha
+ de apuntar al primer elemento del polígono (no se controla
+ internamente).
+\param[in] coorOrig Identificador para copiar las coordenadas originales o
+ perturbadas. Dos posibilidades:
+ - 0: Se copiarán las coordenadas perturbadas _vertPoliClip::xP e
+ _vertPoliClip::yP.
+ - Distinto de 0: Se copiarán las coordenadas originales
+ _vertPoliClip::x e _vertPoliClip::y.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si la variable \em poli es un polígono
+ correctamente almacenado.
+\note Esta función no comprueba si la variable \em anyade es un polígono
+ correctamente almacenado.
+\note Esta función \b *NO* trabaja con listas circulares.
+\note Esta función realiza una copia en memoria de las coordenadas de los
+ vértices de la estructura \em poli a la estructura de salida.
+\note Esta función crea internamente una estructura \ref polig para luego
+ añadirla a \em poli con la función \ref AnyadePoligPolig.
+\date 29 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int AnyadePoligClipPolig(polig* poli,
+ vertPoliClip* anyade,
+ const int coorOrig);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/polig.h b/src/libgeoc/polig.h
new file mode 100755
index 0000000..0588800
--- /dev/null
+++ b/src/libgeoc/polig.h
@@ -0,0 +1,1101 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file polig.h
+\brief Definición de estructuras y declaración de funciones para el trabajo con
+ polígonos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 20 de abril de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _POLIG_H_
+#define _POLIG_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdio.h>
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/dpeucker.h"
+#include"libgeoc/errores.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** \struct polig
+\brief Estructura contenedora de los vértices que definen el contorno de uno o
+ varios polígono.
+\date 20 de abril de 2011: Creación de la estructura.
+\date 26 de mayo de 2011: Reorganización total de la estructura.
+\date 28 de mayo de 2011: Adición de los campos polig::hayArea, polig::area,
+ polig::hayLim, polig::xMin, polig::xMax, polig::yMin e polig::yMax.
+*/
+typedef struct
+{
+ /** \brief Número de elementos de los vectores de coordenadas. */
+ size_t nElem;
+ /**
+ \brief Vector de polig::nElem elementos, que almacena las coordenadas X de
+ los vértices del polígono (o los polígonos), así como los separadores
+ entre polígonos. La primera coordenada de cada polígono se repite al
+ final.
+ */
+ double* x;
+ /**
+ \brief Vector de polig::nElem elementos, que almacena las coordenadas Y de
+ los vértices del polígono (o los polígonos), así como los separadores
+ entre polígonos. La primera coordenada de cada polígono se repite al
+ final.
+ */
+ double* y;
+ /** \brief Número de polígonos almacenados. */
+ size_t nPolig;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena las posiciones en los
+ vectores \em x e \em y de inicio de cada polígono almacenado.
+ */
+ size_t* posIni;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena el número de vértices
+ de cada polígono almacenado. El último vértice de cada polígono, que
+ es el primero repetido, también entra en la cuenta.
+ */
+ size_t* nVert;
+ /**
+ \brief Identificador de si la estructura contiene información acerca de los
+ límites del rectángulo que encierra a cada polígono almacenado.
+
+ Dos posibilidades:
+ - 0: La estructura no contiene información de los límites.
+ - Distinto de 0: La estructura sí contiene información de los
+ límites.
+ */
+ int hayLim;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena la coordenada X
+ mínima de cada polígono almacenado. Este campo sólo contiene
+ información si el campo polig::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* xMin;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena la coordenada X
+ máxima de cada polígono almacenado. Este campo sólo contiene
+ información si el campo polig::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* xMax;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena la coordenada Y
+ mínima de cada polígono almacenado. Este campo sólo contiene
+ información si el campo polig::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* yMin;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena la coordenada Y
+ máxima de cada polígono almacenado. Este campo sólo contiene
+ información si el campo polig::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* yMax;
+ /**
+ \brief Identificador de si la estructura contiene información acerca de la
+ superficie de los polígonos almacenados.
+
+ Dos posibilidades:
+ - 0: La estructura no contiene información de superficie.
+ - Distinto de 0: La estructura sí contiene información de superficie.
+ */
+ int hayArea;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena la superficie de cada
+ polígono almacenado. Este campo sólo contiene información si el campo
+ polig::hayArea es distinto de 0; si no, es igual a \p NULL. La
+ superficie almacenada sólo es correcta si el polígono es simple, esto
+ es, si sus lados no se cortan entre ellos mismos.
+
+ El área de los polígono puede ser negativa o positiva, de tal forma
+ que:
+ - Si es negativa: Los vértices de polígono están ordenados en el
+ sentido de las agujas del reloj.
+ - Si es positiva: Los vértices de polígono están ordenados en sentido
+ contrario al de las agujas del reloj.
+ */
+ double* area;
+}polig;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref polig.c.
+\param[out] version Cadena identificadora de la versión de OpenMP utilizada.
+ Este argumento sólo se utiliza si su valor de entrada es distinto de
+ \p NULL y si hay alguna función compilada con OpenMP.
+\return Dos posibles valores:
+ - 0: No hay ninguna función compilada en paralelo con OpenMP.
+ - Distinto de 0: Sí hay alguna función compilada en paralelo con OpenMP.
+\note Esta función asume que el argumento \em version tiene suficiente memoria
+ asignada (si es distinto de \p NULL).
+\date 27 de mayo de 2011: Creación de la función.
+\date 25 de agosto de 2011: Adición del argumento de entrada \em version.
+*/
+int GeocParOmpPolig(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polig vacía.
+\return Estructura \ref polig vacía. Los campos escalares se inicializan con el
+ valor 0 y los vectoriales con \p NULL. Si se devuelve \p NULL ha
+ ocurrido un error de asignación de memoria.
+\date 26 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polig* IniciaPoligVacio(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para la rutina de creación de una estructura \ref polig
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función calcula el número máximo de elementos que almacenarán los
+ vectores de coordenadas de una estructura \ref polig y el número de
+ polígonos almacenados en los vectores de trabajo.
+\param[in] nElem Número de elementos de los vectores de coordenadas originales.
+\param[in] posNanX Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en el vector \em x de coordenadas originales.
+\param[in] posNanY Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en el vector \em y de coordenadas originales.
+\param[in] nNanX Número de elementos del vector \em posNanX.
+\param[in] nNanY Número de elementos del vector \em posNanY.
+\param[out] nElemMax Número máximo de elementos que contendrán los vectores de
+ coordenadas de los elementos de la estructura.
+\param[out] nPolig Número de polígonos almacenados en los vectores \em x e
+ \em y de coordenadas originales.
+\return Variable de error. Tres posibilidades:
+ - #GEOC_ERR_NO_ERROR: Si todo ha ido bien.
+ - #GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG: Si los vectores \em x e \em y
+ de coordenadas originales almacenan un número distinto de polígonos,
+ es decir, \em nNanX es distinto que \em nNanY.
+ - #GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG: Si algunos polígonos almacenados
+ en \em x e \em y son distintos, es decir, las posiciones almacenadas
+ en \em posNanX son distintas de las almacenadas en \em posNanY.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em posNanX y \em posNanY es congruente con los valores pasados en
+ \em nNanX y \em nNanY.
+\date 26 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int AuxCreaPolig1(const size_t nElem,
+ const size_t* posNanX,
+ const size_t* posNanY,
+ const size_t nNanX,
+ const size_t nNanY,
+ size_t* nElemMax,
+ size_t* nPolig);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para la rutina de creación de una estructura \ref polig
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función copia una serie de datos de dos vectores en otros dos.
+\param[in] x Vector que contiene las coordenadas X de los vértices a copiar.
+\param[in] y Vector que contiene las coordenadas Y de los vértices a copiar.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] xSal Vector para almacenar los elementos copiados del vector \em x.
+ Ha de tener la suficiente memoria asignada para copiar \em nElem
+ elementos más un posible elemento adicional, que es el primer
+ elemento de \em x, si éste no se repite al final.
+\param[out] ySal Vector para almacenar los elementos copiados del vector \em y.
+ Ha de tener la suficiente memoria asignada para copiar \em nElem
+ elementos más un posible elemento adicional, que es el primer
+ elemento de \em y, si éste no se repite al final.
+\param[out] nCopias Número de elementos copiados en los vectores \em xSal e
+ \em ySal, incluido el primer punto repetido al final, si se copia.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y, \em xSal e \em ySal es congruente con los valores pasados en
+ \em nElem, \em incX e \em incY.
+\date 26 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void AuxCreaPolig2(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xSal,
+ double* ySal,
+ size_t* nCopias);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para las rutinas de creación de estructuras \ref polig
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función crea los polígonos en el formato de almacenamiento de
+ \ref polig a partir de los vectores de entrada.
+\param[in] x Vector que contiene las coordenadas X de los vértices de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de trabajo.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] posNan Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en los vectores \em x e \em y.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] xSal Vector para almacenar las coordenadas X de los vértices de los
+ polígonos creados.
+\param[out] ySal Vector para almacenar las coordenadas Y de los vértices de los
+ polígonos creados.
+\param[out] posIni Vector para almacenar las posiciones de inicio de los
+ polígonos creados.
+\param[out] nVert Vector para almacenar el número de vértices de los polígonos
+ creados.
+\param[out] nPtos Número de posiciones con información almacenada en los
+ vectores \em xSal e \em ySal.
+\param[out] nPolig Número de posiciones con información almacenada en los
+ vectores \em posIni y \em nVert.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y y \em posNan es congruente con los valores pasados en \em nElem,
+ \em incX, \em incY y \em nNan.
+\note Esta función asume que los vectores \em xSal, \em ySal, \em posIni y
+ \em nVert tienen asignada suficiente memoria.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void AuxCreaPolig3(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ double* xSal,
+ double* ySal,
+ size_t* posIni,
+ size_t* nVert,
+ size_t* nPtos,
+ size_t* nPolig);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polig a partir de dos vectores que contienen las
+ coordenadas de los vértices de uno o varios polígonos.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ o polígonos de trabajo. Si hay varios polígonos, han de estar
+ separados por un valor #GEOC_NAN.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ o polígonos de trabajo. Si hay varios polígonos, han de estar
+ separados por un valor #GEOC_NAN.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] idError Identificador de error. Varias posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de
+ memoria.
+ - #GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG: Los vectores \em x e \em y
+ contienen un número distinto de polígonos. No contienen el mismo
+ número de identificadores #GEOC_NAN.
+ - #GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG: Los vectores \em x e \em y
+ contienen distintos polígonos. Los marcadores #GEOC_NAN no están
+ colocados en las mismas posiciones.
+\return Estructura \ref polig con los polígonos pasados. Si ocurre algún error,
+ se devuelve \p NULL y el motivo del fallo se codifica en la variable
+ \em idError.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\note Si los vectores \em x e \em y almacenan varios polígonos, éstos se separan
+ mediante valores #GEOC_NAN. Poner #GEOC_NAN en la primera posición y/o la
+ última es opcional.
+\note Los posibles valores #GEOC_NAN han de estar en las mismas posiciones en
+ \em x e \em y.
+\note Para los polígonos, es opcional repetir las coordenadas del primer vértice
+ al final del listado del resto de vértices.
+\note Esta función no calcula los límites de los polígonos ni su área, por lo
+ que los campos polig::hayLim y polig::hayArea se inicializan a 0 y los
+ campos polig::xMin, polig::xMax, polig::yMin, polig::yMax y polig::area se
+ inicializan a \p NULL.
+\date 26 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polig* CreaPolig(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ int* idError);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Enlaza el contenido de una estructura \ref polig a otra.
+\param[in] poliEnt Estructura \ref polig de entrada, que almacena los datos a
+ enlazar.
+\param[out] poliSal Estructura \ref polig, cuyos campos serán enlazados a los de
+ la estructura \em poliEnt. Esta estructura ha de estar, como mínimo,
+ inicializada. Al término de la ejecución de la función, las
+ estructuras \em poliEnt y \em poliSal comparten el mismo espacio de
+ memoria en sus argumentos vectoriales.
+\note Esta función asume que la estructura de entrada \em poligEnt tiene memoria
+ asignada.
+\note Esta función asume que la estructura de salida \em poligSal está, como
+ mínimo, inicializada.
+\note Esta función libera la posible memoria asignada a los campos de
+ \em poliSal antes de realizar el enlace.
+\date 19 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void EnlazaCamposPolig(polig* poliEnt,
+ polig* poliSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Copia el contenido de una estructura \ref polig en otra.
+\param[in] poli Estructura \ref polig de entrada, que almacena los datos a
+ copiar.
+\param[out] idError Identificador de error. Varias posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de
+ memoria.
+ - #GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG: Los campos polig::x e
+ polig::y del polígono de entrada contienen un número distinto de
+ polígonos. No contienen el mismo número de identificadores
+ #GEOC_NAN.
+ - #GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG: Los campos polig::x e
+ polig::y del polígono de entrada contienen distintos polígonos.
+ Los marcadores #GEOC_NAN no están colocados en las mismas
+ posiciones.
+\return Polígono con los datos contenidos en \em poli copiados. Si ocurre algún
+ error se devuelve \p NULL y la causa se almacena en el argumento
+ \em idError.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\date 09 de julio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polig* CopiaPolig(const polig* poli,
+ int* idError);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Añade el contenido de una estructura \ref polig a otra.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se han añadido los
+ polígonos de la estructura \em anyade.
+\param[in] anyade Estructura cuyo contenido será añadido a \em poli.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función asume que la estructura de entrada \ref polig tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de las estructuras
+ de entrada no se libera.
+\note Si la estructura \em poli guarda información de superficie y límites de
+ los polígonos almacenados, esta información se calcula también para los
+ nuevos datos (en realidad, si la estructura \em anyade ya los tiene
+ calculados, simplemente se copian).
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int AnyadePoligPolig(polig* poli,
+ const polig* anyade);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Añade al contenido de una estructura \ref polig un conjunto de polígonos
+ definidos a partir de un listado con las coordenadas de sus vértices, de
+ la misma forma que el utilizado en la función \ref CreaPolig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se han añadido los
+ polígonos pasados en \em x e \em y.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ o polígonos a añadir. Si hay varios polígonos, han de estar separados
+ por un valor #GEOC_NAN.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ o polígonos a añadir. Si hay varios polígonos, han de estar separados
+ por un valor #GEOC_NAN.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+ - #GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG: Los vectores \em x e \em y
+ contienen un número distinto de polígonos. No contienen el mismo
+ número de identificadores #GEOC_NAN.
+ - #GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG: Los vectores \em x e \em y
+ contienen distintos polígonos. Los marcadores #GEOC_NAN no están
+ colocados en las mismas posiciones.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de la estructura y
+ los vectores de entrada no se libera.
+\note Si la estructura \em poli guarda información de superficie y límites de
+ los polígonos almacenados, esta información se calcula también para los
+ nuevos datos.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\note Si los vectores \em x e \em y almacenan varios polígonos, éstos se separan
+ mediante valores #GEOC_NAN. Poner #GEOC_NAN en la primera posición y/o la
+ última es opcional.
+\note Los posibles valores #GEOC_NAN han de estar en las mismas posiciones en
+ \em x e \em y.
+\note Para los polígonos, es opcional repetir las coordenadas del primer vértice
+ al final del listado del resto de vértices.
+\note Esta función crea internamente una estructura \ref polig para luego
+ añadirla a \em poli con la función \ref AnyadePoligPolig.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int AnyadeDatosPolig(polig* poli,
+ const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Libera la memoria asignada a una estructura \ref polig.
+\param[in] datos Estructura \ref polig.
+\date 20 de abril de 2011: Creación de la estructura.
+\date 26 de mayo de 2011: Reescritura de la función para el trabajo con la nueva
+ versión de la estructura.
+\note Esta función todavía no está probada.
+*/
+void LibMemPolig(polig* datos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los límites de todos los polígonos almacenados en una estructura
+ \ref polig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se han añadido los
+ límites de los polígonos almacenados.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función asume que la estructura de entrada \ref polig tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de la estructura de
+ entrada no se libera.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int CalcLimitesPolig(polig* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los límites de un polígono a partir de las coordenadas de sus
+ vértices.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ de trabajo.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] xMin Coordenada X mímina del polígono.
+\param[out] xMax Coordenada X máxima del polígono.
+\param[out] yMin Coordenada Y mímina del polígono.
+\param[out] yMax Coordenada Y máxima del polígono.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void LimitesPoligono(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xMin,
+ double* xMax,
+ double* yMin,
+ double* yMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los límites de una serie de polígonos a partir de las coordenadas
+ de sus vértices, almacenadas en vectores en el formato de la estructura
+ \ref polig.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ de trabajo, tal y como se almacenan en una estructura \ref polig.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ de trabajo, tal y como se almacenan en una estructura \ref polig.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] posIni Vector de \em nPolig elementos, que almacena las posiciones de
+ inicio de los polígonos de trabajo.
+\param[in] nVert Vector de \em nPolig elementos, que almacena el número de
+ vértices de los polígonos de trabajo.
+\param[in] nPolig Número de polígonos de trabajo.
+\param[in] restaPosIni Número de posiciones a restar a los valores almacenados
+ en \em posIni, de tal forma que los índices de los vértices se
+ refieran al inicio pasado mediante los punteros \em x e \em y.
+\param[out] xMin Vector de \em nPolig elementos para almacenar las coordenadas
+ X mínimas calculadas de los polígonos.
+\param[out] xMax Vector de \em nPolig elementos para almacenar las coordenadas
+ X máximas calculadas de los polígonos.
+\param[out] yMin Vector de \em nPolig elementos para almacenar las coordenadas
+ Y mínimas calculadas de los polígonos.
+\param[out] yMax Vector de \em nPolig elementos para almacenar las coordenadas
+ Y máximas calculadas de los polígonos.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y, \em posIni, \em nVert, \em xMin, \em xMax, \em yMin e \em yMax es
+ congruente con los valores pasados de \em incX, \em incY, \em nPolig y
+ \em restaPoliIni.
+\note Esta función no comprueba si las coordenadas almacenadas en los vectores
+ \em x e \em y están en el formato de la estructura \ref polig.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void LimitesPoligonosPolig(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posIni,
+ const size_t* nVert,
+ const size_t nPolig,
+ const size_t restaPosIni,
+ double* xMin,
+ double* xMax,
+ double* yMin,
+ double* yMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el área de todos los polígonos almacenados en una estructura
+ \ref polig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se han añadido las
+ superficies de los polígonos almacenados.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función asume que la estructura de entrada \ref polig tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de la estructura de
+ entrada no se libera.
+\date 29 de mayo de 2011: Creación de la función.
+\date 01 de agosto de 2011: Corregido error que hacía que se calculasen mal las
+ superficies debido a un incorrecto uso del argumento \em restaPosIni de la
+ función \ref AreaPoligonosSimplesPolig.
+\note Esta función todavía no está probada.
+*/
+int CalcAreaPolig(polig* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el área de un polígono simple (sin intersecciones consigo mismo)
+ a partir de las coordenadas de sus vértices.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ de trabajo. Las coordenadas del primer punto pueden repetirse o no al
+ final, indistintamente.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ de trabajo. Las coordenadas del primer punto pueden repetirse o no al
+ final, indistintamente.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\return Superficie del polígono de trabajo. Dos posibilidades:
+ - Número negativo: Los vértices del polígono están ordenados en el
+ sentido de las agujas del reloj.
+ - Número positivo: Los vértices del polígono están ordenados en el
+ sentido contrario al de las agujas del reloj.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\note El algoritmo implementado es el correspondiente a la ecuación 21.4.20 del
+ Numerical Recipes, tercera edición, página 1127. Este algoritmo trabaja
+ con vectores de coordenadas en los que el primer punto no se repite al
+ final. Esta función comprueba internamente si el primer punto se repite al
+ final de los vectores pasados y actua en consecuencia para proporcionar un
+ resultado correcto.
+\date 29 de mayo de 2011: Creación de la función.
+\date 23 de junio de 2011: Adición de la capacidad de trabajar con vectores de
+ coordenadas en los que se repite el primer punto al final.
+\note Esta función todavía no está probada.
+*/
+double AreaPoligonoSimple(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el área de una serie de polígonos simples (sin intersecciones
+ consigo mismo) a partir de las coordenadas de sus vértices, almacenadas
+ en vectores en el formato de la estructura \ref polig.
+\param[in] x Vector que contiene las coordenadas X de los vértices del polígono
+ de trabajo, tal y como se almacenan en una estructura \ref polig.
+\param[in] y Vector que contiene las coordenadas Y de los vértices del polígono
+ de trabajo, tal y como se almacenan en una estructura \ref polig.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] posIni Vector de \em nPolig elementos, que almacena las posiciones de
+ inicio de los polígonos de trabajo.
+\param[in] nVert Vector de \em nPolig elementos, que almacena el número de
+ vértices de los polígonos de trabajo.
+\param[in] nPolig Número de polígonos de trabajo.
+\param[in] restaPosIni Número de posiciones a restar a los valores almacenados
+ en \em posIni, de tal forma que los índices de los vértices se
+ refieran al inicio pasado mediante los punteros \em x e \em y.
+\param[out] area Vector de \em nPolig elementos para almacenar las superficies
+ calculadas de los polígonos. Los valores pueden ser positivos o
+ negativos:
+ - Número negativo: Los vértices del polígono están ordenados en el
+ sentido de las agujas del reloj.
+ - Número positivo: Los vértices del polígono están ordenados en el
+ sentido contrario al de las agujas del reloj.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y, \em posIni, \em nVert y \em area es congruente con los valores
+ pasados de \em incX, \em incY, \em nPolig y \em restaPoliIni.
+\note Esta función no comprueba si las coordenadas almacenadas en los vectores
+ \em x e \em y están en el formato de la estructura \ref polig.
+\date 29 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void AreaPoligonosSimplesPolig(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posIni,
+ const size_t* nVert,
+ const size_t nPolig,
+ const size_t restaPosIni,
+ double* area);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica un factor de escala y una traslación (en este orden) a las
+ coordenadas de todos los polígonos almacenados en una estructura
+ \ref polig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se ha aplicado un
+ factor de escala y una traslación (en este orden) a las
+ coordenadas de todos los polígonos almacenados y, si se indica, a
+ los límites y las superficies.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] aplicaLim Identificador para aplicar o no los factores de escala y
+ las traslaciones a los límites de los polígonos (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican los factores de escala ni las traslaciones a los
+ límites.
+ - Distinto de 0: Sí se aplican los factores de escala y las
+ traslaciones a los límites, si estos están calculados en la
+ estructura de entrada.
+\param[in] aplicaArea Identificador para aplicar o no los factores de escala
+ (que se aplican como un único factor \em escalaX*escalaY) a las áreas
+ de los polígonos (sólo si están previemente calculadas). Dos
+ posibilidades:
+ - 0: No se aplican los factores a las áreas.
+ - Distinto de 0: Sí se aplican los factores a las áreas, si estas
+ están calculadas en la estructura de entrada.
+\note Esta función está paralelizada con OpenMP.
+\note Primero se aplican los factores de escala y luego las traslaciones.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\note A las áreas sólo se aplican los factores de escala, ya que son invariantes
+ ante traslaciones.
+\note A las áreas, los factores de escala se aplican como uno solo, igual a
+ \em escalaX*escalaY, para que éstas queden correctamente expresadas en las
+ nuevas unidades a las que da lugar el escalado.
+\date 02 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void EscalaYTrasladaPolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim,
+ const int aplicaArea);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica una traslación y un factor de escala (en este orden) a las
+ coordenadas de todos los polígonos almacenados en una estructura
+ \ref polig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se ha aplicado una
+ traslación y un factor de escala (en este orden) a las
+ coordenadas de todos los polígonos almacenados y, si se indica, a
+ los límites y las superficies.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] aplicaLim Identificador para aplicar o no las traslaciones y los
+ factores de escala a los límites de los polígonos (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican las traslaciones ni los factores de escala a los
+ límites.
+ - Distinto de 0: Sí se aplican las traslaciones y los factores de
+ escala a los límites, si estos están calculados en la estructura de
+ entrada.
+\param[in] aplicaArea Identificador para aplicar o no los factores de escala
+ (que se aplican como un único factor \em escalaX*escalaY) a las áreas
+ de los polígonos (sólo si están previemente calculadas). Dos
+ posibilidades:
+ - 0: No se aplican los factores a las áreas.
+ - Distinto de 0: Sí se aplican los factores a las áreas, si estas
+ están calculadas en la estructura de entrada.
+\note Esta función está paralelizada con OpenMP.
+\note Primero se aplican las traslaciones y luego los factores de escala.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\note A las áreas sólo se aplican los factores de escala, ya que son invariantes
+ ante traslaciones.
+\note A las áreas, los factores de escala se aplican como uno solo, igual a
+ \em escalaX*escalaY, para que éstas queden correctamente expresadas en las
+ nuevas unidades a las que da lugar el escalado.
+\date 02 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void TrasladaYEscalaPolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim,
+ const int aplicaArea);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica un factor de escala y una traslación (el orden de aplicación se ha
+ de seleccionar) a las coordenadas de todos los polígonos almacenados en
+ una estructura \ref polig.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, se ha aplicado un
+ factor de escala y una traslación (orden a seleccionar) a las
+ coordenadas de todos los polígonos almacenados y, si se indica, a
+ los límites y las superficies.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] orden Orden de aplicación de los factores de escala y traslación. Dos
+ posibilidades:
+ - 0: Primero se aplican los factores de escala y luego las
+ traslaciones \f$x'=f\cdot x+t\f$.
+ - Distinto de 0: Primero se aplican las traslaciones y luego los
+ factores de escala \f$x'=(x+t)\cdot f\f$.
+\param[in] aplicaLim Identificador para aplicar o no los factores de escala y
+ las traslaciones a los límites de los polígonos (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican los factores de escala ni las traslaciones a los
+ límites.
+ - Distinto de 0: Sí se aplican los factores de escala y las
+ traslaciones a los límites, si estos están calculados en la
+ estructura de entrada.
+\param[in] aplicaArea Identificador para aplicar o no los factores de escala
+ (que se aplican como un único factor \em escalaX*escalaY) a las áreas
+ de los polígonos (sólo si están previemente calculadas). Dos
+ posibilidades:
+ - 0: No se aplican los factores a las áreas.
+ - Distinto de 0: Sí se aplican los factores a las áreas, si estas
+ están calculadas en la estructura de entrada.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\note A las áreas sólo se aplican los factores de escala, ya que son invariantes
+ ante traslaciones.
+\note A las áreas, los factores de escala se aplican como uno solo, igual a
+ \em escalaX*escalaY, para que éstas queden correctamente expresadas en las
+ nuevas unidades a las que da lugar el escalado.
+\date 02 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void MuevePolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int orden,
+ const int aplicaLim,
+ const int aplicaArea);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de los polígonos almacenados en una estructura
+ \ref polig mediante un algoritmo inspirado en el de Douglas-Peucker. Se
+ usa internamente la función \ref AligeraPolilinea.
+\param[in,out] poli Estructura \ref polig, que almacena una serie de polígonos.
+ Al término de la ejecución de la función, almacena el resultado
+ de la aplicación a cada polígono del algoritmo de aligerado de
+ vértices implementado en la función \ref AligeraPolilinea.
+\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
+ coordenadas de los vértices. Ver la ayuda de la función
+ \ref AligeraPolilinea.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerRobNo: No se aplica el algoritmo robusto.
+ - #GeocDPeuckerRobSi: Se aplica el algoritmo robusto completo, que
+ garantiza la no ocurrencia de auto intersecciones en el polígono
+ resultante. Internamente, primero se aplica el tratamiento robusto
+ de la opción #GeocDPeuckerRobOrig y luego el de la opción
+ #GeocDPeuckerRobAuto.
+ - #GeocDPeuckerRobOrig: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos del polígono aligerado que
+ se van creando no intersectarán con ninguno de los segmentos que
+ forman los vértices que quedan por procesar del polígono original.
+ En casos muy especiales, este algoritmo puede seguir dando lugar a
+ auto intersecciones.
+ - #GeocDPeuckerRobAuto: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos del polígono aligerado que
+ se van creando no intersectarán con ninguno de los segmentos del
+ polígono aligerado creados con anterioridad. En casos muy
+ especiales, este algoritmo puede seguir dando lugar a auto
+ intersecciones.
+\param[in] nPtosRobusto Número de puntos del polígono original a utilizar en el
+ caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi o
+ #GeocDPeuckerRobOrig. Si se pasa el valor 0, se utilizan todos los
+ puntos hasta el final del polígono original.
+\param[in] nSegRobusto Número de segmentos del polígono aligerado a utilizar en
+ el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi o
+ #GeocDPeuckerRobAuto. Si se pasa el valor 0, se utilizan todos los
+ segmentos hasta el inicio del polígono aligerado.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función asume que \em poli está, como mínimo, inicializado.
+\note Si \em poli tiene límites y/o áreas calculadas en la entrada, también los
+ tendrá en la salida.
+\note Un polígono aligerado sólo será válido si después de aplicarle la función
+ \ref AligeraPolilinea mantiene un mínimo de 3 puntos no alineados por lo
+ que, al término de la ejecución de esta función, el resultado puede ser
+ una estructura \ref polig vacía.
+\date 09 de julio de 2011: Creación de la función.
+\date 10 de julio de 2011: Cambio del tipo del argumento \em robusto al tipo
+ enumerado #GEOC_DPEUCKER_ROBUSTO.
+\date 31 de julio de 2011: Corregido error con índices a la hora de guardar los
+ resultados y comprobación de que los polígonos de salida no estén
+ compuestos por tres puntos alineados.
+\todo Esta función todavía no está probada.
+*/
+int AligeraPolig(polig* poli,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime una línea de cabecera para un polígono almacenado en una
+ estructura \ref polig.
+\param[in] poli Estructura \ref polig.
+\param[in] indice Índice del polígono de trabajo en la estructura.
+\param[in] iniCab Cadena de texto con la que comenzará la cabecera.
+\param[in] impLim Identificador para imprimir o no los límites de coordenadas
+ del polígono de trabajo. Dos posibles valores:
+ - 0: No se imprimen.
+ - Distinto de 0: Sí se imprimen.
+\param[in] formCoor Cadena de carácteres indicadora del formato para escribir
+ las coordenadas de los límites. Este argumento sólo se usa
+ internamente si se ha indicado la impresión de límites.
+\param[in] impArea Identificador para imprimir o no la superficie del polígono
+ de trabajo. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formArea Cadena de carácteres indicadora del formato para escribir el
+ valor de la superficie. Este argumento sólo se usa internamente si se
+ ha indicado la impresión de la superficie del polígono.
+\param[in] factorX Factor para multiplicar las coordenadas X de los vértices
+ antes de imprimirlas.
+\param[in] factorY Factor para multiplicar las coordenadas Y de los vértices
+ antes de imprimirlas.
+\param[in] repitePrimerPunto Identificador para tener o no en cuenta el primer
+ vértice del polígono repetido al final del listado de coordenadas
+ para el cálculo del número de vértices del polígono. Dos posibles
+ valores:
+ - 0: No se repite, luego no se tiene en cuenta.
+ - Distinto de 0: Sí se repite, luego sí se tiene en cuenta.
+\param[in] idFich Identificador de fichero abierto para escribir.
+\note Esta función está paralelizada con OpenMP.
+\note La cabecera completa tiene el siguiente formato:
+ <tt>iniCab númVert área xMín xMáx yMín yMáx</tt>.
+\note Si la estructura no tiene información de límites y/o áreas y se indica que
+ se impriman, los valores se calculan internamente.
+\note Esta función asume que \em poli es una estructura \ref polig correctamente
+ almacenada.
+\note Esta función no comprueba si la estructura pasada tiene memoria asignada.
+\note Esta función no comprueba internamente la validez de los argumentos de
+ formato.
+\note Esta función no comprueba internamente si el identificador pasado
+ corresponde a un fichero abierto para escribir.
+\date 18 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void ImprimeCabeceraPoligFichero(const polig* poli,
+ const size_t indice,
+ const char iniCab[],
+ const int impLim,
+ const char formCoor[],
+ const int impArea,
+ const char formArea[],
+ const double factorX,
+ const double factorY,
+ const int repitePrimerPunto,
+ FILE* idFich);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime una estructura \ref polig en un fichero.
+\param[in] poli Estructura \ref polig.
+\param[in] factorX Factor para multiplicar las coordenadas X de los vértices
+ antes de imprimirlas.
+\param[in] factorY Factor para multiplicar las coordenadas Y de los vértices
+ antes de imprimirlas.
+\param[in] repitePrimerPunto Identificador para repetir o no el primer vértice
+ del polígono al final del listado de coordenadas. Dos posibles
+ valores:
+ - 0: No se repite.
+ - Distinto de 0: Sí se repite.
+\param[in] iniNan Identificador para imprimir o no la marca de separación de
+ polígonos (\p NaN) delante del primer polígono. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] finNan Identificador para imprimir o no la marca de separación de
+ polígonos (\p NaN) detrás del último polígono. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formCoor Cadena de carácteres indicadora del formato de cada
+ coordenada a imprimir.
+\param[in] impCabecera Identificador para imprimir o no una cabecera con
+ información general por cada polígono. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] iniCab Cadena de texto con la que comenzará la cabecera.
+\param[in] impLim Identificador para imprimir o no en la cabecera los límites de
+ coordenadas de los polígonos de trabajo. Dos posibles valores:
+ - 0: No se imprimen.
+ - Distinto de 0: Sí se imprimen.
+\param[in] impArea Identificador para imprimir o no en la cabecera la superficie
+ de los polígonos de trabajo. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formArea Cadena de carácteres indicadora del formato para escribir el
+ valor de la superficie. Este argumento sólo se usa internamente si se
+ ha indicado la impresión de la superficie de los polígonos.
+\param[in] idFich Identificador de fichero abierto para escribir.
+\note La cabecera completa tiene el siguiente formato:
+ <tt>iniCab númVert área xMín xMáx yMín yMáx</tt>.
+\note Si la estructura no tiene información de límites y/o áreas y se indica que
+ se impriman, los valores se calculan internamente.
+\note Esta función asume que \em poli es una estructura \ref polig correctamente
+ almacenada.
+\note Esta función no comprueba si la estructura pasada tiene memoria asignada.
+\note Esta función no comprueba internamente la validez de los argumentos de
+ formato.
+\note Esta función no comprueba internamente si el identificador pasado
+ corresponde a un fichero abierto para escribir.
+\date 26 de mayo de 2011: Creación de la función.
+\date 30 de mayo de 2011: Adición del argumento de entrada \em factor.
+\date 18 de junio de 2011: Adición de la capacidad de escritura de una cabecera
+ y del uso de factores de escala independientes para las coordenadas X e Y.
+\date 22 de septiembre de 2011: Corregido bug que hacía que, dependiendo del
+ compilador y/o los flags de optimización en la compilación, se imprimiesen
+ mal (con un signo menos delante) los valores Not-a-Number.
+\note Esta función todavía no está probada.
+*/
+void ImprimePoligFichero(const polig* poli,
+ const double factorX,
+ const double factorY,
+ const int repitePrimerPunto,
+ const int iniNan,
+ const int finNan,
+ const char formCoor[],
+ const int impCabecera,
+ const char iniCab[],
+ const int impLim,
+ const int impArea,
+ const char formArea[],
+ FILE* idFich);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/polil.h b/src/libgeoc/polil.h
new file mode 100755
index 0000000..174ffae
--- /dev/null
+++ b/src/libgeoc/polil.h
@@ -0,0 +1,799 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file polil.h
+\brief Definición de estructuras y declaración de funciones para el trabajo con
+ polilíneas.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 03 de junio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _POLIL_H_
+#define _POLIL_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdio.h>
+#include<stdlib.h>
+#include"libgeoc/dpeucker.h"
+#include"libgeoc/errores.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/geocomp.h"
+#include"libgeoc/polig.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** \struct polil
+\brief Estructura contenedora de los vértices que definen el contorno de una o
+ varias polilíneas.
+\date 03 de junio de 2011: Creación de la estructura.
+*/
+typedef struct
+{
+ /** \brief Número de elementos de los vectores de coordenadas. */
+ size_t nElem;
+ /**
+ \brief Vector de polil::nElem elementos, que almacena las coordenadas X de
+ los vértices de la polilínea (o las polilíneas), así como los
+ separadores entre polilíneas. La primera coordenada de cada polilínea
+ se repite al final.
+ */
+ double* x;
+ /**
+ \brief Vector de polil::nElem elementos, que almacena las coordenadas Y de
+ los vértices de la polilínea (o las polilíneas), así como los
+ separadores entre polilíneas. La primera coordenada de cada polilínea
+ se repite al final.
+ */
+ double* y;
+ /** \brief Número de polilíneas almacenadas. */
+ size_t nPolil;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena las posiciones en los
+ vectores \em x e \em y de inicio de cada polilínea almacenada.
+ */
+ size_t* posIni;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena el número de vértices
+ de cada polilínea almacenada.
+ */
+ size_t* nVert;
+ /**
+ \brief Identificador de si la estructura contiene información acerca de los
+ límites del rectángulo que encierra a cada polilínea almacenada.
+
+ Dos posibilidades:
+ - 0: La estructura no contiene información de los límites.
+ - Distinto de 0: La estructura sí contiene información de los
+ límites.
+ */
+ int hayLim;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena la coordenada X
+ mínima de cada polilínea almacenada. Este campo sólo contiene
+ información si el campo polil::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* xMin;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena la coordenada X
+ máxima de cada polilínea almacenada. Este campo sólo contiene
+ información si el campo polil::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* xMax;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena la coordenada Y
+ mínima de cada polilínea almacenada. Este campo sólo contiene
+ información si el campo polil::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* yMin;
+ /**
+ \brief Vector de polil::nPolig elementos, que almacena la coordenada Y
+ máxima de cada polilínea almacenada. Este campo sólo contiene
+ información si el campo polil::hayLim es distinto de 0; si no, es
+ igual a \p NULL.
+ */
+ double* yMax;
+}polil;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref polil.c.
+\param[out] version Cadena identificadora de la versión de OpenMP utilizada.
+ Este argumento sólo se utiliza si su valor de entrada es distinto de
+ \p NULL y si hay alguna función compilada con OpenMP.
+\return Dos posibles valores:
+ - 0: No hay ninguna función compilada en paralelo con OpenMP.
+ - Distinto de 0: Sí hay alguna función compilada en paralelo con OpenMP.
+\note Esta función asume que el argumento \em version tiene suficiente memoria
+ asignada (si es distinto de \p NULL).
+\date 03 de junio de 2011: Creación de la función.
+\date 25 de agosto de 2011: Adición del argumento de entrada \em version.
+*/
+int GeocParOmpPolil(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polil vacía.
+\return Estructura \ref polil vacía. Los campos escalares se inicializan con el
+ valor 0 y los vectoriales con \p NULL. Si se devuelve \p NULL ha
+ ocurrido un error de asignación de memoria.
+\date 26 de mayo de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polil* IniciaPolilVacia(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para la rutina de creación de una estructura \ref polil
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función calcula el número máximo de elementos que almacenarán los
+ vectores de coordenadas de una estructura \ref polil y el número de
+ polilíneas almacenadas en los vectores de trabajo.
+\param[in] nElem Número de elementos de los vectores de coordenadas originales.
+\param[in] posNanX Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en el vector \em x de coordenadas originales.
+\param[in] posNanY Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en el vector \em y de coordenadas originales.
+\param[in] nNanX Número de elementos del vector \em posNanX.
+\param[in] nNanY Número de elementos del vector \em posNanY.
+\param[out] nElemMax Número máximo de elementos que contendrán los vectores de
+ coordenadas de los elementos de la estructura.
+\param[out] nPolil Número de polilíneas almacenadas en los vectores \em x e
+ \em y de coordenadas originales.
+\return Variable de error. Tres posibilidades:
+ - #GEOC_ERR_NO_ERROR: Si todo ha ido bien.
+ - #GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL: Si los vectores \em x e \em y
+ de coordenadas originales almacenan un número distinto de polilíneas,
+ es decir, \em nNanX es distinto que \em nNanY.
+ - #GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL: Si algunas polilíneas almacenadas
+ en \em x e \em y son distintas, es decir, las posiciones almacenadas
+ en \em posNanX son distintas de las almacenadas en \em posNanY.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em posNanX y \em posNanY es congruente con los valores pasados en
+ \em nNanX y \em nNanY.
+\date 03 de junio de 2011: Creación de la función.
+\date 13 de junio de 2011: Corrección de error que hacía que el argumento
+ \em nElemMax que calculase mal si los argumentos \em nNanX y/o \em nNanY
+ valían 0.
+\note Esta función todavía no está probada.
+*/
+int AuxCreaPolil1(const size_t nElem,
+ const size_t* posNanX,
+ const size_t* posNanY,
+ const size_t nNanX,
+ const size_t nNanY,
+ size_t* nElemMax,
+ size_t* nPolil);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para la rutina de creación de una estructura \ref polil
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función copia una serie de datos de dos vectores en otros dos.
+\param[in] x Vector que contiene las coordenadas X de los vértices a copiar.
+\param[in] y Vector que contiene las coordenadas Y de los vértices a copiar.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] xSal Vector de \em nElem elementos para almacenar los elementos
+ copiados del vector \em x.
+\param[out] ySal Vector de \em nElem elementos para almacenar los elementos
+ copiados del vector \em y.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y, \em xSal e \em ySal es congruente con los valores pasados en
+ \em nElem, \em incX e \em incY.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void AuxCreaPolil2(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xSal,
+ double* ySal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Función auxiliar para las rutinas de creación de estructuras \ref polil
+ a partir de dos vectores que contienen las coordenadas de los vértices.
+
+ Esta función crea las polilíneas en el formato de almacenamiento de
+ \ref polil a partir de los vectores de entrada.
+\param[in] x Vector que contiene las coordenadas X de los vértices de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de trabajo.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] posNan Vector que almacena las posiciones de los elementos #GEOC_NAN
+ en los vectores \em x e \em y.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] xSal Vector para almacenar las coordenadas X de los vértices de las
+ polilíneas creadas.
+\param[out] ySal Vector para almacenar las coordenadas Y de los vértices de las
+ polilíneas creadas.
+\param[out] posIni Vector para almacenar las posiciones de inicio de las
+ polilíneas creadas.
+\param[out] nVert Vector para almacenar el número de vértices de las polilíneas
+ creadas.
+\param[out] nPtos Número de posiciones con información almacenada en los
+ vectores \em xSal e \em ySal.
+\param[out] nPolil Número de posiciones con información almacenada en los
+ vectores \em posIni y \em nVert.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y y \em posNan es congruente con los valores pasados en \em nElem,
+ \em incX, \em incY y \em nNan.
+\note Esta función asume que los vectores \em xSal, \em ySal, \em posIni y
+ \em nVert tienen asignada suficiente memoria.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void AuxCreaPolil3(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ double* xSal,
+ double* ySal,
+ size_t* posIni,
+ size_t* nVert,
+ size_t* nPtos,
+ size_t* nPolil);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polil a partir de dos vectores que contienen las
+ coordenadas de los vértices de una o varias polilíneas.
+\param[in] x Vector que contiene las coordenadas X de los vértices de la
+ polilínea o polilíneas de trabajo. Si hay varias polilíneas, han de
+ estar separados por un valor #GEOC_NAN.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de la
+ polilínea o polilíneas de trabajo. Si hay varias polilíneas, han de
+ estar separados por un valor #GEOC_NAN.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] idError Identificador de error. Varias posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de
+ memoria.
+ - #GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL: Los vectores \em x e \em y
+ contienen un número distinto de polilíneas. No contienen el mismo
+ número de identificadores #GEOC_NAN.
+ - #GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL: Los vectores \em x e \em y
+ contienen distintas polilíneas. Los marcadores #GEOC_NAN no están
+ colocados en las mismas posiciones.
+\return Estructura \ref polil con las polilíneas pasadas. Si ocurre algún error,
+ se devuelve \p NULL y el motivo del fallo se codifica en la variable
+ \em idError.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\note Si los vectores \em x e \em y almacenan varias polilíneas, éstas se
+ separan mediante valores #GEOC_NAN. Poner #GEOC_NAN en la primera posición
+ y/o la última es opcional.
+\note Los posibles valores #GEOC_NAN han de estar en las mismas posiciones en
+ \em x e \em y.
+\note Esta función no calcula los límites de las polilíneas, por lo que el
+ campo polil::hayLim se inicializa a 0 y los campos polil::xMin,
+ polil::xMax, polil::yMin y polil::yMax se inicializan a \p NULL.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polil* CreaPolil(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ int* idError);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Enlaza el contenido de una estructura \ref polil a otra.
+\param[in] poliEnt Estructura \ref polil de entrada, que almacena los datos a
+ enlazar.
+\param[out] poliSal Estructura \ref polil, cuyos campos serán enlazados a los de
+ la estructura \em poliEnt. Esta estructura ha de estar, como mínimo,
+ inicializada. Al término de la ejecución de la función, las
+ estructuras \em poliEnt y \em poliSal comparten el mismo espacio de
+ memoria en sus argumentos vectoriales.
+\note Esta función asume que la estructura de entrada \em poligEnt tiene memoria
+ asignada.
+\note Esta función asume que la estructura de salida \em poligSal está, como
+ mínimo, inicializada.
+\note Esta función libera la posible memoria asignada a los campos de
+ \em poliSal antes de realizar el enlace.
+\date 19 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void EnlazaCamposPolil(polil* poliEnt,
+ polil* poliSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Copia el contenido de una estructura \ref polil en otra.
+\param[in] poli Estructura \ref polil de entrada, que almacena los datos a
+ copiar.
+\param[out] idError Identificador de error. Varias posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de
+ memoria.
+ - #GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL: Los campos polil::x e
+ polil::y de la polilínea de entrada contienenun número distinto de
+ polilíneas. No contienen el mismo número de identificadores
+ #GEOC_NAN.
+ - #GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL: Los campos polig::x e
+ polig::y de la polilínea de entrada contienen distintas
+ polilíneas. Los marcadores #GEOC_NAN no están colocados en las
+ mismas posiciones.
+\return Polilínea con los datos contenidos en \em poli copiados. Si ocurre algún
+ error se devuelve \p NULL y la causa se almacena en el argumento
+ \em idError.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\date 09 de julio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+polil* CopiaPolil(const polil* poli,
+ int* idError);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Añade el contenido de una estructura \ref polil a otra.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se han añadido las
+ polilíneas de la estructura \em anyade.
+\param[in] anyade Estructura cuyo contenido será añadido a \em poli.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función asume que la estructura de entrada \ref polil tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de las estructuras
+ de entrada no se libera.
+\note Si la estructura \em poli guarda información de límites de las polilíneas
+ almacenadas, esta información se calcula también para los nuevos datos (en
+ realidad, si la estructura \em anyade ya los tiene calculados, simplemente
+ se copian).
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int AnyadePolilPolil(polil* poli,
+ const polil* anyade);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Añade al contenido de una estructura \ref polil un conjunto de polilíneas
+ definidas a partir de un listado con las coordenadas de sus vértices, de
+ la misma forma que el utilizado en la función \ref CreaPolil.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se han añadido las
+ polilíneas pasados en \em x e \em y.
+\param[in] x Vector que contiene las coordenadas X de los vértices de la
+ polilínea o polilíneas a añadir. Si hay varias polilíneas, han de
+ estar separadas por un valor #GEOC_NAN.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de la
+ polilínea o polilíneas a añadir. Si hay varias polilíneas, han de
+ estar separadas por un valor #GEOC_NAN.
+\param[in] nElem Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+ - #GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL: Los vectores \em x e \em y
+ contienen un número distinto de polilíneas. No contienen el mismo
+ número de identificadores #GEOC_NAN.
+ - #GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL: Los vectores \em x e \em y
+ contienen distintas polilíneas. Los marcadores #GEOC_NAN no están
+ colocados en las mismas posiciones.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de la estructura y
+ los vectores de entrada no se libera.
+\note Si la estructura \em poli guarda información de límites de las polilíneas
+ almacenadas, esta información se calcula también para los nuevos datos.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados de \em nElem, \em incX e
+ \em incY.
+\note Si los vectores \em x e \em y almacenan varias polilíneas, éstas se
+ separan mediante valores #GEOC_NAN. Poner #GEOC_NAN en la primera posición
+ y/o la última es opcional.
+\note Los posibles valores #GEOC_NAN han de estar en las mismas posiciones en
+ \em x e \em y.
+\note Esta función crea internamente una estructura \ref polil para luego
+ añadirla a \em poli con la función \ref AnyadePolilPolil.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int AnyadeDatosPolil(polil* poli,
+ const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Libera la memoria asignada a una estructura \ref polil.
+\param[in] datos Estructura \ref polil.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void LibMemPolil(polil* datos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los límites de todas las polilíneas almacenados en una estructura
+ \ref polil.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se han añadido los
+ límites de las polilíneas almacenadas.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función asume que la estructura de entrada \ref polil tiene memoria
+ asignada.
+\note En caso de error de asignación de memoria, la memoria de la estructura de
+ entrada no se libera.
+\date 03 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+int CalcLimitesPolil(polil* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica un factor de escala y una traslación (en este orden) a las
+ coordenadas de todas las polilíneas almacenadas en una estructura
+ \ref polil.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se ha aplicado un
+ factor de escala y una traslación (en este orden) a las
+ coordenadas de todas las polilíneas almacenadas y, si se indica,
+ a los límites.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] aplicaLim Identificador para aplicar o no los factores de escala y
+ las traslaciones a los límites de las polilíneas (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican los factores de escala ni las traslaciones a los
+ límites.
+ - Distinto de 0: Sí se aplican los factores de escala y las
+ traslaciones a los límites, si estos están calculados en la
+ estructura de entrada.
+\note Esta función está paralelizada con OpenMP.
+\note Primero se aplican los factores de escala y luego las traslaciones.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\date 03 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void EscalaYTrasladaPolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica una traslación y un factor de escala (en este orden) a las
+ coordenadas de todas las polilíneas almacenadss en una estructura
+ \ref polil.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se ha aplicado una
+ traslación y un factor de escala (en este orden) a las
+ coordenadas de todas las polilíneas almacenadas y, si se indica,
+ a los límites.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] aplicaLim Identificador para aplicar o no las traslaciones y los
+ factores de escala a los límites de las polilíneas (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican las traslaciones ni los factores de escala a los
+ límites.
+ - Distinto de 0: Sí se aplican las traslaciones y los factores de
+ escala a los límites, si estos están calculados en la estructura de
+ entrada.
+\note Esta función está paralelizada con OpenMP.
+\note Primero se aplican las traslaciones y luego los factores de escala.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\date 03 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void TrasladaYEscalaPolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica un factor de escala y una traslación (el orden de aplicación se ha
+ de seleccionar) a las coordenadas de todas las polilíneas almacenadas en
+ una estructura \ref polil.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, se ha aplicado un
+ factor de escala y una traslación (orden a seleccionar) a las
+ coordenadas de todas las polilíneas almacenadas y, si se indica,
+ a los límites.
+\param[in] escalaX Factor de escala a aplicar a las coordenadas X.
+\param[in] escalaY Factor de escala a aplicar a las coordenadas Y.
+\param[in] trasladaX Traslación a aplicar a las coordenadas X.
+\param[in] trasladaY Traslación a aplicar a las coordenadas Y.
+\param[in] orden Orden de aplicación de los factores de escala y traslación. Dos
+ posibilidades:
+ - 0: Primero se aplican los factores de escala y luego las
+ traslaciones \f$x'=f\cdot x+t\f$.
+ - Distinto de 0: Primero se aplican las traslaciones y luego los
+ factores de escala \f$x'=(x+t)\cdot f\f$.
+\param[in] aplicaLim Identificador para aplicar o no los factores de escala y
+ las traslaciones a los límites de las polilíneas (sólo si están
+ previemente calculados). Dos posibilidades:
+ - 0: No se aplican los factores de escala ni las traslaciones a los
+ límites.
+ - Distinto de 0: Sí se aplican los factores de escala y las
+ traslaciones a los límites, si estos están calculados en la
+ estructura de entrada.
+\note Esta función asume que la estructura de entrada \em poli tiene memoria
+ asignada.
+\date 03 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Distinción entre factores de escala y traslaciones
+ para las coordenadas X e Y.
+\note Esta función todavía no está probada.
+*/
+void MuevePolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int orden,
+ const int aplicaLim);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de las polilíneas almacenadas en una estructura
+ \ref polil mediante un algoritmo inspirado en el de Douglas-Peucker. Se
+ usa internamente la función \ref AligeraPolilinea.
+\param[in,out] poli Estructura \ref polil, que almacena una serie de polilíneas.
+ Al término de la ejecución de la función, almacena el resultado
+ de la aplicación a cada polilínea del algoritmo de aligerado de
+ vértices implementado en la función \ref AligeraPolilinea.
+\param[in] tol Tolerancia para eliminar vértices, en las mismas unidades que las
+ coordenadas de los vértices. Ver la ayuda de la función
+ \ref AligeraPolilinea.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerRobNo: No se aplica el algoritmo robusto.
+ - #GeocDPeuckerRobSi: Se aplica el algoritmo robusto completo, que
+ garantiza la no ocurrencia de auto intersecciones en la polilínea
+ resultante. Internamente, primero se aplica el tratamiento robusto
+ de la opción #GeocDPeuckerRobOrig y luego el de la opción
+ #GeocDPeuckerRobAuto.
+ - #GeocDPeuckerRobOrig: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos de la polilínea aligerada
+ que se van creando no intersectarán con ninguno de los segmentos
+ que forman los vértices que quedan por procesar de la polilínea
+ original. En casos muy especiales, este algoritmo puede seguir
+ dando lugar a auto intersecciones.
+ - #GeocDPeuckerRobAuto: Se aplica un algoritmo semi robusto que
+ consiste en garantizar que los segmentos de la polilínea aligerada
+ que se van creando no intersectarán con ninguno de los segmentos de
+ la polilínea aligerada creados con anterioridad. En casos muy
+ especiales, este algoritmo puede seguir dando lugar a auto
+ intersecciones.
+\param[in] nPtosRobusto Número de puntos de la polilínea original a utilizar en
+ el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi o
+ #GeocDPeuckerRobOrig. Si se pasa el valor 0, se utilizan todos los
+ puntos hasta el final de la polilínea original.
+\param[in] nSegRobusto Número de segmentos de la polilínea aligerada a utilizar
+ en el caso de tratamiento robusto con las opciones #GeocDPeuckerRobSi
+ o #GeocDPeuckerRobAuto. Si se pasa el valor 0, se utilizan todos los
+ segmentos hasta el inicio de la polilínea aligerada.
+\return Variable de error. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función asume que \em poli está, como mínimo, inicializada.
+\note Si \em poli tiene límites calculados en la entrada, también los tendrá en
+ la salida.
+\note Una polilínea aligerada sólo será válida si después de aplicarle la
+ función \ref AligeraPolilinea mantiene un mínimo de 2 puntos que no sean
+ el mismo (esto sólo puede ocurrir si se pasa un polígono -los vértices de
+ inicio y final coinciden- y sólo quedan al final los extremos). Al término
+ de la ejecución de esta función, el resultado puede ser una estructura
+ \ref polil vacía.
+\date 09 de julio de 2011: Creación de la función.
+\date 10 de julio de 2011: Cambio del tipo del argumento \em robusto al tipo
+ enumerado #GEOC_DPEUCKER_ROBUSTO.
+\date 31 de julio de 2011: Corregido error con índices a la hora de guardar los
+ resultados y modificación para no tomar como válidas las polilíneas que se
+ quedan en sólo dos vértices que sean el mismo.
+\todo Esta función todavía no está probada.
+*/
+int AligeraPolil(polil* poli,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime una línea de cabecera para una polilínea almacenada en una
+ estructura \ref polil.
+\param[in] poli Estructura \ref polil.
+\param[in] indice Índice de la polilínea de trabajo en la estructura.
+\param[in] iniCab Cadena de texto con la que comenzará la cabecera.
+\param[in] impLim Identificador para imprimir o no los límites de coordenadas
+ de la polilínea de trabajo. Dos posibles valores:
+ - 0: No se imprimen.
+ - Distinto de 0: Sí se imprimen.
+\param[in] formCoor Cadena de carácteres indicadora del formato para escribir
+ las coordenadas de los límites. Este argumento sólo se usa
+ internamente si se ha indicado la impresión de límites.
+\param[in] factorX Factor para multiplicar las coordenadas X de los vértices
+ antes de imprimirlas.
+\param[in] factorY Factor para multiplicar las coordenadas Y de los vértices
+ antes de imprimirlas.
+\param[in] idFich Identificador de fichero abierto para escribir.
+\note Esta función está paralelizada con OpenMP.
+\note La cabecera completa tiene el siguiente formato:
+ <tt>iniCab númVert xMín xMáx yMín yMáx</tt>.
+\note Si la estructura no tiene información de límites y se indica que se
+ impriman, los valores se calculan internamente.
+\note Esta función asume que \em poli es una estructura \ref polil correctamente
+ almacenada.
+\note Esta función no comprueba si la estructura pasada tiene memoria asignada.
+\note Esta función no comprueba internamente la validez de los argumentos de
+ formato.
+\note Esta función no comprueba internamente si el identificador pasado
+ corresponde a un fichero abierto para escribir.
+\date 18 de junio de 2011: Creación de la función.
+\note Esta función todavía no está probada.
+*/
+void ImprimeCabeceraPolilFichero(const polil* poli,
+ const size_t indice,
+ const char iniCab[],
+ const int impLim,
+ const char formCoor[],
+ const double factorX,
+ const double factorY,
+ FILE* idFich);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Imprime una estructura \ref polil en un fichero.
+\param[in] poli Estructura \ref polil.
+\param[in] factorX Factor para multiplicar las coordenadas X de los vértices
+ antes de imprimirlas.
+\param[in] factorY Factor para multiplicar las coordenadas Y de los vértices
+ antes de imprimirlas.
+\param[in] iniNan Identificador para imprimir o no la marca de separación de
+ polilíneas (\p NaN) delante de la primera polilínea. Dos posibles
+ valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] finNan Identificador para imprimir o no la marca de separación de
+ polilíneas (\p NaN) delante de la última polilínea. Dos posibles
+ valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formCoor Cadena de carácteres indicadora del formato de cada
+ coordenada a imprimir.
+\param[in] impCabecera Identificador para imprimir o no una cabecera con
+ información general por cada polilínea. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] iniCab Cadena de texto con la que comenzará la cabecera.
+\param[in] impLim Identificador para imprimir o no en la cabecera los límites de
+ coordenadas de las polilíneas de trabajo. Dos posibles valores:
+ - 0: No se imprimen.
+ - Distinto de 0: Sí se imprimen.
+\param[in] idFich Identificador de fichero abierto para escribir.
+\note La cabecera completa tiene el siguiente formato:
+ <tt>iniCab númVert xMín xMáx yMín yMáx</tt>.
+\note Si la estructura no tiene información de límites y se indica que se
+ impriman, los valores se calculan internamente.
+\note Esta función asume que \em poli es una estructura \ref polil correctamente
+ almacenada.
+\note Esta función no comprueba si la estructura pasada tiene memoria asignada.
+\note Esta función no comprueba internamente la validez de los argumentos de
+ formato.
+\note Esta función no comprueba internamente si el identificador pasado
+ corresponde a un fichero abierto para escribir.
+\date 03 de junio de 2011: Creación de la función.
+\date 18 de junio de 2011: Adición de la capacidad de escritura de una cabecera
+ y del uso de factores de escala independientes para las coordenadas X e Y.
+\date 22 de septiembre de 2011: Corregido bug que hacía que, dependiendo del
+ compilador y/o los flags de optimización en la compilación, se imprimiesen
+ mal (con un signo menos delante) los valores Not-a-Number.
+\note Esta función todavía no está probada.
+*/
+void ImprimePolilFichero(const polil* poli,
+ const double factorX,
+ const double factorY,
+ const int iniNan,
+ const int finNan,
+ const char formCoor[],
+ const int impCabecera,
+ const char iniCab[],
+ const int impLim,
+ FILE* idFich);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/ptopol.h b/src/libgeoc/ptopol.h
new file mode 100755
index 0000000..6f82b3a
--- /dev/null
+++ b/src/libgeoc/ptopol.h
@@ -0,0 +1,947 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file ptopol.h
+\brief Declaración de funciones para la realización de chequeos de inclusión de
+ puntos en polígonos.
+
+En el momento de la compilación ha de seleccionarse el tipo de dato que se
+utilizará en los cálculos intermedios de las funciones
+\ref PtoEnPoligonoVerticeBorde y \ref PtoEnPoligonoVerticeBordeDouble. Si los
+puntos de trabajo están muy alejados de los polígonos pueden darse casos de
+resultados erróneos. Sería conveniente que los cálculos internedios se hiciesen
+en variables de 64 bits, pero el tipo <tt>long int</tt> suele ser de 4 bytes en
+procesadores de 32 bits. Para seleccionar este tipo como <tt>long long int</tt>,
+lo que en procesadores de 32 bits equivale a una variable de 64 bits, es
+necesario definir la variable para el preprocesador \em PTOPOL_BORDE_LONG_64. En
+procesadores de 64 bits no es necesario (aunque puede utilizarse), ya que el
+tipo <tt>long int</tt> tiene una longitud de 64 bits. Si no se define la
+variable, se usará un tipo <tt>long int</tt> para los cálculos intermedios. En
+\p gcc, las variables para el preprocesador se pasan como \em -DXXX, donde
+\em XXX es la variable a introducir. El uso del tipo <tt>long long int</tt> en
+procesadores de 32 bits puede hacer que las funciones se ejecuten hasta 10 veces
+más lentamente que si se utiliza el tipo <tt>long int</tt>. Con cálculos
+internos de 32 bits las coordenadas de los vértices del polígono no han de estar
+más lejos de las de los puntos de trabajo de unas 40000 unidades. Con cálculos
+de 64 bits, los polígonos pueden estar alejados de los puntos de trabajo unas
+3000000000 unidades, lo que corresponde a coordenadas Y UTM ajustadas al
+centímetro. Con esto podríamos chequear un punto en un polo con respecto a un
+polígono en el ecuador en coordenadas UTM expresadas en centímetros.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 05 de abril de 2010
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _PTOPOL_H_
+#define _PTOPOL_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/errores.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_FUERA_POLIG
+\brief Identificador de punto fuera de un polígono.
+\date 12 de abril de 2011: Creación de la constante.
+*/
+#define GEOC_PTO_FUERA_POLIG 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_DENTRO_POLIG
+\brief Identificador de punto dentro de un polígono.
+\date 12 de abril de 2011: Creación de la constante.
+*/
+#define GEOC_PTO_DENTRO_POLIG 1
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_VERTICE_POLIG
+\brief Identificador de punto que es un vértice de un polígono.
+\date 12 de abril de 2011: Creación de la constante.
+*/
+#define GEOC_PTO_VERTICE_POLIG 2
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_BORDE_POLIG
+\brief Identificador de punto que está en el borde de un polígono.
+\date 12 de abril de 2011: Creación de la constante.
+*/
+#define GEOC_PTO_BORDE_POLIG 3
+/******************************************************************************/
+/******************************************************************************/
+/**
+\typedef ptopol_long
+\brief Nombre del tipo <tt>long int</tt> o <tt>long long int</tt> para utilizar
+ en los cálculos intermedios de las funciones
+ \ref PtoEnPoligonoVerticeBorde y \ref PtoEnPoligonoVerticeBordeDouble. Si
+ los puntos de trabajo están muy alejados de los polígonos pueden darse
+ casos de resultados erróneos. Sería conveniente que los cálculos
+ internedios se hiciesen en variables de 64 bits, pero el tipo
+ <tt>long int</tt> suele ser de 4 bytes en procesadores de 32 bits.
+ Mediante la variable del preprocesador PTOPOL_BORDE_LONG_64 indicamos que
+ este tipo sea <tt>long long int</tt>, lo que en procesadores de 32 bits
+ equivale a una variable de 64 bits.
+\note Este tipo de dato sólo es para uso interno en el fichero \ref ptopol.c. No
+ se recomienda su uso fuera de él, ya que habría que tener el cuenta la
+ variable del preprocesador cada vez que se incluyera este fichero
+ (\ref ptopol.h) en un programa u otro fichero.
+\date 19 de abril de 2011: Creación del tipo.
+*/
+#if defined(PTOPOL_BORDE_LONG_64)
+typedef long long int ptopol_long;
+#else
+typedef long int ptopol_long;
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref ptopol.c.
+\return Dos posibles valores:
+ - 0: No hay ninguna función compilada en paralelo con OpenMP.
+ - Distinto de 0: Sí hay alguna función compilada en paralelo con OpenMP.
+\note Esta función asume que el argumento \em version tiene suficiente memoria
+ asignada (si es distinto de \p NULL).
+\date 13 de abril de 2011: Creación de la función.
+\date 25 de agosto de 2011: Adición del argumento de entrada \em version.
+*/
+int GeocParOmpPtopol(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si se está utilizando el tipo <tt>log long int</tt> para la
+ realización de cálculos intermedios en las funciones de chequeo de puntos
+ en polígonos que son capaces de detectar si un punto está en el borde.
+\return Dos posibles valores:
+ - 0: No se está utilizando <tt>log long int</tt>.
+ - Distinto de 0: Sí se está utilizando <tt>log long int</tt>.
+\date 19 de abril de 2011: Creación de la función.
+*/
+int GeocLongLongIntPtopol(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un rectángulo.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] xMin Coordenada X mínima del rectángulo.
+\param[in] xMax Coordenada X máxima del rectángulo.
+\param[in] yMin Coordenada Y mínima del rectángulo.
+\param[in] yMax Coordenada Y máxima del rectángulo.
+\return Varias posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del rectángulo.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del rectángulo.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice del rectángulo.
+ - #GEOC_PTO_BORDE_POLIG: El punto pertenece a la frontera del
+ rectángulo, pero no es un vértice.
+\note Esta función asume que \em xMin<xMax e \em yMin<yMax.
+\date 05 de abril de 2010: Creación de la función.
+\date 12 de abril de 2011: Las variables de salida son ahora constantes
+ simbólicas.
+\todo Esta función no está probada.
+*/
+int PtoEnRectangulo(const double x,
+ const double y,
+ const double xMin,
+ const double xMax,
+ const double yMin,
+ const double yMax);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un rectángulo 1 está contenido íntegramente en otro 2.
+\param[in] borde Identificador para indicar si los bordes se tienen en cuenta o
+ no. Dos posibilidades:
+ - 0: Lo bordes \b *NO* se tienen en cuenta. Es decir, si algún borde
+ de un rectángulo coincide con el de otro, el resultado es que el
+ rectángulo 1 no está contenido en 2.
+ - Distinto de 0: Lo bordes \b *SÍ* se tienen en cuenta. Es decir, el
+ que un borde del rectángulo 1 coincida con otro del rectángulo 2 no
+ impide que 1 esté contenido en 2.
+\param[in] xMin1 Coordenada X mínima del rectángulo 1.
+\param[in] xMax1 Coordenada X máxima del rectángulo 1.
+\param[in] yMin1 Coordenada Y mínima del rectángulo 1.
+\param[in] yMax1 Coordenada Y máxima del rectángulo 1.
+\param[in] xMin2 Coordenada X mínima del rectángulo 2.
+\param[in] xMax2 Coordenada X máxima del rectángulo 2.
+\param[in] yMin2 Coordenada Y mínima del rectángulo 2.
+\param[in] yMax2 Coordenada Y máxima del rectángulo 2.
+\return Dos posibilidades:
+ - 0: El rectángulo 1 no está contenido íntegramente en el rectángulo 2.
+ - Distinto de 0: El rectángulo 1 está contenido íntegramente en el
+ rectángulo 2.
+\note Esta función asume que \em xMin1<xMax1, \em yMin1<yMax1, \em xMin2<xMax2 e
+ \em yMin2<yMax2.
+\date 20 de junio de 2010: Creación de la función.
+\todo Esta función no está probada.
+*/
+int RectanguloEnRectangulo(const int borde,
+ const double xMin1,
+ const double xMax1,
+ const double yMin1,
+ const double yMax1,
+ const double xMin2,
+ const double xMax2,
+ const double yMin2,
+ const double yMax2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si dos rectángulos son disjuntos.
+\param[in] xMin1 Coordenada X mínima del rectángulo 1.
+\param[in] xMax1 Coordenada X máxima del rectángulo 1.
+\param[in] yMin1 Coordenada Y mínima del rectángulo 1.
+\param[in] yMax1 Coordenada Y máxima del rectángulo 1.
+\param[in] xMin2 Coordenada X mínima del rectángulo 2.
+\param[in] xMax2 Coordenada X máxima del rectángulo 2.
+\param[in] yMin2 Coordenada Y mínima del rectángulo 2.
+\param[in] yMax2 Coordenada Y máxima del rectángulo 2.
+\return Dos posibilidades:
+ - 0: Los rectángulos no son disjuntos, es decir, tienen alguna parte
+ común (se cortan o se tocan) o uno está completamente contenido en
+ el otro.
+ - Distinto de 0: Los rectángulos son disjuntos.
+\note Esta función asume que \em xMin1<xMax1, \em yMin1<yMax1, \em xMin2<xMax2 e
+ \em yMin2<yMax2.
+\date 13 de junio de 2010: Creación de la función.
+\todo Esta función no está probada.
+*/
+int RectDisjuntos(const double xMin1,
+ const double xMax1,
+ const double yMin1,
+ const double yMax1,
+ const double xMin2,
+ const double xMax2,
+ const double yMin2,
+ const double yMax2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un polígono de un número
+ arbitrario de lados. Esta función puede no dar resultados correctos para
+ puntos en los bordes y/o los vértices del polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Puede contener varios polígonos.
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Puede contener varios polígonos.
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+\note El código de esta función ha sido tomado de
+ http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html y
+ se han hecho pequeñas modificaciones para permitir el trabajo con vectores
+ que contengan elementos separados entre sí por varias posiciones.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función no detecta el caso de que el punto de trabajo esté en el
+ borde o en un vértice del polígono. En este caso, el test puede dar el
+ punto dentro o fuera, indistintamente (el chequeo del mismo punto con el
+ mismo polígono siempre dará el mismo resultado).
+\note La estructura de los vectores de coordenadas puede contener uno o varios
+ polígonos, de la siguiente manera:
+ -# Los vectores de vértices pasados puedes contener elementos aislados
+ (varios polígonos) y/o agujeros en los elementos. En los vectores de
+ entrada se han de separar los polígonos y los agujeros mediante un
+ vértice de coordenadas NaN=(#GEOC_NAN, #GEOC_NAN), de la siguiente
+ forma:
+ -# Primero, se incluye un vértice NaN.
+ -# A continuación, se incluyen las coordenadas de los vértices del
+ primer elemento, repitiendo el primer vértice después del último.
+ -# Se incluye otro vértice NaN.
+ -# Se incluye otro elemento, repitiendo el primer vértice después del
+ último.
+ -# Se repiten los dos pasos anteriores por cada elemento o agujero.
+ -# Se incluye un vértice NaN al final.
+ -# Por ejemplo, dados tres elementos aislados de vértices A1, A2, A3, B1,
+ B2, B3 y C1, C2, C3, y dos agujeros de vértices H1, H2, H3 e I1, I2,
+ I3, los vértices serán listados en los vectores de coordenadas como:
+ - NaN,A1,A2,A2,A1,NaN,B1,B2,B3,B1,NaN,C1,C2,C3,C1,NaN,H1,H2,H3,H1,NaN,
+ I1,I2,I3,I1,NaN.
+ -# Los vértices de cada elemento y/o agujero pueden ser listados en
+ sentido dextrógiro o levógiro.
+ -# Si el polígono es único y no tiene agujeros es opcional repetir el
+ primer vértice después del último e iniciar y terminar el listado de
+ coordenadas con el vértice NaN. Pero si se inicia y termina el listado
+ con vértices NaN, ha de repetirse el primer vértice del polígono.
+\date 05 de abril de 2010: Creación de la función.
+\date 10 de abril de 2011: Adición de los argumentos de entrada \em incX e
+ \em incY.
+\date 12 de abril de 2011: Las variables de salida son ahora constantes
+ simbólicas.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligono(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido o es un vértice de un polígono de un
+ número arbitrario de lados. Esta función puede no dar resultados
+ correctos para puntos en los bordes del polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice del polígono.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función utiliza en uno de sus pasos la función \ref PtoEnPoligono y
+ se comporta igual que ella en el caso de puntos en el borde.
+\note La estructura de los vectores de coordenadas es idéntica a la de la
+ función \ref PtoEnPoligono.
+\date 09 de abril de 2010: Creación de la función.
+\date 10 de abril de 2011: Adición de los argumentos de entrada \em incX e
+ \em incY.
+\date 12 de abril de 2011: Las variables de salida son ahora constantes
+ simbólicas.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVertice(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un polígono de un número
+ arbitrario de lados. Esta función trata correctamente los puntos situados
+ en los bordes y/o los vértices del polígono, pero sólo trabaja con datos
+ de tipo entero.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\return Varias posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice del polígono.
+ - #GEOC_PTO_BORDE_POLIG: El punto pertenece a la frontera del polígono,
+ pero no es un vértice.
+\note El código de esta función ha sido tomado del texto Joseph O'Rourke (2001),
+ Computational geometry in C, 2a edición, Cambridge University Press,
+ página 244.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note El polígono ha de ser único, sin huecos. Es opcional repetir las
+ coordenadas del primer punto al final del listado.
+\note Los vértices del polígono pueden listarse en sentido dextrógiro o
+ levógiro.
+\note <b>Esta función puede dar resultados incorrectos para puntos muy alejados
+ de los polígonos de trabajo. Para intentar mitigar este efecto, puede
+ seleccionarse mediante una variable del preprocesador la precisión de
+ algunas variables intermedias. Para más información se recomienda leer el
+ encabezado de este fichero.</b>
+\note Con cálculos internos de 32 bits las coordenadas de los vértices del
+ polígono no han de estar más lejos de las de los puntos de trabajo de unas
+ 40000 unidades. Con cálculos de 64 bits, los polígonos pueden estar
+ alejados de los puntos de trabajo unas 3000000000 unidades, lo que
+ corresponde a coordenadas Y UTM ajustadas al centímetro. Con esto
+ podríamos chequear un punto en un polo con respecto a un polígono en el
+ ecuador en coordenadas UTM expresadas en centímetros.
+\date 06 de abril de 2010: Creación de la función.
+\date 10 de abril de 2011: Adición de los argumentos de entrada \em incX e
+ \em incY.
+\date 12 de abril de 2011: Las variables de salida son ahora constantes
+ simbólicas.
+\date 18 de abril de 2011: Reescritura de la función, siguiendo la página 244
+ del libro de O'Rourke. La versión anterior la había adaptado del código de
+ la web de O'Rourke, y lo había hecho mal.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVerticeBorde(const long x,
+ const long y,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en un polígono de un número
+ arbitrario de lados. Esta función trata correctamente los puntos situados
+ en los bordes y/o los vértices del polígono. Trabaja con datos de tipo
+ real, que convierte a enteros (por redondeo o truncamiento) intermamente,
+ mediante la aplicación de un factor de escala.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Sólo puede contener un polígono.
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[in] factor Factor de multiplicación para aplicar a las coordenadas del
+ punto de trabajo y de los vértices del polígono, con el fin de
+ aumentar su resolución antes de convertirlas en valores de tipo
+ entero (\p long \p int). El uso de factores muy grandes puede
+ provocar resultados erróneos. Ver la nota al final de la
+ documentación de esta función.
+\param[in] redondeo Identificador de redondeo o truncamiento en la conversión
+ interna de variables de tipo \p double en variables de tipo
+ \p long \p int. Dos posibilidades:
+ - 0: La conversión se hace por truncamiento.
+ - Distinto de 0: La conversión se hace por redondeo.
+\return Varias posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice del polígono.
+ - #GEOC_PTO_BORDE_POLIG: El punto pertenece a la frontera del polígono,
+ pero no es un vértice.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note El polígono ha de ser único, sin huecos. Es opcional repetir las
+ coordenadas del primer punto al final del listado.
+\note Los vértices del polígono pueden listarse en sentido dextrógiro o
+ levógiro.
+\note El código de esta función es el mismo que el de la función
+ \ref PtoEnPoligonoVerticeBorde, salvo que convierte internamente varias
+ variables intermedias de tipo \p double a tipo \p long \p int, que es el
+ tipo de datos necesario para detectar correctamente si un punto pertenece
+ al borde de un polígono.
+\note Las variables se redondean internamente con la orden
+ <tt>(long)(round(factor*variable))</tt>, y se truncan con la orden
+ <tt>(long)(factor*variable)</tt>.
+\note <b>Esta función puede dar resultados incorrectos para puntos muy alejados
+ de los polígonos de trabajo. Para intentar mitigar este efecto, puede
+ seleccionarse mediante una variable del preprocesador la precisión de
+ algunas variables intermedias. Para más información se recomienda leer el
+ encabezado de este fichero.</b>
+\note Con cálculos internos de 32 bits las coordenadas de los vértices del
+ polígono no han de estar más lejos de las de los puntos de trabajo de unas
+ 40000 unidades. Con cálculos de 64 bits, los polígonos pueden estar
+ alejados de los puntos de trabajo unas 3000000000 unidades, lo que
+ corresponde a coordenadas Y UTM ajustadas al centímetro. Con esto
+ podríamos chequear un punto en un polo con respecto a un polígono en el
+ ecuador en coordenadas UTM expresadas en centímetros. En este caso nos
+ referimos a las coordenadas una vez aplicado el factor de escala
+ \em factor.
+\date 10 de abril de 2011: Creación de la función.
+\date 11 de abril de 2011: Adición del argumento de entrada \em redondeo.
+\date 12 de abril de 2011: Las variables de salida son ahora constantes
+ simbólicas.
+\date 18 de abril de 2011: Reescritura de la función, siguiendo la página 244
+ del libro de O'Rourke. La versión anterior la había adaptado del código de
+ la web de O'Rourke, y lo había hecho mal.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVerticeBordeDouble(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca valores #GEOC_NAN es uno o dos vectores de datos. Esta función
+ está pensada para el chequeo en paralelo de la inclusión de puntos en
+ polígonos.
+\param[in] x Vector que contiene las coordenadas X de los vértices de una serie
+ de polígonos, tal y como entraría en la definición de múltiples
+ elementos (pero sin huecos) para la función \ref PtoEnPoligono. La
+ marca de separación entre polígonos ha de ser #GEOC_NAN.
+\param[in] y Vector que contiene las coordenadas Y de los vértices de una serie
+ de polígonos, tal y como entraría en la definición de múltiples
+ elementos (pero sin huecos) para la función \ref PtoEnPoligono. La
+ marca de separación entre polígonos ha de ser #GEOC_NAN. Este
+ argumento puede valer NULL, en cuyo caso sólo se trabajará con el
+ vector \em x.
+\param[in] N Número de elementos que contienen los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\param[out] nNan Número de valores #GEOC_NAN encontrados, que es el número de
+ elementos del vector de salida.
+\return Varias posibilidades:
+ - Si todo ha ido bien, vector que contiene las posiciones en el vector o
+ vectores originales donde se almacena el valor #GEOC_NAN. Si se
+ trabaja con los vectores \em x e \em y, la posición sólo se extrae si
+ ambos vectores contienen #GEOC_NAN para una misma posición.
+ - NULL: Pueden haber ocurrido dos cosas:
+ - Si \em nNan vale 0, en los datos de entrada no hay ningún valor
+ #GEOC_NAN.
+ - Si \em nNan es mayor que 0, ha ocurrido un error interno de
+ asignación de memoria.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y es congruente con los valores pasados en \em N, \em incX e
+ \em incY.
+\note Las posiciones de los elementos #GEOC_NAN encontradas se refieren al
+ número de elementos \em N de los vectores de trabajo. Para encontrar la
+ posición real en memoria es necesario tener en cuenta las variables
+ \em incX e \em incY.
+\date 13 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t* BuscaGeocNanEnVectores(const double* x,
+ const double* y,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ size_t* nNan);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Extrae los parámetros de inicio y número de elementos de un polígono en
+ una lista de polígonos separados por un indicador. Esta función está
+ pensada para el chequeo en paralelo de la inclusión de puntos en
+ polígonos.
+\param[in] posInd Vector que contiene las posiciones de los indicadores en el
+ vector original. Este argumento es el vector que devuelve la función
+ \ref BuscaGeocNanEnVectores.
+\param[in] indPosInd Índice en el vector de posiciones de indicadores del
+ indicador que da comienzo al polígono de trabajo.
+\param[in] incX Posiciones de separación entre los elementos del vector original
+ que almacena las coordenadas X del listado de polígonos. Este
+ argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector original
+ que almacena las coordenadas Y del listado de polígonos. Este
+ argumento siempre ha de ser un número positivo.
+\param[out] iniX Posición de inicio de la coordenada X del polígono de trabajo
+ en el vector original que almacena las coordenadas X del listado de
+ polígonos. Para encontrar la posición real en memoria es necesario
+ tener en cuenta la variable \em incX.
+\param[out] iniY Posición de inicio de la coordenada Y del polígono de trabajo
+ en el vector original que almacena las coordenadas Y del listado de
+ polígonos. Para encontrar la posición real en memoria es necesario
+ tener en cuenta la variable \em incY.
+\param[out] nElem Número de elementos que conforman el polígono de trabajo.
+\note Esta función no comprueba si el vector \em posInd contiene datos.
+\note Esta función asume que el vector \em posInd contiene un número \b *PAR* de
+ datos.
+\note Esta función asume que el argumento \em indPosInd no es la última posición
+ del vector \em posInd.
+\date 13 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+void DatosPoliIndividualEnVecInd(const size_t* posInd,
+ const size_t indPosInd,
+ const size_t incX,
+ const size_t incY,
+ size_t* iniX,
+ size_t* iniY,
+ size_t* nElem);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en una serie de polígonos
+ individuales de un número arbitrario de lados. Esta función puede no dar
+ resultados correctos para puntos en los bordes y/o los vértices del
+ polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[in] posNan Vector que almacena las posiciones en los vectores \em coorX y
+ \em coorY de los elementos #GEOC_NAN, que separan los polígonos
+ individuales. Este vector es la salida de la función
+ \ref BuscaGeocNanEnVectores.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] poli Número del polígono en que está incluido el punto de trabajo.
+ Si hay varios polígonos que contienen al punto de trabajo no se
+ puede asegurar cuál de ellos será el indicado en este argumento.
+ Este argumento sólo tiene sentido si el valor retornado por la
+ función es distinto de #GEOC_PTO_FUERA_POLIG.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de todos los polígonos
+ listados.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de, al menos, un polígono
+ de entre los listados.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función no comprueba si el número de elementos del vector \em posNan
+ es congruente con el valor pasado en \em nNan.
+\note Esta función no detecta el caso de que el punto de trabajo esté en el
+ borde o en un vértice del polígono. En este caso, el test puede dar el
+ punto dentro o fuera, indistintamente (el chequeo del mismo punto con el
+ mismo polígono siempre dará el mismo resultado).
+\note La estructura de los vectores de coordenadas es la misma que la de la
+ función \ref PtoEnPoligono. Las marcas de comienzo y final de los
+ listados, así como las de separación entre polígonos han de ser valores
+ #GEOC_NAN.
+\note Aunque los vectores \em coorX y \em coorY sólo contengan un polígono, los
+ elementos primero y último han de ser #GEOC_NAN.
+\note Los huecos en los polígonos no serán tenidos en cuenta, serán tratados
+ como polígonos individuales.
+\date 14 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en una serie de polígonos
+ individuales de un número arbitrario de lados. Esta función puede no dar
+ resultados correctos para puntos en los bordes del polígono.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[in] posNan Vector que almacena las posiciones en los vectores \em coorX y
+ \em coorY de los elementos #GEOC_NAN, que separan los polígonos
+ individuales. Este vector es la salida de la función
+ \ref BuscaGeocNanEnVectores.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] poli Número del polígono en que está incluido el punto de trabajo.
+ Si hay varios polígonos que contienen al punto de trabajo no se
+ puede asegurar cuál de ellos será el indicado en este argumento.
+ Este argumento sólo tiene sentido si el valor retornado por la
+ función es distinto de #GEOC_PTO_FUERA_POLIG.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de todos los polígonos
+ listados.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de, al menos, un polígono
+ de entre los listados.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice de, al menos, un
+ polígono de entre los listados.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función no comprueba si el número de elementos del vector \em posNan
+ es congruente con el valor pasado en \em nNan.
+\note Esta función no detecta el caso de que el punto de trabajo esté en el
+ borde del polígono. En este caso, el test puede dar el punto dentro o
+ fuera, indistintamente (el chequeo del mismo punto con el mismo polígono
+ siempre dará el mismo resultado).
+\note La estructura de los vectores de coordenadas es la misma que la de la
+ función \ref PtoEnPoligono. Las marcas de comienzo y final de los
+ listados, así como las de separación entre polígonos han de ser valores
+ #GEOC_NAN.
+\note Aunque los vectores \em coorX y \em coorY sólo contengan un polígono, los
+ elementos primero y último han de ser #GEOC_NAN.
+\note Los huecos en los polígonos no serán tenidos en cuenta, serán tratados
+ como polígonos individuales.
+\date 14 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVerticeInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en una serie de polígonos
+ individuales de un número arbitrario de lados. Esta función trata
+ correctamente los puntos situados en los bordes y/o los vértices del
+ polígono, pero sólo trabaja con datos de tipo entero.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[in] posNan Vector que almacena las posiciones en los vectores \em coorX y
+ \em coorY de los elementos #GEOC_NAN, que separan los polígonos
+ individuales. Este vector es la salida de la función
+ \ref BuscaGeocNanEnVectores.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] poli Número del polígono en que está incluido el punto de trabajo.
+ Si hay varios polígonos que contienen al punto de trabajo no se
+ puede asegurar cuál de ellos será el indicado en este argumento.
+ Este argumento sólo tiene sentido si el valor retornado por la
+ función es distinto de #GEOC_PTO_FUERA_POLIG.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de todos los polígonos
+ listados.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de, al menos, un polígono
+ de entre los listados.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice de, al menos, un
+ polígono de entre los listados.
+ - #GEOC_PTO_BORDE_POLIG: El punto pertenece a la frontera de, al menos,
+ un polígono de entre los listados, pero no es un vértice.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función no comprueba si el número de elementos del vector \em posNan
+ es congruente con el valor pasado en \em nNan.
+\note La estructura de los vectores de coordenadas es la misma que la de la
+ función \ref PtoEnPoligono. Las marcas de comienzo y final de los
+ listados, así como las de separación entre polígonos han de ser valores
+ #GEOC_NAN.
+\note Aunque los vectores \em coorX y \em coorY sólo contengan un polígono, los
+ elementos primero y último han de ser #GEOC_NAN.
+\note Los huecos en los polígonos no serán tenidos en cuenta, serán tratados
+ como polígonos individuales.
+\note <b>Esta función puede dar resultados incorrectos para puntos muy alejados
+ de los polígonos de trabajo. Para intentar mitigar este efecto, puede
+ seleccionarse mediante una variable del preprocesador la precisión de
+ algunas variables intermedias. Para más información se recomienda leer el
+ encabezado de este fichero.</b>
+\note Con cálculos internos de 32 bits las coordenadas de los vértices del
+ polígono no han de estar más lejos de las de los puntos de trabajo de unas
+ 40000 unidades. Con cálculos de 64 bits, los polígonos pueden estar
+ alejados de los puntos de trabajo unas 3000000000 unidades, lo que
+ corresponde a coordenadas Y UTM ajustadas al centímetro. Con esto
+ podríamos chequear un punto en un polo con respecto a un polígono en el
+ ecuador en coordenadas UTM expresadas en centímetros.
+\date 14 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVerticeBordeInd(const long x,
+ const long y,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido en una serie de polígonos
+ individuales de un número arbitrario de lados. Esta función trata
+ correctamente los puntos situados en los bordes y/o los vértices del
+ polígono. Trabaja con datos de tipo real, que convierte a enteros (por
+ redondeo o truncamiento) intermamente, mediante a aplicación de un factor
+ de escala.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] coorX Vector que contiene las coordenadas X de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices de los
+ elementos. Puede contener varios polígonos, pero no huecos (si los
+ hay, serán tratados como otros polígonos).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[in] factor Factor de multiplicación para aplicar a las coordenadas del
+ punto de trabajo y de los vértices de los polígonos, con el fin de
+ aumentar su resolución antes de convertirlas en valores de tipo
+ entero (\p long \p int). El uso de factores muy grandes puede
+ provocar resultados erróneos. Ver la nota al final de la
+ documentación de esta función.
+\param[in] redondeo Identificador de redondeo o truncamiento en la conversión
+ interna de variables de tipo \p double en variables de tipo
+ \p long \p int. Dos posibilidades:
+ - 0: La conversión se hace por truncamiento.
+ - Distinto de 0: La conversión se hace por redondeo.
+\param[in] posNan Vector que almacena las posiciones en los vectores \em coorX y
+ \em coorY de los elementos #GEOC_NAN, que separan los polígonos
+ individuales. Este vector es la salida de la función
+ \ref BuscaGeocNanEnVectores.
+\param[in] nNan Número de elementos del vector \em posNan.
+\param[out] poli Número del polígono en que está incluido el punto de trabajo.
+ Si hay varios polígonos que contienen al punto de trabajo no se
+ puede asegurar cuál de ellos será el indicado en este argumento.
+ Este argumento sólo tiene sentido si el valor retornado por la
+ función es distinto de #GEOC_PTO_FUERA_POLIG.
+\return Dos posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de todos los polígonos
+ listados.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de, al menos, un polígono
+ de entre los listados.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice de, al menos, un
+ polígono de entre los listados.
+ - #GEOC_PTO_BORDE_POLIG: El punto pertenece a la frontera de, al menos,
+ un polígono de entre los listados, pero no es un vértice.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em coorX y \em coorY es congruente con los valores pasados en \em N,
+ \em incX e \em incY. Tampoco comprueba si \em N es un valor mayor o igual
+ a 3, que es el número mínimo de vértices que ha de tener un polígono.
+\note Esta función no comprueba si el número de elementos del vector \em posNan
+ es congruente con el valor pasado en \em nNan.
+\note Las variables se redondean internamente con la orden
+ <tt>(long)(round(factor*variable))</tt>, y se truncan con la orden
+ <tt>(long)(factor*variable)</tt>.
+\note La estructura de los vectores de coordenadas es la misma que la de la
+ función \ref PtoEnPoligono. Las marcas de comienzo y final de los
+ listados, así como las de separación entre polígonos han de ser valores
+ #GEOC_NAN.
+\note Aunque los vectores \em coorX y \em coorY sólo contengan un polígono, los
+ elementos primero y último han de ser #GEOC_NAN.
+\note Los huecos en los polígonos no serán tenidos en cuenta, serán tratados
+ como polígonos individuales.
+\note <b>Esta función puede dar resultados incorrectos para puntos muy alejados
+ de los polígonos de trabajo. Para intentar mitigar este efecto, puede
+ seleccionarse mediante una variable del preprocesador la precisión de
+ algunas variables intermedias. Para más información se recomienda leer el
+ encabezado de este fichero.</b>
+\note Con cálculos internos de 32 bits las coordenadas de los vértices del
+ polígono no han de estar más lejos de las de los puntos de trabajo de unas
+ 40000 unidades. Con cálculos de 64 bits, los polígonos pueden estar
+ alejados de los puntos de trabajo unas 3000000000 unidades, lo que
+ corresponde a coordenadas Y UTM ajustadas al centímetro. Con esto
+ podríamos chequear un punto en un polo con respecto a un polígono en el
+ ecuador en coordenadas UTM expresadas en centímetros. En este caso nos
+ referimos a las coordenadas una vez aplicado el factor de escala
+ \em factor.
+\date 14 de abril de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PtoEnPoligonoVerticeBordeDoubleInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/recpolil.h b/src/libgeoc/recpolil.h
new file mode 100755
index 0000000..6957b92
--- /dev/null
+++ b/src/libgeoc/recpolil.h
@@ -0,0 +1,439 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file recpolil.h
+\brief Definición de estructuras y declaración de funciones para el recorte de
+ polilíneas por medio de polígonos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 04 de junio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _RECPOLIL_H_
+#define _RECPOLIL_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/errores.h"
+#include"libgeoc/eucli.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/greiner.h"
+#include"libgeoc/polig.h"
+#include"libgeoc/polil.h"
+#include"libgeoc/ptopol.h"
+#include"libgeoc/segmento.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_RECPOLIL_BUFFER_PTOS
+\brief Número de puntos para ir asignando memoria en bloques para las polilíneas
+ de salida en la funcion \ref Paso2Recpolil. Ha de ser un número mayor o
+ igual a 2.
+\date 04 de junio de 2011: Creación de la constante.
+*/
+#define GEOC_RECPOLIL_BUFFER_PTOS 100
+/******************************************************************************/
+/******************************************************************************/
+/** \enum GEOC_OP_BOOL_POLIL
+\brief Operación booleana entre polilínea y polígono.
+\date 04 de junio de 2011: Creación del tipo.
+*/
+enum GEOC_OP_BOOL_POLIL
+{
+ /** \brief Polilínea interior al polígono. */
+ GeocOpBoolDentro=111,
+ /** \brief Polilínea exterior al polígono. */
+ GeocOpBoolFuera=112
+};
+/******************************************************************************/
+/******************************************************************************/
+/** \struct _vertPolilClip
+\brief Estructura de definición de un vértice de una polilínea usada en
+ operaciones de recorte. La polilínea se almacena en memoria como una
+ lista doblemente enlazada de vértices.
+\date 04 de junio de 2011: Creación de la estructura.
+*/
+typedef struct _vertPolilClip
+{
+ /** \brief Coordenada X del vértice. */
+ double x;
+ /** \brief Coordenada Y del vértice. */
+ double y;
+ /** \brief Vértice anterior. */
+ struct _vertPolilClip* anterior;
+ /** \brief Vértice siguiente. */
+ struct _vertPolilClip* siguiente;
+ /**
+ \brief Indicador de punto de la polilínea original.
+
+ Dos posibilidades:
+ - 0: No es un punto de la polilínea original.
+ - Distinto de 0: Sí es un punto de la polilínea original.
+ */
+ char orig;
+ /**
+ \brief Posición del vértice con respecto al polígono de recorte.
+
+ Tres posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera del polígono.
+ - #GEOC_PTO_BORDE_POLIG: El punto está en el borde o en un vértice
+ del polígono.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro del polígono.
+ */
+ char pos;
+ /** \brief Distancia, en tanto por uno, de un nodo de intersección con
+ respecto al primer vértice del segmento que lo contiene. */
+ double alfa;
+}vertPolilClip;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea un vértice de tipo \ref _vertPolilClip y lo inserta entre otros dos.
+\param[in] x Coordenada X del vértice.
+\param[in] y Coordenada Y del vértice.
+\param[in] anterior Vértice anterior (puede ser \p NULL).
+\param[in] siguiente Vértice siguiente (puede ser \p NULL).
+\param[in] orig Campo _vertPolilClip::orig.
+\param[in] pos Campo _vertPolilClip::pos.
+\param[in] alfa Campo _vertPolilClip::alfa.
+\return Puntero al nuevo vértice creado. Si se devuelve \p NULL, ha ocurrido un
+ error de asignación de memoria.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPolilClip* CreaVertPolilClip(const double x,
+ const double y,
+ vertPolilClip* anterior,
+ vertPolilClip* siguiente,
+ const char orig,
+ const char pos,
+ const double alfa);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una polilínea, como una lista doblemente enlazada de elementos
+ \ref _vertPolilClip.
+\param[in] x Vector de coordenadas X de los nodos de la polilínea.
+\param[in] y Vector de coordenadas Y de los nodos de la polilínea.
+\param[in] nCoor Número de elementos de los vectores \em x e \em y.
+\param[in] incX Posiciones de separación entre los elementos del vector \em x.
+ Este argumento siempre ha de ser un número positivo.
+\param[in] incY Posiciones de separación entre los elementos del vector \em y.
+ Este argumento siempre ha de ser un número positivo.
+\return Puntero al primer vértice de la lista. Si se devuelve \p NULL, ha
+ ocurrido un error de asignación de memoria.
+\note Esta función asume que el argumento \em nCoor es mayor que 0.
+\note Si en los vectores de coordenadas \em x e \em y hay valores #GEOC_NAN,
+ éstos no se tienen en cuenta a la hora de la creación de la estructura de
+ salida.
+\note Que los vectores de coordenadas \em x e \em y admitan vértices con
+ coordenadas (#GEOC_NAN,#GEOC_NAN) no quiere decir que éstos sean
+ separadores de múltiples polilíneas. \em x e \em y \b *SÓLO* deben
+ almacenar una única polilínea.
+\note Esta función asigna el valor 0 a todos los campos _vertPolilClip::pos de
+ los elementos creados.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPolilClip* CreaPolilClip(const double* x,
+ const double* y,
+ const size_t nCoor,
+ const size_t incX,
+ const size_t incY);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Libera la memoria asignada a una polilínea almacenada como una lista
+ doblemente enlazada de elementos \ref _vertPolilClip.
+\param[in] poli Puntero al primer elemento de la polilínea.
+\note Esta función no comprueba si hay vértices de la polilínea anteriores al
+ vértice de entrada, por lo que si se quiere liberar toda la memoria
+ asignada a una polilínea, el vértice pasado ha de ser el primero de la
+ lista.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void LibMemPolilClip(vertPolilClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina los vértices no originales de una polilínea almacenada como una
+ lista doblemente enlazada de elementos \ref _vertPolilClip.
+\param[in] poli Puntero al primer elemento de la polilínea.
+\return Puntero al primer elemento de la polilínea original. Si se devuelve
+ \p NULL, ninguno de los vértices pertenecía a la polilínea original.
+\note Los vértices eliminados por esta función son todos aquéllos cuyo campo
+ _vertPolilClip::orig sea igual a 0.
+\note Aunque se supone que el primer vértice de una polilínea siempre es un
+ vértice original, si no lo es, la variable de entrada queda modificada.
+ Por tanto, siempre es recomendable capturar la variable de salida, que
+ garantiza la posición del primer elemento.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPolilClip* ReiniciaPolilClip(vertPolilClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Busca el siguiente vértice original en una polilínea.
+\param[in] vert Puntero al vértice a partir del cual se ha de buscar.
+\return Puntero al siguiente vértice original en la polilínea. Si se devuelve
+ \p NULL, se ha llegado al final.
+\note Los vértices no originales son todos aquéllos cuyo campo
+ _vertPolilClip::orig es distinto de 0.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+vertPolilClip* SiguienteVertOrigPolilClip(vertPolilClip* vert);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Inserta un vértice de tipo \ref _vertPolilClip entre otros dos,
+ atendiendo al campo _vertPolilClip::alfa.
+\param[in] ins Vértice a insertar.
+\param[in] extremoIni Extremo inicial del segmento donde se insertará \em ins.
+\param[in] extremoFin Extremo final del segmento donde se insertará \em ins.
+\note Esta función asume que todos los elementos pasados tienen memoria
+ asignada.
+\note Si entre \em extremoIni y \em extremoFin hay más vértices, \em ins se
+ insertará de tal modo que los campos _vertPolilClip::alfa queden ordenados
+ de menor a mayor.
+\note Si el campo _vertPolilClip::alfa de \em ins tiene el mismo valor que el
+ de \em extremoIni, \em ins se insertará justo a continuación de
+ \em extremoIni.
+\note Si el campo _vertPolilClip::alfa de \em ins tiene el mismo valor que el
+ de \em extremoFin, \em ins se insertará justo antes de \em extremoIni.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void InsertaVertPolilClip(vertPolilClip* ins,
+ vertPolilClip* extremoIni,
+ vertPolilClip* extremoFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Cuenta el número de vértices originales que hay en una polilínea
+ almacenada como una lista doblemente enlazada de elementos
+ \ref _vertPolilClip.
+\param[in] poli Polilínea, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPolilClip. Sólo se tienen en cuenta los vértices
+ originales de la polilínea, que son todos aquéllos cuyo campo
+ _vertPolilClip::orig es distinto de 0.
+\return Número de vértices originales almacenados.
+\note Esta función no comprueba si la variable \em poli es una polilínea
+ correctamente almacenada.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t NumeroVertOrigPolilClip(vertPolilClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Cuenta el número total de vértices que hay en una polilínea almacenada
+ como una lista doblemente enlazada de elementos \ref _vertPolilClip.
+\param[in] poli Polilínea, almacenado como una lista doblemente enlazada de
+ elementos \ref _vertPolilClip. Se tienen en cuenta todos los
+ vértices.
+\return Número total de vértices almacenados.
+\note Esta función no comprueba si la variable \em poli es una polilínea
+ correctamente almacenada.
+\date 04 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+size_t NumeroVertPolilClip(vertPolilClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza el paso número 1 del algoritmo de recorte de polilíneas, que
+ consiste en el cálculo de los puntos de intersección de la polilínea de
+ trabajo con el polígono de recorte.
+
+ Este paso está inspirado en el primer paso del algoritmo de
+ Greiner-Hormann.
+\param[in,out] poli Polilínea de trabajo, representada como una lista doblemente
+ enlazada de elementos \ref _vertPolilClip. Al término de la
+ ejecución de la función se le han añadido los puntos de
+ intersección con el polígono de recorte y se han asignado los
+ valores correctos al campo _vertPolilClip::pos de cada vértice.
+\param[in] poliRec Polígono de recorte, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip.
+\param[out] nIntersec Número de intersecciones (intersecciones propiamente
+ dichas y puntos en el borde del polígono) calculadas.
+\return Variable de estado. Dos posibilidades:
+ - #GEOC_ERR_NO_ERROR: Todo ha ido bien.
+ - #GEOC_ERR_ASIG_MEMORIA: Ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si las variables \em polil y \em poliRec son
+ estructuras correctamente almacenadas.
+\note El polígono \em poliRec puede provenir de una operación booleana previa
+ entre polígonos, ya que sólo se recorrerán sus vértices originales, que
+ serán aquéllos cuyo campo _vertPoliClip::interseccion valga 0.
+\date 06 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int Paso1Recpolil(vertPolilClip* poli,
+ vertPoliClip* poliRec,
+ size_t* nIntersec);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Realiza el paso número 2 del algoritmo de recorte de polilíneas, que
+ consiste en la generación de lss polilíneas resultado.
+\param[in] poli Polilínea a recortar, representada como una lista doblemente
+ enlazada de elementos \ref _vertPolilClip, tal y como sale de la
+ función \ref Paso1Recpolil.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIL.
+\return Estructura \ref polil con las polilíneas resultado de la operación. Si
+ se devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si la variable \em polil es una polilínea
+ correctamente almacenada.
+\date 06 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polil* Paso2Recpolil(vertPolilClip* poli,
+ const enum GEOC_OP_BOOL_POLIL op);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Recorta una polilínea según un polígono de recorte.
+\param[in,out] poli Polilínea de trabajo, representada como una lista doblemente
+ enlazada de elementos \ref _vertPolilClip. Al término de la
+ ejecución de la función se le han añadido los puntos de
+ intersección con el polígono de recorte y se han asignado los
+ valores correctos al campo _vertPolilClip::pos de cada vértice.
+\param[in] poliRec Polígono de recorte, representado como una lista doblemente
+ enlazada de elementos \ref _vertPoliClip.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIL. Varias posibilidades:
+ - #GeocOpBoolDentro: Calcula la porción de \em poli que está dentro
+ \em poliRec.
+ - #GeocOpBoolFuera: Calcula la porción de \em poli que está fuera
+ \em poliRec.
+\param[out] nIntersec Número de intersecciones calculadas.
+\return Estructura \ref polil con las polilíneas resultado de la operación. Si
+ se devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si las variables \em poli y \em poliRec son
+ estructuras correctamente almacenadas.
+\note Esta función no comprueba internamente si \em op pertenece al tipo
+ enumerado #GEOC_OP_BOOL_POLIL. Si se introduce un valor no perteneciente
+ al tipo, se realiza la operación #GeocOpBoolDentro.
+\note Esta función asume que los puntos de borde pertenecen al interior del
+ polígono de recorte.
+\note Esta función asume que los puntos de borde sólo pertenecen al exterior del
+ polígono de recorte cuando son principio o final de polilínea recortada.
+\date 06 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polil* RecortaPolil(vertPolilClip* poli,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIL op,
+ size_t* nIntersec);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Recorta múltiples polilíneas según múltiples polígonos de recorte.
+\param[in] poli Estructura \ref polil que almacena las polilíneas de trabajo.
+\param[in] poliRec Estructura \ref polig que almacena los polígonos de recorte.
+\param[in] op Identificador de la operación a realizar. Ha de ser un elemento
+ del tipo enumerado #GEOC_OP_BOOL_POLIL. Varias posibilidades:
+ - #GeocOpBoolDentro: Calcula la porción de las polilíneas almacenadas
+ en \em poli que están dentro de los polígonos almacenados en
+ \em poliRec.
+ - #GeocOpBoolFuera: Calcula la porción de las polilíneas almacenadas
+ en \em poli que están fuera de los polígonos almacenados en
+ \em poliRec.
+\param[out] nIntersec Número total de intersecciones calculadas entre todas las
+ polilíneas con todos los polígonos.
+\return Estructura \ref polil con las polilíneas resultado de las operaciones.
+ Si se devuelve \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función realiza la operación \em op con todas las combinaciones
+ posibles de polilíneas y polígonos. Es decir, se recorren todas las
+ polilíneas y con cada una de ellas se realiza la operación \em op con cada
+ polígono almacenado en \em poliRec.
+\note Esta función no comprueba si las variables \em poli y \em poliRec son
+ estructuras correctamente almacenadas.
+\note Esta función no comprueba internamente si \em op pertenece al tipo
+ enumerado #GEOC_OP_BOOL_POLIL. Si se introduce un valor no perteneciente
+ al tipo, se realiza la operación #GeocOpBoolDentro.
+\note Esta función asume que los puntos de borde pertenecen al interior de los
+ polígonos de recorte.
+\note Esta función asume que los puntos de borde sólo pertenecen al exterior de
+ los polígonos de recorte cuando son principio o final de polilínea
+ recortada.
+\date 06 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polil* RecortaPolilMult(const polil* poli,
+ const polig* poliRec,
+ const enum GEOC_OP_BOOL_POLIL op,
+ size_t* nIntersec);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Crea una estructura \ref polil a partir de todos los vértices de una
+ polilínea almacenada como una lista doblemente enlazada de elementos
+ \ref _vertPolilClip.
+\param[in] poli Polilínea de trabajo, representada como una lista doblemente
+ enlazada de elementos \ref _vertPolilClip. El puntero pasado ha
+ de apuntar al primer elemento de la polilínea (no se controla
+ internamente).
+\return Estructura \ref polil que representa la polilínea. Si se devuelve
+ \p NULL ha ocurrido un error de asignación de memoria.
+\note Esta función no comprueba si la variable \em poli es una polilínea
+ correctamente almacenada.
+\note Esta función realiza una copia en memoria de las coordenadas de los
+ vértices de la estructura \em poli a la estructura de salida.
+\date 06 de junio de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+polil* CreaPolilPolilClip(vertPolilClip* poli);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/segmento.h b/src/libgeoc/segmento.h
new file mode 100755
index 0000000..3b3ef04
--- /dev/null
+++ b/src/libgeoc/segmento.h
@@ -0,0 +1,299 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file segmento.h
+\brief Declaración de funciones para la realización de cálculos con segmentos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 22 de abril de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _SEGMENTO_H_
+#define _SEGMENTO_H_
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/ptopol.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_NO_INTERSEC
+\brief Identificador de que dos segmentos no se cortan.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_NO_INTERSEC 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC
+\brief Identificador de que dos segmentos se cortan en un punto, pero no son
+ colineales.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC 1
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN
+\brief Identificador de que dos segmentos se cortan en un punto, el cual es un
+ extremo que está encima del otro segmento, pero no son colineales.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN 2
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_EXTREMO_COLIN
+\brief Identificador de que dos segmentos tienen un punto común y son
+ colineales.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_EXTREMO_COLIN 3
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_MISMO_SEG
+\brief Identificador de que dos segmentos tienen todos sus puntos extremos en
+ común.
+\date 21 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_MISMO_SEG 4
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_COLIN
+\brief Identificador de que dos segmentos tienen más de un punto en común.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_COLIN 5
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición relativa de un punto con respecto a una recta en el
+ plano.
+\param[in] x Coordenada X del punto de trabajo.
+\param[in] y Coordenada Y del punto de trabajo.
+\param[in] xIni Coordenada X del punto inicial del segmento que define la recta.
+\param[in] yIni Coordenada Y del punto inicial del segmento que define la recta.
+\param[in] xFin Coordenada X del punto final del segmento que define la recta.
+\param[in] yFin Coordenada Y del punto final del segmento que define la recta.
+\return Varias posibilidades:
+ - Menor que 0: El punto está a la derecha de la recta.
+ - 0: El punto pertenece a la recta.
+ - Mayor que 0: El punto está a la izquierda de la recta.
+\note Para la definición de derecha e izquierda, se considera que el sentido de
+ la recta es aquél que se define del punto de inicio al punto final del
+ segmento de trabajo.
+\note El resultado de esta función no es robusto, es decir, puede dar resultados
+ incorrectos debido a errores de redondeo (salvo que todas las coordenadas
+ pasadas sean números enteros).
+\note El código de esta función ha sido tomado de la función orient2dfast(), de
+ http://www.cs.cmu.edu/afs/cs/project/quake/public/code/predicates.c
+\date 20 de abril de 2010: Creación de la función.
+\date 14 de mayo de 2011: Cambio de nombre a la función.
+*/
+double PosPtoRecta2D(const double x,
+ const double y,
+ const double xIni,
+ const double yIni,
+ const double xFin,
+ const double yFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si tres puntos (A, B, C) del plano son colineales.
+\param[in] xA Coordenada X del punto A.
+\param[in] yA Coordenada Y del punto A.
+\param[in] xB Coordenada X del punto B.
+\param[in] yB Coordenada Y del punto B.
+\param[in] xC Coordenada X del punto C.
+\param[in] yC Coordenada Y del punto C.
+\return Dos posibilidades:
+ - 0: Los puntos no son colineales.
+ - Distinto de 0: Los puntos son colineales.
+\note Esta función utiliza internamente la función \ref PtoComunSegmParalelos2D,
+ que no es robusta. En consecuencia, los resultados de esta función tampoco
+ lo son.
+\note Estafunción sirve de apoyo para \ref PtoComunSegmParalelos2D.
+\date 14 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int TresPuntosColineales2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está situado entre dos puntos (pero no es igual a
+ ninguno de ellos) en el plano. Se asume que los tres puntos con
+ colineales.
+\param[in] x Coordenada X del punto a comprobar.
+\param[in] y Coordenada Y del punto a comprobar.
+\param[in] xA Coordenada X del primer punto del segmento.
+\param[in] yA Coordenada Y del primer punto del segmento.
+\param[in] xB Coordenada X del segundo punto del segmento.
+\param[in] yB Coordenada Y del segundo punto del segmento.
+\return Dos posibilidades:
+ - 0: El punto de trabajo no está situado entre los dos puntos dato o es
+ igual a alguno de ellos.
+ - Distinto de 0: El punto de trabajo sí está situado entre los dos
+ puntos dato.
+\note Esta función sirve de apoyo para \ref PtoComunSegmParalelos2D.
+\date 14 de mayo de 2011: Creación de la función.
+\todo Esta función no está probada.
+*/
+int PuntoEntreDosPuntos2DColin(const double x,
+ const double y,
+ const double xA,
+ const double yA,
+ const double xB,
+ const double yB);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula un punto común entre dos segmentos paralelos AB y CD.
+\param[in] xA Coordenada X del punto A.
+\param[in] yA Coordenada Y del punto A.
+\param[in] xB Coordenada X del punto B.
+\param[in] yB Coordenada Y del punto B.
+\param[in] xC Coordenada X del punto C.
+\param[in] yC Coordenada Y del punto C.
+\param[in] xD Coordenada X del punto D.
+\param[in] yD Coordenada Y del punto D.
+\param[out] x Coordenada X del punto común.
+\param[out] y Coordenada Y del punto común.
+\return Dos posibilidades:
+ - #GEOC_SEG_NO_INTERSEC: Los segmentos no tienen ningún punto en común.
+ - #GEOC_SEG_INTERSEC_EXTREMO_COLIN: Los segmentos tienen un extremo
+ común y son colineales.
+ - #GEOC_SEG_INTERSEC_MISMO_SEG: Los dos segmentos son idénticos.
+ - #GEOC_SEG_INTERSEC_COLIN: Los segmentos tienen más de un punto en
+ común.
+\note Esta función sirve de apoyo para \ref IntersecSegmentos2D.
+\note Esta función utiliza internamente la función \ref TresPuntosColineales2D,
+ que no es robusta. En consecuencia, los resultados de esta función tampoco
+ lo son.
+\note Si los segmentos se tocan en los dos extremos (son el mismo segmento), las
+ coordenadas devueltas son siempre las del vértice A.
+\note Si los segmentos tienen más de un punto en común, pero no son el mismo
+ segmento, las coordenadas de salida siempre son las de un punto extremo de
+ un segmento. Este punto extremo se intentará que sea uno de los puntos
+ iniciales de algún segmento, anque si no lo es, será uno de los finales.
+ El orden de preferencia de las coordenadas de salida es: A, C, B, D.
+\date 14 de mayo de 2011: Creación de la función.
+\date 21 de mayo de 2011: Adición de nuevos valores de salida:
+ #GEOC_SEG_INTERSEC_EXTREMO_COLIN y #GEOC_SEG_INTERSEC_MISMO_SEG.
+\todo Esta función no está probada.
+*/
+int PtoComunSegmParalelos2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ double* x,
+ double* y);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos segmentos AB y CD en el plano.
+\param[in] xA Coordenada X del punto A.
+\param[in] yA Coordenada Y del punto A.
+\param[in] xB Coordenada X del punto B.
+\param[in] yB Coordenada Y del punto B.
+\param[in] xC Coordenada X del punto C.
+\param[in] yC Coordenada Y del punto C.
+\param[in] xD Coordenada X del punto D.
+\param[in] yD Coordenada Y del punto D.
+\param[out] x Coordenada X del punto común.
+\param[out] y Coordenada Y del punto común.
+\return Cinco posibilidades:
+ - #GEOC_SEG_NO_INTERSEC: Los segmentos no tienen ningún punto en común.
+ - #GEOC_SEG_INTERSEC: Los segmentos se cortan en un punto.
+ - #GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN: El extremo de un segmento toca
+ al otro segmento, pero los segmentos no son colineales.
+ - #GEOC_SEG_INTERSEC_EXTREMO_COLIN: Los segmentos tienen un extremo
+ común y son colineales.
+ - #GEOC_SEG_INTERSEC_MISMO_SEG: Los dos segmentos son idénticos.
+ - #GEOC_SEG_INTERSEC_COLIN: Los segmentos tienen más de un punto en
+ común.
+\note Esta función utiliza internamente la función \ref PtoComunSegmParalelos2D,
+ que no es robusta. En consecuencia, los resultados de esta función tampoco
+ lo son.
+\note Si los segmentos se tocan en los dos extremos (son el mismo segmento), las
+ coordenadas devueltas son siempre las del vértice A.
+\note Si los segmentos tienen más de un punto en común, pero no son el mismo
+ segmento, las coordenadas de salida siempre son las de un punto extremo de
+ un segmento. Este punto extremo se intentará que sea uno de los puntos
+ iniciales de algún segmento, anque si no lo es, será uno de los finales.
+ El orden de preferencia de las coordenadas de salida es: A, C, B, D.
+\date 14 de mayo de 2011: Creación de la función.
+\date 21 de mayo de 2011: Adición de un nuevo valor de salida:
+ #GEOC_SEG_INTERSEC_MISMO_SEG.
+\date 06 de julio de 2011: Adición de chequeo rápido al principio de la función
+ para descartar que los segmentos no tienen ningún punto en común.
+*/
+int IntersecSegmentos2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ double* x,
+ double* y);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/libgeoc/ventorno.h b/src/libgeoc/ventorno.h
new file mode 100755
index 0000000..d330d35
--- /dev/null
+++ b/src/libgeoc/ventorno.h
@@ -0,0 +1,100 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec general
+@{
+\file ventorno.h
+\brief Definición de variables de entorno y declaración de funciones para su
+ control.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 31 de marzo de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _VENTORNO_H_
+#define _VENTORNO_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<string.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ENV_NOM_VAR_PILOMBS
+\brief Nombre de la variable de entorno para imprimir o no pasos intermedios en
+ la ejecución de la función \ref AnalisisLombSig.
+\date 31 de marzo de 2011: Creación de la constante.
+*/
+#define GEOC_ENV_NOM_VAR_PILOMBS "GEOC_ENV_PILOMBS"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ENV_VAL_REF_PILOMBS
+\brief Valor de referencia de la variable de entorno #GEOC_ENV_NOM_VAR_PILOMBS.
+\date 31 de marzo de 2011: Creación de la constante.
+*/
+#define GEOC_ENV_VAL_REF_PILOMBS "0"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si una variable de entorno está definida y es igual a un valor.
+\param[in] var Nombre de la variable de entorno a comprobar.
+\param[in] valRef Valor de referencia de la variable de entorno.
+\return Tres posibilidades:
+ - Menor que 0: La variable de entorno no está definida.
+ - 0: La variable de entorno existe, pero tiene un valor distinto a
+ \em valRef.
+ - Mayor que 0: La variable de entorno existe y tiene el mismo valor que
+ \em valRef.
+\date 31 de marzo de 2011: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+int VarEnvValRef(const char* var,
+ const char* valRef);
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/octclip.h b/src/octclip.h
new file mode 100644
index 0000000..fbb2dea
--- /dev/null
+++ b/src/octclip.h
@@ -0,0 +1,31 @@
+/* -*- coding: utf-8 -*- */
+/* Copyright (C) 2011 José Luis García Pallero, <jgpallero at gmail.com>
+ *
+ * This file is part of OctCLIP.
+ *
+ * OctCLIP 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 software; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+/******************************************************************************/
+/******************************************************************************/
+#ifndef _OCTCLIP_H_
+#define _OCTCLIP_H_
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/geom.h"
+/******************************************************************************/
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
diff --git a/src/polig.c b/src/polig.c
new file mode 100755
index 0000000..4cb3df9
--- /dev/null
+++ b/src/polig.c
@@ -0,0 +1,1815 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file polig.c
+\brief Definición de funciones para el trabajo con polígonos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 20 de abril de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/polig.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpPolig(char version[])
+{
+ //comprobamos si hay paralelización
+#if defined(_OPENMP)
+ //comprobamos si hay que extraer versión
+ if(version!=NULL)
+ {
+ //calculamos la versión
+ VersionOpenMP(_OPENMP,version);
+ }
+ //salimos de la función
+ return 1;
+#else
+ if(version!=NULL)
+ {
+ //utilizamos la variable version para que no dé warming al compilar
+ strcpy(version,"");
+ }
+ //salimos de la función
+ return 0;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* IniciaPoligVacio(void)
+{
+ //estructura de salida
+ polig* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para la estructura
+ sal = (polig*)malloc(sizeof(polig));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //inicializamos los campos escalares a 0
+ sal->nElem = 0;
+ sal->nPolig = 0;
+ sal->hayLim = 0;
+ sal->hayArea = 0;
+ //inicializamos los campos vectoriales a NULL
+ sal->x = NULL;
+ sal->y = NULL;
+ sal->posIni = NULL;
+ sal->nVert = NULL;
+ sal->xMin = NULL;
+ sal->xMax = NULL;
+ sal->yMin = NULL;
+ sal->yMax = NULL;
+ sal->area = NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AuxCreaPolig1(const size_t nElem,
+ const size_t* posNanX,
+ const size_t* posNanY,
+ const size_t nNanX,
+ const size_t nNanY,
+ size_t* nElemMax,
+ size_t* nPolig)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de salida
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay el mismo número de NaN en los dos vectores
+ if(nNanX!=nNanY)
+ {
+ //salimos de la función
+ return GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG;
+ }
+ //comprobamos si hay NaN en las mismas posiciones de los vectores
+ for(i=0;i<nNanX;i++)
+ {
+ //comprobamos si las posiciones no son las mismas
+ if(posNanX[i]!=posNanY[i])
+ {
+ //salimos de la función
+ return GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos un número máximo de elementos de los vectores de coordenadas
+ //suponiendo que no hay NaN al principio ni al final y que no se repiten las
+ //coordenadas iniciales de cada polígono
+ *nElemMax = nElem+2+nNanX+1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número de polígonos, dependiendo del número de NaN
+ if((nNanX==0)||
+ ((nNanX==1)&&(posNanX[0]==0))||
+ ((nNanX==1)&&(posNanX[nNanX-1]==(nElem-1)))||
+ ((nNanX==2)&&(posNanX[0]==0)&&(posNanX[nNanX-1]==(nElem-1))))
+ {
+ //sólo hay un polígono
+ *nPolig = 1;
+ }
+ else if((posNanX[0]!=0)&&(posNanX[nNanX-1]!=(nElem-1)))
+ {
+ //si no hay NaN en los extremos, el número de polígonos es nNan+1
+ *nPolig = nNanX+1;
+ }
+ else if((posNanX[0]==0)&&(posNanX[nNanX-1]==(nElem-1)))
+ {
+ //si hay NaN en los dos extremos, el número de polígonos es nNan-1
+ *nPolig = nNanX-1;
+ }
+ else
+ {
+ //en otro caso, es el número de NaN
+ *nPolig = nNanX;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AuxCreaPolig2(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xSal,
+ double* ySal,
+ size_t* nCopias)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //en principio, el número de puntos copiados es igual al indicado
+ *nCopias = nElem;
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //salimos de la función
+ return;
+ }
+ //recorremos los puntos de trabajo
+ for(i=0;i<nElem;i++)
+ {
+ //vamos copiando
+ xSal[i] = x[i*incX];
+ ySal[i] = y[i*incY];
+ }
+ //comprobamos si hay que copiar el primer punto al final
+ if((x[0]!=x[(nElem-1)*incX])||(y[0]!=y[(nElem-1)*incY]))
+ {
+ //repetimos el primer punto
+ xSal[nElem] = x[0];
+ ySal[nElem] = y[0];
+ //aumentamos el contador de puntos copiados
+ (*nCopias)++;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AuxCreaPolig3(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ double* xSal,
+ double* ySal,
+ size_t* posIni,
+ size_t* nVert,
+ size_t* nPtos,
+ size_t* nPolig)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de vértices del polígono a copiar y posición inicial de un polígono
+ size_t nV=0,pI=0;
+ //número de vértices copiados
+ size_t nCopias=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos las variables de número de puntos copiados y número de
+ //polígonos
+ *nPtos = 0;
+ *nPolig = 0;
+ //comprobamos si los vectores empiezan directamente con coordenadas
+ if((nNan==0)||(posNan[0]!=0))
+ {
+ //el primer elemento de los vectores de salida es NaN
+ xSal[0] = GeocNan();
+ ySal[0] = GeocNan();
+ //aumentamos la variable de número de puntos copiados
+ (*nPtos)++;
+ //calculamos el número de vértices del polígono
+ if(nNan)
+ {
+ //si hay valores NaN, el número de vértices es igual a la posición
+ //del siguiente NaN
+ nV = posNan[0];
+ }
+ else
+ {
+ //si no hay NaN, el número de vértices es igual al número de
+ //elementos de los vectores de coordenadas
+ nV = nElem;
+ }
+ //copiamos el primer polígono
+ AuxCreaPolig2(&x[0],&y[0],nV,incX,incY,&xSal[*nPtos],&ySal[*nPtos],
+ &nCopias);
+ //indicamos la posición de inicio del polígono y el número de vértices
+ posIni[*nPolig] = 1;
+ nVert[*nPolig] = nCopias;
+ //sumamos el número de puntos copiados a la variable
+ (*nPtos) += nCopias;
+ //aumentamos el contador de polígonos
+ (*nPolig)++;
+ }
+ //recorremos el número de NaN
+ for(i=0;i<nNan;i++)
+ {
+ //copiamos el NaN
+ xSal[*nPtos] = GeocNan();
+ ySal[*nPtos] = GeocNan();
+ //aumentamos la variable de número de puntos copiados
+ (*nPtos)++;
+ //posición del primer punto del polígono
+ pI = posNan[i]+1;
+ //sólo continuamos si el NaN no es la última posición de los vectores
+ if(pI!=nElem)
+ {
+ //calculo el número de puntos del polígono, dependiendo del NaN de
+ //trabajo
+ if(i!=(nNan-1))
+ {
+ //todavía hay más NaN por delante
+ nV = posNan[i+1]-pI;
+ }
+ else
+ {
+ //este es el último NaN de la lista
+ nV = nElem-pI;
+ }
+ //copiamos las coordenadas del polígono
+ AuxCreaPolig2(&x[pI*incX],&y[pI*incY],nV,incX,incY,&xSal[*nPtos],
+ &ySal[*nPtos],&nCopias);
+ //comprobamos el número de puntos copiados
+ if(nCopias)
+ {
+ //indicamos la posición de inicio del polígono y el número de
+ //vértices
+ posIni[*nPolig] = *nPtos;
+ nVert[*nPolig] = nCopias;
+ //sumamos el número de puntos copiados a la variable
+ (*nPtos) += nCopias;
+ //aumentamos el contador de polígonos
+ (*nPolig)++;
+ }
+ else
+ {
+ //si no se han copiado puntos, el polígono era falso (había dos
+ //NaN seguidos, luego descuento el último NaN copiado
+ (*nPtos)--;
+ }
+ }
+ }
+ //copiamos el último NaN, si no se ha copiado ya
+ if(!EsGeocNan(xSal[(*nPtos)-1]))
+ {
+ //copiamos
+ xSal[*nPtos] = GeocNan();
+ ySal[*nPtos] = GeocNan();
+ //aumentamos el contador de puntos
+ (*nPtos)++;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* CreaPolig(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ int* idError)
+{
+ //número de puntos
+ size_t ptos=0;
+ //número máximo de elementos de los vectores de coordenadas
+ size_t nElemMax=0;
+ //número de polígonos
+ size_t nPolig=0;
+ //número de identificadores NaN
+ size_t nNanX=0,nNanY=0;
+ //posiciones de los identificadores NaN
+ size_t* posNanX=NULL;
+ size_t* posNanY=NULL;
+ //estructura de salida
+ polig* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de error
+ *idError = GEOC_ERR_NO_ERROR;
+ //creamos la estructura vacía
+ sal = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //devolvemos la estructura vacía
+ return sal;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contamos el número de identificadores NaN en los vectores de entrada
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(posNanX,x,nNanX,posNanY,y,nNanY)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //contamos el número de indentificadores NaN en el vector X
+ posNanX = PosGeocNanEnVector(x,nElem,incX,&nNanX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //contamos el número de indentificadores NaN en el vector Y
+ posNanY = PosGeocNanEnVector(y,nElem,incY,&nNanY);
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores de asignación de memoria
+ if(((posNanX==NULL)&&(nNanX!=0))||((posNanY==NULL)&&(nNanY!=0)))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los vectores tienen bien colocados los NaN y calculamos
+ //el número máximo de elementos de los vectores de la estructura y el
+ //número de polígonos
+ *idError = AuxCreaPolig1(nElem,posNanX,posNanY,nNanX,nNanY,&nElemMax,
+ &nPolig);
+ //comprobamos los posibles errores
+ if(*idError!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ free(posNanX);
+ free(posNanY);
+ //escribimos el mensaje de error
+ if(*idError==GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen el mismo "
+ "número de polígonos");
+ }
+ else if(*idError==GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen los mismos "
+ "polígonos");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el número de polígonos
+ sal->nPolig = nPolig;
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(sal,nElemMax,nPolig)
+#endif
+{
+ //asignamos memoria para los vectores de la estructura
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->x = (double*)malloc(nElemMax*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->y = (double*)malloc(nElemMax*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->posIni = (size_t*)malloc(nPolig*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->nVert = (size_t*)malloc(nPolig*sizeof(double));
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores
+ if((sal->x==NULL)||(sal->y==NULL)||(sal->posIni==NULL)||(sal->nVert==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //copiamos los polígonos a la estructura
+ //como ya sabemos que el número de NaN y sus posiciones son los mismos para
+ //los vectores x e y, trabajamos con los valores para el vector x
+ AuxCreaPolig3(x,y,nElem,incX,incY,posNanX,nNanX,sal->x,sal->y,sal->posIni,
+ sal->nVert,&ptos,&nPolig);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay de verdad algún polígono
+ if(nPolig==0)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ free(posNanX);
+ free(posNanY);
+ //creamos la estructura vacía
+ sal = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //salimos de la función
+ return sal;
+ }
+ //asignamos el número de elementos a la estructura
+ sal->nElem = ptos;
+ //comprobamos si hay que reajustar el tamaño de los vectores de coordenadas
+ if(ptos!=nElemMax)
+ {
+ //asignamos el nuevo tamaño de los vectores
+ sal->nElem = ptos;
+ //reajustamos los tamaños
+ sal->x = (double*)realloc(sal->x,ptos*sizeof(double));
+ sal->y = (double*)realloc(sal->y,ptos*sizeof(double));
+ }
+ //comprobamos si el número de polígonos es el estimado
+ if(nPolig!=sal->nPolig)
+ {
+ //asignamos de nuevo la variable de número de polígonos
+ sal->nPolig = nPolig;
+ //reajustamos los tamaños
+ sal->posIni = (size_t*)realloc(sal->posIni,nPolig*sizeof(size_t));
+ sal->nVert = (size_t*)realloc(sal->nVert,nPolig*sizeof(size_t));
+ }
+ //comprobamos los posibles errores
+ if((sal->x==NULL)||(sal->y==NULL)||(sal->posIni==NULL)||(sal->nVert==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria asignada
+ free(posNanX);
+ free(posNanY);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+void EnlazaCamposPolig(polig* poliEnt,
+ polig* poliSal)
+{
+ //LIBERAMOS LA POSIBLE MEMORIA ASIGNADA A LOS CAMPOS VECTORIALES DE LA
+ //ESTRUCTURA DE SALIDA
+ //comprobamos si hay algún elemento en los vectores de coordenadas
+ if(poliSal->nElem)
+ {
+ free(poliSal->x);
+ free(poliSal->y);
+ }
+ //comprobamos si hay algún polígono en los vectores de posiciones
+ if(poliSal->nPolig)
+ {
+ free(poliSal->posIni);
+ free(poliSal->nVert);
+ }
+ //comprobamos si hay límites calculados
+ if(poliSal->hayLim)
+ {
+ free(poliSal->xMin);
+ free(poliSal->xMax);
+ free(poliSal->yMin);
+ free(poliSal->yMax);
+ }
+ //comprobamos si hay superficies calculadas
+ if(poliSal->hayArea)
+ {
+ free(poliSal->area);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //enlazamos todos los campos de la estructura de entrada en la de salida
+ poliSal->nElem = poliEnt->nElem;
+ poliSal->x = poliEnt->x;
+ poliSal->y = poliEnt->y;
+ poliSal->nPolig = poliEnt->nPolig;
+ poliSal->posIni = poliEnt->posIni;
+ poliSal->nVert = poliEnt->nVert;
+ poliSal->hayLim = poliEnt->hayLim;
+ poliSal->xMin = poliEnt->xMin;
+ poliSal->xMax = poliEnt->xMax;
+ poliSal->yMin = poliEnt->yMin;
+ poliSal->yMax = poliEnt->yMax;
+ poliSal->hayArea = poliEnt->hayArea;
+ poliSal->area = poliEnt->area;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+polig* CopiaPolig(const polig* poli,
+ int* idError)
+{
+ //polígono de salida
+ polig* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de error
+ *idError = GEOC_ERR_NO_ERROR;
+ //inicializamos el polígono de salida
+ sal = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo continuamos si el polígono de entrada contiene datos
+ if(poli->nElem)
+ {
+ //copiamos las coordenadas de los vértices
+ *idError = AnyadeDatosPolig(sal,poli->x,poli->y,poli->nElem,1,1);
+ //comprobamos si ha ocurrido algún error
+ if((*idError)!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ //escribimos el mensaje de error
+ if((*idError)==GEOC_ERR_ASIG_MEMORIA)
+ {
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else if((*idError)==GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de coordenadas del polígono\n"
+ "de entrada no contienen el mismo número de "
+ "polígonos");
+ }
+ else if((*idError)==GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de coordenadas del polígono\n"
+ "de entrada no contienen los mismos polígonos");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //calculamos los límites
+ *idError = CalcLimitesPolig(sal);
+ //comprobamos los posibles errores
+ if((*idError)!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //comprobamos si hay que calcular superficies
+ if(poli->hayArea)
+ {
+ //calculamos las áreas
+ *idError = CalcAreaPolig(sal);
+ //comprobamos los posibles errores
+ if((*idError)!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(sal);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AnyadePoligPolig(polig* poli,
+ const polig* anyade)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //número total de elementos
+ size_t nElem=0,nPolig=0;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si el polígono a añadir está vacío, salimos de la función
+ if((anyade!=NULL)&&(anyade->nPolig==0))
+ {
+ //salimos de la función sin hacer nada
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número total de elementos del polígono conjunto
+ nElem = poli->nElem+anyade->nElem;
+ //si el polígono original contenía datos, al número total de elementos hay
+ //que restarle 1 por el NaN común que sobra al juntar las dos estructuras
+ if(poli->nPolig)
+ {
+ nElem--;
+ }
+ //calculamos el número total de polígonos
+ nPolig = poli->nPolig+anyade->nPolig;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //reasignamos memoria para cubrir los nuevos datos
+ poli->x = (double*)realloc(poli->x,nElem*sizeof(double));
+ poli->y = (double*)realloc(poli->y,nElem*sizeof(double));
+ poli->posIni = (size_t*)realloc(poli->posIni,nPolig*sizeof(size_t));
+ poli->nVert = (size_t*)realloc(poli->nVert,nPolig*sizeof(size_t));
+ //reasignamos también para los posibles vectores de límites y superficies
+ if(poli->hayLim)
+ {
+ poli->xMin = (double*)realloc(poli->xMin,nPolig*sizeof(double));
+ poli->xMax = (double*)realloc(poli->xMax,nPolig*sizeof(double));
+ poli->yMin = (double*)realloc(poli->yMin,nPolig*sizeof(double));
+ poli->yMax = (double*)realloc(poli->yMax,nPolig*sizeof(double));
+ }
+ if(poli->hayArea)
+ {
+ poli->area = (double*)realloc(poli->area,nPolig*sizeof(double));
+ }
+ //comprobamos los posibles errores en las asignaciones obligatorias
+ if((poli->x==NULL)||(poli->y==NULL)||(poli->posIni==NULL)||
+ (poli->nVert==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //comprobamos los posibles errores en las asignaciones de límites
+ if(poli->hayLim)
+ {
+ if((poli->xMin==NULL)||(poli->xMax==NULL)||(poli->yMin==NULL)||
+ (poli->yMax==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ //comprobamos los posibles errores en las asignaciones de áreas
+ if(poli->hayArea)
+ {
+ if(poli->area==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición de inicio para copiar en la estructura de salida
+ //si la estructura de salida está vacía, se comienza en la primera posición
+ //si tiene datos, se comienza a continuación en la última (dentro del bucle,
+ //la suma de posIni hace que se comience a continuación de la última)
+ pos = (poli->nPolig==0) ? 0 : poli->nElem-1;
+ //recorremos el número de nuevos elementos
+ for(i=0;i<anyade->nElem;i++)
+ {
+ //copiamos las coordenadas
+ poli->x[pos+i] = anyade->x[i];
+ poli->y[pos+i] = anyade->y[i];
+ }
+ //calculamos las posiciones a sumar para ajustar las posiciones de inicio de
+ //los polígonos añadidos
+ //si la estructura de salida está vacía, se copian las posiciones tal cual
+ //si tiene datos, se suman las posiciones ya ocupadas
+ pos = (poli->nPolig==0) ? 0 : poli->nElem-1;
+ //recorremos el número de polígonos
+ for(i=0;i<anyade->nPolig;i++)
+ {
+ //copiamos las posiciones de inicio actualizadas y el número de vértices
+ poli->posIni[poli->nPolig+i] = anyade->posIni[i]+pos;
+ poli->nVert[poli->nPolig+i] = anyade->nVert[i];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //comprobamos si ya están calculados
+ if(anyade->hayLim)
+ {
+ //recorremos el número de polígonos y copiamos los límites
+ for(i=0;i<anyade->nPolig;i++)
+ {
+ //copiamos los límites
+ poli->xMin[poli->nPolig+i] = anyade->xMin[i];
+ poli->xMax[poli->nPolig+i] = anyade->xMax[i];
+ poli->yMin[poli->nPolig+i] = anyade->yMin[i];
+ poli->yMax[poli->nPolig+i] = anyade->yMax[i];
+ }
+ }
+ else
+ {
+ //calculamos los límites y los copiamos
+ LimitesPoligonosPolig(&(anyade->x[1]),&(anyade->y[1]),1,1,
+ anyade->posIni,anyade->nVert,anyade->nPolig,
+ anyade->posIni[0],&(poli->xMin[poli->nPolig]),
+ &(poli->xMax[poli->nPolig]),
+ &(poli->yMin[poli->nPolig]),
+ &(poli->yMax[poli->nPolig]));
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular áreas
+ if(poli->hayArea)
+ {
+ //comprobamos si ya están calculadas
+ if(anyade->hayArea)
+ {
+ //recorremos el número de polígonos y copiamos las superficies
+ for(i=0;i<anyade->nPolig;i++)
+ {
+ //copiamos los límites
+ poli->area[poli->nPolig+i] = anyade->area[i];
+ }
+ }
+ else
+ {
+ //calculamos las superficies y las copiamos
+ AreaPoligonosSimplesPolig(&(anyade->x[1]),&(anyade->y[1]),1,1,
+ anyade->posIni,anyade->nVert,
+ anyade->nPolig,anyade->posIni[0],
+ &(poli->area[poli->nPolig]));
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ajustamos los tamaños antes de salir
+ poli->nElem = nElem;
+ poli->nPolig = nPolig;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AnyadeDatosPolig(polig* poli,
+ const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY)
+{
+ //polígono auxiliar
+ polig* aux=NULL;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos un nuevo polígono con los datos a añadir
+ aux = CreaPolig(x,y,nElem,incX,incY,&estado);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //escribimos el mensaje de error
+ if(estado==GEOC_ERR_ASIG_MEMORIA)
+ {
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else if(estado==GEOC_ERR_POLIG_VEC_DISTINTO_NUM_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen el mismo "
+ "número de polígonos");
+ }
+ else if(estado==GEOC_ERR_POLIG_VEC_DISTINTOS_POLIG)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen los mismos "
+ "polígonos");
+ }
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //añadimos la nueva estructura
+ estado = AnyadePoligPolig(poli,aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria utilizada
+ LibMemPolig(aux);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LibMemPolig(polig* datos)
+{
+ //comprobamos si hay memoria que liberar
+ if(datos!=NULL)
+ {
+ //liberamos la memoria asignada al vector de coordenadas X
+ if(datos->x!=NULL)
+ {
+ free(datos->x);
+ }
+ //liberamos la memoria asignada al vector de coordenadas Y
+ if(datos->y!=NULL)
+ {
+ free(datos->y);
+ }
+ //liberamos la memoria asignada al vector de posiciones
+ if(datos->posIni!=NULL)
+ {
+ free(datos->posIni);
+ }
+ //liberamos la memoria asignada al vector de número de vértices
+ if(datos->nVert!=NULL)
+ {
+ free(datos->nVert);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas X mínimas
+ if(datos->xMin!=NULL)
+ {
+ free(datos->xMin);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas X máximas
+ if(datos->xMax!=NULL)
+ {
+ free(datos->xMax);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas Y mínimas
+ if(datos->yMin!=NULL)
+ {
+ free(datos->yMin);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas Y máximas
+ if(datos->yMax!=NULL)
+ {
+ free(datos->yMax);
+ }
+ //liberamos la memoria asignada al vector de áreas
+ if(datos->area!=NULL)
+ {
+ free(datos->area);
+ }
+ //liberamos la memoria asignada a la estructura
+ free(datos);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int CalcLimitesPolig(polig* poli)
+{
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((poli->nPolig==0)||(poli->hayLim))
+ {
+ //salimos de la función si la estructura no contiene polígonos o si
+ //éstos ya tienen calculados sus límites
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+ //asignamos memoria para los vectores de límites
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->xMin = (double*)malloc((poli->nPolig)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->xMax = (double*)malloc((poli->nPolig)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->yMin = (double*)malloc((poli->nPolig)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->yMax = (double*)malloc((poli->nPolig)*sizeof(double));
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores
+ if((poli->xMin==NULL)||(poli->xMax==NULL)||(poli->yMin==NULL)||
+ (poli->yMax==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //indicamos que sí hay límites
+ poli->hayLim = 1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos los límites de todos los polígonos
+ LimitesPoligonosPolig(poli->x,poli->y,1,1,poli->posIni,poli->nVert,
+ poli->nPolig,0,poli->xMin,poli->xMax,poli->yMin,
+ poli->yMax);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LimitesPoligono(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xMin,
+ double* xMax,
+ double* yMin,
+ double* yMax)
+{
+ //posiciones de los elementos máximo y mínimo
+ size_t posXMin=0,posXMax=0,posYMin=0,posYMax=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //buscamos las posiciones de los elementos máximo y mínimo
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(x,posXMin,posXMax,y,posYMin,posYMax)
+#endif
+{
+ //posiciones en el vector X
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(x,nElem,incX,&posXMin,&posXMax);
+ //posiciones en el vector Y
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(y,nElem,incY,&posYMin,&posYMax);
+} // --> fin del #pragma omp parallel sections
+ //extraemos los valores de las posiciones calculadas
+ *xMin = x[posXMin*incX];
+ *xMax = x[posXMax*incX];
+ *yMin = y[posYMin*incY];
+ *yMax = y[posYMax*incY];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LimitesPoligonosPolig(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posIni,
+ const size_t* nVert,
+ const size_t nPolig,
+ const size_t restaPosIni,
+ double* xMin,
+ double* xMax,
+ double* yMin,
+ double* yMax)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posición inicial del polígono de trabajo
+ size_t pI=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(posIni,x,y,nVert,xMin,xMax,yMin,yMax) \
+ private(i,pI)
+#endif
+ //recorremos el número de polígonos
+ for(i=0;i<nPolig;i++)
+ {
+ //calculamos la posición inicial del polígono
+ pI = posIni[i]-restaPosIni;
+ //calculamos los límites
+ LimitesPoligono(&x[pI*incX],&y[pI*incY],nVert[i],incX,incY,&xMin[i],
+ &xMax[i],&yMin[i],&yMax[i]);
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int CalcAreaPolig(polig* poli)
+{
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((poli->nPolig==0)||(poli->hayArea))
+ {
+ //salimos de la función si la estructura no contiene polígonos o si
+ //éstos ya tienen calculada su superficie
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el vector de superficies
+ poli->area = (double*)malloc((poli->nPolig)*sizeof(double));
+ //comprobamos los posibles errores
+ if(poli->area==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //indicamos que sí hay superficies
+ poli->hayArea = 1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las superficies de todos los polígonos
+ AreaPoligonosSimplesPolig(poli->x,poli->y,1,1,poli->posIni,poli->nVert,
+ poli->nPolig,0,poli->area);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double AreaPoligonoSimple(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de elementos de trabajo, que inicializamos con el valor pasado
+ size_t nElemTrab=nElem;
+ //variable de salida
+ double area=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si el primero punto es el mismo que el último, restamos una unidad al
+ //número de elementos pasado, ya que el algoritmo está preparado para
+ //trabajar con un vector en el que no se repite el primer punto
+ if((x[0]==x[(nElem-1)*incX])&&(y[0]==y[(nElem-1)*incY]))
+ {
+ //el número de elementos de trabajo es uno menos que el pasado
+ nElemTrab = nElem-1;
+ }
+ //el algoritmo utilizado es la segunda expresión de la ecuación 21.4.20 del
+ //Numerical Recipes, tercera edición, página 1127
+ //recorremos los puntos hasta el penúltimo
+ for(i=0;i<(nElemTrab-1);i++)
+ {
+ //vamos sumando
+ area += (x[(i+1)*incX]+x[i*incX])*(y[(i+1)*incY]-y[i*incY]);
+ }
+ //sumamos la contribución del último lado, es decir, el lado que contiene
+ //como vértice final al primer punto
+ area += (x[0]+x[(nElemTrab-1)*incX])*(y[0]-y[(nElemTrab-1)*incY]);
+ //dividimos entre dos para calcular el área real
+ area /= 2.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return area;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AreaPoligonosSimplesPolig(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posIni,
+ const size_t* nVert,
+ const size_t nPolig,
+ const size_t restaPosIni,
+ double* area)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posición inicial del polígono de trabajo
+ size_t pI=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(posIni,area,x,y,nVert) \
+ private(i,pI)
+#endif
+ //recorremos el número de polígonos
+ for(i=0;i<nPolig;i++)
+ {
+ //calculamos la posición inicial del polígono
+ pI = posIni[i]-restaPosIni;
+ //calculamos la superficie
+ area[i] = AreaPoligonoSimple(&x[pI*incX],&y[pI*incY],nVert[i],incX,
+ incY);
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void EscalaYTrasladaPolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim,
+ const int aplicaArea)
+{
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos los factores de escala y las traslaciones a las coordenadas X
+ EscalaYTrasladaVector(poli->x,poli->nElem,1,escalaX,trasladaX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos los factores de escala y las traslaciones a las coordenadas Y
+ EscalaYTrasladaVector(poli->y,poli->nElem,1,escalaY,trasladaY);
+} // --> fin del #pragma omp parallel sections
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ESTA PARTE NO LA PARALELIZAMOS, YA QUE SUPONEMOS QUE EL NÚMERO DE
+ //POLÍGONOS EN UNA ESTRUCTURA SIEMPRE SERÁ MUCHÍSIMO MENOR QUE EL NÚMERO
+ //TOTAL DE VÉRTICES
+ //comprobamos si hay que aplicar el factor a los límites
+ if(aplicaLim&&poli->hayLim)
+ {
+ //aplicamos los factores de escala y las traslaciones a los límites
+ EscalaYTrasladaVector(poli->xMin,poli->nPolig,1,escalaX,trasladaX);
+ EscalaYTrasladaVector(poli->xMax,poli->nPolig,1,escalaX,trasladaX);
+ EscalaYTrasladaVector(poli->yMin,poli->nPolig,1,escalaY,trasladaY);
+ EscalaYTrasladaVector(poli->yMax,poli->nPolig,1,escalaY,trasladaY);
+ }
+ //comprobamos si hay que aplicar el factor a las superficies
+ if(aplicaArea&&poli->hayArea)
+ {
+ //aplicamos el factor de escala a las áreas
+ EscalaYTrasladaVector(poli->area,poli->nPolig,1,fabs(escalaX*escalaY),
+ 0.0);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void TrasladaYEscalaPolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim,
+ const int aplicaArea)
+{
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos las traslaciones y los factores de escala a las coordenadas X
+ TrasladaYEscalaVector(poli->x,poli->nElem,1,escalaX,trasladaX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos las traslaciones y los factores de escala a las coordenadas Y
+ TrasladaYEscalaVector(poli->y,poli->nElem,1,escalaY,trasladaY);
+} // --> fin del #pragma omp parallel sections
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ESTA PARTE NO LA PARALELIZAMOS, YA QUE SUPONEMOS QUE EL NÚMERO DE
+ //POLÍGONOS EN UNA ESTRUCTURA SIEMPRE SERÁ MUCHÍSIMO MENOR QUE EL NÚMERO
+ //TOTAL DE VÉRTICES
+ //comprobamos si hay que aplicar el factor a los límites
+ if(aplicaLim&&poli->hayLim)
+ {
+ //aplicamos las traslaciones y los factores de escala a los límites
+ TrasladaYEscalaVector(poli->xMin,poli->nPolig,1,escalaX,trasladaX);
+ TrasladaYEscalaVector(poli->xMax,poli->nPolig,1,escalaX,trasladaX);
+ TrasladaYEscalaVector(poli->yMin,poli->nPolig,1,escalaY,trasladaY);
+ TrasladaYEscalaVector(poli->yMax,poli->nPolig,1,escalaY,trasladaY);
+ }
+ //comprobamos si hay que aplicar el factor a las superficies
+ if(aplicaArea&&poli->hayArea)
+ {
+ //aplicamos el factor de escala a las áreas
+ TrasladaYEscalaVector(poli->area,poli->nPolig,1,fabs(escalaX*escalaY),
+ 0.0);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void MuevePolig(polig* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int orden,
+ const int aplicaLim,
+ const int aplicaArea)
+{
+ //comprobamos el orden de aplicación de los factores
+ if(orden==0)
+ {
+ //primero los factores de escala y luego las traslaciones
+ EscalaYTrasladaPolig(poli,escalaX,escalaY,trasladaX,trasladaY,aplicaLim,
+ aplicaArea);
+ }
+ else
+ {
+ //primero las traslaciones y luego los factores de escala
+ TrasladaYEscalaPolig(poli,escalaX,escalaY,trasladaX,trasladaY,aplicaLim,
+ aplicaArea);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AligeraPolig(polig* poli,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //posición inicial del polígono de trabajo y número de puntos del aligerado
+ size_t posIni=0,nPtos=0;
+ //puntos colineales
+ int colin=0;
+ //coordenadas de los polígonos aligerados
+ double* x=NULL;
+ double* y=NULL;
+ //estructura auxiliar
+ polig* aux=NULL;
+ //vector de posiciones después del aligerado
+ size_t* pos=NULL;
+ //variable de salida
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos una posible salida rápida
+ if(poli->nPolig==0)
+ {
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar vacía
+ aux = IniciaPoligVacio();
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos el número de polígonos almacenados
+ for(i=0;i<poli->nPolig;i++)
+ {
+ //extraemos la posición inicial del polígono de trabajo
+ posIni = poli->posIni[i];
+ //aligeramos el polígono de trabajo
+ pos = AligeraPolilinea(&(poli->x[posIni]),&(poli->y[posIni]),
+ poli->nVert[i],1,1,tol,robusto,nPtosRobusto,
+ nSegRobusto,&nPtos);
+ //comprobamos posibles errores
+ if(pos==NULL)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //comprobamos si el polígono se ha quedado en tres puntos
+ if(nPtos==3)
+ {
+ //comprobamos si los tres puntos son colineales
+ colin = TresPuntosColineales2D(poli->x[posIni+pos[0]],
+ poli->y[posIni+pos[0]],
+ poli->x[posIni+pos[1]],
+ poli->y[posIni+pos[1]],
+ poli->x[posIni+pos[2]],
+ poli->y[posIni+pos[2]]);
+ }
+ //comprobamos si después del aligerado queda algún polígono
+ if((nPtos>3)||((nPtos==3)&&(!colin)))
+ {
+ //asignamos memoria para los vectores de coordenadas del polígono
+ //aligerado
+ x = (double*)malloc(nPtos*sizeof(double));
+ y = (double*)malloc(nPtos*sizeof(double));
+ //comprobamos posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ free(pos);
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //recorremos el número de puntos del polígono aligerado
+ for(j=0;j<nPtos;j++)
+ {
+ //copiamos las coordenadas
+ x[j] = poli->x[posIni+pos[j]];
+ y[j] = poli->y[posIni+pos[j]];
+ }
+ //añadimos las coordenadas al polígono aligerado
+ estado = AnyadeDatosPolig(aux,x,y,nPtos,1,1);
+ //sólo puede haber ocurrido un error de asignación de memoria, ya
+ //que suponemos que el polígono de entrada es correcto
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ free(pos);
+ free(x);
+ free(y);
+ //escribimos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //liberamos la memoria asignada a los vectores de coordenadas
+ free(x);
+ free(y);
+ }
+ //liberamos la memoria asignada al vector de posiciones del aligerado
+ free(pos);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //calculamos los límites
+ estado = CalcLimitesPolig(aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ //comprobamos si hay que calcular superficies
+ if(poli->hayArea)
+ {
+ //calculamos las áreas
+ estado = CalcAreaPolig(aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //enlazamos los campos de la estructura auxiliar a los de la estructura de
+ //salida
+ EnlazaCamposPolig(aux,poli);
+ //liberamos la memoria asignada a la estructura auxiliar (pero no a sus
+ //campos)
+ free(aux);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ImprimeCabeceraPoligFichero(const polig* poli,
+ const size_t indice,
+ const char iniCab[],
+ const int impLim,
+ const char formCoor[],
+ const int impArea,
+ const char formArea[],
+ const double factorX,
+ const double factorY,
+ const int repitePrimerPunto,
+ FILE* idFich)
+{
+ //número de vértices del polígono de trabajo
+ size_t nVert=0;
+ //superficie de los polígonos
+ double area=0.0;
+ //límites
+ double xMin=0.0,xMax=0.0,yMin=0.0,yMax=0.0,limAux=0.0;
+ //variables de posición
+ size_t pos=0,posXMin=0,posXMax=0,posYMin=0,posYMax=0;
+ //variable auxiliar
+ size_t aux=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ajustamos la variable auxiliar como el posible número a restar si no hay
+ //que repetir el primer vértice del polígono
+ aux = (repitePrimerPunto) ? 0 : 1;
+ //número de vértices a imprimir del polígono
+ nVert = poli->nVert[indice]-aux;
+ //posición de inicio del polígono
+ pos = poli->posIni[indice];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //imprimimos la marca de inicio y el número de vértices
+ fprintf(idFich,"%s %8zu",iniCab,nVert);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que imprimir la superficie
+ if(impArea)
+ {
+ //comprobamos si ya está calculada la superficie o no
+ if(poli->hayArea)
+ {
+ //aplicamos los factores de escala y extraemos la superficie
+ area = poli->area[indice]*fabs(factorX)*fabs(factorY);
+ }
+ else
+ {
+ //calculamos la superficie
+ area = AreaPoligonoSimple(&(poli->x[pos]),&(poli->y[pos]),
+ poli->nVert[indice],1,1);
+ //aplicamos los factores de escala
+ area *= fabs(factorX)*fabs(factorY);
+ }
+ //imprimimos el valor de la superficie
+ fprintf(idFich," ");
+ fprintf(idFich,formArea,area);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que imprimir los límites
+ if(impLim)
+ {
+ //comprobamos si ya están calculados los límites
+ if(poli->hayLim)
+ {
+ //extraemos los límites
+ xMin = poli->xMin[indice];
+ xMax = poli->xMax[indice];
+ yMin = poli->yMin[indice];
+ yMax = poli->yMax[indice];
+ }
+ else
+ {
+ //buscamos las posiciones de los elementos máximo y mínimo
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+shared(poli,pos,nVert,posXMin,posXMax,posYMin,posYMax)
+#endif
+{
+ //posiciones en el vector X
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(&(poli->x[pos]),nVert,1,&posXMin,&posXMax);
+ //posiciones en el vector Y
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(&(poli->y[pos]),nVert,1,&posYMin,&posYMax);
+} // --> fin del #pragma omp parallel sections
+ //extraemos los valores extremos
+ xMin = poli->x[pos+posXMin];
+ xMax = poli->x[pos+posXMax];
+ yMin = poli->y[pos+posYMin];
+ yMax = poli->y[pos+posYMax];
+ }
+ //comprobamos si el factor de escala para X es negativo
+ if(factorX<0.0)
+ {
+ //los límites cambian
+ limAux = xMin;
+ xMin = xMax;
+ xMax = limAux;
+ //aplicamos el factor de escala
+ xMin *= factorX;
+ xMax *= factorX;
+ }
+ //comprobamos si el factor de escala para Y es negativo
+ if(factorY<0.0)
+ {
+ //los límites cambian
+ limAux = yMin;
+ yMin = yMax;
+ yMax = limAux;
+ //aplicamos el factor de escala
+ yMin *= factorY;
+ yMax *= factorY;
+ }
+ //imprimimos los límites
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,xMin);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,xMax);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,yMin);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,yMax);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salto de línea final
+ fprintf(idFich,"\n");
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ImprimePoligFichero(const polig* poli,
+ const double factorX,
+ const double factorY,
+ const int repitePrimerPunto,
+ const int iniNan,
+ const int finNan,
+ const char formCoor[],
+ const int impCabecera,
+ const char iniCab[],
+ const int impLim,
+ const int impArea,
+ const char formArea[],
+ FILE* idFich)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //cadena de formato para imprimir los posibles valores NaN
+ char formNan[GEOC_NAN_LON_FORM_NUM_SIMPLE+1];
+ //variable de posición
+ size_t pos=0;
+ //variable auxiliar
+ size_t aux=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si la estructura contiene algún polígono
+ if(poli->nPolig==0)
+ {
+ //salimos sin imprimir nada
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la cadena de formato para imprimir los polibles NaN
+ FormatoNumFormatoTexto(formCoor,formNan);
+ //ajustamos la variable auxiliar como el posible número a restar si no hay
+ //que repetir el primer vértice de los polígonos
+ aux = (repitePrimerPunto) ? 0 : 1;
+ //comprobamos si hay que imprimir la marca separadora al principio
+ if(iniNan)
+ {
+ //la imprimimos
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ //recorremos el número de polígonos
+ for(i=0;i<poli->nPolig;i++)
+ {
+ //comprobamos si hay que imprimir la cabecera
+ if(impCabecera)
+ {
+ //imprimos la cabecera
+ ImprimeCabeceraPoligFichero(poli,i,iniCab,impLim,formCoor,impArea,
+ formArea,factorX,factorY,
+ repitePrimerPunto,idFich);
+ }
+ //posición del punto inicial del polígono
+ pos = poli->posIni[i];
+ //recorremos el número de vértices del polígono de trabajo
+ for(j=0;j<(poli->nVert[i]-aux);j++)
+ {
+ //imprimimos las coordenadas, multiplicadas por los factores
+ fprintf(idFich,formCoor,factorX*poli->x[pos+j]);
+ fprintf(idFich,formCoor,factorY*poli->y[pos+j]);
+ fprintf(idFich,"\n");
+ }
+ //imprimimos la marca separadora al final (menos para el último)
+ if(i!=(poli->nPolig-1))
+ {
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ }
+ //comprobamos si hay que imprimir la marca separadora al final
+ if(finNan)
+ {
+ //la imprimimos
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/polil.c b/src/polil.c
new file mode 100755
index 0000000..1da9d89
--- /dev/null
+++ b/src/polil.c
@@ -0,0 +1,1463 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file polil.c
+\brief Definición de funciones para el trabajo con polilíneas.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 03 de junio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/polil.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpPolil(char version[])
+{
+ //comprobamos si hay paralelización
+#if defined(_OPENMP)
+ //comprobamos si hay que extraer versión
+ if(version!=NULL)
+ {
+ //calculamos la versión
+ VersionOpenMP(_OPENMP,version);
+ }
+ //salimos de la función
+ return 1;
+#else
+ if(version!=NULL)
+ {
+ //utilizamos la variable version para que no dé warming al compilar
+ strcpy(version,"");
+ }
+ //salimos de la función
+ return 0;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* IniciaPolilVacia(void)
+{
+ //estructura de salida
+ polil* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para la estructura
+ sal = (polil*)malloc(sizeof(polil));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //inicializamos los campos escalares a 0
+ sal->nElem = 0;
+ sal->nPolil = 0;
+ sal->hayLim = 0;
+ //inicializamos los campos vectoriales a NULL
+ sal->x = NULL;
+ sal->y = NULL;
+ sal->posIni = NULL;
+ sal->nVert = NULL;
+ sal->xMin = NULL;
+ sal->xMax = NULL;
+ sal->yMin = NULL;
+ sal->yMax = NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AuxCreaPolil1(const size_t nElem,
+ const size_t* posNanX,
+ const size_t* posNanY,
+ const size_t nNanX,
+ const size_t nNanY,
+ size_t* nElemMax,
+ size_t* nPolil)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de salida
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay el mismo número de NaN en los dos vectores
+ if(nNanX!=nNanY)
+ {
+ //salimos de la función
+ return GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL;
+ }
+ //comprobamos si hay NaN en las mismas posiciones de los vectores
+ for(i=0;i<nNanX;i++)
+ {
+ //comprobamos si las posiciones no son las mismas
+ if(posNanX[i]!=posNanY[i])
+ {
+ //salimos de la función
+ return GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos un número máximo de elementos de los vectores de coordenadas
+ //inicializamos con el número de elementos pasados
+ *nElemMax = nElem;
+ //comprobamos si en la primera posición hay NaN o si no hay ninguno
+ if((nNanX==0)||(nNanX&&(posNanX[0]!=0)))
+ {
+ //hace falta un elemento para el primer NaN
+ (*nElemMax)++;
+ }
+ //comprobamos si en la última posición hay NaN o si no hay ninguno
+ if((nNanX==0)||(nNanX&&(posNanX[nNanX-1]!=(nElem-1))))
+ {
+ //hace falta un elemento para el último NaN
+ (*nElemMax)++;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número de polilíneas, dependiendo del número de NaN
+ if((nNanX==0)||
+ ((nNanX==1)&&(posNanX[0]==0))||
+ ((nNanX==1)&&(posNanX[nNanX-1]==(nElem-1)))||
+ ((nNanX==2)&&(posNanX[0]==0)&&(posNanX[nNanX-1]==(nElem-1))))
+ {
+ //sólo hay un polígono
+ *nPolil = 1;
+ }
+ else if((posNanX[0]!=0)&&(posNanX[nNanX-1]!=(nElem-1)))
+ {
+ //si no hay NaN en los extremos, el número de polilíneas es nNan+1
+ *nPolil = nNanX+1;
+ }
+ else if((posNanX[0]==0)&&(posNanX[nNanX-1]==(nElem-1)))
+ {
+ //si hay NaN en los dos extremos, el número de polilíneas es nNan-1
+ *nPolil = nNanX-1;
+ }
+ else
+ {
+ //en otro caso, es el número de NaN
+ *nPolil = nNanX;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AuxCreaPolil2(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ double* xSal,
+ double* ySal)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //salimos de la función
+ return;
+ }
+ //recorremos los puntos de trabajo
+ for(i=0;i<nElem;i++)
+ {
+ //vamos copiando
+ xSal[i] = x[i*incX];
+ ySal[i] = y[i*incY];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AuxCreaPolil3(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ double* xSal,
+ double* ySal,
+ size_t* posIni,
+ size_t* nVert,
+ size_t* nPtos,
+ size_t* nPolil)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de vértices de la polilínea a copiar
+ size_t nV=0;
+ //posición inicial de una polilínea
+ size_t pI=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos las variables de número de puntos copiados y número de
+ //polilíneas
+ *nPtos = 0;
+ *nPolil = 0;
+ //comprobamos si los vectores empiezan directamente con coordenadas
+ if((nNan==0)||(posNan[0]!=0))
+ {
+ //el primer elemento de los vectores de salida es NaN
+ xSal[0] = GeocNan();
+ ySal[0] = GeocNan();
+ //aumentamos la variable de número de puntos copiados
+ (*nPtos)++;
+ //calculamos el número de vértices de la polilínea
+ if(nNan)
+ {
+ //si hay valores NaN, el número de vértices es igual a la posición
+ //del siguiente NaN
+ nV = posNan[0];
+ }
+ else
+ {
+ //si no hay NaN, el número de vértices es igual al número de
+ //elementos de los vectores de coordenadas
+ nV = nElem;
+ }
+ //copiamos la primera polilínea
+ AuxCreaPolil2(&x[0],&y[0],nV,incX,incY,&xSal[*nPtos],&ySal[*nPtos]);
+ //indicamos la posición de inicio del polígono y el número de vértices
+ posIni[*nPolil] = 1;
+ nVert[*nPolil] = nV;
+ //sumamos el número de puntos copiados a la variable
+ (*nPtos) += nV;
+ //aumentamos el contador de polilíneas
+ (*nPolil)++;
+ }
+ //recorremos el número de NaN
+ for(i=0;i<nNan;i++)
+ {
+ //copiamos el NaN
+ xSal[*nPtos] = GeocNan();
+ ySal[*nPtos] = GeocNan();
+ //aumentamos la variable de número de puntos copiados
+ (*nPtos)++;
+ //posición del primer punto de la polilínea
+ pI = posNan[i]+1;
+ //sólo continuamos si el NaN no es la última posición de los vectores
+ if(pI!=nElem)
+ {
+ //calculo el número de puntos de la polilínea, dependiendo del NaN
+ //de trabajo
+ if(i!=(nNan-1))
+ {
+ //todavía hay más NaN por delante
+ nV = posNan[i+1]-pI;
+ }
+ else
+ {
+ //este es el último NaN de la lista
+ nV = nElem-pI;
+ }
+ //copiamos las coordenadas de la polilínea
+ AuxCreaPolil2(&x[pI*incX],&y[pI*incY],nV,incX,incY,&xSal[*nPtos],
+ &ySal[*nPtos]);
+ //comprobamos el número de puntos copiados
+ if(nV)
+ {
+ //indicamos la posición de inicio de la polilínea y el número de
+ //vértices
+ posIni[*nPolil] = *nPtos;
+ nVert[*nPolil] = nV;
+ //sumamos el número de puntos copiados a la variable
+ (*nPtos) += nV;
+ //aumentamos el contador de polilíneas
+ (*nPolil)++;
+ }
+ else
+ {
+ //si no se han copiado puntos, la polilínea era falsa (había dos
+ //NaN seguidos, luego descuento el último NaN copiado
+ (*nPtos)--;
+ }
+ }
+ }
+ //copiamos el último NaN, si no se ha copiado ya
+ if(!EsGeocNan(xSal[(*nPtos)-1]))
+ {
+ //copiamos
+ xSal[*nPtos] = GeocNan();
+ ySal[*nPtos] = GeocNan();
+ //aumentamos el contador de puntos
+ (*nPtos)++;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* CreaPolil(const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY,
+ int* idError)
+{
+ //número de puntos
+ size_t ptos=0;
+ //número máximo de elementos de los vectores de coordenadas
+ size_t nElemMax=0;
+ //número de polilíneas
+ size_t nPolil=0;
+ //número de identificadores NaN
+ size_t nNanX=0,nNanY=0;
+ //posiciones de los identificadores NaN
+ size_t* posNanX=NULL;
+ size_t* posNanY=NULL;
+ //estructura de salida
+ polil* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de error
+ *idError = GEOC_ERR_NO_ERROR;
+ //creamos la estructura vacía
+ sal = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //devolvemos la estructura vacía
+ return sal;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contamos el número de identificadores NaN en los vectores de entrada
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(posNanX,x,nNanX,posNanY,y,nNanY)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //contamos el número de indentificadores NaN en el vector X
+ posNanX = PosGeocNanEnVector(x,nElem,incX,&nNanX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //contamos el número de indentificadores NaN en el vector Y
+ posNanY = PosGeocNanEnVector(y,nElem,incY,&nNanY);
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores de asignación de memoria
+ if(((posNanX==NULL)&&(nNanX!=0))||((posNanY==NULL)&&(nNanY!=0)))
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los vectores tienen bien colocados los NaN y calculamos
+ //el número máximo de elementos de los vectores de la estructura y el
+ //número de polilíneas
+ *idError = AuxCreaPolil1(nElem,posNanX,posNanY,nNanX,nNanY,&nElemMax,
+ &nPolil);
+ //comprobamos los posibles errores
+ if(*idError!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ free(posNanX);
+ free(posNanY);
+ //escribimos el mensaje de error
+ if(*idError==GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen el mismo "
+ "número de polilíneas");
+ }
+ else if(*idError==GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen las mismas "
+ "polilíneas");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el número de polilíneas
+ sal->nPolil = nPolil;
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(sal,nElemMax,nPolil)
+#endif
+{
+ //asignamos memoria para los vectores de la estructura
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->x = (double*)malloc(nElemMax*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->y = (double*)malloc(nElemMax*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->posIni = (size_t*)malloc(nPolil*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ sal->nVert = (size_t*)malloc(nPolil*sizeof(double));
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores
+ if((sal->x==NULL)||(sal->y==NULL)||(sal->posIni==NULL)||(sal->nVert==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //copiamos las polilíneas a la estructura
+ //como ya sabemos que el número de NaN y sus posiciones son los mismos para
+ //los vectores x e y, trabajamos con los valores para el vector x
+ AuxCreaPolil3(x,y,nElem,incX,incY,posNanX,nNanX,sal->x,sal->y,sal->posIni,
+ sal->nVert,&ptos,&nPolil);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay de verdad alguna polilínea
+ if(nPolil==0)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ free(posNanX);
+ free(posNanY);
+ //creamos la estructura vacía
+ sal = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //salimos de la función
+ return sal;
+ }
+ //asignamos el número de elementos a la estructura
+ sal->nElem = ptos;
+ //comprobamos si hay que reajustar el tamaño de los vectores de coordenadas
+ if(ptos!=nElemMax)
+ {
+ //asignamos el nuevo tamaño de los vectores
+ sal->nElem = ptos;
+ //reajustamos los tamaños
+ sal->x = (double*)realloc(sal->x,ptos*sizeof(double));
+ sal->y = (double*)realloc(sal->y,ptos*sizeof(double));
+ }
+ //comprobamos si el número de polilíneas es el estimado
+ if(nPolil!=sal->nPolil)
+ {
+ //asignamos de nuevo la variable de número de polilíneas
+ sal->nPolil = nPolil;
+ //reajustamos los tamaños
+ sal->posIni = (size_t*)realloc(sal->posIni,nPolil*sizeof(size_t));
+ sal->nVert = (size_t*)realloc(sal->nVert,nPolil*sizeof(size_t));
+ }
+ //comprobamos los posibles errores
+ if((sal->x==NULL)||(sal->y==NULL)||(sal->posIni==NULL)||(sal->nVert==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ free(posNanX);
+ free(posNanY);
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria asignada
+ free(posNanX);
+ free(posNanY);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+void EnlazaCamposPolil(polil* poliEnt,
+ polil* poliSal)
+{
+ //LIBERAMOS LA POSIBLE MEMORIA ASIGNADA A LOS CAMPOS VECTORIALES DE LA
+ //ESTRUCTURA DE SALIDA
+ //comprobamos si hay algún elemento en los vectores de coordenadas
+ if(poliSal->nElem)
+ {
+ free(poliSal->x);
+ free(poliSal->y);
+ }
+ //comprobamos si hay alguna polilínea en los vectores de posiciones
+ if(poliSal->nPolil)
+ {
+ free(poliSal->posIni);
+ free(poliSal->nVert);
+ }
+ //comprobamos si hay límites calculados
+ if(poliSal->hayLim)
+ {
+ free(poliSal->xMin);
+ free(poliSal->xMax);
+ free(poliSal->yMin);
+ free(poliSal->yMax);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //enlazamos todos los campos de la estructura de entrada en la de salida
+ poliSal->nElem = poliEnt->nElem;
+ poliSal->x = poliEnt->x;
+ poliSal->y = poliEnt->y;
+ poliSal->nPolil = poliEnt->nPolil;
+ poliSal->posIni = poliEnt->posIni;
+ poliSal->nVert = poliEnt->nVert;
+ poliSal->hayLim = poliEnt->hayLim;
+ poliSal->xMin = poliEnt->xMin;
+ poliSal->xMax = poliEnt->xMax;
+ poliSal->yMin = poliEnt->yMin;
+ poliSal->yMax = poliEnt->yMax;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* CopiaPolil(const polil* poli,
+ int* idError)
+{
+ //polilínea de salida
+ polil* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de error
+ *idError = GEOC_ERR_NO_ERROR;
+ //inicializamos la polilínea de salida
+ sal = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //asignamos la variable de error
+ *idError = GEOC_ERR_ASIG_MEMORIA;
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo continuamos si la polilínea de entrada contiene datos
+ if(poli->nElem)
+ {
+ //copiamos las coordenadas de los vértices
+ *idError = AnyadeDatosPolil(sal,poli->x,poli->y,poli->nElem,1,1);
+ //comprobamos si ha ocurrido algún error
+ if((*idError)!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ //escribimos el mensaje de error
+ if((*idError)==GEOC_ERR_ASIG_MEMORIA)
+ {
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else if((*idError)==GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de coordenadas de la\n"
+ "polilínea de entrada no contienen el mismo número "
+ "de polilíneas");
+ }
+ else if((*idError)==GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de coordenadas de la\n"
+ "polilínea de entrada no contienen las mismas "
+ "polilíneas");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //calculamos los límites
+ *idError = CalcLimitesPolil(sal);
+ //comprobamos los posibles errores
+ if((*idError)!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(sal);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AnyadePolilPolil(polil* poli,
+ const polil* anyade)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de posición
+ size_t pos=0;
+ //número total de elementos
+ size_t nElem=0,nPolil=0;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si la polilínea a añadir está vacía, salimos de la función
+ if((anyade!=NULL)&&(anyade->nPolil==0))
+ {
+ //salimos de la función sin hacer nada
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el número total de elementos de la polilínea conjunta
+ nElem = poli->nElem+anyade->nElem;
+ //si la polilínea original contenía datos, al número total de elementos hay
+ //que restarle 1 por el NaN común que sobra al juntar las dos estructuras
+ if(poli->nPolil)
+ {
+ nElem--;
+ }
+ //calculamos el número total de polilíneas
+ nPolil = poli->nPolil+anyade->nPolil;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //reasignamos memoria para cubrir los nuevos datos
+ poli->x = (double*)realloc(poli->x,nElem*sizeof(double));
+ poli->y = (double*)realloc(poli->y,nElem*sizeof(double));
+ poli->posIni = (size_t*)realloc(poli->posIni,nPolil*sizeof(size_t));
+ poli->nVert = (size_t*)realloc(poli->nVert,nPolil*sizeof(size_t));
+ //reasignamos también para los posibles vectores de límites
+ if(poli->hayLim)
+ {
+ poli->xMin = (double*)realloc(poli->xMin,nPolil*sizeof(double));
+ poli->xMax = (double*)realloc(poli->xMax,nPolil*sizeof(double));
+ poli->yMin = (double*)realloc(poli->yMin,nPolil*sizeof(double));
+ poli->yMax = (double*)realloc(poli->yMax,nPolil*sizeof(double));
+ }
+ //comprobamos los posibles errores en las asignaciones obligatorias
+ if((poli->x==NULL)||(poli->y==NULL)||(poli->posIni==NULL)||
+ (poli->nVert==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //comprobamos los posibles errores en las asignaciones de límites
+ if(poli->hayLim)
+ {
+ if((poli->xMin==NULL)||(poli->xMax==NULL)||(poli->yMin==NULL)||
+ (poli->yMax==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición de inicio para copiar en la estructura de salida
+ //si la estructura de salida está vacía, se comienza en la primera posición
+ //si tiene datos, se comienza a continuación en la última (dentro del bucle,
+ //la suma de posIni hace que se comience a continuación de la última)
+ pos = (poli->nPolil==0) ? 0 : poli->nElem-1;
+ //recorremos el número de nuevos elementos
+ for(i=0;i<anyade->nElem;i++)
+ {
+ //copiamos las coordenadas
+ poli->x[pos+i] = anyade->x[i];
+ poli->y[pos+i] = anyade->y[i];
+ }
+ //calculamos las posiciones a sumar para ajustar las posiciones de inicio de
+ //las polilíneas añadidas
+ //si la estructura de salida está vacía, se copian las posiciones tal cual
+ //si tiene datos, se suman las posiciones ya ocupadas
+ pos = (poli->nPolil==0) ? 0 : poli->nElem-1;
+ //recorremos el número de polilíneas
+ for(i=0;i<anyade->nPolil;i++)
+ {
+ //copiamos las posiciones de inicio actualizadas y el número de vértices
+ poli->posIni[poli->nPolil+i] = anyade->posIni[i]+pos;
+ poli->nVert[poli->nPolil+i] = anyade->nVert[i];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //comprobamos si ya están calculados
+ if(anyade->hayLim)
+ {
+ //recorremos el número de polilíneas y copiamos los límites
+ for(i=0;i<anyade->nPolil;i++)
+ {
+ //copiamos los límites
+ poli->xMin[poli->nPolil+i] = anyade->xMin[i];
+ poli->xMax[poli->nPolil+i] = anyade->xMax[i];
+ poli->yMin[poli->nPolil+i] = anyade->yMin[i];
+ poli->yMax[poli->nPolil+i] = anyade->yMax[i];
+ }
+ }
+ else
+ {
+ //calculamos los límites y los copiamos
+ LimitesPoligonosPolig(&(anyade->x[1]),&(anyade->y[1]),1,1,
+ anyade->posIni,anyade->nVert,anyade->nPolil,
+ anyade->posIni[0],&(poli->xMin[poli->nPolil]),
+ &(poli->xMax[poli->nPolil]),
+ &(poli->yMin[poli->nPolil]),
+ &(poli->yMax[poli->nPolil]));
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ajustamos los tamaños antes de salir
+ poli->nElem = nElem;
+ poli->nPolil = nPolil;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AnyadeDatosPolil(polil* poli,
+ const double* x,
+ const double* y,
+ const size_t nElem,
+ const size_t incX,
+ const size_t incY)
+{
+ //polilínea auxiliar
+ polil* aux=NULL;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contemplamos una posible salida rápida
+ if(nElem==0)
+ {
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos una nueva polilínea con los datos a añadir
+ aux = CreaPolil(x,y,nElem,incX,incY,&estado);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ //escribimos el mensaje de error
+ if(estado==GEOC_ERR_ASIG_MEMORIA)
+ {
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else if(estado==GEOC_ERR_POLIL_VEC_DISTINTO_NUM_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen el mismo "
+ "número de polilíneas");
+ }
+ else if(estado==GEOC_ERR_POLIL_VEC_DISTINTAS_POLIL)
+ {
+ GEOC_ERROR("Error: Los vectores de trabajo no contienen las mismas "
+ "polilíneas");
+ }
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //añadimos la nueva estructura
+ estado = AnyadePolilPolil(poli,aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria utilizada
+ LibMemPolil(aux);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LibMemPolil(polil* datos)
+{
+ //comprobamos si hay memoria que liberar
+ if(datos!=NULL)
+ {
+ //liberamos la memoria asignada al vector de coordenadas X
+ if(datos->x!=NULL)
+ {
+ free(datos->x);
+ }
+ //liberamos la memoria asignada al vector de coordenadas Y
+ if(datos->y!=NULL)
+ {
+ free(datos->y);
+ }
+ //liberamos la memoria asignada al vector de posiciones
+ if(datos->posIni!=NULL)
+ {
+ free(datos->posIni);
+ }
+ //liberamos la memoria asignada al vector de número de vértices
+ if(datos->nVert!=NULL)
+ {
+ free(datos->nVert);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas X mínimas
+ if(datos->xMin!=NULL)
+ {
+ free(datos->xMin);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas X máximas
+ if(datos->xMax!=NULL)
+ {
+ free(datos->xMax);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas Y mínimas
+ if(datos->yMin!=NULL)
+ {
+ free(datos->yMin);
+ }
+ //liberamos la memoria asignada a los vector de coordenadas Y máximas
+ if(datos->yMax!=NULL)
+ {
+ free(datos->yMax);
+ }
+ //liberamos la memoria asignada a la estructura
+ free(datos);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int CalcLimitesPolil(polil* poli)
+{
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((poli->nPolil==0)||(poli->hayLim))
+ {
+ //salimos de la función si la estructura no contiene polilíneas o si
+ //éstas ya tienen calculados sus límites
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+ //asignamos memoria para los vectores de límites
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->xMin = (double*)malloc((poli->nPolil)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->xMax = (double*)malloc((poli->nPolil)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->yMin = (double*)malloc((poli->nPolil)*sizeof(double));
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ poli->yMax = (double*)malloc((poli->nPolil)*sizeof(double));
+} // --> fin del #pragma omp parallel sections
+ //comprobamos los posibles errores
+ if((poli->xMin==NULL)||(poli->xMax==NULL)||(poli->yMin==NULL)||
+ (poli->yMax==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //indicamos que sí hay límites
+ poli->hayLim = 1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos los límites de todas las polilíneas
+ LimitesPoligonosPolig(poli->x,poli->y,1,1,poli->posIni,poli->nVert,
+ poli->nPolil,0,poli->xMin,poli->xMax,poli->yMin,
+ poli->yMax);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void EscalaYTrasladaPolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim)
+{
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos los factores de escala y las traslaciones a las coordenadas X
+ EscalaYTrasladaVector(poli->x,poli->nElem,1,escalaX,trasladaX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos los factores de escala y las traslaciones a las coordenadas Y
+ EscalaYTrasladaVector(poli->y,poli->nElem,1,escalaY,trasladaY);
+} // --> fin del #pragma omp parallel sections
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ESTA PARTE NO LA PARALELIZAMOS, YA QUE SUPONEMOS QUE EL NÚMERO DE
+ //POLÍGONOS EN UNA ESTRUCTURA SIEMPRE SERÁ MUCHÍSIMO MENOR QUE EL NÚMERO
+ //TOTAL DE VÉRTICES
+ //comprobamos si hay que aplicar el factor a los límites
+ if(aplicaLim&&poli->hayLim)
+ {
+ //aplicamos los factores de escala y las traslaciones a los límites
+ EscalaYTrasladaVector(poli->xMin,poli->nPolil,1,escalaX,trasladaX);
+ EscalaYTrasladaVector(poli->xMax,poli->nPolil,1,escalaX,trasladaX);
+ EscalaYTrasladaVector(poli->yMin,poli->nPolil,1,escalaY,trasladaY);
+ EscalaYTrasladaVector(poli->yMax,poli->nPolil,1,escalaY,trasladaY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void TrasladaYEscalaPolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int aplicaLim)
+{
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(poli)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos las traslaciones y los factores de escala a las coordenadas X
+ TrasladaYEscalaVector(poli->x,poli->nElem,1,escalaX,trasladaX);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos las traslaciones y los factores de escala a las coordenadas Y
+ TrasladaYEscalaVector(poli->y,poli->nElem,1,escalaY,trasladaY);
+} // --> fin del #pragma omp parallel sections
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ESTA PARTE NO LA PARALELIZAMOS, YA QUE SUPONEMOS QUE EL NÚMERO DE
+ //POLÍGONOS EN UNA ESTRUCTURA SIEMPRE SERÁ MUCHÍSIMO MENOR QUE EL NÚMERO
+ //TOTAL DE VÉRTICES
+ //comprobamos si hay que aplicar el factor a los límites
+ if(aplicaLim&&poli->hayLim)
+ {
+ //aplicamos las traslaciones y los factores de escala a los límites
+ TrasladaYEscalaVector(poli->xMin,poli->nPolil,1,escalaX,trasladaX);
+ TrasladaYEscalaVector(poli->xMax,poli->nPolil,1,escalaX,trasladaX);
+ TrasladaYEscalaVector(poli->yMin,poli->nPolil,1,escalaY,trasladaY);
+ TrasladaYEscalaVector(poli->yMax,poli->nPolil,1,escalaY,trasladaY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void MuevePolil(polil* poli,
+ const double escalaX,
+ const double escalaY,
+ const double trasladaX,
+ const double trasladaY,
+ const int orden,
+ const int aplicaLim)
+{
+ //comprobamos el orden de aplicación de los factores
+ if(orden==0)
+ {
+ //primero los factores de escala y luego las traslaciones
+ EscalaYTrasladaPolil(poli,escalaX,escalaY,trasladaX,trasladaY,
+ aplicaLim);
+ }
+ else
+ {
+ //primero las traslaciones y luego los factores de escala
+ TrasladaYEscalaPolil(poli,escalaX,escalaY,trasladaX,trasladaY,
+ aplicaLim);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int AligeraPolil(polil* poli,
+ const double tol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nPtosRobusto,
+ const size_t nSegRobusto)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //posición inicial de la polilínea de trabajo y número de puntos aligerados
+ size_t posIni=0,nPtos=0;
+ //polilínea que es un mismo punto
+ int pmp=0;
+ //coordenadas de las polilíneas aligeradas
+ double* x=NULL;
+ double* y=NULL;
+ //estructura auxiliar
+ polil* aux=NULL;
+ //vector de posiciones después del aligerado
+ size_t* pos=NULL;
+ //variable de salida
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos una posible salida rápida
+ if(poli->nPolil==0)
+ {
+ //salimos de la función
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar vacía
+ aux = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos el número de polilíneas almacenadas
+ for(i=0;i<poli->nPolil;i++)
+ {
+ //extraemos la posición inicial de la polilínea de trabajo
+ posIni = poli->posIni[i];
+ //aligeramos la polilínea de trabajo
+ pos = AligeraPolilinea(&(poli->x[posIni]),&(poli->y[posIni]),
+ poli->nVert[i],1,1,tol,robusto,nPtosRobusto,
+ nSegRobusto,&nPtos);
+ //comprobamos posibles errores
+ if(pos==NULL)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //comprobamos si la polilínea se ha quedado en dos puntos
+ if(nPtos==2)
+ {
+ //comprobamos si los tres puntos son colineales
+ pmp = ((poli->x[posIni+pos[0]])==(poli->x[posIni+pos[1]]))&&
+ ((poli->y[posIni+pos[0]])==(poli->y[posIni+pos[1]]));
+ }
+ //comprobamos si después del aligerado todavía queda una polilínea que
+ //no sea un único punto
+ if((nPtos>2)||((nPtos==2)&&(!pmp)))
+ {
+ //asignamos memoria para los vectores de coordenadas de la polilínea
+ //aligerada
+ x = (double*)malloc(nPtos*sizeof(double));
+ y = (double*)malloc(nPtos*sizeof(double));
+ //comprobamos posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ free(pos);
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //recorremos el número de puntos de la polilínea aligerada
+ for(j=0;j<nPtos;j++)
+ {
+ //copiamos las coordenadas
+ x[j] = poli->x[posIni+pos[j]];
+ y[j] = poli->y[posIni+pos[j]];
+ }
+ //añadimos las coordenadas a la polilínea aligerada
+ estado = AnyadeDatosPolil(aux,x,y,nPtos,1,1);
+ //sólo puede haber ocurrido un error de asignación de memoria, ya
+ //que suponemos que la polilínea de entrada es correcta
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ free(pos);
+ free(x);
+ free(y);
+ //escribimos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //liberamos la memoria asignada a los vectores de coordenadas
+ free(x);
+ free(y);
+ }
+ //liberamos la memoria asignada al vector de posiciones del aligerado
+ free(pos);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular límites
+ if(poli->hayLim)
+ {
+ //calculamos los límites
+ estado = CalcLimitesPolil(aux);
+ //comprobamos los posibles errores
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //enlazamos los campos de la estructura auxiliar a los de la estructura de
+ //salida
+ EnlazaCamposPolil(aux,poli);
+ //liberamos la memoria asignada a la estructura auxiliar (pero no a sus
+ //campos)
+ free(aux);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return estado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ImprimeCabeceraPolilFichero(const polil* poli,
+ const size_t indice,
+ const char iniCab[],
+ const int impLim,
+ const char formCoor[],
+ const double factorX,
+ const double factorY,
+ FILE* idFich)
+{
+ //número de vértices de la polilínea de trabajo
+ size_t nVert=0;
+ //límites
+ double xMin=0.0,xMax=0.0,yMin=0.0,yMax=0.0,limAux=0.0;
+ //variables de posición
+ size_t pos=0,posXMin=0,posXMax=0,posYMin=0,posYMax=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //número de vértices a imprimir de la polilínea
+ nVert = poli->nVert[indice];
+ //posición de inicio de la polilínea
+ pos = poli->posIni[indice];
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //imprimimos la marca de inicio y el número de vértices
+ fprintf(idFich,"%s %8zu",iniCab,nVert);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que imprimir los límites
+ if(impLim)
+ {
+ //comprobamos si ya están calculados los límites
+ if(poli->hayLim)
+ {
+ //extraemos los límites
+ xMin = poli->xMin[indice];
+ xMax = poli->xMax[indice];
+ yMin = poli->yMin[indice];
+ yMax = poli->yMax[indice];
+ }
+ else
+ {
+ //buscamos las posiciones de los elementos máximo y mínimo
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+shared(poli,pos,nVert,posXMin,posXMax,posYMin,posYMax)
+#endif
+{
+ //posiciones en el vector X
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(&(poli->x[pos]),nVert,1,&posXMin,&posXMax);
+ //posiciones en el vector Y
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ MinMax(&(poli->y[pos]),nVert,1,&posYMin,&posYMax);
+} // --> fin del #pragma omp parallel sections
+ //extraemos los valores extremos
+ xMin = poli->x[pos+posXMin];
+ xMax = poli->x[pos+posXMax];
+ yMin = poli->y[pos+posYMin];
+ yMax = poli->y[pos+posYMax];
+ }
+ //comprobamos si el factor de escala para X es negativo
+ if(factorX<0.0)
+ {
+ //los límites cambian
+ limAux = xMin;
+ xMin = xMax;
+ xMax = limAux;
+ //aplicamos el factor de escala
+ xMin *= factorX;
+ xMax *= factorX;
+ }
+ //comprobamos si el factor de escala para Y es negativo
+ if(factorY<0.0)
+ {
+ //los límites cambian
+ limAux = yMin;
+ yMin = yMax;
+ yMax = limAux;
+ //aplicamos el factor de escala
+ yMin *= factorY;
+ yMax *= factorY;
+ }
+ //imprimimos los límites
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,xMin);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,xMax);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,yMin);
+ fprintf(idFich," ");
+ fprintf(idFich,formCoor,yMax);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salto de línea final
+ fprintf(idFich,"\n");
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ImprimePolilFichero(const polil* poli,
+ const double factorX,
+ const double factorY,
+ const int iniNan,
+ const int finNan,
+ const char formCoor[],
+ const int impCabecera,
+ const char iniCab[],
+ const int impLim,
+ FILE* idFich)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //cadena de formato para imprimir los posibles valores NaN
+ char formNan[GEOC_NAN_LON_FORM_NUM_SIMPLE+1];
+ //variable de posición
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si la estructura contiene alguna polilínea
+ if(poli->nPolil==0)
+ {
+ //salimos sin imprimir nada
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la cadena de formato para imprimir los polibles NaN
+ FormatoNumFormatoTexto(formCoor,formNan);
+ //comprobamos si hay que imprimir la marca separadora al principio
+ if(iniNan)
+ {
+ //la imprimimos
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ //recorremos el número de polilíneas
+ for(i=0;i<poli->nPolil;i++)
+ {
+ //comprobamos si hay que imprimir la cabecera
+ if(impCabecera)
+ {
+ //imprimos la cabecera
+ ImprimeCabeceraPolilFichero(poli,i,iniCab,impLim,formCoor,factorX,
+ factorY,idFich);
+ }
+ //posición del punto inicial de la polilínea
+ pos = poli->posIni[i];
+ //recorremos el número de vértices de la polilínea de trabajo
+ for(j=0;j<poli->nVert[i];j++)
+ {
+ //imprimimos las coordenadas, multiplicadas por factor
+ fprintf(idFich,formCoor,factorX*poli->x[pos+j]);
+ fprintf(idFich,formCoor,factorY*poli->y[pos+j]);
+ fprintf(idFich,"\n");
+ }
+ //imprimimos la marca separadora al final (menos para el último)
+ if(i!=(poli->nPolil-1))
+ {
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ }
+ //comprobamos si hay que imprimir la marca separadora al final
+ if(finNan)
+ {
+ //la imprimimos
+ ImprimeGeocNanTexto(idFich,2,formNan,1);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/ptopol.c b/src/ptopol.c
new file mode 100755
index 0000000..a44d9e0
--- /dev/null
+++ b/src/ptopol.c
@@ -0,0 +1,1007 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file ptopol.c
+\brief Declaración de funciones para la realización de chequeos de inclusión de
+ puntos en polígonos.
+
+En el momento de la compilación ha de seleccionarse el tipo de dato que se
+utilizará en los cálculos intermedios de las funciones
+\ref PtoEnPoligonoVerticeBorde y \ref PtoEnPoligonoVerticeBordeDouble. Si los
+puntos de trabajo están muy alejados de los polígonos pueden darse casos de
+resultados erróneos. Sería conveniente que los cálculos internedios se hiciesen
+en variables de 64 bits, pero el tipo <tt>long int</tt> suele ser de 4 bytes en
+procesadores de 32 bits. Para seleccionar este tipo como <tt>long long int</tt>,
+lo que en procesadores de 32 bits equivale a una variable de 64 bits, es
+necesario definir la variable para el preprocesador \em PTOPOL_BORDE_LONG_64. En
+procesadores de 64 bits no es necesario (aunque puede utilizarse), ya que el
+tipo <tt>long int</tt> tiene una longitud de 64 bits. Si no se define la
+variable, se usará un tipo <tt>long int</tt> para los cálculos intermedios. En
+\p gcc, las variables para el preprocesador se pasan como \em -DXXX, donde
+\em XXX es la variable a introducir. El uso del tipo <tt>long long int</tt> en
+procesadores de 32 bits puede hacer que las funciones se ejecuten hasta 10 veces
+más lentamente que si se utiliza el tipo <tt>long int</tt>. Con cálculos
+internos de 32 bits las coordenadas de los vértices del polígono no han de estar
+más lejos de las de los puntos de trabajo de unas 40000 unidades. Con cálculos
+de 64 bits, los polígonos pueden estar alejados de los puntos de trabajo unas
+3000000000 unidades, lo que corresponde a coordenadas Y UTM ajustadas al
+centímetro. Con esto podríamos chequear un punto en un polo con respecto a un
+polígono en el ecuador en coordenadas UTM expresadas en centímetros.
+\author José Luis García Pallero, jgpallero at gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 05 de abril de 2010
+\section Licencia Licencia
+Copyright (c) 2009-2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/ptopol.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpPtopol(char version[])
+{
+ //comprobamos si hay paralelización
+#if defined(_OPENMP)
+ //comprobamos si hay que extraer versión
+ if(version!=NULL)
+ {
+ //calculamos la versión
+ VersionOpenMP(_OPENMP,version);
+ }
+ //salimos de la función
+ return 1;
+#else
+ if(version!=NULL)
+ {
+ //utilizamos la variable version para que no dé warming al compilar
+ strcpy(version,"");
+ }
+ //salimos de la función
+ return 0;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+int GeocLongLongIntPtopol(void)
+{
+ //comprobamos si se ha pasado la variable del preprocesador
+#if defined(PTOPOL_BORDE_LONG_64)
+ return 1;
+#else
+ return 0;
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnRectangulo(const double x,
+ const double y,
+ const double xMin,
+ const double xMax,
+ const double yMin,
+ const double yMax)
+{
+ //posibles posiciones del punto
+ if((x<xMin)||(x>xMax)||(y<yMin)||(y>yMax))
+ {
+ //punto fuera
+ return GEOC_PTO_FUERA_POLIG;
+ }
+ else if((x>xMin)&&(x<xMax)&&(y>yMin)&&(y<yMax))
+ {
+ //punto dentro
+ return GEOC_PTO_DENTRO_POLIG;
+ }
+ else if(((x==xMin)&&(y==yMax))||((x==xMax)&&(y==yMax))||
+ ((x==xMax)&&(y==yMin))||((x==xMin)&&(y==yMin)))
+ {
+ //punto en un vértice
+ return GEOC_PTO_VERTICE_POLIG;
+ }
+ else
+ {
+ //punto en el borde
+ return GEOC_PTO_BORDE_POLIG;
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+int RectanguloEnRectangulo(const int borde,
+ const double xMin1,
+ const double xMax1,
+ const double yMin1,
+ const double yMax1,
+ const double xMin2,
+ const double xMax2,
+ const double yMin2,
+ const double yMax2)
+{
+ //variable de salida, que inicializamos como polígonos no disjuntos
+ int sal=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el borde se tiene en cuenta o no
+ if(borde)
+ {
+ //el borde se tiene en cuenta
+ if((xMin1>=xMin2)&&(xMax1<=xMax2)&&(yMin1>=yMin2)&&(yMax1<=yMax2))
+ {
+ //el rectángulo está contenido
+ sal = 1;
+ }
+ }
+ else
+ {
+ //el borde no se tiene en cuenta
+ if((xMin1>xMin2)&&(xMax1<xMax2)&&(yMin1>yMin2)&&(yMax1<yMax2))
+ {
+ //el rectángulo está contenido
+ sal = 1;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int RectDisjuntos(const double xMin1,
+ const double xMax1,
+ const double yMin1,
+ const double yMax1,
+ const double xMin2,
+ const double xMax2,
+ const double yMin2,
+ const double yMax2)
+{
+ //variable de salida, que inicializamos como polígonos no disjuntos
+ int sal=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si son disjuntos
+ if((xMin1>xMax2)||(xMax1<xMin2)||(yMin1>yMax2)||(yMax1<yMin2))
+ {
+ //los restángulos son disjuntos
+ sal = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligono(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY)
+{
+ //índices para recorrer un bucle
+ size_t i=0,j=0;
+ //variables de posición
+ size_t posIX=0,posJX=0,posIY=0,posJY=0;
+ //variable de salida
+ int c=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos todos los vértices del polígono
+ for(i=0,j=N-1;i<N;j=i++)
+ {
+ //calculamos previamente las posiciones para multiplicar menos
+ posIX = i*incX;
+ posJX = j*incX;
+ posIY = i*incY;
+ posJY = j*incY;
+ //calculamos
+ if(((coorY[posIY]>y)!=(coorY[posJY]>y))&&
+ (x<(coorX[posJX]-coorX[posIX])*(y-coorY[posIY])/
+ (coorY[posJY]-coorY[posIY])+coorX[posIX]))
+ {
+ c = !c;
+ }
+ }
+ //asignamos el elemento de salida
+ if(c)
+ {
+ //el punto está dentro del polígono
+ c = GEOC_PTO_DENTRO_POLIG;
+ }
+ else
+ {
+ //el punto está fuera del polígono
+ c = GEOC_PTO_FUERA_POLIG;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return c;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVertice(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable de salida, que inicializamos fuera del polígono
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el punto es un vértice
+ for(i=0;i<N;i++)
+ {
+ //comprobamos las coordenadas
+ if((x==coorX[i*incX])&&(y==coorY[i*incY]))
+ {
+ //indicamos que el punto es un vértice
+ pos = GEOC_PTO_VERTICE_POLIG;
+ //salimos del bucle
+ break;
+ }
+ }
+ //sólo continuamos si el punto no es un vértice
+ if(pos!=GEOC_PTO_VERTICE_POLIG)
+ {
+ //calculamos la posición sin tener en cuenta el borde
+ pos = PtoEnPoligono(x,y,coorX,coorY,N,incX,incY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVerticeBorde(const long x,
+ const long y,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY)
+{
+ //NOTA: SE MANTIENEN MUCHOS DE LOS COMENTARIOS ORIGINALES
+ //índices de vértices
+ size_t i=0,i1=0;
+ //number of (right,left) edge/ray crossings
+ int Rcross=0,Lcross=0;
+ //flags indicating the edge strads the X axis
+ int Rstrad=0,Lstrad=0;
+ //coordenadas del polígono referidas al punto de trabajo
+ ptopol_long cx=0,cy=0,cx1=0,cy1=0;
+ //número de elementos de trabajo del polígono
+ size_t n=N;
+ //variable auxiliar
+ double X=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el primer vértice se repite al final
+ if((coorX[0]==coorX[(N-1)*incX])&&(coorY[0]==coorY[(N-1)*incY]))
+ {
+ //trabajamos con todos los vértices, menos el último
+ n = N-1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //for each edge e=(i-1,i), see if crosses ray
+ for(i=0;i<n;i++)
+ {
+ //referimos el vértice de trabajo al punto
+ cx = coorX[i*incX]-x;
+ cy = coorY[i*incY]-y;
+ //comprobamos si el punto es un vértice del polígono
+ if((cx==0)&&(cy==0))
+ {
+ //el punto es un vértice
+ return GEOC_PTO_VERTICE_POLIG;
+ }
+ //calculamos el índice del punto anterior en el polígono
+ i1 = (i) ? i-1 : n-1;
+ //referimos el vértice de trabajo al punto según el nuevo índice
+ cx1 = coorX[i1*incX]-x;
+ cy1 = coorY[i1*incY]-y;
+ //check if e straddles X axis, with bias above/below
+ Rstrad = (cy>0)!=(cy1>0);
+ Lstrad = (cy<0)!=(cy1<0);
+ //straddle computation
+ if(Rstrad||Lstrad)
+ {
+ //compute intersection of e with x axis
+ X = ((double)(cx*cy1-cx1*cy))/((double)(cy1-cy));
+ //crosses ray if strictly positive intersection
+ if(Rstrad&&(X>0.0))
+ {
+ Rcross++;
+ }
+ //crosses ray if strictly negative intersection
+ if(Lstrad&&(X<0.0))
+ {
+ Lcross++;
+ }
+ }
+ }
+ //q on the edge if left and right cross are not the same parity
+ if((Rcross%2)!=(Lcross%2))
+ {
+ //el punto está en un borde
+ return GEOC_PTO_BORDE_POLIG;
+ }
+ //q inside if an odd number of crossings
+ if((Rcross%2)==1)
+ {
+ //el punto es interior
+ return GEOC_PTO_DENTRO_POLIG;
+ }
+ else
+ {
+ //el punto es exterior
+ return GEOC_PTO_FUERA_POLIG;
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVerticeBordeDouble(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo)
+{
+ //NOTA: SE MANTIENEN LOS COMENTARIOS ORIGINALES DE LA FUNCIÓN PARA VARIABLES
+ //DE TIPO ENTERO
+ //índices de vértices
+ size_t i=0,i1=0;
+ //number of (right,left) edge/ray crossings
+ int Rcross=0,Lcross=0;
+ //flags indicating the edge strads the X axis
+ int Rstrad=0,Lstrad=0;
+ //punto a evaluar pasado a número entero
+ ptopol_long fX=0,fY=0;
+ //coordenadas del polígono referidas al punto de trabajo
+ ptopol_long cx=0,cy=0,cx1=0,cy1=0;
+ //número de elementos de trabajo del polígono
+ size_t n=N;
+ //variable auxiliar
+ double X=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el primer vértice se repite al final
+ if((coorX[0]==coorX[(N-1)*incX])&&(coorY[0]==coorY[(N-1)*incY]))
+ {
+ //trabajamos con todos los vértices, menos el último
+ n = N-1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //pasamos a número entero el punto a evaluar
+ if(redondeo)
+ {
+ //redondeo
+ fX = (ptopol_long)(round(factor*x));
+ fY = (ptopol_long)(round(factor*y));
+ }
+ else
+ {
+ //truncamiento
+ fX = (ptopol_long)(factor*x);
+ fY = (ptopol_long)(factor*y);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //for each edge e=(i-1,i), see if crosses ray
+ for(i=0;i<n;i++)
+ {
+ //calculamos el índice del punto anterior en el polígono
+ i1 = (i) ? i-1 : n-1;
+ //para referir los vértices de trabajo al punto, comprobamos si hay que
+ //redondear o truncar
+ if(redondeo)
+ {
+ //redondeo del vértice actual
+ cx = (ptopol_long)(round(factor*coorX[i*incX]))-fX;
+ cy = (ptopol_long)(round(factor*coorY[i*incY]))-fY;
+ //redondeo del vértice anterior
+ cx1 = (ptopol_long)(round(factor*coorX[i1*incX]))-fX;
+ cy1 = (ptopol_long)(round(factor*coorY[i1*incY]))-fY;
+ }
+ else
+ {
+ //truncamiento del vértice actual
+ cx = (ptopol_long)(factor*coorX[i*incX])-fX;
+ cy = (ptopol_long)(factor*coorY[i*incY])-fY;
+ //redondeo del vértice anterior
+ cx1 = (ptopol_long)(factor*coorX[i1*incX])-fX;
+ cy1 = (ptopol_long)(factor*coorY[i1*incY])-fY;
+ }
+ //comprobamos si el punto es un vértice del polígono
+ if((cx==0)&&(cy==0))
+ {
+ //el punto es un vértice
+ return GEOC_PTO_VERTICE_POLIG;
+ }
+ //check if e straddles X axis, with bias above/below
+ Rstrad = (cy>0)!=(cy1>0);
+ Lstrad = (cy<0)!=(cy1<0);
+ //straddle computation
+ if(Rstrad||Lstrad)
+ {
+ //compute intersection of e with x axis
+ X = ((double)(cx*cy1-cx1*cy))/((double)(cy1-cy));
+ //crosses ray if strictly positive intersection
+ if(Rstrad&&(X>0.0))
+ {
+ Rcross++;
+ }
+ //crosses ray if strictly negative intersection
+ if(Lstrad&&(X<0.0))
+ {
+ Lcross++;
+ }
+ }
+ }
+ //q on the edge if left and right cross are not the same parity
+ if((Rcross%2)!=(Lcross%2))
+ {
+ //el punto está en un borde
+ return GEOC_PTO_BORDE_POLIG;
+ }
+ //q inside if an odd number of crossings
+ if((Rcross%2)==1)
+ {
+ //el punto es interior
+ return GEOC_PTO_DENTRO_POLIG;
+ }
+ else
+ {
+ //el punto es exterior
+ return GEOC_PTO_FUERA_POLIG;
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* BuscaGeocNanEnVectores(const double* x,
+ const double* y,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ size_t* nNan)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //identificadores de NaN
+ int esNanX=0,esNanY=0;
+ //vector de salida
+ size_t* salida=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos a 0 el número de NaN encontrados
+ *nNan = 0;
+ //comprobamos una posible salida rápida
+ if(N==0)
+ {
+ //salimos de la función
+ return salida;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los elementos de los vectores
+ for(i=0;i<N;i++)
+ {
+ //inicializamos los identificadores de NaN
+ esNanX = 0;
+ esNanY = 0;
+ //comprobamos si el elemento del vector X es NaN
+ if(EsGeocNan(x[i*incX]))
+ {
+ //la X es NaN
+ esNanX = 1;
+ //comprobamos si tenemos vector Y
+ if(y!=NULL)
+ {
+ //comprobamos si el elemento del vector Y es NaN
+ if(EsGeocNan(y[i*incY]))
+ {
+ //la Y es NaN
+ esNanY = 1;
+ }
+ }
+ }
+ //comprobamos si hemos encontrado NaN
+ if((esNanX&&(y==NULL))||(esNanX&&esNanY))
+ {
+ //aumentamos el contador de NaN encontrados
+ (*nNan)++;
+ //reasignamos memoria a la salida
+ salida = (size_t*)realloc(salida,(*nNan)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //indicamos la posición del valor NaN
+ salida[(*nNan)-1] = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DatosPoliIndividualEnVecInd(const size_t* posInd,
+ const size_t indPosInd,
+ const size_t incX,
+ const size_t incY,
+ size_t* iniX,
+ size_t* iniY,
+ size_t* nElem)
+{
+ //posiciones de inicio y final en los vectores de vértices
+ *iniX = (posInd[indPosInd]+1)*incX;
+ *iniY = (posInd[indPosInd]+1)*incY;
+ //número de vértices del polígono
+ *nElem = posInd[indPosInd+1]-posInd[indPosInd]-1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posiciones de inicio de los vértices X e Y
+ size_t iniX=0,iniY=0;
+ //número de elementos del polígono a chequear
+ size_t nElem=0;
+ //variable auxiliar de situación de punto
+ int posAux=0;
+ //variable indicadora de continuación de chequeos
+ size_t continuar=1;
+ //variable de salida
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el polígono que contiene al punto
+ *poli = 0;
+ //comprobamos si hay valores NaN
+ if(nNan)
+ {
+ //paralelización con OpenMP
+ //utilizo schedule(dynamic) para que los polígonos vayan siendo
+ //chequeados uno a uno según los hilos de ejecución van quedándose
+ //libres
+ //hago esto porque es muy probable que los polígonos vengan listados de
+ //mayor a menor número de vértices y así se podrá trabajar con varios
+ //polígonos pequeños mientras se testea uno grande
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(continuar,posNan,coorX,coorY,pos,poli) \
+ private(i,iniX,iniY,nElem,posAux)
+#endif
+ //recorremos desde el primer NaN hasta el penúltimo
+ for(i=0;i<(nNan-1);i++)
+ {
+ //hacemos que todos los hilos vean la variable continuar actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ //comprobamos si hay que continuar chequeando polígonos
+ if(continuar)
+ {
+ //extraemos los datos de definición del polígono
+ DatosPoliIndividualEnVecInd(posNan,i,incX,incY,&iniX,&iniY,
+ &nElem);
+ //comprobamos la inclusión para el polígono de trabajo
+ posAux = PtoEnPoligono(x,y,&coorX[iniX],&coorY[iniY],nElem,incX,
+ incY);
+ //me aseguro de que las variables involucradas sean actualizadas
+ //por un hilo cada vez, sin posibilidad de modificación por
+ //varios al mismo tiempo
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el continuar==1 asegura que nos quedemos con el primer
+ //polígono en que está incluido el punto, ya que una vez que el
+ //hilo con punto encontrado actualice la variable continuar, el
+ //resto con posibles resultados positivos no pasarán este if()
+ if((continuar==1)&&(posAux!=GEOC_PTO_FUERA_POLIG))
+ {
+ //asignamos la variable de salida
+ pos = posAux;
+ //asignamos el polígono que contiene al punto
+ *poli = i;
+ //indicamos que no hay que continuar haciendo pruebas
+ //esta variable se usa para el caso de ejecución en paralelo
+ continuar = 0;
+ //hacemos que todos los hilos vean la variable continuar
+ //actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ }
+}
+ }
+ } // --> fin del #pragma omp parallel for
+ }
+ else
+ {
+ //hacemos una comprobación normal
+ pos = PtoEnPoligono(x,y,coorX,coorY,N,incX,incY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVerticeInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posiciones de inicio de los vértices X e Y
+ size_t iniX=0,iniY=0;
+ //número de elementos del polígono a chequear
+ size_t nElem=0;
+ //variable auxiliar de situación de punto
+ int posAux=0;
+ //variable indicadora de continuación de chequeos
+ size_t continuar=1;
+ //variable de salida
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el polígono que contiene al punto
+ *poli = 0;
+ //comprobamos si hay valores NaN
+ if(nNan)
+ {
+ //paralelización con OpenMP
+ //utilizo schedule(dynamic) para que los polígonos vayan siendo
+ //chequeados uno a uno según los hilos de ejecución van quedándose
+ //libres
+ //hago esto porque es muy probable que los polígonos vengan listados de
+ //mayor a menor número de vértices y así se podrá trabajar con varios
+ //polígonos pequeños mientras se testea uno grande
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(continuar,posNan,coorX,coorY,pos,poli) \
+ private(i,iniX,iniY,nElem,posAux)
+#endif
+ //recorremos desde el primer NaN hasta el penúltimo
+ for(i=0;i<(nNan-1);i++)
+ {
+ //hacemos que todos los hilos vean la variable continuar actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ //comprobamos si hay que continuar chequeando polígonos
+ if(continuar)
+ {
+ //extraemos los datos de definición del polígono
+ DatosPoliIndividualEnVecInd(posNan,i,incX,incY,&iniX,&iniY,
+ &nElem);
+ //comprobamos la inclusión para el polígono de trabajo
+ posAux = PtoEnPoligonoVertice(x,y,&coorX[iniX],&coorY[iniY],
+ nElem,incX,incY);
+ //me aseguro de que las variables involucradas sean actualizadas
+ //por un hilo cada vez, sin posibilidad de modificación por
+ //varios al mismo tiempo
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el continuar==1 asegura que nos quedemos con el primer
+ //polígono en que está incluido el punto, ya que una vez que el
+ //hilo con punto encontrado actualice la variable continuar, el
+ //resto con posibles resultados positivos no pasarán este if()
+ if((continuar==1)&&(posAux!=GEOC_PTO_FUERA_POLIG))
+ {
+ //asignamos la variable de salida
+ pos = posAux;
+ //asignamos el polígono que contiene al punto
+ *poli = i;
+ //indicamos que no hay que continuar haciendo pruebas
+ //esta variable se usa para el caso de ejecución en paralelo
+ continuar = 0;
+ //hacemos que todos los hilos vean la variable continuar
+ //actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ }
+}
+ }
+ } // --> fin del #pragma omp parallel for
+ }
+ else
+ {
+ //hacemos una comprobación normal
+ pos = PtoEnPoligonoVertice(x,y,coorX,coorY,N,incX,incY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVerticeBordeInd(const long x,
+ const long y,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posiciones de inicio de los vértices X e Y
+ size_t iniX=0,iniY=0;
+ //número de elementos del polígono a chequear
+ size_t nElem=0;
+ //variable auxiliar de situación de punto
+ int posAux=0;
+ //variable indicadora de continuación de chequeos
+ size_t continuar=1;
+ //variable de salida
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el polígono que contiene al punto
+ *poli = 0;
+ //comprobamos si hay valores NaN
+ if(nNan)
+ {
+ //paralelización con OpenMP
+ //utilizo schedule(dynamic) para que los polígonos vayan siendo
+ //chequeados uno a uno según los hilos de ejecución van quedándose
+ //libres
+ //hago esto porque es muy probable que los polígonos vengan listados de
+ //mayor a menor número de vértices y así se podrá trabajar con varios
+ //polígonos pequeños mientras se testea uno grande
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(continuar,posNan,coorX,coorY,pos,poli) \
+ private(i,iniX,iniY,nElem,posAux)
+#endif
+ //recorremos desde el primer NaN hasta el penúltimo
+ for(i=0;i<(nNan-1);i++)
+ {
+ //hacemos que todos los hilos vean la variable continuar actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ //comprobamos si hay que continuar chequeando polígonos
+ if(continuar)
+ {
+ //extraemos los datos de definición del polígono
+ DatosPoliIndividualEnVecInd(posNan,i,incX,incY,&iniX,&iniY,
+ &nElem);
+ //comprobamos la inclusión para el polígono de trabajo
+ posAux = PtoEnPoligonoVerticeBorde(x,y,&coorX[iniX],
+ &coorY[iniY],nElem,incX,
+ incY);
+ //me aseguro de que las variables involucradas sean actualizadas
+ //por un hilo cada vez, sin posibilidad de modificación por
+ //varios al mismo tiempo
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el continuar==1 asegura que nos quedemos con el primer
+ //polígono en que está incluido el punto, ya que una vez que el
+ //hilo con punto encontrado actualice la variable continuar, el
+ //resto con posibles resultados positivos no pasarán este if()
+ if((continuar==1)&&(posAux!=GEOC_PTO_FUERA_POLIG))
+ {
+ //asignamos la variable de salida
+ pos = posAux;
+ //asignamos el polígono que contiene al punto
+ *poli = i;
+ //indicamos que no hay que continuar haciendo pruebas
+ //esta variable se usa para el caso de ejecución en paralelo
+ continuar = 0;
+ //hacemos que todos los hilos vean la variable continuar
+ //actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ }
+}
+ }
+ } // --> fin del #pragma omp parallel for
+ }
+ else
+ {
+ //hacemos una comprobación normal
+ pos = PtoEnPoligonoVerticeBorde(x,y,coorX,coorY,N,incX,incY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoEnPoligonoVerticeBordeDoubleInd(const double x,
+ const double y,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo,
+ const size_t* posNan,
+ const size_t nNan,
+ size_t* poli)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posiciones de inicio de los vértices X e Y
+ size_t iniX=0,iniY=0;
+ //número de elementos del polígono a chequear
+ size_t nElem=0;
+ //variable auxiliar de situación de punto
+ int posAux=0;
+ //variable indicadora de continuación de chequeos
+ size_t continuar=1;
+ //variable de salida
+ int pos=GEOC_PTO_FUERA_POLIG;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el polígono que contiene al punto
+ *poli = 0;
+ //comprobamos si hay valores NaN
+ if(nNan)
+ {
+ //paralelización con OpenMP
+ //utilizo schedule(dynamic) para que los polígonos vayan siendo
+ //chequeados uno a uno según los hilos de ejecución van quedándose
+ //libres
+ //hago esto porque es muy probable que los polígonos vengan listados de
+ //mayor a menor número de vértices y así se podrá trabajar con varios
+ //polígonos pequeños mientras se testea uno grande
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) schedule(dynamic) \
+ shared(continuar,posNan,coorX,coorY,pos,poli) \
+ private(i,iniX,iniY,nElem,posAux)
+#endif
+ //recorremos desde el primer NaN hasta el penúltimo
+ for(i=0;i<(nNan-1);i++)
+ {
+ //hacemos que todos los hilos vean la variable continuar actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ //comprobamos si hay que continuar chequeando polígonos
+ if(continuar)
+ {
+ //extraemos los datos de definición del polígono
+ DatosPoliIndividualEnVecInd(posNan,i,incX,incY,&iniX,&iniY,
+ &nElem);
+ //comprobamos la inclusión para el polígono de trabajo
+ posAux = PtoEnPoligonoVerticeBordeDouble(x,y,&coorX[iniX],
+ &coorY[iniY],nElem,
+ incX,incY,factor,
+ redondeo);
+ //me aseguro de que las variables involucradas sean actualizadas
+ //por un hilo cada vez, sin posibilidad de modificación por
+ //varios al mismo tiempo
+#if defined(_OPENMP)
+#pragma omp critical
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el continuar==1 asegura que nos quedemos con el primer
+ //polígono en que está incluido el punto, ya que una vez que el
+ //hilo con punto encontrado actualice la variable continuar, el
+ //resto con posibles resultados positivos no pasarán este if()
+ if((continuar==1)&&(posAux!=GEOC_PTO_FUERA_POLIG))
+ {
+ //asignamos la variable de salida
+ pos = posAux;
+ //asignamos el polígono que contiene al punto
+ *poli = i;
+ //indicamos que no hay que continuar haciendo pruebas
+ //esta variable se usa para el caso de ejecución en paralelo
+ continuar = 0;
+ //hacemos que todos los hilos vean la variable continuar
+ //actualizada
+#if defined(_OPENMP)
+#pragma omp flush(continuar)
+#endif
+ }
+}
+ }
+ } // --> fin del #pragma omp parallel for
+ }
+ else
+ {
+ //hacemos una comprobación normal
+ pos = PtoEnPoligonoVerticeBordeDouble(x,y,coorX,coorY,N,incX,incY,
+ factor,redondeo);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/recpolil.c b/src/recpolil.c
new file mode 100755
index 0000000..c7ba145
--- /dev/null
+++ b/src/recpolil.c
@@ -0,0 +1,1402 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom gshhs
+@{
+\file recpolil.c
+\brief Definición funciones para el recorte de polilíneas por medio de
+ polígonos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 05 de junio de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/recpolil.h"
+/******************************************************************************/
+/******************************************************************************/
+vertPolilClip* CreaVertPolilClip(const double x,
+ const double y,
+ vertPolilClip* anterior,
+ vertPolilClip* siguiente,
+ const char orig,
+ const char pos,
+ const double alfa)
+{
+ //variable de salida (nuevo vértice)
+ vertPolilClip* nuevoVert=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para el nuevo vértice
+ nuevoVert = (vertPolilClip*)malloc(sizeof(vertPolilClip));
+ //comprobamos los posibles errores
+ if(nuevoVert==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos los vértices anterior y posterior
+ nuevoVert->anterior = anterior;
+ nuevoVert->siguiente = siguiente;
+ //si anterior es un vértice bueno
+ if(anterior!=NULL)
+ {
+ //lo apuntamos al vértice creado
+ nuevoVert->anterior->siguiente = nuevoVert;
+ }
+ //si siguiente es un vértice bueno
+ if(siguiente!=NULL)
+ {
+ //indicamos que el vértice creado es el anterior
+ nuevoVert->siguiente->anterior = nuevoVert;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el resto de campos
+ nuevoVert->x = x;
+ nuevoVert->y = y;
+ nuevoVert->orig = orig;
+ nuevoVert->pos = pos;
+ nuevoVert->alfa = alfa;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return nuevoVert;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPolilClip* CreaPolilClip(const double* x,
+ const double* y,
+ const size_t nCoor,
+ const size_t incX,
+ const size_t incY)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //variable auxiliar de posición
+ size_t posIni=0;
+ //otra variable auxiliar
+ int hayVert=0;
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ //variable de salida
+ vertPolilClip* poli=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //buscamos el primer punto que sea distinto de NaN
+ for(i=0;i<nCoor;i++)
+ {
+ //comprobamos si el elemento es distinto de NaN
+ if((!EsGeocNan(x[i*incX]))&&(!EsGeocNan(y[i*incY])))
+ {
+ //indicamos que sí hay vértices de trabajo
+ hayVert = 1;
+ //guardamos la posición de este elemento
+ posIni = i;
+ //salimos del bucle
+ break;
+ }
+ }
+ //si no hay ningún vértice distinto de NaN
+ if(!hayVert)
+ {
+ //salimos de la función
+ return poli;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el primer elemento (indicamos que está fuera del polígono
+ //que recortará a la polilínea, ya que el valor verdadero de pos se indicará
+ //en otra función)
+ poli = CreaVertPolilClip(x[posIni*incX],y[posIni*incY],NULL,NULL,1,0,0.0);
+ //comprobamos los posibles errores
+ if(poli==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //asignamos el elemento creado a la variable auxiliar
+ aux = poli;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos de trabajo
+ for(i=(posIni+1);i<nCoor;i++)
+ {
+ //comprobamos si el elemento es distinto de NaN
+ if((!EsGeocNan(x[i*incX]))&&(!EsGeocNan(y[i*incY])))
+ {
+ //vamos añadiendo vértices al final (seguimos indicando que están
+ //fuera del polígono que recortará a la polilínea)
+ aux = CreaVertPolilClip(x[i*incX],y[i*incY],aux,NULL,1,0,0.0);
+ //comprobamos los posibles errores
+ if(aux==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPolilClip(poli);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return poli;
+}
+/******************************************************************************/
+/******************************************************************************/
+void LibMemPolilClip(vertPolilClip* poli)
+{
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //trabajamos mientras quede memoria
+ while(poli!=NULL)
+ {
+ //apuntamos con la estructura auxiliar hacia la memoria a liberar
+ aux = poli;
+ //apuntamos con la estructura principal al siguiente vértice
+ poli = poli->siguiente;
+ //liberamos la memoria
+ free(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPolilClip* ReiniciaPolilClip(vertPolilClip* poli)
+{
+ //estructura que apunta al espacio en memoria a liberar
+ vertPolilClip* borra=NULL;
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ //estructura de salida
+ vertPolilClip* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar
+ aux = poli;
+ //comprobamos una posible salida rápida
+ if(aux==NULL)
+ {
+ //salimos de la función
+ return NULL;
+ }
+ //buscamos para la estructura de salida el primer vértice original
+ while(aux!=NULL)
+ {
+ //comprobamos si estamos ante un vértice bueno
+ if(aux->orig)
+ {
+ //asignamos la variable de salida
+ sal = aux;
+ //salimos del bucle
+ break;
+ }
+ //siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //volvemos a inicializar la variable auxiliar
+ aux = poli;
+ //mientras la variable de trabajo no apunte a NULL
+ while(aux!=NULL)
+ {
+ //comprobamos si estamos ante un vértice a borrar
+ if(aux->orig==0)
+ {
+ //lo almacenamos en la estructura de borrado
+ borra = aux;
+ //actualizamos el puntero de vértice siguiente
+ if(aux->anterior!=NULL)
+ {
+ //cuando el vértice a borrar no es el primero de la lista
+ aux->anterior->siguiente = aux->siguiente;
+ }
+ else if(aux->siguiente!=NULL)
+ {
+ //cuando el vértice a borrar es el primero de la lista
+ aux->siguiente->anterior = NULL;
+ }
+ //actualizamos el puntero de vértice anterior
+ if(aux->siguiente!=NULL)
+ {
+ //cuando el vértice a borrar no es el último de la lista
+ aux->siguiente->anterior = aux->anterior;
+ }
+ else if(aux->anterior!=NULL)
+ {
+ //cuando el vértice a borrar es el último de la lista
+ aux->anterior->siguiente = NULL;
+ }
+ //apuntamos al siguiente elemento
+ aux = aux->siguiente;
+ //liberamos la memoria
+ free(borra);
+ }
+ else
+ {
+ //reinicializamos el resto de miembros, menos las coordenadas
+ //originales y el identificador de vértice original
+ aux->pos = GEOC_PTO_FUERA_POLIG;
+ aux->alfa = 0.0;
+ //siguiente elemento
+ aux = aux->siguiente;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+vertPolilClip* SiguienteVertOrigPolilClip(vertPolilClip* vert)
+{
+ //variable de salida, que inicializamos con la dirección de entrada
+ vertPolilClip* sal=vert;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si estamos ante un vértice original, pasamos al siguiente
+ if((sal!=NULL)&&sal->orig)
+ {
+ //apuntamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //vamos rechazando vérties no originales (el bucle se para cuando llegamos
+ //al final o a un vértice que no es original)
+ while((sal!=NULL)&&(sal->orig==0))
+ {
+ //pasamos al siguiente vértice
+ sal = sal->siguiente;
+ }
+ //si hemos llegado a un vértice que no es original, apuntamos a NULL
+ if((sal!=NULL)&&(sal->orig==0))
+ {
+ //asignamos NULL
+ sal = NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+void InsertaVertPolilClip(vertPolilClip* ins,
+ vertPolilClip* extremoIni,
+ vertPolilClip* extremoFin)
+{
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el vértice auxiliar como el extremo inicial pasado
+ aux = extremoIni;
+ //mientras no lleguemos al extremo final y el punto a insertar esté más
+ //lejos del origen que el punto de trabajo
+ while((aux!=extremoFin)&&((aux->alfa)<=(ins->alfa)))
+ {
+ //avanzamos al siguiente vértice
+ aux = aux->siguiente;
+ }
+ //insertamos el punto y ordenamos los punteros de vértices anterior y
+ //posterior
+ ins->siguiente = aux;
+ ins->anterior = aux->anterior;
+ ins->anterior->siguiente = ins;
+ ins->siguiente->anterior = ins;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t NumeroVertOrigPolilClip(vertPolilClip* poli)
+{
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ //variable de salida
+ size_t num=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //comprobamos si estamos ante un vértice original
+ if(aux->orig)
+ {
+ //si no es un vértice original, nos posicionamos en el siguiente que sí
+ //lo sea
+ aux = SiguienteVertOrigPolilClip(aux);
+ }
+ //mientras no lleguemos al final
+ while(aux!=NULL)
+ {
+ //aumentamos el contador de vértices originales
+ num++;
+ //nos posicionamos en el siguiente vértice original
+ aux = SiguienteVertOrigPolilClip(aux);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return num;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t NumeroVertPolilClip(vertPolilClip* poli)
+{
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ //variable de salida
+ size_t num=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //mientras no lleguemos al final
+ while(aux!=NULL)
+ {
+ //aumentamos el contador de vértices
+ num++;
+ //nos posicionamos en el siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return num;
+}
+/******************************************************************************/
+/******************************************************************************/
+int Paso1Recpolil(vertPolilClip* poli,
+ vertPoliClip* poliRec,
+ size_t* nIntersec)
+{
+ //estructuras auxiliares que apuntan a los elementos pasados
+ vertPolilClip* auxA=NULL;
+ vertPoliClip* auxC=NULL;
+ //estructuras auxiliares para trabajar con el siguiente vértice
+ vertPolilClip* auxB=NULL;
+ vertPoliClip* auxD=NULL;
+ //vértices de intersección a insertar
+ vertPolilClip* insPolil=NULL;
+ //coordenadas de la intersección de dos segmentos
+ double xI=0.0,yI=0.0;
+ //longitud de segmento y parámetro alfa
+ double lon=0.0,alfa=0.0;
+ //código de intersección de segmentos
+ int intersec=0;
+ //variable auxiliar
+ int nuevoPunto=0;
+ //variable de salida
+ int salida=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el número de intersecciones a 0
+ *nIntersec = 0;
+ //EL PRIMER PASO DEL ALGORITMO DE RECORTE DE POLILÍNEAS ES EL CÁLCULO DE
+ //TODOS LOS PUNTOS DE INTERSECCIÓN ENTRE LOS POLÍGONOS
+ //recorremos los vértices de la polilínea
+ for(auxA=poli;auxA->siguiente!=NULL;auxA=auxA->siguiente)
+ {
+ //sólo trabajamos si el vértice es original
+ if(auxA->orig)
+ {
+ //recorremos los vértices del polígono de recorte
+ for(auxC=poliRec;auxC->siguiente!=NULL;auxC=auxC->siguiente)
+ {
+ //sólo trabajamos si el vértice es original (esto hace que
+ //podamos trabajar con un polígono proveniente de una operación
+ //booleana previa entre polígonos
+ if(auxC->interseccion==0)
+ {
+ //siguiente vértice de los segmentos
+ auxB = SiguienteVertOrigPolilClip(auxA);
+ auxD = SiguienteVertOrigPoliClip(auxC);
+ //calculamos la intersección de los segmentos
+ intersec = IntersecSegmentos2D(auxA->x,auxA->y,auxB->x,
+ auxB->y,auxC->x,auxC->y,
+ auxD->x,auxD->y,&xI,&yI);
+ //comprobamos la posición relativa del primer punto del
+ //segmento de la polilínea con respecto al polígono
+ //esta función sólo marca dentro o fuera
+ auxA->pos = (char)PtoEnPoliClip(auxA->x,auxA->y,poliRec);
+ //comprobamos si el segmento de la polilínea contiene al
+ //último punto de ésta, por lo que el bucle se acabará aquí
+ if(auxB->siguiente==NULL)
+ {
+ //comprobamos la posición relativa del último punto
+ auxB->pos = (char)PtoEnPoliClip(auxB->x,auxB->y,
+ poliRec);
+ }
+ //comprobamos si hay que aumentar el contador de
+ //intersecciones
+ if(intersec!=GEOC_SEG_NO_INTERSEC)
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ }
+ //comprobamos el tipo de intersección
+ if(intersec==GEOC_SEG_INTERSEC)
+ {
+ //INTERSECCIÓN LIMPIA
+ //calculamos la longitud del segmento de la polilínea
+ lon = Dist2D(auxA->x,auxA->y,auxB->x,auxB->y);
+ //calculamos los parámetros alfa
+ alfa = Dist2D(auxA->x,auxA->y,xI,yI)/lon;
+ //creamos el nuevo vértice a insertar
+ insPolil = CreaVertPolilClip(xI,yI,NULL,NULL,0,
+ (char)GEOC_PTO_BORDE_POLIG,
+ alfa);
+ //comprobamos los posibles errores
+ if(insPolil==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //añadimos el punto de intersección
+ InsertaVertPolilClip(insPolil,auxA,auxB);
+ }
+ else if(intersec==GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN)
+ {
+ //EL EXTREMO DE UN SEGMENTO TOCA AL OTRO SEGMENTO, PERO
+ //LOS SEGMENTOS NO SON COLINEALES
+ //comprobamos si el extremo que toca es el inicial del
+ //segmento de la polilínea
+ if((xI==auxA->x)&&(yI==auxA->y))
+ {
+ //el primer punto del segmento está en el borde
+ auxA->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ else if((xI!=auxB->x)||(yI!=auxB->y))
+ {
+ //el extremo que toca es del segmento del polígono y
+ //no toca al punto final del segmento de la
+ //polilínea
+ //calculamos la longitud del segmento de la
+ //polilínea
+ lon = Dist2D(auxA->x,auxA->y,auxB->x,auxB->y);
+ //calculamos los parámetros alfa
+ alfa = Dist2D(auxA->x,auxA->y,xI,yI)/lon;
+ //creamos el nuevo vértice a insertar
+ insPolil = CreaVertPolilClip(xI,yI,NULL,NULL,0,
+ (char)GEOC_PTO_BORDE_POLIG,
+ alfa);
+ //comprobamos los posibles errores
+ if(insPolil==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //añadimos el punto de intersección
+ InsertaVertPolilClip(insPolil,auxA,auxB);
+ }
+ else
+ {
+ //comprobamos si estamos ante el segmento que
+ //contiene al último punto de la polilínea
+ if(auxB->siguiente==NULL)
+ {
+ //el último punto del segmento está en el borde
+ auxB->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ else
+ {
+ //disminuimos el contador de intersecciones, ya
+ //que esta se detectará en la siguiente vuelta
+ //del bucle
+ (*nIntersec)--;
+ }
+ }
+ }
+ else if(intersec==GEOC_SEG_INTERSEC_EXTREMO_COLIN)
+ {
+ //LOS SEGMENTOS SON COLINEALES PERO SÓLO SE TOCAN EN EL
+ //EXTREMO
+ //comprobamos si el extremo que toca es el primero
+ if((xI==auxA->x)&&(yI==auxA->y))
+ {
+ //el primer punto del segmento está en el borde
+ auxA->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ else
+ {
+ //comprobamos si estamos ante el segmento que
+ //contiene al último punto de la polilínea
+ if(auxB->siguiente==NULL)
+ {
+ //el último punto del segmento está en el borde
+ auxB->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ else
+ {
+ //disminuimos el contador de intersecciones, ya
+ //que esta se detectará en la siguiente vuelta
+ //del bucle
+ (*nIntersec)--;
+ }
+ }
+ }
+ else if(intersec==GEOC_SEG_INTERSEC_MISMO_SEG)
+ {
+ //AMBOS SEGMENTOS SON EL MISMO
+ //el primer punto del segmento está en el borde
+ auxA->pos = (char)GEOC_PTO_BORDE_POLIG;
+ //comprobamos si estamos ante el segmento que contiene
+ //al último punto de la polilínea
+ if(auxB->siguiente==NULL)
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ //el último punto del segmento está en el borde
+ auxB->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ }
+ else if(intersec==GEOC_SEG_INTERSEC_COLIN)
+ {
+ //LOS SEGMENTOS TIENEN MÁS DE UN PUNTO EN COMÚN, PERO NO
+ //SON EL MISMO
+ //comprobamos si el extremo inicial está tocando el
+ //polígono o no
+ if((xI==auxA->x)&&(yI==auxA->y))
+ {
+ //el primer punto del segmento está en el borde
+ auxA->pos = (char)GEOC_PTO_BORDE_POLIG;
+ //identificador de nuevo punto
+ nuevoPunto = 0;
+ //comprobamos si alguno de los extremos del segmento
+ //del polígono está dentro del segmento de la
+ //polilínea
+ if(PuntoEntreDosPuntos2DColin(auxC->x,auxC->y,
+ auxA->x,auxA->y,
+ auxB->x,auxB->y))
+ {
+ //nuevo punto
+ nuevoPunto = 1;
+ //coordenadas del punto intersección
+ xI = auxC->x;
+ yI = auxC->y;
+ }
+ else if(PuntoEntreDosPuntos2DColin(auxD->x,auxD->y,
+ auxA->x,auxA->y,
+ auxB->x,auxB->y))
+ {
+ //nuevo punto
+ nuevoPunto = 1;
+ //coordenadas del punto intersección
+ xI = auxD->x;
+ yI = auxD->y;
+ }
+ //comprobamos si hay que añadir el nuevo punto
+ if(nuevoPunto)
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ //calculamos la longitud del segmento de la
+ //polilínea
+ lon = Dist2D(auxA->x,auxA->y,auxB->x,auxB->y);
+ //calculamos los parámetros alfa
+ alfa = Dist2D(auxA->x,auxA->y,xI,yI)/lon;
+ //creamos el nuevo vértice a insertar
+ insPolil = CreaVertPolilClip(xI,yI,NULL,NULL,0,
+ (char)GEOC_PTO_BORDE_POLIG,
+ alfa);
+ //comprobamos los posibles errores
+ if(insPolil==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //añadimos el punto de intersección
+ InsertaVertPolilClip(insPolil,auxA,auxB);
+ }
+ //comprobamos si estamos ante el segmento que
+ //contiene al último punto de la polilínea
+ if(auxB->siguiente==NULL)
+ {
+ //comprobamos si el último punto del segmento
+ //de la polilínea está contenido en el segmento
+ //del polígono
+ if(PuntoEntreDosPuntos2DColin(auxB->x,auxB->y,
+ auxC->x,auxC->y,
+ auxD->x,auxD->y))
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ //indicamos que el último punto del segmento
+ //de la polilínea está en el borde
+ auxB->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ }
+ }
+ else
+ {
+ //comprobamos si el vértice a añadir es el extremo
+ //final del segmento del polígono (la función
+ //devuelve las coordenadas del extremo final del
+ //segmento de la polilínea
+ if((xI==auxB->x)&&(yI==auxB->y))
+ {
+ //asignamos las coordenadas de salida correctas
+ xI = auxD->x;
+ yI = auxD->y;
+ }
+ //calculamos la longitud del segmento de la
+ //polilínea
+ lon = Dist2D(auxA->x,auxA->y,auxB->x,auxB->y);
+ //calculamos los parámetros alfa
+ alfa = Dist2D(auxA->x,auxA->y,xI,yI)/lon;
+ //creamos el nuevo vértice a insertar
+ insPolil = CreaVertPolilClip(xI,yI,NULL,NULL,0,
+ (char)GEOC_PTO_BORDE_POLIG,
+ alfa);
+ //comprobamos los posibles errores
+ if(insPolil==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return GEOC_ERR_ASIG_MEMORIA;
+ }
+ //añadimos el punto de intersección
+ InsertaVertPolilClip(insPolil,auxA,auxB);
+ //comprobamos si estamos ante el segmento que
+ //contiene al último punto de la polilínea
+ if(auxB->siguiente==NULL)
+ {
+ //aumentamos el contador de intersecciones
+ (*nIntersec)++;
+ //indicamos que el último punto del segmento de
+ //la polilínea está en el borde
+ auxB->pos = (char)GEOC_PTO_BORDE_POLIG;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* Paso2Recpolil(vertPolilClip* poli,
+ const enum GEOC_OP_BOOL_POLIL op)
+{
+ //estructura auxiliar
+ vertPolilClip* aux=NULL;
+ //vectores de coordenadas de los vértices del resultado
+ double* x=NULL;
+ double* y=NULL;
+ //número de elementos de los vectores x e y
+ size_t nPtos=0;
+ //número de elementos para los que ha sido asignada memoria
+ size_t nElem=0;
+ //variable de estado
+ int estado=GEOC_ERR_NO_ERROR;
+ //polilínea de salida
+ polil* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //chequeamos una posible salida rápida porque la polilínea sea NULL
+ if(poli==NULL)
+ {
+ //creamos la estructura vacía
+ resultado = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //salimos de la función
+ return resultado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la estructura auxiliar con la dirección de entrada
+ aux = poli;
+ //distinguimos entre las dos operaciones
+ //por defecto, recorte
+ if(op!=GeocOpBoolFuera)
+ {
+ //vamos recorriendo vértices de la polilínea
+ do
+ {
+ //comprobamos si el vértice es del borde o de dentro del polígono
+ if(aux->pos==GEOC_PTO_DENTRO_POLIG)
+ {
+ //un punto de dentro del polígono siempre pertenece a la
+ //polilínea recortada
+ //no hace falta asignar los elementos NaN de separación de
+ //polilíneas, que ya se añaden cuando de trabaja con un punto de
+ //borde
+ //aumentamos el número de elementos almacenados en los vectores
+ //de coordenadas
+ nPtos++;
+ //comprobamos si hay que reasignar memoria
+ if(nPtos>nElem)
+ {
+ //aumentamos el número de elementos
+ nElem += GEOC_RECPOLIL_BUFFER_PTOS;
+ //reasignamos memoria
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos los posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos las coordenadas del vértice
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ else if(aux->pos==GEOC_PTO_BORDE_POLIG)
+ {
+ //comprobamos la situación de los vértices anterior y siguiente
+ //para la posible reasignación de memoria
+ if((aux->anterior==NULL)||(aux->siguiente==NULL)||
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG)||
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //este es un vértice de comienzo o fin de una polilínea, por
+ //lo que necesitamos memoria para las coordenadas y el
+ //marcador NaN
+ nPtos += 2;
+ }
+ else
+ {
+ //este vértice pertenece al interior del polígono
+ nPtos++;
+ }
+ //comprobamos si hay que reasignar memoria
+ if(nPtos>nElem)
+ {
+ //aumentamos el número de elementos
+ nElem += GEOC_RECPOLIL_BUFFER_PTOS;
+ //reasignamos memoria
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos los posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //comprobamos de nuevo la situación de los vértices anterior y
+ //posterior
+ if((aux->anterior==NULL)||
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //el vértice es inicio de polilínea
+ //asignamos los valores NaN de separación
+ x[nPtos-2] = GeocNan();
+ y[nPtos-2] = GeocNan();
+ //asignamos las coordenadas del vértice
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ else if((aux->siguiente==NULL)||
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //el vértice es final de polilínea
+ //asignamos las coordenadas del vértice
+ x[nPtos-2] = aux->x;
+ y[nPtos-2] = aux->y;
+ //asignamos los valores NaN de separación
+ x[nPtos-1] = GeocNan();
+ y[nPtos-1] = GeocNan();
+ }
+ else
+ {
+ //el vértice pertenece a la polilínea recortada
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ }
+ //avanzamos al siguiente vértice
+ aux = aux->siguiente;
+ }while(aux!=NULL);
+ }
+ else
+ {
+ //vamos recorriendo vértices de la polilínea
+ do
+ {
+ //comprobamos si el vértice es del borde o de fuera del polígono
+ if(aux->pos==GEOC_PTO_FUERA_POLIG)
+ {
+ //un punto de fuera del polígono siempre pertenece a la
+ //polilínea exterior
+ //no hace falta asignar los elementos NaN de separación de
+ //polilíneas, que ya se añaden cuando de trabaja con un punto de
+ //borde
+ //aumentamos el número de elementos almacenados en los vectores
+ //de coordenadas
+ nPtos++;
+ //comprobamos si hay que reasignar memoria
+ if(nPtos>nElem)
+ {
+ //aumentamos el número de elementos
+ nElem += GEOC_RECPOLIL_BUFFER_PTOS;
+ //reasignamos memoria
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos los posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //asignamos las coordenadas del vértice
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ else if(aux->pos==GEOC_PTO_BORDE_POLIG)
+ {
+ //comprobamos la situación de los vértices anterior y siguiente
+ //para la posible reasignación de memoria
+ if((aux->anterior!=NULL)&&(aux->siguiente!=NULL)&&
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG)&&
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //este vértice pertenece al exterior del polígono
+ nPtos++;
+ }
+ else if(((aux->anterior==NULL)||
+ (aux->anterior->pos!=GEOC_PTO_FUERA_POLIG))&&
+ (aux->siguiente!=NULL)&&
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //este es un vértice de comienzo de una polilínea, por lo
+ //que necesitamos memoria para las coordenadas y el marcador
+ //NaN
+ nPtos += 2;
+ }
+ else if(((aux->siguiente==NULL)||
+ (aux->siguiente->pos!=GEOC_PTO_FUERA_POLIG))&&
+ (aux->anterior!=NULL)&&
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //este es un vértice de fin de una polilínea, por lo que
+ //necesitamos memoria para las coordenadas y el marcador NaN
+ nPtos += 2;
+ }
+ //comprobamos si hay que reasignar memoria
+ if(nPtos>nElem)
+ {
+ //aumentamos el número de elementos
+ nElem += GEOC_RECPOLIL_BUFFER_PTOS;
+ //reasignamos memoria
+ x = (double*)realloc(x,nElem*sizeof(double));
+ y = (double*)realloc(y,nElem*sizeof(double));
+ //comprobamos los posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //liberamos la posible memoria asignada
+ free(x);
+ free(y);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //comprobamos de nuevo la situación de los vértices anterior y
+ //posterior
+ if((aux->anterior!=NULL)&&(aux->siguiente!=NULL)&&
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG)&&
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //el vértice pertenece a la polilínea recortada
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ else if(((aux->anterior==NULL)||
+ (aux->anterior->pos!=GEOC_PTO_FUERA_POLIG))&&
+ (aux->siguiente!=NULL)&&
+ (aux->siguiente->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //el vértice es inicio de polilínea
+ //asignamos los valores NaN de separación
+ x[nPtos-2] = GeocNan();
+ y[nPtos-2] = GeocNan();
+ //asignamos las coordenadas del vértice
+ x[nPtos-1] = aux->x;
+ y[nPtos-1] = aux->y;
+ }
+ else if(((aux->siguiente==NULL)||
+ (aux->siguiente->pos!=GEOC_PTO_FUERA_POLIG))&&
+ (aux->anterior!=NULL)&&
+ (aux->anterior->pos==GEOC_PTO_FUERA_POLIG))
+ {
+ //el vértice es final de polilínea
+ //asignamos las coordenadas del vértice
+ x[nPtos-2] = aux->x;
+ y[nPtos-2] = aux->y;
+ //asignamos los valores NaN de separación
+ x[nPtos-1] = GeocNan();
+ y[nPtos-1] = GeocNan();
+ }
+ }
+ //avanzamos al siguiente vértice
+ aux = aux->siguiente;
+ }while(aux!=NULL);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la estructura de salida
+ resultado = CreaPolil(x,y,nPtos,1,1,&estado);
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //liberamos la memoria asignada
+ free(x);
+ free(y);
+ //comprobamos el error
+ if(estado==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ }
+ else
+ {
+ //mensaje de error
+ GEOC_ERROR("Error en la llamada a 'CreaPolil()'\nEste error no "
+ "puede producirse aquí porque los NaN deben estar "
+ "bien puestos");
+ }
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria utilizada
+ free(x);
+ free(y);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* RecortaPolil(vertPolilClip* poli,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIL op,
+ size_t* nIntersec)
+{
+ //identificador de error
+ int idError=GEOC_ERR_NO_ERROR;
+ //polilínea de salida de salida
+ polil* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //PRIMER PASO DEL ALGORITMO: CÁLCULO DE TODOS LOS PUNTOS DE INTERSECCIÓN
+ //ENTRE LA POLILÍNEA Y EL POLÍGONO
+ //calculamos los puntos de intersección
+ idError = Paso1Recpolil(poli,poliRec,nIntersec);
+ //comprobamos los posibles errores
+ if(idError==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso1Recpolil'");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si no hay intersecciones
+ if(!(*nIntersec))
+ {
+ //comprobamos las posibles situaciones relativas entre la polilínea y el
+ //polígono que pueden producir cero intersecciones
+ if(PtoEnPoliClip(poli->x,poli->y,poliRec)==GEOC_PTO_FUERA_POLIG)
+ {
+ //LA POLILÍNEA ESTÁ FUERA DEL POLÍGONO DE RECORTE
+ //distinguimos las operaciones (por defecto, dentro)
+ if(op!=GeocOpBoolFuera)
+ {
+ //el resultado es una polilínea vacía
+ resultado = CreaPolilPolilClip(NULL);
+ }
+ else
+ {
+ //el resultado es la polilínea original
+ resultado = CreaPolilPolilClip(poli);
+ }
+ }
+ else
+ {
+ //LA POLILÍNEA ESTÁ DENTRO DEL POLÍGONO DE RECORTE
+ //distinguimos las operaciones (por defecto, dentro)
+ if(op!=GeocOpBoolFuera)
+ {
+ //el resultado es la polilínea original
+ resultado = CreaPolilPolilClip(poli);
+ }
+ else
+ {
+ //el resultado es una polilínea vacía
+ resultado = CreaPolilPolilClip(NULL);
+ }
+ }
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //salimos de la función
+ return resultado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //realizamos la operación si hay alguna intersección
+ resultado = Paso2Recpolil(poli,op);
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'Paso2Recpolil'");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* RecortaPolilMult(const polil* poli,
+ const polig* poliRec,
+ const enum GEOC_OP_BOOL_POLIL op,
+ size_t* nIntersec)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //variable de posición
+ size_t pos=0;
+ //posición de un rectángulo con respecto a otro
+ int pr=0;
+ //número de intersecciones auxiliar
+ size_t nInt=0;
+ //variable de error
+ int estado=GEOC_ERR_NO_ERROR;
+ //listas de trabajo
+ vertPolilClip* polilClip=NULL;
+ vertPoliClip* poligClip=NULL;
+ //polilínea auxiliar
+ polil* polilAux=NULL;
+ //variable de salida
+ polil* resultado=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el número total de intersecciones
+ *nIntersec = 0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos la variable de salida
+ resultado = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(resultado==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos las polilíneas a recortar
+ for(i=0;i<poli->nPolil;i++)
+ {
+ //dirección de inicio de los vértices de la polilínea
+ pos = poli->posIni[i];
+ //creamos la polilínea a recortar de trabajo
+ polilClip = CreaPolilClip(&(poli->x[pos]),&(poli->y[pos]),
+ poli->nVert[i],1,1);
+ //comprobamos los posibles errores
+ if(polilClip==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPolil(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //recorremos los polígonos de recorte
+ for(j=0;j<poliRec->nPolig;j++)
+ {
+ //comprobamos si la polilínea y el polígono tienen definidos sus
+ //límites
+ if((poli->hayLim)&&(poliRec->hayLim))
+ {
+ //comprobamos si los restángulos que encierran a la polilínea y
+ //al polígono son disjuntos o no
+ pr = RectDisjuntos(poli->xMin[i],poli->xMax[i],poli->yMin[i],
+ poli->yMax[i],
+ poliRec->xMin[j],poliRec->xMax[j],
+ poliRec->yMin[j],poliRec->yMax[j]);
+ //comprobamos los casos particulares si los rectángulos son
+ //disjuntos
+ if(pr&&(op==GeocOpBoolDentro))
+ {
+ //si buscamos la parte de la polilínea que cae dentro del
+ //polígono, no se añade nada
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ else if(pr&&(op==GeocOpBoolFuera))
+ {
+ //si buscamos la parte de la polilínea que cae fuera del
+ //polígono, se añade la polilínea entera
+ estado = AnyadeDatosPolil(resultado,&(poli->x[pos]),
+ &(poli->y[pos]),poli->nVert[i],1,
+ 1);
+ //comprobamos los posibles errores, que sólo pueden ser de
+ //asignación de memoria
+ if(estado!=GEOC_ERR_NO_ERROR)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPolilClip(polilClip);
+ LibMemPolil(resultado);
+ //lanzamos el mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //vamos a la siguiente vuelta del bucle
+ continue;
+ }
+ }
+ //dirección de inicio de los vértices del polígono de recorte
+ pos = poliRec->posIni[j];
+ //creamos el polígono de recorte de trabajo
+ poligClip = CreaPoliClip(&(poliRec->x[pos]),&(poliRec->y[pos]),
+ poliRec->nVert[j],1,1);
+ //comprobamos los posibles errores
+ if(poligClip==NULL)
+ {
+ //liberamos la memoria asignada hasta ahora
+ LibMemPolilClip(polilClip);
+ LibMemPolil(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //recortamos
+ polilAux = RecortaPolil(polilClip,poligClip,op,&nInt);
+ //comprobamos los posibles errores
+ if(polilAux==NULL)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPolilClip(polilClip);
+ LibMemPoliClip(poligClip);
+ LibMemPolil(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //sumamos el número de intersecciones
+ (*nIntersec) += nInt;
+ //añadimos la polilínea recortada a la variable de salida
+ if(AnyadePolilPolil(resultado,polilAux)==GEOC_ERR_ASIG_MEMORIA)
+ {
+ //liberamos la posible memoria asignada hasta ahora
+ LibMemPolilClip(polilClip);
+ LibMemPoliClip(poligClip);
+ LibMemPolil(polilAux);
+ LibMemPolil(resultado);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //liberamos la memoria asignada al polígono de esta vuelta del bucle
+ LibMemPoliClip(poligClip);
+ //liberamos la memoria asignada a la polilínea auxiliar
+ LibMemPolil(polilAux);
+ //reinicializamos la polilínea a recortar
+ polilClip = ReiniciaPolilClip(polilClip);
+ }
+ //liberamos la memoria asignada a la polilínea de esta vuelta del bucle
+ LibMemPolilClip(polilClip);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+polil* CreaPolilPolilClip(vertPolilClip* poli)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //número de elementos
+ size_t nVert=0,nElem=0;
+ //estructura auxiliar
+ vertPolilClip* aux=poli;
+ //variable de salida
+ polil* result=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //creamos la estructura vacía
+ result = IniciaPolilVacia();
+ //comprobamos los posibles errores
+ if(result==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //contamos todos los vértices de la polilínea
+ nVert = NumeroVertPolilClip(poli);
+ //contemplamos una posible salida rápida
+ if(nVert==0)
+ {
+ //devolvemos la estructura vacía
+ return result;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //número de elementos de los vectores de coordenadas
+ nElem = nVert+2;
+ //asignamos memoria para los vectores de coordenadas de la estructura
+ result->x = (double*)malloc(nElem*sizeof(double));
+ result->y = (double*)malloc(nElem*sizeof(double));
+ //asignamos memoria para los vectores de posición
+ result->posIni = (size_t*)malloc(sizeof(size_t));
+ result->nVert = (size_t*)malloc(sizeof(size_t));
+ //comprobamos los posibles errores de asignación de memoria
+ if((result->x==NULL)||(result->y==NULL)||(result->posIni==NULL)||
+ (result->nVert==NULL))
+ {
+ //liberamos la posible memoria asignada
+ LibMemPolil(result);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos el número de elementos de los vectores de coordenadas y de
+ //polilíneas
+ result->nElem = nElem;
+ result->nPolil = 1;
+ //asignamos la posición de inicio y el número de vértices
+ result->posIni[0] = 1;
+ result->nVert[0] = nVert;
+ //asignamos los separadores de polilínea al principio y al final
+ result->x[0] = GeocNan();
+ result->y[0] = GeocNan();
+ result->x[nElem-1] = GeocNan();
+ result->y[nElem-1] = GeocNan();
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los vértices de la polilínea
+ for(i=1;i<=nVert;i++)
+ {
+ //copio las coordenadas del vértice
+ result->x[i] = aux->x;
+ result->y[i] = aux->y;
+ //siguiente vértice
+ aux = aux->siguiente;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return result;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/segmento.c b/src/segmento.c
new file mode 100755
index 0000000..6bb5220
--- /dev/null
+++ b/src/segmento.c
@@ -0,0 +1,292 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file segmento.c
+\brief Definición de funciones para la realización de cálculos con segmentos.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 22 de abril de 2011
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/segmento.h"
+/******************************************************************************/
+/******************************************************************************/
+double PosPtoRecta2D(const double x,
+ const double y,
+ const double xIni,
+ const double yIni,
+ const double xFin,
+ const double yFin)
+{
+ //calculamos y salimos de la función
+ return (xIni-x)*(yFin-y)-(xFin-x)*(yIni-y);
+}
+/******************************************************************************/
+/******************************************************************************/
+int TresPuntosColineales2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC)
+{
+ //variable de salida
+ int colin=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //utilizamos la función de posición de punto con respecto a una recta,
+ //aunque no es una función robusta
+ //son colineales si el resultado es 0.0
+ colin = (PosPtoRecta2D(xA,yA,xB,yB,xC,yC)==0.0) ? 1 : 0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return colin;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PuntoEntreDosPuntos2DColin(const double x,
+ const double y,
+ const double xA,
+ const double yA,
+ const double xB,
+ const double yB)
+{
+ //código de salida
+ int cod=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos entre segmento vertical y no vertical
+ if(xA!=xB)
+ {
+ //segmento no vertical, utilizamos las coordenadas X
+ cod = ((xA<x)&&(x<xB))||((xA>x)&&(x>xB));
+ }
+ else
+ {
+ //segmento vertical, utilizamos las coordenadas Y
+ cod = ((yA<y)&&(y<yB))||((yA>y)&&(y>yB));
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int PtoComunSegmParalelos2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ double* x,
+ double* y)
+{
+ //variable de salida
+ int cod=GEOC_SEG_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los puntos son colineales
+ if(!TresPuntosColineales2D(xA,yA,xB,yB,xC,yC))
+ {
+ //los segmentos son paralelos, pero no se cortan
+ return GEOC_SEG_NO_INTERSEC;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los segmentos son el mismo
+ if(((xA==xC)&&(yA==yC)&&(xB==xD)&&(yB==yD))||
+ ((xA==xD)&&(yA==yD)&&(xB==xC)&&(yB==yC)))
+ {
+ //coordenadas de salida
+ *x = xA;
+ *y = yA;
+ //los segmentos son el mismo
+ return GEOC_SEG_INTERSEC_MISMO_SEG;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si algún punto está entre medias del otro segmento
+ if(PuntoEntreDosPuntos2DColin(xA,yA,xC,yC,xD,yD))
+ {
+ //el punto A está en el segmento CD
+ *x = xA;
+ *y = yA;
+ //salimos
+ return GEOC_SEG_INTERSEC_COLIN;
+ }
+ else if(PuntoEntreDosPuntos2DColin(xC,yC,xA,yA,xB,yB))
+ {
+ //el punto C está en el segmento AB
+ *x = xC;
+ *y = yC;
+ //salimos
+ return GEOC_SEG_INTERSEC_COLIN;
+ }
+ else if(PuntoEntreDosPuntos2DColin(xB,yB,xC,yC,xD,yD))
+ {
+ //el punto B está en el segmento CD
+ *x = xB;
+ *y = yB;
+ //salimos
+ return GEOC_SEG_INTERSEC_COLIN;
+ }
+ else if(PuntoEntreDosPuntos2DColin(xD,yD,xA,yA,xB,yB))
+ {
+ //el punto D está en el segmento AB
+ *x = xD;
+ *y = yD;
+ //salimos
+ return GEOC_SEG_INTERSEC_COLIN;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si sólo comparten el extremo A
+ if(((xA==xC)&&(yA==yC))||((xA==xD)&&(yA==yD)))
+ {
+ //coordenadas de salida
+ *x = xA;
+ *y = yA;
+ //los segmentos comparten un extremo
+ return GEOC_SEG_INTERSEC_EXTREMO_COLIN;
+ }
+ //comprobamos si sólo comparten el extremo B
+ if(((xB==xC)&&(yB==yC))||((xB==xD)&&(yB==yD)))
+ {
+ //coordenadas de salida
+ *x = xB;
+ *y = yB;
+ //los segmentos comparten un extremo
+ return GEOC_SEG_INTERSEC_EXTREMO_COLIN;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecSegmentos2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ double* x,
+ double* y)
+{
+ //parámetros de las ecuaciones
+ double s=0.0,t=0.0,num=0.0,den=0.0;
+ //variable de salida
+ int cod=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los rectángulos que encierran a los segmentos son disjuntos
+ if(RectDisjuntos(GEOC_MIN(xA,xB),GEOC_MAX(xA,xB),GEOC_MIN(yA,yB),
+ GEOC_MAX(yA,yB),GEOC_MIN(xC,xD),GEOC_MAX(xC,xD),
+ GEOC_MIN(yC,yD),GEOC_MAX(yC,yD)))
+ {
+ //si los rectángulos son disjuntos, los segmentos no se tocan
+ cod = GEOC_SEG_NO_INTERSEC;
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el denominador
+ den = xA*(yD-yC)+xB*(yC-yD)+xD*(yB-yA)+xC*(yA-yB);
+ //si el denominador es 0.0, los segmentos son paralelos
+ if(den==0.0)
+ {
+ //calculamos el punto común
+ cod = PtoComunSegmParalelos2D(xA,yA,xB,yB,xC,yC,xD,yD,x,y);
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el numerador
+ num = xA*(yD-yC)+xC*(yA-yD)+xD*(yC-yA);
+ //un extremo de un segmento puede estar encima del otro segmento, pero los
+ //segmentos no son colineales
+ if((num==0.0)||(num==den))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN;
+ }
+ //calculamos el parámetro s
+ s = num/den;
+ //calculamos de nuevo el numerador
+ num = -(xA*(yC-yB)+xB*(yA-yC)+xC*(yB-yA));
+ //un extremo de un segmento puede estar encima del otro segmento, pero los
+ //segmentos no son colineales
+ if((num==0.0)||(num==den))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN;
+ }
+ //calculamos el parámetro t
+ t = num/den;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si estamos ante una intersección pura y dura o los segmentos
+ //no se cortan
+ if((s>0.0)&&(s<1.0)&&(t>0.0)&&(t<1.0))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_INTERSEC;
+ }
+ else if((s<0.0)||(s>1.0)||(t<0.0)||(t>1.0))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_NO_INTERSEC;
+ }
+ //calculamos las coordenadas del punto intersección
+ *x = xA+s*(xB-xA);
+ *y = yA+s*(yB-yA);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
diff --git a/src/ventorno.c b/src/ventorno.c
new file mode 100755
index 0000000..d5ca57f
--- /dev/null
+++ b/src/ventorno.c
@@ -0,0 +1,86 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec general
+@{
+\file ventorno.c
+\brief Definición de funciones para el control de variables de entorno.
+\author José Luis García Pallero, jgpallero at gmail.com
+\date 31 de marzo de 2011
+\version 1.0
+\section Licencia Licencia
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name of the copyright holders nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/******************************************************************************/
+/******************************************************************************/
+#include"libgeoc/ventorno.h"
+/******************************************************************************/
+/******************************************************************************/
+int VarEnvValRef(const char* var,
+ const char* valRef)
+{
+ //posible valor de la variable de entorno
+ char* valEnv=NULL;
+ //variable de salida
+ int salida=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //extraemos el valor de la variable de entorno
+ valEnv = getenv(var);
+ //comprobamos si la variable está definida
+ if(valEnv==NULL)
+ {
+ //se devuelve menor que 0
+ salida = -1;
+ }
+ else
+ {
+ //comprobamos su valor
+ if(strcmp(valEnv,valRef))
+ {
+ //su valor es distinto al de referencia
+ salida = 0;
+ }
+ else
+ {
+ //si es igual al de referencia
+ salida = 1;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return salida;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
+/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
+/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
+/* kate: backspace-indents on; show-tabs on; */
+/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
--
Alioth's /home/groups/pkg-octave/bin/git-commit-notice on /srv/git.debian.org/git/pkg-octave/octave-octclip.git
More information about the Pkg-octave-commit
mailing list