summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Laboissière <rafael@debian.org>2020-05-26 05:46:48 -0300
committerRafael Laboissière <rafael@debian.org>2020-05-26 05:46:48 -0300
commitd109b848ad8eff44ef33e19f5510059b81b20b90 (patch)
tree027dcceae0d4c91400020b4e535d8afc1eb91278
Import octave-octclip_2.0.1.orig.tar.gz
[dgit import orig octave-octclip_2.0.1.orig.tar.gz]
-rw-r--r--COPYING674
-rw-r--r--DESCRIPTION12
-rw-r--r--INDEX5
-rw-r--r--NEWS47
-rw-r--r--doc/octclip.pdfbin0 -> 212089 bytes
-rw-r--r--doc/octclip.tex146
-rw-r--r--inst/oc_polybool.m456
-rw-r--r--src/Makefile51
-rw-r--r--src/_oc_polybool.cc288
-rw-r--r--src/arco.c910
-rw-r--r--src/calctopo.c71
-rw-r--r--src/compilador.c82
-rw-r--r--src/dpeucker.c304
-rw-r--r--src/dpeuckera.c204
-rw-r--r--src/dpeuckere.c1495
-rw-r--r--src/dpeuckerp.c1114
-rw-r--r--src/errores.c119
-rw-r--r--src/eucli.c238
-rw-r--r--src/fgeneral.c884
-rw-r--r--src/geocnan.c184
-rw-r--r--src/geocomp.c129
-rw-r--r--src/greiner.c1922
-rw-r--r--src/libgeoc/arco.h617
-rw-r--r--src/libgeoc/calctopo.h81
-rw-r--r--src/libgeoc/compilador.h96
-rw-r--r--src/libgeoc/constantes.h264
-rw-r--r--src/libgeoc/dpeucker.h333
-rw-r--r--src/libgeoc/dpeuckera.h210
-rw-r--r--src/libgeoc/dpeuckere.h1002
-rw-r--r--src/libgeoc/dpeuckerp.h774
-rw-r--r--src/libgeoc/errores.h1058
-rw-r--r--src/libgeoc/eucli.h237
-rw-r--r--src/libgeoc/fgeneral.h736
-rw-r--r--src/libgeoc/general.h61
-rw-r--r--src/libgeoc/geocnan.h233
-rw-r--r--src/libgeoc/geocomp.h208
-rw-r--r--src/libgeoc/geom.h64
-rw-r--r--src/libgeoc/greiner.h855
-rw-r--r--src/libgeoc/mate.h482
-rw-r--r--src/libgeoc/polig.h1215
-rw-r--r--src/libgeoc/polil.h836
-rw-r--r--src/libgeoc/posmatvec.h512
-rw-r--r--src/libgeoc/proyecaux.h90
-rw-r--r--src/libgeoc/ptopol.h1377
-rw-r--r--src/libgeoc/recpolil.h440
-rw-r--r--src/libgeoc/segmento.h377
-rw-r--r--src/libgeoc/ventorno.h100
-rw-r--r--src/mate.c813
-rw-r--r--src/octclip.h31
-rw-r--r--src/polig.c2048
-rw-r--r--src/polil.c1535
-rw-r--r--src/posmatvec.c292
-rw-r--r--src/proyecaux.c92
-rw-r--r--src/ptopol.c1332
-rw-r--r--src/recpolil.c1403
-rw-r--r--src/segmento.c476
-rw-r--r--src/ventorno.c86
57 files changed, 29701 insertions, 0 deletions
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..0f11518
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,12 @@
+Name: OctCLIP
+Version: 2.0.1
+Date: 2020-05-16
+Author: José Luis García Pallero <jgpallero@gmail.com>
+Maintainer: José Luis García Pallero <jgpallero@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 (>= 3.6.0)
+Url: 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..3c40549
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,47 @@
+Summary of important user-visible changes for version 2.0.1:
+------------------------------------------------------------
+
+** Minor changes in src/Makefile
+
+Summary of important user-visible changes for version 2.0.0:
+------------------------------------------------------------
+
+** API changed, added XOR operation, and help strings rewritten
+
+Summary of important user-visible changes for version 1.0.9:
+------------------------------------------------------------
+
+** Minor changes due to http://wiki.octave.org/Remove_class_of_function_from_documentation_strings
+
+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..c0afbef
--- /dev/null
+++ b/doc/octclip.pdf
Binary files differ
diff --git a/doc/octclip.tex b/doc/octclip.tex
new file mode 100644
index 0000000..c39623c
--- /dev/null
+++ b/doc/octclip.tex
@@ -0,0 +1,146 @@
+\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 in \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@upm.es}, \texttt{jgpallero@gmail.com}}}
+\date{May 16, 2020 (version 2.0.1)\\
+ May 11, 2020 (version 2.0.0)\\
+ May 9, 2020 (version 1.1.0)\\
+ May 9, 2020 (version 1.0.9)\\
+ June 16, 2015 (version 1.0.8)\\
+ April 28, 2015 (version 1.0.7)\\
+ 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
+
+\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 as presented in \cite{greiner1998}. This method is an
+efficient algorithm for clipping arbitrary 2D polygons. The algorithm can handle
+arbitrary closed polygons included the cases when the subject and/or clipper
+polygons contain self-intersections.
+
+\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{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/}.
+
+\begin{thebibliography}{9}
+\bibitem{eat-om} \textsc{Eaton}, John W.; \textsc{Bateman}, David;
+ \textsc{Hauberg}, S\o{}ren; and \textsc{Wehbring}, Rik;
+ GNU Octave. A high-level interactive language for numerical
+ computations; Edition 5 for Octave version 5.2.0, January 2020;
+ \url{https://www.gnu.org/software/octave/octave.pdf};
+ Permanently updated at
+ \url{https://www.gnu.org/software/octave/support.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/}.
+\end{thebibliography}
+
+\end{document}
+
+%Copyright (C) 2011-2020, José Luis García Pallero, <jgpallero@gmail.com>
+%This document is distributed under the terms of the GNU Free Documentation
+%License. Please, see http://www.gnu.org/licenses/
diff --git a/inst/oc_polybool.m b/inst/oc_polybool.m
new file mode 100644
index 0000000..92b85af
--- /dev/null
+++ b/inst/oc_polybool.m
@@ -0,0 +1,456 @@
+## Copyright (C) 2011-2020, José Luis García Pallero, <jgpallero@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 {}{[@var{p},@var{details}] =}_oc_polybool(@var{sub},@var{clip})
+## @deftypefnx {}{[@var{p},@var{details}] =}_oc_polybool(@var{sub},@var{clip},@var{op})
+## @deftypefnx {}{[@var{p},@var{details}] =}_oc_polybool(@var{sub},@var{clip},@var{op},@var{hor})
+##
+## @cindex Performs boolean operations between two polygons.
+##
+## This function performs boolean operations between two polygons using the
+## Greiner-Hormann algorithm as it is presented in
+## 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 (it must be unique, although
+## self-intersections are permitted).
+##
+## @var{clip} is a two column matrix containing the X and Y coordinates of the
+## vertices for the clipper polygon(it must be unique, although
+## self-intersections are permitted).
+##
+## @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}. This value is set by default.
+## @item @var{'OR'}
+## Union of @var{sub} and @var{clip}.
+## @item @var{'AB'}
+## Operation @var{sub} - @var{clip}.
+## @item @var{'BA'}
+## Operation of @var{clip} - @var{sub}.
+## @item @var{'XOR'}
+## Exclusive disjunction between @var{clip} and @var{sub}. This operation is
+## performed as the joining of 'AB' and 'BA' consecutively applied
+## @end itemize
+##
+## @var{hor} is an identifier for performing (value 1, by default) or not
+## (value 0) the searching for holes in the result of the operation OR. When OR
+## is applied with non convex entities some of the resulting polygons can be
+## actually holes. Activating this argument the possible holes are identified.
+## If the operation is other than OR the value of this argument is irrelevant
+##
+## 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, i.e., this function does not admit boolean
+## operations between multiple polygons of between polygons with holes, although
+## polygons containing self-intersections are permitted
+##
+## @var{p} is a two column matrix containing the X and Y coordinates of the
+## vertices of the resultant polygon(s). If the result consist of multiple
+## polygons they are separated by rows os (NaN,NaN) values.
+##
+## @var{details} is a struct containing details of the computation. Its fields
+## (IN LOWERCASE!) are:
+##
+## @itemize @bullet
+## @item @var{poly}
+## Three-column matrix with a number of rows equal to the number of polygons
+## stored in the matrix @var{p}. The first column stores the row of @var{p}
+## where the corresponding polygon starts, the second column the row of @var{p}
+## where the polygon end, and the third colum is a mark identifying if the
+## polygon is a hole (value 0) or not (value 1). The values of the third column
+## are relevant only in the case of the OR operation
+## @item @var{nint}
+## Number of intersections between @var{sub} and @var{clip}.
+## @item @var{npert}
+## Number of perturbed points of the @var{clip} polygon if any particular case
+## (points in the border of the other polygon) occurs see
+## http://davis.wpi.edu/~matt/courses/clipping/ for details.
+## @end itemize
+##
+## This function does not check if the dimensions of @var{sub} and @var{clip}
+## are correct.
+##
+## @end deftypefn
+
+function [p,details] = oc_polybool(sub,clip,op,hor)
+
+try
+ functionName = 'oc_polybool';
+ minArg = 2;
+ maxArg = 4;
+
+%*******************************************************************************
+%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
+ %values by default
+ opDef = 'AND';
+ horDef = 1;
+ %check if we omit some input arguments
+ if nargin<maxArg
+ %hor by default
+ hor = horDef;
+ %check for op
+ if nargin==minArg
+ %op by default
+ op = opDef;
+ end
+ 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
+ [p,pp,nInt,nPert] = _oc_polybool(sub,clip,op,hor);
+ %creation of the output struct
+ details.poly = pp;
+ details.nint = nInt;
+ details.npert = nPert;
+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 = upper(inOp);
+ %check values
+ if (~strcmp(outOp,'AND'))&&(~strcmp(outOp,'OR'))&& ...
+ (~strcmp(outOp,'AB'))&&(~strcmp(outOp,'BA'))&&(~strcmp(outOp,'XOR'))
+ 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))
+%!error(oc_polybool(1,2,3,4,5))
+%!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
+%! [pI,detI] = oc_polybool(clSub,clClip,'and');
+%! %compute union
+%! [pU,detU] = oc_polybool(clSub,clClip,'or',1);
+%! %compute A-B
+%! [pA,detA] = oc_polybool(clSub,clClip,'ab');
+%! %compute B-A
+%! [pB,detB] = oc_polybool(clSub,clClip,'ba');
+%! %compute XOR
+%! [pX,detX] = oc_polybool(clSub,clClip,'xor');
+%! %plotting
+%! figure(1);
+%! %plot window for original data
+%! subplot(3,2,1);
+%! plot(clSub(:,1),clSub(:,2),clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('Original polygons');
+%! legend('Subject polygon','Clipper polygon','location','southeast');
+%! %plot window for intersection
+%! subplot(3,2,2);
+%! hold('on');
+%! for i=1:size(detI.poly,1)
+%! pS = detI.poly(i,1);
+%! pE = detI.poly(i,2);
+%! fill(pI(pS:pE,1),pI(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP intersection');
+%! %plot window for union
+%! subplot(3,2,3);
+%! hold('on');
+%! for i=1:size(detU.poly,1)
+%! pS = detU.poly(i,1);
+%! pE = detU.poly(i,2);
+%! if detU.poly(i,3)~=0
+%! fill(pU(pS:pE,1),pU(pS:pE,2),'r');
+%! else
+%! hax = fill(pU(pS:pE,1),pU(pS:pE,2),'b');
+%! legend(hax,'Holes');
+%! end
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP union');
+%! %plot window for A-B
+%! subplot(3,2,4);
+%! hold('on');
+%! for i=1:size(detA.poly,1)
+%! pS = detA.poly(i,1);
+%! pE = detA.poly(i,2);
+%! fill(pA(pS:pE,1),pA(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP A-B');
+%! %plot window for B-A
+%! subplot(3,2,5);
+%! hold('on');
+%! for i=1:size(detB.poly,1)
+%! pS = detB.poly(i,1);
+%! pE = detB.poly(i,2);
+%! fill(pB(pS:pE,1),pB(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP B-A');
+%! %plot window for XOR
+%! subplot(3,2,6);
+%! hold('on');
+%! for i=1:size(detX.poly,1)
+%! pS = detX.poly(i,1);
+%! pE = detX.poly(i,2);
+%! fill(pX(pS:pE,1),pX(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP XOR');
+%! %input message
+%! disp('Press ENTER to continue ...');
+%! pause();
+%!
+%! %subject polygon
+%! clSub = [1000.0 1000.0
+%! 2000.0 1000.0
+%! 2000.0 2800.0
+%! 800.0 2800.0
+%! 2400.0 1900.0
+%! 1000.0 1000.0];
+%! %clipper polygon
+%! clClip = [ 300.0 2500.0
+%! 2500.0 2600.0
+%! 1600.0 600.0
+%! 1300.0 3100.0
+%! 500.0 900.0
+%! 300.0 2500.0];
+%! %limits for the plots
+%! auxLim = [clSub;clClip];
+%! clXLim = [min(auxLim(:,1)) max(auxLim(:,1))];
+%! clYLim = [min(auxLim(:,2)) max(auxLim(:,2))];
+%! %compute intersection
+%! [pI,detI] = oc_polybool(clSub,clClip,'and');
+%! %compute union
+%! [pU,detU] = oc_polybool(clSub,clClip,'or',1);
+%! %compute A-B
+%! [pA,detA] = oc_polybool(clSub,clClip,'ab');
+%! %compute B-A
+%! [pB,detB] = oc_polybool(clSub,clClip,'ba');
+%! %compute XOR
+%! [pX,detX] = oc_polybool(clSub,clClip,'xor');
+%! %plotting
+%! figure(2);
+%! %plot window for original data
+%! subplot(3,2,1);
+%! plot(clSub(:,1),clSub(:,2),clClip(:,1),clClip(:,2));
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('Original polygons');
+%! legend('Subject polygon','Clipper polygon','location','southeast');
+%! %plot window for intersection
+%! subplot(3,2,2);
+%! hold('on');
+%! for i=1:size(detI.poly,1)
+%! pS = detI.poly(i,1);
+%! pE = detI.poly(i,2);
+%! fill(pI(pS:pE,1),pI(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP intersection');
+%! %plot window for union
+%! subplot(3,2,3);
+%! hold('on');
+%! for i=1:size(detU.poly,1)
+%! pS = detU.poly(i,1);
+%! pE = detU.poly(i,2);
+%! if detU.poly(i,3)~=0
+%! fill(pU(pS:pE,1),pU(pS:pE,2),'r');
+%! else
+%! hax = fill(pU(pS:pE,1),pU(pS:pE,2),'b');
+%! legend(hax,'Holes');
+%! end
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP union');
+%! %plot window for A-B
+%! subplot(3,2,4);
+%! hold('on');
+%! for i=1:size(detA.poly,1)
+%! pS = detA.poly(i,1);
+%! pE = detA.poly(i,2);
+%! fill(pA(pS:pE,1),pA(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP A-B');
+%! %plot window for B-A
+%! subplot(3,2,5);
+%! hold('on');
+%! for i=1:size(detB.poly,1)
+%! pS = detB.poly(i,1);
+%! pE = detB.poly(i,2);
+%! fill(pB(pS:pE,1),pB(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP B-A');
+%! %plot window for XOR
+%! subplot(3,2,6);
+%! hold('on');
+%! for i=1:size(detX.poly,1)
+%! pS = detX.poly(i,1);
+%! pE = detX.poly(i,2);
+%! fill(pX(pS:pE,1),pX(pS:pE,2),'r');
+%! end
+%! hold('off');
+%! axis('equal');
+%! xlim(clXLim);
+%! ylim(clYLim);
+%! title('OctCLIP XOR');
+
+
+
+
+%*****END OF TESTS*****
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..e15c37a
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,51 @@
+# -*- 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. dpeuckera.c -o dpeuckera.o
+ $(MKOCTFILE) -c -I. dpeuckere.c -o dpeuckere.o
+ $(MKOCTFILE) -c -I. dpeuckerp.c -o dpeuckerp.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. -DCOLUMN_MAJOR_ORDER_MATVEC posmatvec.c -o posmatvec.o
+ $(MKOCTFILE) -c -I. -DCALCULO_PRODUCTO_MULT mate.c -o mate.o
+ $(MKOCTFILE) -c -I. arco.c -o arco.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) -c -I. proyecaux.c -o proyecaux.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..058bdf8
--- /dev/null
+++ b/src/_oc_polybool.cc
@@ -0,0 +1,288 @@
+/* -*- coding: utf-8 -*- */
+/* Copyright (C) 2011-2020 José Luis García Pallero, <jgpallero@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\
+@deftypefn {}{[@var{p},@var{pp},@var{ni},@var{np}] =}_oc_polybool(@var{sub},@var{clip},@var{op},@var{hor})\n\
+\n\
+@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\
+@var{sub} is a two column matrix containing the X and Y coordinates of the\n\
+vertices for the subject polygon (it must be unique, although\n\
+self-intersections are permitted).\n\n\
+@var{clip} is a two column matrix containing the X and Y coordinates of the\n\
+vertices for the clipper polygon(it must be unique, although\n\
+self-intersections are permitted).\n\n\
+@var{op} is a text string containing the operation to perform between\n\
+@var{sub} and @var{clip}. Possible values are:\n\
+\n\
+@itemize @bullet\n\
+@item @var{'AND'}\n\
+Intersection of @var{sub} and @var{clip}.\n\n\
+@item @var{'OR'}\n\
+Union of @var{sub} and @var{clip}.\n\n\
+@item @var{'AB'}\n\
+Operation @var{sub} - @var{clip}.\n\n\
+@item @var{'BA'}\n\
+Operation of @var{clip} - @var{sub}.\n\n\
+@item @var{'XOR'}\n\
+Exclusive disjunction between @var{clip} and @var{sub}. This operation is\n\
+performed as the joining of 'AB' and 'BA' consecutively applied\n\
+@end itemize\n\
+\n\
+@var{hor} is an identifier for performing (value 1) or not (value 0) the\n\
+searching for holes in the result of the operation OR. When OR is applied\n\
+with non convex entities some of the resulting polygons can be actually\n\
+holes. Activating this argument the possible holes are identified. If the\n\
+operation is other than OR the value of this argument is irrelevant\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\
+@var{sub} and/or @var{clip} are omitted, so they are treated as if each one\n\
+stored a single polygon, i.e., this function does not admit boolean\n\
+operations between multiple polygons of between polygons with holes, although\n\
+polygons containing self-intersections are permitted\n\
+\n\
+The output arguments are:\n\
+\n\
+@var{p} is a two column matrix containing the X and Y coordinates of the\n\
+vertices of the resultant polygon(s). If the result consist of multiple\n\
+polygons they are separated by rows os (NaN,NaN) values.\n\n\
+@var{pp} is a three-column matrix with a number of rows equal to the number\n\
+of polygons stored in the matrix @var{p}. The first column stores the row of\n\
+@var{p} where the corresponding polygon starts, the second column the row of\n\
+@var{p} where the polygon end, and the third colum is a mark identifying if\n\
+the polygon is a hole (value 0) or not (value 1). The values of the third\n\
+column are relevant only in the case of the OR operation\n\n\
+@var{ni} is the number of intersections between @var{sub} and @var{clip}.\n\n\
+@var{np} is the number of perturbed points of the @var{clip} polygon if any\n\
+particular case (points in the border 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\
+@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()!=4)
+ {
+ //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();
+ int sfh=args(3).int_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,posStart=0,posEnd=0,pos=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.numel()),1,1);
+ polB = CreaPoliClip(xB,yB,static_cast<size_t>(xClip.numel()),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 if((!strcmp(opchar.c_str(),"XOR"))||
+ (!strcmp(opchar.c_str(),"xor")))
+ {
+ op = GeocOpBoolXor;
+ }
+ 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,sfh,
+ &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;
+ //output matrix
+ Matrix pp(nPol,3);
+ //dimensions for the output vectors
+ if(nPol)
+ {
+ //Number of elements
+ nElem = result->nElem;
+ posStart = 0;
+ posEnd = nElem-1;
+ if(EsGeocNan(result->x[0]))
+ {
+ nElem--;
+ posStart = 1;
+ }
+ if(EsGeocNan(result->x[posEnd]))
+ {
+ nElem--;
+ posEnd = result->nElem-2;
+ }
+ //output polygons data
+ for(i=0;i<nPol;i++)
+ {
+ //positions start in 1
+ pp(i,0) = result->posIni[i]+1-posStart;
+ pp(i,1) = pp(i,0)+result->nVert[i]-1;
+ pp(i,2) = result->atr[i];
+ }
+ }
+ else
+ {
+ nElem = 0;
+ }
+ //output matrix
+ Matrix p(nElem,2);
+ //copy output data
+ pos = 0;
+ for(i=posStart;i<=posEnd;i++)
+ {
+ p(pos,0) = result->x[i];
+ p(pos,1) = result->y[i];
+ pos++;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //output parameters list
+ outputList(0) = p;
+ outputList(1) = pp;
+ outputList(2) = nInter;
+ outputList(3) = nPert;
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //free memory
+ LibMemPoliClip(polA);
+ LibMemPoliClip(polB);
+ LibMemPolig(result);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //exit
+ return outputList;
+}
diff --git a/src/arco.c b/src/arco.c
new file mode 100644
index 0000000..e8a7fa6
--- /dev/null
+++ b/src/arco.c
@@ -0,0 +1,910 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file arco.c
+\brief Definición de funciones para la realización de cálculos con arcos de
+ circunferencia.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 08 de agosto de 2013
+\copyright
+Copyright (c) 2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/arco.h"
+/******************************************************************************/
+/******************************************************************************/
+int ArcosCircMaxDisjuntos(const double tol,
+ const double lonMin1,
+ const double lonMax1,
+ const double lonMin2,
+ const double lonMax2)
+{
+ //comprobamos los casos de trabajo
+ if(((lonMax1-lonMin1)>(GEOC_CONST_PI-tol))||
+ ((lonMax2-lonMin2)>(GEOC_CONST_PI-tol)))
+ {
+ //indicamos que no son disjuntos, aunque en puridad no lo podemos decir,
+ //pero estos casos son difíciles de determinar porque el arco cruza el
+ //meridiano origen o su antimeridiano
+ return 0;
+ }
+ else
+ {
+ //consideramos únicamente solapamientos en longitud
+ return (!((lonMin1<(lonMax2+tol))&&(lonMax1>(lonMin2-tol))));
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+double AcimutArcoCircMaxEsf(const double tol,
+ const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ double mRot[][3])
+{
+ //variables auxiliares
+ double sLat=0.0,cLat=0.0,sLon=0.0,cLon=0.0;
+ double x=0.0,y=0.0,z=0.0,yR=0.0,zR=0.0;
+ //variable de salida
+ double aci=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las razones trigonométricas de las coordenadas del vértice A
+ sLat = sin(latA);
+ cLat = cos(latA);
+ sLon = sin(lonA);
+ cLon = cos(lonA);
+ //construimos la matriz de rotación para llevar el punto A a (lat=0,lon=0)
+ //primero se rota en torno a Z el valor de la longitud, y luego en torno a Y
+ //el valor -latitud
+ //tal y como aquí se aplican, las rotaciones giran el sistema de coordenadas
+ //en lugar del radio vector del punto de trabajo
+ // | cos(lon) sin(lon) 0|
+ //Rz = |-sin(lon) cos(lon) 0|
+ // | 0 0 1|
+ //
+ // |cos(-lat) 0 -sin(-lat)| | cos(lat) 0 sin(lat)|
+ //Ry = | 0 1 0| = | 0 1 1|
+ // |sin(-lat) 0 cos(-lat)| |-sin(lat) 0 cos(lat)|
+ //
+ //la matriz de rotación es, entonces R = Ry*Rz, donde este orden de
+ //multiplicación de las matrices indica que primero se rota en torno a Z y
+ //luego en torno a Y
+ mRot[0][0] = cLat*cLon;
+ mRot[0][1] = cLat*sLon;
+ mRot[0][2] = sLat;
+ mRot[1][0] = -sLon;
+ mRot[1][1] = cLon;
+ mRot[1][2] = 0.0;
+ mRot[2][0] = -sLat*cLon;
+ mRot[2][1] = -sLat*sLon;
+ mRot[2][2] = cLat;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los puntos son coincidentes
+ //aunque esta comprobación se podría haber hecho al principio, se hace aquí
+ //para poder construir previamente la matriz de rotación que lleve al punto
+ //A a (lat=0,lon=0)
+ if(GEOC_ES_CERO(latA-latB,tol)&&GEOC_ES_CERO(lonA-lonB,tol))
+ {
+ //imponemos un acimut igual a 0.0
+ aci = 0.0;
+ //salimos de la función
+ return aci;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //transformamos las coordenadas del extremo B a cartesianas
+ cLat = cos(latB);
+ x = cLat*cos(lonB);
+ y = cLat*sin(lonB);
+ z = sin(latB);
+ //transformamos al nuevo sistema las coordenadas Y y Z de B
+ AplicaMatrizRotacionCoorCart(1,x,y,z,mRot,NULL,&yR,&zR);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //esta variable es como si fuera una especie de longitud de B en un sistema
+ //en el cual el eje de rotación fuese el X del nuevo sistema
+ //si es >= 0.0, es ya directamente el acimut buscado
+ aci = atan2(yR,zR);
+ //metemos la variable auxiliar en el dominio [0,2*pi), si ha lugar
+ if(aci<0.0)
+ {
+ aci += 2.0*GEOC_CONST_PI;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return aci;
+}
+/******************************************************************************/
+/******************************************************************************/
+void RotaArco00Ecuador(const double tol,
+ const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ double mRot[][3],
+ double* lonBR)
+{
+ //coordenadas cartesianas
+ double x=0.0,y=0.0,z=0.0,xR=0.0,yR=0.0;
+ //matriz de rotación auxiliar
+ double mRotAux[3][3];
+ //acimut del arco AB
+ double aci=0.0;
+ //variables auxiliares
+ double alfa=0.0,cLat=0.0,sAlfa=0.0,cAlfa=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //roto el sistema para llevar el punto A al punto (lat=0,lon=0)
+ aci = AcimutArcoCircMaxEsf(tol,latA,lonA,latB,lonB,mRotAux);
+ //el ángulo a rotar sobre el eje X será 90-aci
+ alfa = GEOC_CONST_PI/2.0-aci;
+ //calculo la matriz de rotación
+ //tal y como aquí se aplica, las rotación gira el sistema de coordenadas en
+ //lugar del radio vector del punto de trabajo
+ // |1 0 0|
+ //Rx = |0 cos(alfa) sin(alfa)|
+ // |0 -sin(alfa) con(alfa)|
+ //la matriz de rotación es, entonces R = Rx*mRotAux, donde este orden de
+ //multiplicación de las matrices indica que primero se rota en torno a los
+ //ejes que indique mRorAux y luego en torno a X
+ sAlfa = sin(alfa);
+ cAlfa = cos(alfa);
+ mRot[0][0] = mRotAux[0][0];
+ mRot[0][1] = mRotAux[0][1];
+ mRot[0][2] = mRotAux[0][2];
+ mRot[1][0] = cAlfa*mRotAux[1][0]+sAlfa*mRotAux[2][0];
+ mRot[1][1] = cAlfa*mRotAux[1][1]+sAlfa*mRotAux[2][1];
+ mRot[1][2] = sAlfa*mRotAux[2][2]; //+cAlfa*mRotAux[1][2], mRotAux[1][2]==0.0
+ mRot[2][0] = -sAlfa*mRotAux[1][0]+cAlfa*mRotAux[2][0];
+ mRot[2][1] = -sAlfa*mRotAux[1][1]+cAlfa*mRotAux[2][1];
+ mRot[2][2] = cAlfa*mRotAux[2][2]; //-sAlfa*mRotAux[1][2], mRotAux[1][2]==0.0
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular la longitud de B en el nuevo sistema
+ if(lonBR!=NULL)
+ {
+ //transformamos las coordenadas del extremo B a cartesianas
+ cLat = cos(latB);
+ x = cLat*cos(lonB);
+ y = cLat*sin(lonB);
+ z = sin(latB);
+ //calculamos las coordenadas X e Y de B en el nuevo sistema
+ AplicaMatrizRotacionCoorCart(1,x,y,z,mRot,&xR,&yR,NULL);
+ //calculamos la longitud de B en el nuevo sistema
+ *lonBR = atan2(yR,xR);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AplicaMatrizRotacionCoorCart(const int sentido,
+ const double x,
+ const double y,
+ const double z,
+ double mRot[][3],
+ double* xR,
+ double* yR,
+ double* zR)
+{
+ //comprobamos el sentido de la rotación
+ if(sentido>=0)
+ {
+ //transformamos las coordenadas que se hayan pedido
+ if(xR!=NULL)
+ {
+ *xR = mRot[0][0]*x+mRot[0][1]*y+mRot[0][2]*z;
+ }
+ if(yR!=NULL)
+ {
+ *yR = mRot[1][0]*x+mRot[1][1]*y+mRot[1][2]*z;
+ }
+ if(zR!=NULL)
+ {
+ *zR = mRot[2][0]*x+mRot[2][1]*y+mRot[2][2]*z;
+ }
+ }
+ else
+ {
+ //transformamos las coordenadas que se hayan pedido
+ if(xR!=NULL)
+ {
+ *xR = mRot[0][0]*x+mRot[1][0]*y+mRot[2][0]*z;
+ }
+ if(yR!=NULL)
+ {
+ *yR = mRot[0][1]*x+mRot[1][1]*y+mRot[2][1]*z;
+ }
+ if(zR!=NULL)
+ {
+ *zR = mRot[0][2]*x+mRot[1][2]*y+mRot[2][2]*z;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void AplicaMatrizRotacionCoorGeod(const int sentido,
+ const double lat,
+ const double lon,
+ double mRot[][3],
+ double* latR,
+ double* lonR)
+{
+ //variables auxiliares
+ double x=0.0,y=0.0,z=0.0,xR=0.0,yR=0.0,zR=0.0,cLat=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que hacer cálculos
+ if((latR!=NULL)||(lonR!=NULL))
+ {
+ //razones trigonométricas auxiliares
+ cLat = cos(lat);
+ //trasformamos las coordenadas de entrada a cartesianas
+ x = cLat*cos(lon);
+ y = cLat*sin(lon);
+ z = sin(lat);
+ //aplicamos la rotación
+ AplicaMatrizRotacionCoorCart(sentido,x,y,z,mRot,&xR,&yR,&zR);
+ //convertimos de nuevo a geodésicas, si ha lugar
+ if(latR!=NULL)
+ {
+ *latR = asin(zR);
+ }
+ if(lonR!=NULL)
+ {
+ *lonR = atan2(yR,xR);
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecCircMaxEsfAux(const double tol,
+ const double xC,
+ const double yC,
+ const double zC,
+ const double xD,
+ const double yD,
+ const double zD,
+ double* xP,
+ double* yP,
+ double* zP)
+{
+ //vectores normales
+ double NABx=0.0,NABy=0.0,NABz=0.0,NCDx=0.0,NCDy=0.0,NCDz=0.0;
+ double dx=0.0,dy=0.0,dz=0.0;
+ //variable auxiliar
+ double t=0.0;
+ //variable de salida
+ int cod=GEOC_ARC_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //vector normal al plano del ecuador AOB
+ NABx = 0.0;
+ NABy = 0.0;
+ NABz = 1.0;
+ //vector normal al plano COD
+ ProductoVectorial(xC,yC,zC,xD,yD,zD,&NCDx,&NCDy,&NCDz);
+ //vector director de la línea intersección de los dos planos
+ ProductoVectorial(NABx,NABy,NABz,NCDx,NCDy,NCDz,&dx,&dy,&dz);
+ //sólo seguimos si no hay casos especiales
+ if((!GEOC_ES_CERO(dx,tol))||
+ (!GEOC_ES_CERO(dy,tol))||
+ (!GEOC_ES_CERO(dz,tol)))
+ {
+ //hay intersección
+ cod = GEOC_ARC_INTERSEC;
+ //comprobamos si hay que devolver coordenadas
+ if((xP!=NULL)&&(yP!=NULL)&&(zP!=NULL))
+ {
+ //calculamos el inverso del módulo del vector (dx,dy,dz)
+ t = 1.0/sqrt(dx*dx+dy*dy+dz*dz);
+ //coordenadas del punto de intersección en la esfera de radio unidad
+ *xP = dx*t;
+ *yP = dy*t;
+ *zP = dz*t;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecArcCirMaxEsferaVertComunAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP)
+{
+ //identificadores de igualdad entre puntos
+ int AiC=0,AiD=0,BiC=0,BiD=0;
+ //variables auxiliares
+ double latA=0.0,lonA=0.0,latB=0.0;
+ double lonAAux=0.0,lonCAux=0.0,lonDAux=0.0;
+ //variable de salida
+ int cod=GEOC_ARC_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //por defecto, las coordenadas de salida son 0.0
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ *latP = 0.0;
+ *lonP = 0.0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //chequeamos la posible igualdad entre los vértices de los arcos
+ AiC = (GEOC_ES_CERO(latA-latC,tol))&&(GEOC_ES_CERO(lonA-lonC,tol));
+ AiD = (GEOC_ES_CERO(latA-latD,tol))&&(GEOC_ES_CERO(lonA-lonD,tol));
+ BiC = (GEOC_ES_CERO(latB-latC,tol))&&(GEOC_ES_CERO(lonB-lonC,tol));
+ BiD = (GEOC_ES_CERO(latB-latD,tol))&&(GEOC_ES_CERO(lonB-lonD,tol));
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos los posibles casos en que los arcos tengan algún extremo común
+ if((AiC&&BiD)||(AiD&&BiC))
+ {
+ //los vértices coinciden, dos a dos: los arcos son el mismo
+ cod = GEOC_ARC_INTERSEC_MISMO_ARC;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latA;
+ *lonP = lonA;
+ }
+ }
+ else if(AiC)
+ {
+ //compruebo si D está en el ecuador
+ if(GEOC_ES_CERO(latD,tol))
+ {
+ //comprobamos el tipo de colinelidad
+ if((lonB*lonD)<=0.0)
+ {
+ //si el producto de las longitudes es negativo quiere decir que
+ //los extremos B y D están cada uno a un lado del meridiano
+ //origen, luego los arcos se tocan en un punto y son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_COLIN;
+ }
+ else
+ {
+ //los arcos se tocan en un punto y se solapan parcialmente
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ }
+ }
+ else
+ {
+ //los arcos se tocan en un punto, pero no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latA;
+ *lonP = lonA;
+ }
+ }
+ else if(AiD)
+ {
+ //compruebo si C está en el ecuador
+ if(GEOC_ES_CERO(latC,tol))
+ {
+ //comprobamos el tipo de colinelidad
+ if((lonB*lonC)<=0.0)
+ {
+ //si el producto de las longitudes es negativo quiere decir que
+ //los extremos B y C están cada uno a un lado del meridiano
+ //origen, luego los arcos se tocan en un punto y son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_COLIN;
+ }
+ else
+ {
+ //los arcos se tocan en un punto y se solapan parcialmente
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ }
+ }
+ else
+ {
+ //los arcos se tocan en un punto, pero no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latA;
+ *lonP = lonA;
+ }
+ }
+ else if(BiC)
+ {
+ //compruebo si D está en el ecuador
+ if(GEOC_ES_CERO(latD,tol))
+ {
+ //ponemos el origen de longitudes en B
+ lonAAux = -lonB;
+ lonDAux = lonD-lonB;
+ //comprobamos el tipo de colinelidad
+ if((lonAAux*lonDAux)<=0.0)
+ {
+ //si el producto de las longitudes es negativo quiere decir que
+ //los extremos A y D están cada uno a un lado de B, luego los
+ //arcos se tocan en un punto y son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_COLIN;
+ }
+ else
+ {
+ //los arcos se tocan en un punto y se solapan parcialmente
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ }
+ }
+ else
+ {
+ //los arcos se tocan en un punto, pero no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice B
+ *latP = latB;
+ *lonP = lonB;
+ }
+ }
+ else if(BiD)
+ {
+ //compruebo si C está en el ecuador
+ if(GEOC_ES_CERO(latC,tol))
+ {
+ //ponemos el origen de longitudes en B
+ lonAAux = -lonB;
+ lonCAux = lonC-lonB;
+ //comprobamos el tipo de colinelidad
+ if((lonAAux*lonCAux)<=0.0)
+ {
+ //si el producto de las longitudes es negativo quiere decir que
+ //los extremos A y C están cada uno a un lado de B, luego los
+ //arcos se tocan en un punto y son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_COLIN;
+ }
+ else
+ {
+ //los arcos se tocan en un punto y se solapan parcialmente
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ }
+ }
+ else
+ {
+ //los arcos se tocan en un punto, pero no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latB;
+ *lonP = lonB;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecArcCirMaxEsferaVertApoyadoAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP)
+{
+ //coordenadas de trabajo
+ double xC=0.0,yC=0.0,zC=0.0,xD=0.0,yD=0.0,zD=0.0,xP=0.0,yP=0.0,zP=0.0;
+ double latA=0.0,lonA=0.0,latB=0.0,lonP1=0.0,lonP2=0.0;
+ //variables auxiliares
+ double cLat=0.0;
+ //variable de salida
+ int cod=GEOC_ARC_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //por defecto, las coordenadas de salida son 0.0
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ *latP = 0.0;
+ *lonP = 0.0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si el arco CD está sobre el ecuador
+ if(GEOC_ES_CERO(latC,tol)&&GEOC_ES_CERO(latD,tol))
+ {
+ //comprobamos qué punto está en qué segmento
+ //consideramos también el caso de que los segmentos sólo se toquen en un
+ //extremo
+ if(((lonA>(lonC-tol))&&(lonA<(lonD+tol)))||
+ ((lonA<(lonC+tol))&&(lonA>(lonD-tol))))
+ {
+ //el punto A está entre C y D, los arcos se solapan
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latA;
+ *lonP = lonA;
+ }
+ //salimos de la función
+ return cod;
+ }
+ else if(((lonB>(lonC-tol))&&(lonB<(lonD+tol)))||
+ ((lonB<(lonC+tol))&&(lonB>(lonD-tol))))
+ {
+ //el punto B está entre C y D, los arcos se solapan
+ cod = GEOC_ARC_INTERSEC_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice B
+ *latP = latB;
+ *lonP = lonB;
+ }
+ //salimos de la función
+ return cod;
+ }
+ else
+ {
+ //salimos de la función
+ return cod;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas cartesianas tridimensionales geocéntricas de C
+ cLat = cos(latC);
+ xC = cLat*cos(lonC);
+ yC = cLat*sin(lonC);
+ zC = sin(latC);
+ //coordenadas cartesianas tridimensionales geocéntricas de D
+ cLat = cos(latD);
+ xD = cLat*cos(lonD);
+ yD = cLat*sin(lonD);
+ zD = sin(latD);
+ //calculamos la intersección de dos círculos máximos
+ //aquí ya no cabe caso singular, ya que si los dos arcos estuviesen en el
+ //ecuador habría sido detectado en el chequeo del principio de la función
+ IntersecCircMaxEsfAux(tol,xC,yC,zC,xD,yD,zD,&xP,&yP,&zP);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos los posibles puntos de intersección
+ lonP1 = atan2(yP,xP);
+ lonP2 = lonP1+GEOC_CONST_PI;
+ lonP2 = (lonP2>GEOC_CONST_PI) ? lonP2-2.0*GEOC_CONST_PI : lonP2;
+ //vamos comprobando si algún punto de corte coincide con A, B, C o D
+ if(GEOC_ES_CERO(lonP1,tol)||GEOC_ES_CERO(lonP2,tol))
+ {
+ //los arcos no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice A
+ *latP = latA;
+ *lonP = lonA;
+ }
+ }
+ else if(GEOC_ES_CERO(lonP1-lonB,tol)||GEOC_ES_CERO(lonP2-lonB,tol))
+ {
+ //los arcos no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice B
+ *latP = latB;
+ *lonP = lonB;
+ }
+ }
+ else if((GEOC_ES_CERO(latC,tol))&&
+ (GEOC_ES_CERO(lonP1-lonC,tol)||GEOC_ES_CERO(lonP2-lonC,tol)))
+ {
+ //los arcos no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice C
+ *latP = 0.0;
+ *lonP = lonC;
+ }
+ }
+ else if((GEOC_ES_CERO(latD,tol))&&
+ (GEOC_ES_CERO(lonP1-lonD,tol)||GEOC_ES_CERO(lonP2-lonD,tol)))
+ {
+ //los arcos no son colineales
+ cod = GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN;
+ //comprobamos si hay que asignar coordenadas de salida
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ //el punto de corte es el vértice D
+ *latP = 0.0;
+ *lonP = lonD;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecArcCircMaxEsferaAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ const double xGC,
+ const double yGC,
+ const double zGC,
+ const double xGD,
+ const double yGD,
+ const double zGD,
+ double* latP,
+ double* lonP)
+{
+ //coordenadas de trabajo
+ double xC=0.0,yC=0.0,zC=0.0,xD=0.0,yD=0.0,zD=0.0;
+ double xP=0.0,yP=0.0,zP=0.0,lonP1=0.0,lonP2=0.0,lonPI=0.0;
+ //variables auxiliares
+ double cLat=0.0;
+ //variable de salida
+ int cod=GEOC_ARC_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //por defecto, las coordenadas de salida son 0.0
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ *latP = 0.0;
+ *lonP = 0.0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si CD cruza o no el ecuador
+ if(((latC>tol)&&(latD>tol))||((latC<-tol)&&(latD<-tol)))
+ {
+ //salimos de la función
+ return cod;
+ }
+ else
+ {
+ //casos en que los arcos puedan tener algún extremo común
+ cod = IntersecArcCirMaxEsferaVertComunAux(tol,lonB,latC,lonC,latD,lonD,
+ latP,lonP);
+ //si se ha encontrado intersección, salimos de la función
+ if(cod!=GEOC_ARC_NO_INTERSEC)
+ {
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //comprobamos si un extremo de un arco se apoya en el otro
+ cod = IntersecArcCirMaxEsferaVertApoyadoAux(tol,lonB,latC,lonC,
+ latD,lonD,latP,lonP);
+ //si se ha encontrado intersección, salimos de la función
+ if(cod!=GEOC_ARC_NO_INTERSEC)
+ {
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //comprobamos si no se han pasado coordenadas cartesianas para C
+ if(EsGeocNan(xC)&&EsGeocNan(yC)&&EsGeocNan(zC))
+ {
+ //coordenadas cartesianas tridimensionales geocéntricas de C
+ cLat = cos(latC);
+ xC = cLat*cos(lonC);
+ yC = cLat*sin(lonC);
+ zC = sin(latC);
+ }
+ else
+ {
+ //copiamos las coordenadas pasadas
+ xC = xGC;
+ yC = yGC;
+ zC = zGC;
+ }
+ //comprobamos si no se han pasado coordenadas cartesianas para D
+ if(EsGeocNan(xD)&&EsGeocNan(yD)&&EsGeocNan(zD))
+ {
+ //coordenadas cartesianas tridimensionales geocéntricas de D
+ cLat = cos(latD);
+ xD = cLat*cos(lonD);
+ yD = cLat*sin(lonD);
+ zD = sin(latD);
+ }
+ else
+ {
+ //copiamos las coordenadas pasadas
+ xD = xGD;
+ yD = yGD;
+ zD = zGD;
+ }
+ //calculamos la intersección de dos círculos máximos
+ //aquí ya no cabe caso singular, ya que si los dos arcos estuviesen en
+ //el ecuador habría sido detectado por la llamadas a
+ //IntersecArcCirMaxEsferaVertComunAux() o
+ //IntersecArcCirMaxEsferaVertApoyadoAux()
+ IntersecCircMaxEsfAux(tol,xC,yC,zC,xD,yD,zD,&xP,&yP,&zP);
+ //calculamos los posibles puntos de intersección
+ lonP1 = atan2(yP,xP);
+ lonP2 = lonP1+GEOC_CONST_PI;
+ lonP2 = (lonP2>GEOC_CONST_PI) ? lonP2-2.0*GEOC_CONST_PI : lonP2;
+ //compruebo si alguna de esas longitudes está en el segmento AB
+ if(((lonP1>-tol)&&(lonP1<lonB+tol))||((lonP1<tol)&&(lonP1>lonB-tol)))
+ {
+ //asigno el código de salida
+ cod = GEOC_ARC_INTERSEC;
+ //longitud de la intersección
+ lonPI = lonP1;
+ }
+ else if(((lonP2>-tol)&&(lonP2<lonB+tol))||
+ ((lonP2<tol)&&(lonP2>lonB-tol)))
+ {
+ //asigno el código de salida
+ cod = GEOC_ARC_INTERSEC;
+ //longitud de la intersección
+ lonPI = lonP2;
+ }
+ //compruebo si, habiendo corte, hay coordenadas de salida
+ if((cod!=GEOC_ARC_NO_INTERSEC)&&(latP!=NULL)&&(lonP!=NULL))
+ {
+ //asigno las coordenadas a las variables de salida
+ *latP = 0.0;
+ *lonP = lonPI;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecArcCircMaxEsfera(const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP)
+{
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de trabajo
+ double xC=0.0,yC=0.0,zC=0.0,xD=0.0,yD=0.0,zD=0.0;
+ double xCR=0.0,yCR=0.0,zCR=0.0,xDR=0.0,yDR=0.0,zDR=0.0;
+ double lonBR=0.0,latCR=0.0,lonCR=0.0,latDR=0.0,lonDR=0.0;
+ double latPR=0.0,lonPR=0.0;
+ //matriz de rotación
+ double mRot[3][3];
+ //variable auxiliar
+ double cLat=0.0;
+ //variable de salida
+ int cod=GEOC_ARC_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //por defecto, si no hay intersección, las coordenadas de salida son 0.0
+ if((latP!=NULL)&&(lonP!=NULL))
+ {
+ *latP = 0.0;
+ *lonP = 0.0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los rectángulos son disjuntos, los segmentos no se tocan
+ if(ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(lonA,lonB),GEOC_MAX(lonA,lonB),
+ GEOC_MIN(lonC,lonD),GEOC_MAX(lonC,lonD)))
+ {
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la matriz de rotación para llevar AB al ecuador
+ RotaArco00Ecuador(tol,latA,lonA,latB,lonB,mRot,&lonBR);
+ //calculamos las coordenadas cartesianas de los puntos C y D
+ cLat = cos(latC);
+ xC = cLat*cos(lonC);
+ yC = cLat*sin(lonC);
+ zC = sin(latC);
+ cLat = cos(latD);
+ xD = cLat*cos(lonD);
+ yD = cLat*sin(lonD);
+ zD = sin(latD);
+ //rotamos los puntos C y D
+ AplicaMatrizRotacionCoorCart(1,xC,yC,zC,mRot,&xCR,&yCR,&zCR);
+ AplicaMatrizRotacionCoorCart(1,xD,yD,zD,mRot,&xDR,&yDR,&zDR);
+ //calculamos las coordenadas geodésicas rotadas
+ latCR = asin(zCR);
+ lonCR = atan2(yCR,xCR);
+ latDR = asin(zDR);
+ lonDR = atan2(yDR,xDR);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la intersección
+ cod = IntersecArcCircMaxEsferaAux(tol,lonBR,latCR,lonCR,latDR,lonDR,xCR,yCR,
+ zCR,xDR,yDR,zDR,&latPR,&lonPR);
+ //transformamos el resultado al sistema original, si ha lugar
+ if((cod!=GEOC_ARC_NO_INTERSEC)&&(latP!=NULL)&&(lonP!=NULL))
+ {
+ AplicaMatrizRotacionCoorGeod(-1,latPR,lonPR,mRot,latP,lonP);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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/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@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 100644
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@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..1d06156
--- /dev/null
+++ b/src/dpeucker.c
@@ -0,0 +1,304 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 17 de agosto de 2013
+\copyright
+Copyright (c) 2013-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const int esf,
+ size_t* nPtosSal)
+{
+ //identificador de caso especial
+ int hayCasoEspecial=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ sal = CasosEspecialesAligeraPolilinea(x,y,nPtos,incX,incY,atol,nPtosSal,
+ &hayCasoEspecial);
+ //comprobamos si ha habido algún caso especial
+ if(hayCasoEspecial)
+ {
+ //comprobamos si ha ocurrido algún error de asignación de memoria
+ if(nPtos&&(sal==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ else
+ {
+ //salimos de la función
+ return sal;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si trabajamos con el algoritmo original o con el robusto
+ if(robusto==GeocDPeuckerOriginal)
+ {
+ //versión original del algoritmo
+ sal = DouglasPeuckerOriginal(x,y,nPtos,incX,incY,atol,esf,nPtosSal);
+ }
+ else
+ {
+ //utilizamos la variación robusta del algoritmo
+ sal = DouglasPeuckerRobusto(x,y,nPtos,incX,incY,atol,paralelizaTol,
+ robusto,nSegRobOrig,nSegRobAuto,esf,
+ nPtosSal);
+ }
+ //comprobamos los posibles errores
+ if(nPtos&&(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;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* DouglasPeuckerOriginal(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int esf,
+ size_t* nPtosSal)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //variables auxiliares
+ int aux=0;
+ size_t pos=0;
+ //vector de identificadores de elementos usados
+ char* usados=NULL;
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //iniciamos la variable de salida de número de puntos a 0
+ *nPtosSal = 0;
+ //asigno memoria para los puntos usados y la inicializo a ceros (calloc)
+ usados = (char*)calloc(nPtos,sizeof(char));
+ //comprobamos los posibles errores
+ if(usados==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //indico el primer punto y el último como usados
+ usados[0] = 1;
+ usados[nPtos-1] = 1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si trabajamos sobre la esfera o sobre el plano
+ if(esf)
+ {
+ //aplico el algoritmo original sobre la esfera
+ DouglasPeuckerOriginalEsfera(x,y,nPtos,incX,incY,atol,0,nPtos-1,usados);
+ }
+ else
+ {
+ //aplico el algoritmo original sobre el plano
+ DouglasPeuckerOriginalPlano(x,y,nPtos,incX,incY,atol,0,nPtos-1,usados);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //cuento los puntos usados
+ for(i=0;i<nPtos;i++)
+ {
+ //copio el identificador de uso en una variable de tipo entero, ya
+ //que si no el compilador gcc 4.7.0 da warning si asigno el valor de
+ //tipo char a la variable size_t
+ //da warning de posible error de conversión por cambio de signo
+ //aunque se haga la conversión explícita
+ aux = (int)usados[i];
+ //voy contando
+ (*nPtosSal) += (size_t)aux;
+ }
+ //asigno memoria para el vector de salida
+ sal = (size_t*)malloc((*nPtosSal)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //libero la memoria utilizada
+ free(usados);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //inicio la variable de posición
+ pos = 0;
+ //recorro el vector de elementos usados
+ for(i=0;i<nPtos;i++)
+ {
+ //compruebo si el elemento se ha usado
+ if(usados[i])
+ {
+ //asigno la posición
+ sal[pos] = i;
+ //aumento el contador de posiciones en el vector de salida
+ pos++;
+ }
+ }
+ //compruebo si sólo se han usado dos puntos que son el mismo
+ if((*nPtosSal==2)&&(x[0]==x[(nPtos-1)*incX])&&(y[0]==y[(nPtos-1)*incY]))
+ {
+ //actualizamos el número de puntos de salida
+ *nPtosSal = 1;
+ //reasigno memoria
+ sal = (size_t*)realloc(sal,(*nPtosSal)*sizeof(size_t));
+ //comprobamos los posibles errores
+ if(sal==NULL)
+ {
+ //libero la memoria utilizada
+ free(usados);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //libero la memoria utilizada
+ free(usados);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* DouglasPeuckerRobusto(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const int esf,
+ size_t* nPtosSal)
+{
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //identificador de caso especial
+ int hayCasoEspecial=0;
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ sal = CasosEspecialesAligeraPolilinea(x,y,nPtos,incX,incY,atol,nPtosSal,
+ &hayCasoEspecial);
+ //comprobamos si ha habido algún caso especial
+ if(hayCasoEspecial)
+ {
+ //comprobamos si ha ocurrido algún error de asignación de memoria
+ if(nPtos&&(sal==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ else
+ {
+ //salimos de la función
+ return sal;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si trabajamos sobre la esfera o sobre el plano
+ if(esf)
+ {
+ //aplico el algoritmo robusto sobre la esfera
+ sal = DouglasPeuckerRobustoEsfera(x,y,nPtos,incX,incY,atol,
+ paralelizaTol,robusto,nSegRobOrig,
+ nSegRobAuto,nPtosSal);
+ }
+ else
+ {
+ //aplico el algoritmo robusto sobre el plano
+ sal = DouglasPeuckerRobustoPlano(x,y,nPtos,incX,incY,tol,paralelizaTol,
+ robusto,nSegRobOrig,nSegRobAuto,
+ nPtosSal);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* 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/dpeuckera.c b/src/dpeuckera.c
new file mode 100644
index 0000000..1a98e73
--- /dev/null
+++ b/src/dpeuckera.c
@@ -0,0 +1,204 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckera.c
+\brief Declaración de funciones auxiliares para el uso de la familia de
+ algoritmos de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 01 de abril de 2014
+\copyright
+Copyright (c) 2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/dpeuckera.h"
+/******************************************************************************/
+/******************************************************************************/
+size_t* CasosEspecialesAligeraPolilinea(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ size_t* nPtosSal,
+ int* hayCasoEspecial)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //vector de salida
+ size_t* salida=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //en principio, el número de puntos de salida es el mismo que el de entrada
+ *nPtosSal = nPtos;
+ //inicializamos la variable indicadora de caso especial a 0
+ *hayCasoEspecial = 0;
+ //vamos comprobando casos especiales
+ if(nPtos==0)
+ {
+ //indicamos que estamos anteun caso especial
+ *hayCasoEspecial = 1;
+ //actualizamos la variable de número de puntos de salida
+ *nPtosSal = 0;
+ //salimos de la función
+ return NULL;
+ }
+ else if(nPtos==1)
+ {
+ //indicamos que estamos anteun caso especial
+ *hayCasoEspecial = 1;
+ //asignamos memoria para el vector de salida
+ salida = (size_t*)malloc(sizeof(size_t));
+ //comprobamos si ha ocurrido algún error
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //la entrada sólo es un punto
+ *nPtosSal = 1;
+ salida[0] = 0;
+ }
+ else if(nPtos==2)
+ {
+ //indicamos que estamos ante un caso especial
+ *hayCasoEspecial = 1;
+ //en principio, los dos puntos son válidos
+ *nPtosSal = 2;
+ //comprobamos si los puntos son o no el mismo
+ if((x[0]==x[incX])&&(y[0]==y[incY]))
+ {
+ //sólo vale el primer punto
+ *nPtosSal = 1;
+ }
+ //asignamos memoria para el vector de salida
+ salida = (size_t*)malloc((*nPtosSal)*sizeof(size_t));
+ //comprobamos si ha ocurrido algún error
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //copiamos los puntos válidos
+ for(i=0;i<(*nPtosSal);i++)
+ {
+ salida[i] = i;
+ }
+ }
+ else if((nPtos==3)&&(x[0]==x[2*incX])&&(y[0]==y[2*incY]))
+ {
+ //indicamos que estamos ante un caso especial
+ *hayCasoEspecial = 1;
+ //en principio, hay dos puntos válidos
+ *nPtosSal = 2;
+ //comprobamos también si el segundo punto es el mismo que el primero
+ if((x[0]==x[incX])&&(y[0]==y[incY]))
+ {
+ //sólo vale el primer punto
+ *nPtosSal = 1;
+ }
+ //asignamos memoria para el vector de salida
+ salida = (size_t*)malloc((*nPtosSal)*sizeof(size_t));
+ //comprobamos si ha ocurrido algún error
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //copiamos los puntos válidos
+ for(i=0;i<(*nPtosSal);i++)
+ {
+ salida[i] = i;
+ }
+ }
+ else if(atol==0.0)
+ {
+ //indicamos que estamos anteun caso especial
+ *hayCasoEspecial = 1;
+ //asignamos memoria para el vector de salida
+ salida = (size_t*)malloc(nPtos*sizeof(size_t));
+ //comprobamos si ha ocurrido algún error
+ if(salida==NULL)
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //inicializamos el número de puntos de salida y la posición del primero
+ *nPtosSal = 1;
+ salida[0] = 0;
+ //recorremos el resto de puntos
+ for(i=1;i<nPtos;i++)
+ {
+ //comprobamos si el punto de trabajo es distinto al anterior
+ if((x[i*incX]!=x[(i-1)*incX])&&(y[i*incY]!=y[(i-1)*incY]))
+ {
+ //asignamos la posición del punto de trabajo
+ salida[*nPtosSal] = i;
+ //actualizamos el número de puntos de salida
+ (*nPtosSal)++;
+ }
+ }
+ //comprobamos si se ha quitado algún punto
+ if(nPtos!=(*nPtosSal))
+ {
+ //reasignamos memoria para el vector de salida
+ salida = (size_t*)realloc(salida,(*nPtosSal)*sizeof(size_t));
+ //comprobamos si ha ocurrido algún error
+ if(salida==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 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/dpeuckere.c b/src/dpeuckere.c
new file mode 100644
index 0000000..5436759
--- /dev/null
+++ b/src/dpeuckere.c
@@ -0,0 +1,1495 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckere.c
+\brief Definición de funciones auxiliares para el aligerado de polilíneas sobre
+ la superficie de la esfera, basadas en el algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 15 de agosto de 2013
+\copyright
+Copyright (c) 2013-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/dpeuckere.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpDpeuckere(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
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerOriginalEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posIni,
+ const size_t posFin,
+ char* usados)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //seno de la distancia angular de los puntos al segmento base
+ double dist=0.0;
+ //valor absoluto del seno de la tolerancia, excepto en el caso en que ésta
+ //sea mayor que pi/2, que hacemos 1-cos(tol) para que quede un valor mayor
+ //que 1
+ double stol=(tol<=(2.0*GEOC_CONST_PI)) ? fabs(sin(tol)) : 1.0-cos(tol);
+ //posición de la distancia máxima
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ if((nPtos<=2)||(stol==0.0))
+ {
+ //se usan todos los puntos
+ for(i=0;i<nPtos;i++)
+ {
+ usados[i] = 1;
+ }
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo continuamos si los puntos extremos no están seguidos
+ if(posIni!=(posFin-1))
+ {
+ //calculamos la distancia máxima de los puntos de trabajo al arco
+ //formado por los extremos
+ dist = DouglasPeuckerSenDistMaxEsfera(y,x,incY,incX,posIni,posFin,&pos);
+ //comprobamos si esa distancia está fuera de tolerancia
+ if(dist>stol)
+ {
+ //indicamos que el punto se usa
+ usados[pos] = 1;
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(incY,y,incX,x,nPtos,tol,posIni,posFin,pos,usados)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos el algoritmo a la parte anterior al punto de trabajo
+ DouglasPeuckerOriginalEsfera(x,y,nPtos,incX,incY,tol,posIni,pos,
+ usados);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos el algoritmo a la parte posterior al punto de trabajo
+ DouglasPeuckerOriginalEsfera(x,y,nPtos,incX,incY,tol,pos,posFin,
+ usados);
+} // --> fin del #pragma omp parallel sections
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* DouglasPeuckerRobustoEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ size_t* nPtosSal)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //tolerancia angular
+ double tolAng=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de trabajo
+ double lonFinR=0.0;
+ //matriz de rotación
+ double mRot[3][3];
+ //variable indicadora de punto en tolerancia
+ int entol=0;
+ //identificador de caso especial
+ int hayCasoEspecial=0;
+ //identificadores de utilización de algoritmos semi robustos
+ int robOrig=0,robAuto=0;
+ //número de elementos de trabajo internos del vector de salida
+ size_t nElem=0;
+ //identificador de paralelización
+ int paraleliza=0;
+ //vectores para almacenar coordenadas cartesianas geocéntricas
+ double* xG=NULL;
+ double* yG=NULL;
+ double* zG=NULL;
+ //variable auxiliar
+ double cLat=0.0,latVert=0.0,lonVert=0.0;
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ sal = CasosEspecialesAligeraPolilinea(x,y,nPtos,incX,incY,atol,nPtosSal,
+ &hayCasoEspecial);
+ //comprobamos si ha habido algún caso especial
+ if(hayCasoEspecial)
+ {
+ //comprobamos si ha ocurrido algún error de asignación de memoria
+ if(nPtos&&(sal==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ else
+ {
+ //salimos de la función
+ return sal;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //asignamos memoria para las coordenadas cartesianas geocéntricas
+ xG = (double*)malloc(nPtos*sizeof(double));
+ yG = (double*)malloc(nPtos*sizeof(double));
+ zG = (double*)malloc(nPtos*sizeof(double));
+ //comprobamos los posibles errores
+ if((xG==NULL)||(yG==NULL)||(zG==NULL))
+ {
+ //liberamos la posible memoeia asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(nPtos,incY,y,incX,x,xG,yG,zG) \
+ private(i,latVert,lonVert,cLat)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=0;i<nPtos;i++)
+ {
+ //extraemos las coordenadas geodésicas
+ latVert = y[i*incY];
+ lonVert = x[i*incX];
+ //calculamos el coseno de la latitud
+ cLat = cos(latVert);
+ //calculamos las coordenadas cartesianas, considerando radio unidad
+ xG[i] = cLat*cos(lonVert);
+ yG[i] = cLat*sin(lonVert);
+ zG[i] = sin(latVert);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si se utiliza algoritmo de intersección con línea original
+ if((robusto==GeocDPeuckerRobSi)||(robusto==GeocDPeuckerRobOrig))
+ {
+ robOrig = 1;
+ }
+ //comprobamos si se utiliza algoritmo de intersección con línea generada
+ if((robusto==GeocDPeuckerRobSi)||(robusto==GeocDPeuckerRobAuto))
+ {
+ robAuto = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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)
+ {
+ //liberamos la posible memoria asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ //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 = 2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //entramos en un bucle mientras no hayamos llegado hasta el último punto
+ while(j<nPtos)
+ {
+ //hacemos el cambio de sistema para qua la base AB quede en el ecuador,
+ //con A en el punto (lat=0,lon=0)
+ RotaArco00Ecuador(tolAng,y[i*incY],x[i*incX],y[j*incY],x[j*incX],mRot,
+ &lonFinR);
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ //comprobamos si los puntos intermedios están en tolerancia
+ //sólo paralelizamos si el número de puntos intermedios es mayor que uno
+ if(paraleliza&&paralelizaTol&&((j-i-1)>1))
+ {
+ //aplicamos el algoritmo en paralelo
+ entol = DouglasPeuckerPuntosEnTolEsferaOMP(x,y,incX,incY,xG,yG,zG,
+ atol,i,j,i+1,j-1,lonFinR,
+ mRot);
+ }
+ else
+ {
+ //aplicamos el algoritmo en serie
+ entol = DouglasPeuckerPuntosEnTolEsferaSerie(x,y,incX,incY,xG,yG,zG,
+ atol,i,j,i+1,j-1,
+ lonFinR,mRot);
+ }
+ //comprobamos si todos los puntos están en tolerancia
+ if(entol)
+ {
+ //pasamos al siguiente punto como extremo del segmento
+ j++;
+ }
+ else
+ {
+ //el punto final será el anterior al actual, ya que con el actual
+ //hay al menos un vértice fuera de tolerancia y con el anterior se
+ //comprobó en el paso previo del bucle que no había ningún vértice
+ //fuera
+ j--;
+ //aplicación del algoritmo de intersección con puntos originales
+ if(robOrig)
+ {
+ //aplicamos el algoritmo
+ DouglasPeuckerRobIntersecOrigEsfera(x,y,nPtos,incX,incY,xG,yG,
+ zG,nSegRobOrig,i,&j);
+ }
+ //aplicación del algoritmo de auto intersección
+ if(robAuto)
+ {
+ //aplicamos el algoritmo
+ DouglasPeuckerRobAutoIntersecEsfera(x,y,incX,incY,xG,yG,zG,i,&j,
+ sal,*nPtosSal,nSegRobAuto);
+ }
+ //añadimos al contador el 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)
+ {
+ //liberamos la posible memoria asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ //añadimos el punto al vector de salida
+ sal[(*nPtosSal)-1] = j;
+ //actualizamos los índices de los puntos de trabajo
+ i = j;
+ j = i+2;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que añadir el último punto
+ if((sal[(*nPtosSal)-1]!=(nPtos-1))&&
+ ((x[sal[(*nPtosSal)-1]*incX]!=x[(nPtos-1)*incX])||
+ (y[sal[(*nPtosSal)-1]*incY]!=y[(nPtos-1)*incY])))
+ {
+ //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)
+ {
+ //liberamos la posible memoria asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ //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)
+ {
+ //liberamos la posible memoria asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la posible memoria asignada
+ free(xG);
+ free(yG);
+ free(zG);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerPuntosEnTolEsferaOMP(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin,
+ const double lonFinR,
+ double mRot[][3])
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //identificador de punto fuera de tolerancia
+ int ftol=0;
+ //coordenadas de los vértices de trabajo
+ double xTrab=0.0,yTrab=0.0,xGTrab=0.0,yGTrab=0.0,zGTrab=0.0;
+ //distancia calculada
+ double dist=0.0;
+ //identificador de existencia de coordenadas cartesianas geocéntricas
+ int ccart=0;
+ //variable de salida
+ int entol=1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((posBaseIni+1)>=posBaseFin)
+ {
+ //salimos de la función
+ return entol;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //valor absoluto del seno de la tolerancia, excepto en el caso en que ésta
+ //sea mayor que pi/2, que hacemos 1-cos(tol) para que quede un valor > 1
+ atol = (atol<=(2.0*GEOC_CONST_PI)) ? sin(atol) : 1.0-cos(atol);
+ //comprobamos si se han pasado coordenadas cartesianas geocénticas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //indicamos que sí existen
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posPtoIni,posPtoFin,incX,x,incY,y,ccart,xG,yG,zG,mRot,lonFinR,atol) \
+ private(i,xTrab,yTrab,xGTrab,yGTrab,zGTrab,dist) \
+ reduction(+:ftol)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posPtoIni;i<=posPtoFin;i++)
+ {
+ //sólo calculo si no se ha encontrado ningún punto fuera de tolerancia
+ //en este hilo
+ if(!ftol)
+ {
+ //extraemos las coordenadas del vértice de trabajo
+ xTrab = x[i*incX];
+ yTrab = y[i*incY];
+ //comprobamos si hay coordenadas cartesianas
+ if(ccart)
+ {
+ //extraigo las coordenadas cartesianas del vértice de trabajo
+ xGTrab = xG[i];
+ yGTrab = yG[i];
+ zGTrab = zG[i];
+ }
+ else
+ {
+ //como no hay coordenadas cartesianas, asigno NaN
+ xGTrab = GeocNan();
+ yGTrab = xGTrab;
+ zGTrab = xGTrab;
+ }
+ //calculamos la distancia sobre la esfera de radio unidad
+ dist = DouglasPeuckerSenDistMaxEsferaAux(yTrab,xTrab,xGTrab,yGTrab,
+ zGTrab,lonFinR,mRot);
+ //comprobamos si está fuera de tolerancia
+ if(dist>atol)
+ {
+ //aumentamos el indicador de fuera de tolerancia
+ ftol++;
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay algún punto fuera de tolerancia
+ if(ftol)
+ {
+ //indicamos que hay algún punto que no está en tolerancia
+ entol = 0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return entol;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerPuntosEnTolEsferaSerie(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin,
+ const double lonFinR,
+ double mRot[][3])
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //coordenadas de los vértices
+ double xTrab=0.0,yTrab=0.0;
+ double xGTrab=GeocNan(),yGTrab=GeocNan(),zGTrab=GeocNan();
+ //distancia calculada
+ double dist=0.0;
+ //identificador de existencia de coordenadas cartesianas geocéntricas
+ int ccart=0;
+ //variable de salida
+ int entol=1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((posBaseIni+1)>=posBaseFin)
+ {
+ //salimos de la función
+ return entol;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //valor absoluto del seno de la tolerancia, excepto en el caso en que ésta
+ //sea mayor que pi/2, que hacemos 1-cos(tol) para que quede un valor > 1
+ atol = (atol<=(2.0*GEOC_CONST_PI)) ? sin(atol) : 1.0-cos(atol);
+ //comprobamos si se han pasado coordenadas cartesianas geocénticas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //indicamos que sí existen
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos a chequear
+ for(i=posPtoIni;i<=posPtoFin;i++)
+ {
+ //extraemos las coordenadas del vértice de trabajo
+ xTrab = x[i*incX];
+ yTrab = y[i*incY];
+ //extraemos las coordenadas cartesianas del vértice de trabajo
+ if(ccart)
+ {
+ xGTrab = xG[i];
+ yGTrab = yG[i];
+ zGTrab = zG[i];
+ }
+ //calculamos la distancia sobre la esfera de radio unidad
+ dist = DouglasPeuckerSenDistMaxEsferaAux(yTrab,xTrab,xGTrab,yGTrab,
+ zGTrab,lonFinR,mRot);
+ //comprobamos si está fuera de tolerancia
+ if(dist>atol)
+ {
+ //indicamos que estamos fuera de tolerancia
+ entol = 0;
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return entol;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerRobIntersecOrigEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas del arco base
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0;
+ //posición de parada para comprobar la intersección de arcos
+ size_t posParada=0;
+ //identificación de paralelización
+ int paraleliza=0;
+ //variable identificadora de existencia de corte de segmentos
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los puntos de inicio y fin son contiguos, hay salida rápida
+ if((posIni+1)>=(*posFin))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //posición de parada para el chequeo de segmentos/arcos
+ posParada = ((segAUsar==0)||(segAUsar>=(nPtos-(*posFin))))
+ ? nPtos-1
+ : (*posFin)+segAUsar;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas del punto inicial del segmento/arco base (no cambian)
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ //construimos todos los segmentos/arcos base posibles
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //este punto es el siguiente al punto inicial del segmento/arco base
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ //coordenadas del punto final del segmento/arco base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //comprobamos si hay que paralelizar
+ if(paraleliza)
+ {
+ //calculamos en paralelo
+ corte = DouglasPeuckerRobIntersecOrigEsferaOMP(xA,yA,xB,yB,x,y,incX,
+ incY,xG,yG,zG,i,
+ posParada);
+ }
+ else
+ {
+ //calculamos en serie
+ corte = DouglasPeuckerRobIntersecOrigEsferaSerie(xA,yA,xB,yB,x,y,
+ incX,incY,xG,yG,zG,
+ i,posParada);
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(!corte)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle de segmentos base
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecOrigEsferaOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de los arcos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ double xBR=0.0,xCR=0.0,yCR=0.0,xDR=0.0,yDR=0.0;
+ double xGC=0.0,yGC=0.0,zGC=0.0,xGD=0.0,yGD=0.0,zGD=0.0;
+ double xGCR=0.0,yGCR=0.0,zGCR=0.0,xGDR=0.0,yGDR=0.0,zGDR=0.0;
+ //matriz de rotación
+ double mRot[3][3];
+ //identificador de haber pasado coordenadas cartesianas
+ int ccart=0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //llevamos AB al ecuador, con A en (lat=0,lon=0)
+ RotaArco00Ecuador(tol,yA,xA,yB,xB,mRot,&xBR);
+ //comprobamos si se han pasado coordenadas cartesianas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //se han pasado
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posIni,posFin,incX,x,incY,y,tol,xA,xB,ccart,xG,yG,zG,mRot,xBR) \
+ private(i,xGC,yGC,zGC,xGD,yGD,zGD,xGCR,yGCR,zGCR,xGDR,yGDR,zGDR, \
+ xC,yC,xD,yD,xCR,yCR,xDR,yDR) \
+ reduction(+:corte)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posIni;i<posFin;i++)
+ {
+ //sólo realizo cálculos si no se ha encontrado ningún corte en este hilo
+ if(!corte)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[i*incX];
+ yC = y[i*incY];
+ xD = x[(i+1)*incX];
+ yD = y[(i+1)*incY];
+ //sigo si los rectángulos que encierran a los segmentos se cortan
+ if(!ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(xA,xB),GEOC_MAX(xA,xB),
+ GEOC_MIN(xC,xD),GEOC_MAX(xC,xD)))
+ {
+ //comprobamos si hay coordenadas cartesianas
+ if(ccart)
+ {
+ //extraigo las coordenadas cartesianas
+ xGC = xG[i];
+ yGC = yG[i];
+ zGC = zG[i];
+ xGD = xG[i+1];
+ yGD = yG[i+1];
+ zGD = zG[i+1];
+ //aplico la rotación a las coordenadas cartesianas
+ AplicaMatrizRotacionCoorCart(1,xGC,yGC,zGC,mRot,&xGCR,&yGCR,
+ &zGCR);
+ AplicaMatrizRotacionCoorCart(1,xGD,yGD,zGD,mRot,&xGDR,&yGDR,
+ &zGDR);
+ //coordenadas geodésicas de los puntos rotados
+ yCR = asin(zGCR);
+ xCR = atan2(yGCR,xGCR);
+ yDR = asin(zGDR);
+ xDR = atan2(yGDR,xGDR);
+ }
+ else
+ {
+ //como no hay coordenadas cartesianas, asigno NaN
+ xGCR = GeocNan();
+ yGCR = xGCR;
+ zGCR = xGCR;
+ xGDR = xGCR;
+ yGDR = xGCR;
+ zGDR = xGCR;
+ //rotamos las coordenadas de C y D
+ AplicaMatrizRotacionCoorGeod(1,yC,xC,mRot,&yCR,&xCR);
+ AplicaMatrizRotacionCoorGeod(1,yD,xD,mRot,&yDR,&xDR);
+ }
+ //comprobamos si hay intersección
+ corte += DouglasPeuckerRobIntersecEsfera(xBR,xCR,yCR,xDR,yDR,
+ xGCR,yGCR,zGCR,xGDR,
+ yGDR,zGDR,posIni,i);
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecOrigEsferaSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ double xBR=0.0,xCR=0.0,yCR=0.0,xDR=0.0,yDR=0.0;
+ double xGC=0.0,yGC=0.0,zGC=0.0,xGD=0.0,yGD=0.0,zGD=0.0;
+ double xGCR=GeocNan(),yGCR=GeocNan(),zGCR=GeocNan();
+ double xGDR=GeocNan(),yGDR=GeocNan(),zGDR=GeocNan();
+ //matriz de rotación
+ double mRot[3][3];
+ //identificador de haber pasado coordenadas cartesianas
+ int ccart=0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //llevamos AB al ecuador, con A en (lat=0,lon=0)
+ RotaArco00Ecuador(tol,yA,xA,yB,xB,mRot,&xBR);
+ //comprobamos si se han pasado coordenadas cartesianas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //se han pasado
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos de trabajo
+ for(i=posIni;i<posFin;i++)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[i*incX];
+ yC = y[i*incY];
+ xD = x[(i+1)*incX];
+ yD = y[(i+1)*incY];
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(xA,xB),GEOC_MAX(xA,xB),
+ GEOC_MIN(xC,xD),GEOC_MAX(xC,xD)))
+ {
+ //comprobamos si hay coordenadas cartesianas
+ if(ccart)
+ {
+ //extraigo las coordenadas cartesianas
+ xGC = xG[i];
+ yGC = yG[i];
+ zGC = zG[i];
+ xGD = xG[i+1];
+ yGD = yG[i+1];
+ zGD = zG[i+1];
+ //aplico la rotación a las coordenadas cartesianas
+ AplicaMatrizRotacionCoorCart(1,xGC,yGC,zGC,mRot,&xGCR,&yGCR,
+ &zGCR);
+ AplicaMatrizRotacionCoorCart(1,xGD,yGD,zGD,mRot,&xGDR,&yGDR,
+ &zGDR);
+ //coordenadas geodésicas de los puntos rotados
+ yCR = asin(zGCR);
+ xCR = atan2(yGCR,xGCR);
+ yDR = asin(zGDR);
+ xDR = atan2(yGDR,xGDR);
+ }
+ else
+ {
+ //rotamos las coordenadas de C y D
+ AplicaMatrizRotacionCoorGeod(1,yC,xC,mRot,&yCR,&xCR);
+ AplicaMatrizRotacionCoorGeod(1,yD,xD,mRot,&yDR,&xDR);
+ }
+ //comprobamos si hay intersección
+ corte = DouglasPeuckerRobIntersecEsfera(xBR,xCR,yCR,xDR,yDR,xGCR,
+ yGCR,zGCR,xGDR,yGDR,zGDR,
+ posIni,i);
+ }
+ //si ha habido intersección de segmentos/arcos, salimos del bucle
+ if(corte)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerRobAutoIntersecEsfera(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ size_t* posFin,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas del arco base
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0;
+ //posición de parada para comprobar la intersección de arcos
+ size_t posParada=0;
+ //identificación de paralelización
+ int paraleliza=0;
+ //variable identificadora de existencia de corte de segmentos
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los puntos de inicio y fin son contiguos, hay salida rápida
+ if((posIni+1)>=(*posFin))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //posición de parada en el vector posAlig para el chequeo de segmentos/arcos
+ posParada = ((segAUsar==0)||(segAUsar>=(nPosAlig-1)))
+ ? 0
+ : nPosAlig-1-segAUsar;
+ //coordenadas del punto inicial del arco base (no cambian)
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ //construimos todos los arcos base posibles
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //este punto es el siguiente al punto inicial del segmento/arco base
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ //coordenadas del punto final del segmento/arco base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //comprobamos si hay que paralelizar
+ if(paraleliza)
+ {
+ //calculamos en paralelo
+ corte = DouglasPeuckerRobAutoIntersecEsferaOMP(xA,yA,xB,yB,x,y,incX,
+ incY,xG,yG,zG,
+ posAlig,nPosAlig,
+ nPosAlig-1,
+ posParada);
+ }
+ else
+ {
+ //calculamos en serie
+ corte = DouglasPeuckerRobAutoIntersecEsferaSerie(xA,yA,xB,yB,x,y,
+ incX,incY,xG,yG,zG,
+ posAlig,nPosAlig,
+ nPosAlig-1,
+ posParada);
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(!corte)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle de segmentos base
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobAutoIntersecEsferaOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ double xBR=0.0,xCR=0.0,yCR=0.0,xDR=0.0,yDR=0.0;
+ double xGC=0.0,yGC=0.0,zGC=0.0,xGD=0.0,yGD=0.0,zGD=0.0;
+ double xGCR=0.0,yGCR=0.0,zGCR=0.0,xGDR=0.0,yGDR=0.0,zGDR=0.0;
+ //matriz de rotación
+ double mRot[3][3];
+ //identificador de haber pasado coordenadas cartesianas
+ int ccart=0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //llevamos AB al ecuador, con A en (lat=0,lon=0)
+ RotaArco00Ecuador(tol,yA,xA,yB,xB,mRot,&xBR);
+ //comprobamos si se han pasado coordenadas cartesianas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //se han pasado
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posIni,posFin,incX,x,posAlig,incY,y,tol,xA,xB,ccart,xG,yG,zG,mRot,xBR, \
+ nPosAlig) \
+ private(i,xGC,yGC,zGC,xGD,yGD,zGD,xGCR,yGCR,zGCR,xGDR,yGDR,zGDR, \
+ xC,yC,xD,yD,xCR,yCR,xDR,yDR) \
+ reduction(+:corte)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posIni;i>posFin;i--)
+ {
+ //sólo realizo cálculos si no se ha encontrado ningún corte en este hilo
+ if(!corte)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[posAlig[i]*incX];
+ yC = y[posAlig[i]*incY];
+ xD = x[posAlig[i-1]*incX];
+ yD = y[posAlig[i-1]*incY];
+ //sigo si los rectángulos que encierran a los segmentos se cortan
+ if(!ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(xA,xB),GEOC_MAX(xA,xB),
+ GEOC_MIN(xC,xD),GEOC_MAX(xC,xD)))
+ {
+ //comprobamos si hay coordenadas cartesianas
+ if(ccart)
+ {
+ //extraigo las coordenadas cartesianas
+ xGC = xG[posAlig[i]];
+ yGC = yG[posAlig[i]];
+ zGC = zG[posAlig[i]];
+ xGD = xG[posAlig[i-1]];
+ yGD = yG[posAlig[i-1]];
+ zGD = zG[posAlig[i-1]];
+ //aplico la rotación a las coordenadas cartesianas
+ AplicaMatrizRotacionCoorCart(1,xGC,yGC,zGC,mRot,&xGCR,&yGCR,
+ &zGCR);
+ AplicaMatrizRotacionCoorCart(1,xGD,yGD,zGD,mRot,&xGDR,&yGDR,
+ &zGDR);
+ //coordenadas geodésicas de los puntos rotados
+ yCR = asin(zGCR);
+ xCR = atan2(yGCR,xGCR);
+ yDR = asin(zGDR);
+ xDR = atan2(yGDR,xGDR);
+ }
+ else
+ {
+ //como no hay coordenadas cartesianas, asigno NaN
+ xGCR = GeocNan();
+ yGCR = xGCR;
+ zGCR = xGCR;
+ xGDR = xGCR;
+ yGDR = xGCR;
+ zGDR = xGCR;
+ //rotamos las coordenadas de C y D
+ AplicaMatrizRotacionCoorGeod(1,yC,xC,mRot,&yCR,&xCR);
+ AplicaMatrizRotacionCoorGeod(1,yD,xD,mRot,&yDR,&xDR);
+ }
+ //comprobamos si hay intersección
+ corte += DouglasPeuckerRobIntersecEsfera(xBR,xCR,yCR,xDR,yDR,
+ xGCR,yGCR,zGCR,xGDR,
+ yGDR,zGDR,
+ posAlig[nPosAlig-1],
+ posAlig[i]);
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobAutoIntersecEsferaSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ double xBR=0.0,xCR=0.0,yCR=0.0,xDR=0.0,yDR=0.0;
+ double xGC=0.0,yGC=0.0,zGC=0.0,xGD=0.0,yGD=0.0,zGD=0.0;
+ double xGCR=GeocNan(),yGCR=GeocNan(),zGCR=GeocNan();
+ double xGDR=GeocNan(),yGDR=GeocNan(),zGDR=GeocNan();
+ //matriz de rotación
+ double mRot[3][3];
+ //identificador de haber pasado coordenadas cartesianas
+ int ccart=0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //llevamos AB al ecuador, con A en (lat=0,lon=0)
+ RotaArco00Ecuador(tol,yA,xA,yB,xB,mRot,&xBR);
+ //comprobamos si se han pasado coordenadas cartesianas
+ if((xG!=NULL)&&(yG!=NULL)&&(zG!=NULL))
+ {
+ //se han pasado
+ ccart = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos de trabajo
+ for(i=posIni;i>posFin;i--)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[posAlig[i]*incX];
+ yC = y[posAlig[i]*incY];
+ xD = x[posAlig[i-1]*incX];
+ yD = y[posAlig[i-1]*incY];
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(xA,xB),GEOC_MAX(xA,xB),
+ GEOC_MIN(xC,xD),GEOC_MAX(xC,xD)))
+ {
+ //comprobamos si hay coordenadas cartesianas
+ if(ccart)
+ {
+ //extraigo las coordenadas cartesianas
+ xGC = xG[posAlig[i]];
+ yGC = yG[posAlig[i]];
+ zGC = zG[posAlig[i]];
+ xGD = xG[posAlig[i-1]];
+ yGD = yG[posAlig[i-1]];
+ zGD = zG[posAlig[i-1]];
+ //aplico la rotación a las coordenadas cartesianas
+ AplicaMatrizRotacionCoorCart(1,xGC,yGC,zGC,mRot,&xGCR,&yGCR,
+ &zGCR);
+ AplicaMatrizRotacionCoorCart(1,xGD,yGD,zGD,mRot,&xGDR,&yGDR,
+ &zGDR);
+ //coordenadas geodésicas de los puntos rotados
+ yCR = asin(zGCR);
+ xCR = atan2(yGCR,xGCR);
+ yDR = asin(zGDR);
+ xDR = atan2(yGDR,xGDR);
+ }
+ else
+ {
+ //rotamos las coordenadas de C y D
+ AplicaMatrizRotacionCoorGeod(1,yC,xC,mRot,&yCR,&xCR);
+ AplicaMatrizRotacionCoorGeod(1,yD,xD,mRot,&yDR,&xDR);
+ }
+ //comprobamos si hay intersección
+ corte = DouglasPeuckerRobIntersecEsfera(xBR,xCR,yCR,xDR,yDR,xGCR,
+ yGCR,zGCR,xGDR,yGDR,zGDR,
+ posAlig[nPosAlig-1],
+ posAlig[i]);
+ }
+ //si ha habido intersección de segmentos/arcos, salimos del bucle
+ if(corte)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecEsfera(const double xB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ const double xGC,
+ const double yGC,
+ const double zGC,
+ const double xGD,
+ const double yGD,
+ const double zGD,
+ const size_t posFinAB,
+ const size_t posIniCD)
+{
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //variables auxiliares
+ double xAux=0.0,yAux=0.0;
+ //identificador de intersección
+ int inter=GEOC_DPEUCKER_NO_INTERSEC;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //seguimos si los rectángulos que encierran a los arcos se cortan
+ if(!ArcosCircMaxDisjuntos(tol,
+ GEOC_MIN(0.0,xB),GEOC_MAX(0.0,xB),
+ GEOC_MIN(xC,xD),GEOC_MAX(xC,xD)))
+ {
+ //comprobamos la posible intersección de los arcos
+ inter = IntersecArcCircMaxEsferaAux(tol,xB,yC,xC,yD,xD,xGC,yGC,zGC,xGD,
+ yGD,zGD,&yAux,&xAux);
+ //compruebo si los dos arcos son contiguos
+ if(posFinAB==posIniCD)
+ {
+ //compruebo si es la sucesión de arco inicial+final
+ if((inter!=GEOC_ARC_INTERSEC_MISMO_ARC)&&
+ (inter!=GEOC_ARC_INTERSEC_COLIN))
+ {
+ //en este caso, no hay intersección
+ inter = GEOC_DPEUCKER_NO_INTERSEC;
+ }
+ }
+ //unificamos los identificadores de intersección
+ if(!((inter==GEOC_ARC_NO_INTERSEC)||(inter==GEOC_DPEUCKER_NO_INTERSEC)))
+ {
+ //hay intersección
+ corte = 1;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+double DouglasPeuckerSenDistMaxEsfera(const double* lat,
+ const double* lon,
+ const size_t incLat,
+ const size_t incLon,
+ const size_t posIni,
+ const size_t posFin,
+ size_t* pos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //tolerancia angular
+ double tol=fabs(GEOC_ARC_RES_ANG);
+ //coordenadas del punto de trabajo
+ double latP=0.0,lonP=0.0;
+ //matriz de rotación
+ double mRot[3][3];
+ //longitud del extremo final de la base en el sistema rotado
+ double lonFinR=0.0;
+ //variable auxiliar
+ double distAux=0.0;
+ //variable de salida
+ double dist=-1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los dos puntos están seguidos
+ if((posIni+1)==posFin)
+ {
+ //la posición que devolvemos es la del punto inicial
+ *pos = posIni;
+ //la distancia devuelta es -1.0
+ return dist;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la matriz de rotación para llevar la base al ecuador
+ RotaArco00Ecuador(tol,
+ lat[posIni*incLat],lon[posIni*incLon],
+ lat[posFin*incLat],lon[posFin*incLon],mRot,&lonFinR);
+ //recorremos los puntos entre los extremos
+ for(i=posIni+1;i<posFin;i++)
+ {
+ //extraemos las coordenadas del punto de trabajo
+ latP = lat[i*incLat];
+ lonP = lon[i*incLon];
+ //calculamos la distancia desde el punto a la base
+ distAux = DouglasPeuckerSenDistMaxEsferaAux(latP,lonP,GeocNan(),
+ GeocNan(),GeocNan(),lonFinR,
+ mRot);
+ //comprobamos si la distancia calculada es mayor que la anterior
+ if(distAux>dist)
+ {
+ //actualizamos la distancia máxima
+ dist = distAux;
+ //guardamos la posición del punto
+ *pos = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return dist;
+}
+/******************************************************************************/
+/******************************************************************************/
+double DouglasPeuckerSenDistMaxEsferaAux(const double latVert,
+ const double lonVert,
+ const double xVert,
+ const double yVert,
+ const double zVert,
+ const double lonBase2R,
+ double mRot[][3])
+{
+ //coordenadas cartesianas tridimensionales geocéntricas
+ double x=0.0,y=0.0,z=0.0,xR=0.0,yR=0.0,zR=0.0,xB2R=0.0,yB2R=0.0;
+ //longitud del vértice en el sistema rotado
+ double lonVR=0.0;
+ //variables auxiliares
+ double cLat=0.0,alfa=0.0,cAlfa=0.0;
+ //variable de salida
+ double dist=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si se han pasado las coordenadas cartesianas del vértice
+ if((!EsGeocNan(xVert))&&(!EsGeocNan(yVert))&&(!EsGeocNan(zVert)))
+ {
+ //asignamos las coordenadas a las variables de trabajo
+ x = xVert;
+ y = yVert;
+ z = zVert;
+ }
+ else
+ {
+ //calculamos las coordenadas tridimensionales del vértice de trabajo
+ cLat = cos(latVert);
+ x = cLat*cos(lonVert);
+ y = cLat*sin(lonVert);
+ z = sin(latVert);
+ }
+ //aplicamos la rotación
+ AplicaMatrizRotacionCoorCart(1,x,y,z,mRot,&xR,&yR,&zR);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //distinguimos todos los casos de trabajo
+ if((xR==0.0)&&(yR==0.0))
+ {
+ //el vértice queda en el polo
+ dist = 1.0;
+ }
+ else
+ {
+ //distinguimos casos especiales
+ if(((lonBase2R>0.0)&&(yR<0.0))||((lonBase2R<0.0)&&(yR>0.0)))
+ {
+ //vértice fuera de la base: izquierda de AB o derecha de BA
+ //coseno del ángulo en el espacio que forma el eje X con el vector
+ //OV, es decir, entre los vectores (1,0,0) y (xR,yR,zR)
+ cAlfa = xR/sqrt(xR*xR+yR*yR+zR*zR);
+ //ángulo
+ alfa = acos(cAlfa);
+ //comprobamos si el ángulo es mayor o menor de pi/2
+ if(alfa<=(2.0*GEOC_CONST_PI))
+ {
+ //la variable de salida es el seno del ángulo
+ dist = sin(alfa);
+ }
+ else
+ {
+ //la variable de salida es 1 menos el coseno del ángulo, para
+ //quede un valor mayor que 1
+ dist = 1.0-cos(alfa);
+ }
+ }
+ else
+ {
+ //longitud del vértice en el sistema rotado
+ lonVR = atan2(yR,xR);
+ //distinguimos casos especiales
+ if(((lonBase2R>0.0)&&(lonVR>lonBase2R))||
+ ((lonBase2R<0.0)&&(lonVR<lonBase2R)))
+ {
+ //vértice fuera de la base: derecha de AB o izquierda de BA
+ //coordenadas cartesianas del punto de la base que no es (0,0,0)
+ xB2R = cos(lonBase2R);
+ yB2R = sin(lonBase2R);
+ //coseno del ángulo en el espacio que forma el vector OBase2R
+ //con el vector OV, es decir, entre los vectores
+ //(xBase2R,yBase2R,0) y (xR,yR,zR)
+ cAlfa = (xB2R*xR+yB2R*yR)/sqrt(xR*xR+yR*yR+zR*zR);
+ //ángulo
+ alfa = acos(cAlfa);
+ //comprobamos si el ángulo es mayor o menor de pi/2
+ if(alfa<=(2.0*GEOC_CONST_PI))
+ {
+ //la variable de salida es el seno del ángulo
+ dist = sin(alfa);
+ }
+ else
+ {
+ //la variable de salida es 1 menos el coseno del ángulo,
+ //para quede un valor mayor que 1
+ dist = 1.0-cos(alfa);
+ }
+ }
+ else
+ {
+ //en el caso normal, la distancia es directamente el seno de la
+ //latitud del vértice, que es igual a la coordenada Z
+ dist = fabs(zR);
+ }
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return dist;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* 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/dpeuckerp.c b/src/dpeuckerp.c
new file mode 100644
index 0000000..ef8af84
--- /dev/null
+++ b/src/dpeuckerp.c
@@ -0,0 +1,1114 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckerp.c
+\brief Definición de funciones para el aligerado de polilíneas en el plano
+ basadas en el algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 04 de julio de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/dpeuckerp.h"
+/******************************************************************************/
+/******************************************************************************/
+int GeocParOmpDpeuckerp(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
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerOriginalPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posIni,
+ const size_t posFin,
+ char* usados)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //distancia de los puntos al segmento base
+ double dist=0.0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //posición de la distancia máxima
+ size_t pos=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ if((nPtos<=2)||(atol==0.0))
+ {
+ //se usan todos los puntos
+ for(i=0;i<nPtos;i++)
+ {
+ usados[i] = 1;
+ }
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //sólo continuamos si los puntos extremos no están seguidos
+ if(posIni!=(posFin-1))
+ {
+ //calculamos la distancia máxima de los puntos de trabajo al segmento
+ //formado por los extremos
+ dist = DouglasPeuckerDistMaxPlano(x,y,incX,incY,posIni,posFin,&pos);
+ //comprobamos si esa distancia está fuera de tolerancia
+ if(dist>atol)
+ {
+ //indicamos que el punto se usa
+ usados[pos] = 1;
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel sections default(none) \
+ shared(nPtos,incX,x,incY,y,posIni,posFin,pos,tol,usados)
+#endif
+{
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos el algoritmo a la parte anterior al punto de trabajo
+ DouglasPeuckerOriginalPlano(x,y,nPtos,incX,incY,tol,posIni,pos,
+ usados);
+#if defined(_OPENMP)
+#pragma omp section
+#endif
+ //aplicamos el algoritmo a la parte posterior al punto de trabajo
+ DouglasPeuckerOriginalPlano(x,y,nPtos,incX,incY,tol,pos,posFin,
+ usados);
+} // --> fin del #pragma omp parallel sections
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t* DouglasPeuckerRobustoPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ size_t* nPtosSal)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //variable indicadora de punto en tolerancia
+ int entol=0;
+ //identificador de caso especial
+ int hayCasoEspecial=0;
+ //identificadores de utilización de algoritmos semi robustos
+ int robOrig=0,robAuto=0;
+ //número de elementos de trabajo internos del vector de salida
+ size_t nElem=0;
+ //identificador de paralelización
+ int paraleliza=0;
+ //vector de salida
+ size_t* sal=NULL;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos casos especiales
+ sal = CasosEspecialesAligeraPolilinea(x,y,nPtos,incX,incY,atol,nPtosSal,
+ &hayCasoEspecial);
+ //comprobamos si ha habido algún caso especial
+ if(hayCasoEspecial)
+ {
+ //comprobamos si ha ocurrido algún error de asignación de memoria
+ if(nPtos&&(sal==NULL))
+ {
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria");
+ //salimos de la función
+ return NULL;
+ }
+ else
+ {
+ //salimos de la función
+ return sal;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si se utiliza algoritmo de intersección con línea original
+ if((robusto==GeocDPeuckerRobSi)||(robusto==GeocDPeuckerRobOrig))
+ {
+ robOrig = 1;
+ }
+ //comprobamos si se utiliza algoritmo de intersección con línea generada
+ if((robusto==GeocDPeuckerRobSi)||(robusto==GeocDPeuckerRobAuto))
+ {
+ robAuto = 1;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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 = 2;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //entramos en un bucle mientras no hayamos llegado hasta el último punto
+ while(j<nPtos)
+ {
+ //comprobamos si los puntos intermedios están en tolerancia
+ //sólo paralelizamos si el número de puntos intermedios es mayor que uno
+ if(paraleliza&&paralelizaTol&&((j-i-1)>1))
+ {
+ //aplicamos el algoritmo en paralelo
+ entol = DouglasPeuckerPuntosEnTolPlanoOMP(x,y,incX,incY,atol,i,j,
+ i+1,j-1);
+ }
+ else
+ {
+ //aplicamos el algoritmo en serie
+ entol = DouglasPeuckerPuntosEnTolPlanoSerie(x,y,incX,incY,atol,i,j,
+ i+1,j-1);
+ }
+ //comprobamos si todos los puntos están en tolerancia
+ if(entol)
+ {
+ //pasamos al siguiente punto como extremo del segmento
+ j++;
+ }
+ else
+ {
+ //el punto final será el anterior al actual, ya que con el actual
+ //hay al menos un vértice fuera de tolerancia y con el anterior se
+ //comprobó en el paso previo del bucle que no había ningún vértice
+ //fuera
+ j--;
+ //aplicación del algoritmo de intersección con puntos originales
+ if(robOrig)
+ {
+ //aplicamos el algoritmo
+ DouglasPeuckerRobIntersecOrigPlano(x,y,nPtos,incX,incY,
+ nSegRobOrig,i,&j);
+ }
+ //aplicación del algoritmo de auto intersección
+ if(robAuto)
+ {
+ //aplicamos el algoritmo
+ DouglasPeuckerRobAutoIntersecPlano(x,y,incX,incY,i,&j,sal,
+ *nPtosSal,nSegRobAuto);
+ }
+ //añadimos al contador el 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 punto al vector de salida
+ sal[(*nPtosSal)-1] = j;
+ //actualizamos los índices de los puntos de trabajo
+ i = j;
+ j = i+2;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que añadir el último punto
+ if((sal[(*nPtosSal)-1]!=(nPtos-1))&&
+ ((x[sal[(*nPtosSal)-1]*incX]!=x[(nPtos-1)*incX])||
+ (y[sal[(*nPtosSal)-1]*incY]!=y[(nPtos-1)*incY])))
+ {
+ //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;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerPuntosEnTolPlanoOMP(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //identificador de punto fuera de tolerancia
+ int ftol=0;
+ //coordenadas de los vértices de trabajo
+ double xIni=0.0,yIni=0.0,xFin=0.0,yFin=0.0,xTrab=0.0,yTrab=0.0;
+ //longitud de la base y parámetros de rotación para el plano
+ double dx=0.0,sA=0.0,cA=0.0;
+ //distancia calculada
+ double dist=0.0;
+ //variable de salida
+ int entol=1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((posBaseIni+1)>=posBaseFin)
+ {
+ //salimos de la función
+ return entol;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas del primer punto de la base
+ xIni = x[posBaseIni*incX];
+ yIni = y[posBaseIni*incY];
+ //coordenadas del segundo punto de la base, referidas al primero
+ xFin = x[posBaseFin*incX]-xIni;
+ yFin = y[posBaseFin*incY]-yIni;
+ //calculamos la longitud de la base y la rotación
+ DouglasPeuckerParamRotaBase(xFin,yFin,&sA,&cA,&dx);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posPtoIni,posPtoFin,incX,x,incY,y,xIni,yIni,dx,sA,cA,atol) \
+ private(i,xTrab,yTrab,dist) \
+ reduction(+:ftol)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posPtoIni;i<=posPtoFin;i++)
+ {
+ //sólo calculo si no se ha encontrado ningún punto fuera de tolerancia
+ //en este hilo
+ if(!ftol)
+ {
+ //extraemos las coordenadas del vértice de trabajo y las referimos
+ //al punto inicial de la base
+ xTrab = x[i*incX]-xIni;
+ yTrab = y[i*incY]-yIni;
+ //calculamos la distancia del punto a la base
+ dist = DouglasPeuckerDistMaxPlanoAux(dx,sA,cA,xTrab,yTrab);
+ //comprobamos si está fuera de tolerancia
+ if(dist>atol)
+ {
+ //aumentamos el indicador de fuera de tolerancia
+ ftol++;
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay algún punto fuera de tolerancia
+ if(ftol)
+ {
+ //indicamos que hay algún punto que no está en tolerancia
+ entol = 0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return entol;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerPuntosEnTolPlanoSerie(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //valor absoluto de la tolerancia
+ double atol=fabs(tol);
+ //coordenadas de los vértices
+ double xIni=0.0,yIni=0.0,xFin=0.0,yFin=0.0,xTrab=0.0,yTrab=0.0;
+ //longitud de la base y parámetros de rotación para el plano
+ double dx=0.0,sA=0.0,cA=0.0;
+ //distancia calculada
+ double dist=0.0;
+ //variable de salida
+ int entol=1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if((posBaseIni+1)>=posBaseFin)
+ {
+ //salimos de la función
+ return entol;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas del primer punto de la base
+ xIni = x[posBaseIni*incX];
+ yIni = y[posBaseIni*incY];
+ //coordenadas del segundo punto de la base, referidas al primero
+ xFin = x[posBaseFin*incX]-xIni;
+ yFin = y[posBaseFin*incY]-yIni;
+ //calculamos la longitud de la base y la rotación
+ DouglasPeuckerParamRotaBase(xFin,yFin,&sA,&cA,&dx);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos a chequear
+ for(i=posPtoIni;i<=posPtoFin;i++)
+ {
+ //extraemos las coordenadas del vértice de trabajo y las referimos al
+ //punto inicial de la base
+ xTrab = x[i*incX]-xIni;
+ yTrab = y[i*incY]-yIni;
+ //calculamos la distancia del punto a la base
+ dist = DouglasPeuckerDistMaxPlanoAux(dx,sA,cA,xTrab,yTrab);
+ //comprobamos si está fuera de tolerancia
+ if(dist>atol)
+ {
+ //indicamos que estamos fuera de tolerancia
+ entol = 0;
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return entol;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerRobIntersecOrigPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas del segmento base
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0;
+ //posición de parada para comprobar la intersección de segmentos/arcos
+ size_t posParada=0;
+ //identificación de paralelización
+ int paraleliza=0;
+ //variable identificadora de existencia de corte de segmentos
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los puntos de inicio y fin son contiguos, hay salida rápida
+ if((posIni+1)>=(*posFin))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //posición de parada para el chequeo de segmentos/arcos
+ posParada = ((segAUsar==0)||(segAUsar>=(nPtos-(*posFin))))
+ ? nPtos-1
+ : (*posFin)+segAUsar;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas del punto inicial del segmento/arco base (no cambian)
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ //construimos todos los segmentos/arcos base posibles
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //este punto es el siguiente al punto inicial del segmento/arco base
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ //coordenadas del punto final del segmento base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //comprobamos si hay que paralelizar
+ if(paraleliza)
+ {
+ //calculamos en paralelo
+ corte = DouglasPeuckerRobIntersecOrigPlanoOMP(xA,yA,xB,yB,x,y,incX,
+ incY,i,posParada);
+ }
+ else
+ {
+ //calculamos en serie
+ corte = DouglasPeuckerRobIntersecOrigPlanoSerie(xA,yA,xB,yB,x,y,
+ incX,incY,i,
+ posParada);
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(!corte)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle de segmentos base
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecOrigPlanoOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posIni,posFin,incX,x,incY,y,xA,xB,yA,yB) \
+ private(i,xC,yC,xD,yD) \
+ reduction(+:corte)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posIni;i<posFin;i++)
+ {
+ //sólo realizo cálculos si no se ha encontrado ningún corte en este hilo
+ if(!corte)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[i*incX];
+ yC = y[i*incY];
+ xD = x[(i+1)*incX];
+ yD = y[(i+1)*incY];
+ //sigo si los rectángulos que encierran a los segmentos se cortan
+ if(!GEOC_RECT_DISJUNTOS(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)))
+ {
+ //comprobamos si hay intersección
+ corte += DouglasPeuckerRobIntersecPlano(xA,yA,xB,yB,xC,yC,xD,yD,
+ posIni,i);
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecOrigPlanoSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos de trabajo
+ for(i=posIni;i<posFin;i++)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[i*incX];
+ yC = y[i*incY];
+ xD = x[(i+1)*incX];
+ yD = y[(i+1)*incY];
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!GEOC_RECT_DISJUNTOS(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)))
+ {
+ //comprobamos si hay intersección
+ corte = DouglasPeuckerRobIntersecPlano(xA,yA,xB,yB,xC,yC,xD,yD,
+ posIni,i);
+ }
+ //si ha habido intersección de segmentos/arcos, salimos del bucle
+ if(corte)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerRobAutoIntersecPlano(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ size_t* posFin,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas del segmento base
+ double xA=0.0,yA=0.0,xB=0.0,yB=0.0;
+ //posición de parada para comprobar la intersección de segmentos/arcos
+ size_t posParada=0;
+ //identificación de paralelización
+ int paraleliza=0;
+ //variable identificadora de existencia de corte de segmentos
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los puntos de inicio y fin son contiguos, hay salida rápida
+ if((posIni+1)>=(*posFin))
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+#if defined(_OPENMP)
+ //comprobamos si hay más de un procesador
+ if(omp_get_num_procs()>1)
+ {
+ //indicamos que hay paralelización
+ paraleliza = 1;
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //posición de parada en el vector posAlig para el chequeo de segmentos/arcos
+ posParada = ((segAUsar==0)||(segAUsar>=(nPosAlig-1)))
+ ? 0
+ : nPosAlig-1-segAUsar;
+ //coordenadas del punto inicial del segmento base (no cambian)
+ xA = x[posIni*incX];
+ yA = y[posIni*incY];
+ //construimos todos los segmentos base posibles
+ for(i=(*posFin);i>posIni;i--)
+ {
+ //comprobamos si estamos ante el punto posterior al inicial
+ if(i==(posIni+1))
+ {
+ //este punto es el siguiente al punto inicial del segmento base
+ *posFin = i;
+ //salimos del bucle
+ break;
+ }
+ //coordenadas del punto final del segmento base
+ xB = x[i*incX];
+ yB = y[i*incY];
+ //comprobamos si hay que paralelizar
+ if(paraleliza)
+ {
+ //calculamos en paralelo
+ corte = DouglasPeuckerRobAutoIntersecPlanoOMP(xA,yA,xB,yB,x,y,incX,
+ incY,posAlig,nPosAlig,
+ nPosAlig-1,posParada);
+ }
+ else
+ {
+ //calculamos en serie
+ corte = DouglasPeuckerRobAutoIntersecPlanoSerie(xA,yA,xB,yB,x,y,
+ incX,incY,posAlig,
+ nPosAlig,nPosAlig-1,
+ posParada);
+ }
+ //comprobamos si no ha habido ninguna intersección
+ if(!corte)
+ {
+ //indicamos el índice del vértice final
+ *posFin = i;
+ //salimos del bucle de segmentos base
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobAutoIntersecPlanoOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ 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 posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(posIni,posFin,incX,x,posAlig,incY,y,xA,xB,yA,yB,nPosAlig) \
+ private(i,xC,yC,xD,yD) \
+ reduction(+:corte)
+#endif
+ //recorremos los puntos de trabajo
+ for(i=posIni;i>posFin;i--)
+ {
+ //sólo realizo cálculos si no se ha encontrado ningún corte en este hilo
+ if(!corte)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[posAlig[i]*incX];
+ yC = y[posAlig[i]*incY];
+ xD = x[posAlig[i-1]*incX];
+ yD = y[posAlig[i-1]*incY];
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!GEOC_RECT_DISJUNTOS(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)))
+ {
+ //comprobamos si hay intersección
+ corte += DouglasPeuckerRobIntersecPlano(xB,yB,xA,yA,xC,yC,xD,yD,
+ posAlig[nPosAlig-1],
+ posAlig[i]);
+ }
+ }
+ } // --> fin del #pragma omp parallel for
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobAutoIntersecPlanoSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ 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 posIni,
+ const size_t posFin)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas de los segmentos de trabajo
+ double xC=0.0,yC=0.0,xD=0.0,yD=0.0;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //recorremos los puntos de trabajo
+ for(i=posIni;i>posFin;i--)
+ {
+ //puntos inicial y final del siguiente segmento/arco de trabajo
+ xC = x[posAlig[i]*incX];
+ yC = y[posAlig[i]*incY];
+ xD = x[posAlig[i-1]*incX];
+ yD = y[posAlig[i-1]*incY];
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!GEOC_RECT_DISJUNTOS(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)))
+ {
+ //comprobamos si hay intersección
+ corte = DouglasPeuckerRobIntersecPlano(xB,yB,xA,yA,xC,yC,xD,yD,
+ posAlig[nPosAlig-1],
+ posAlig[i]);
+ }
+ //si ha habido intersección de segmentos/arcos, salimos del bucle
+ if(corte)
+ {
+ //salimos del bucle
+ break;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+int DouglasPeuckerRobIntersecPlano(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ const size_t posFinAB,
+ const size_t posIniCD)
+{
+ //variables auxiliares
+ double xAux=0.0,yAux=0.0;
+ //identificador de intersección
+ int inter=GEOC_DPEUCKER_NO_INTERSEC;
+ //variable de salida
+ int corte=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //seguimos si los rectángulos que encierran a los segmentos se cortan
+ if(!GEOC_RECT_DISJUNTOS(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)))
+ {
+ //compruebo si los dos segmentos son contiguos
+ if(posFinAB==posIniCD)
+ {
+ //compruebo intersección con la función completa (lenta)
+ inter = IntersecSegmentos2D(xA,yA,xB,yB,xC,yC,xD,yD,
+ &xAux,&yAux);
+ //compruebo si es la sucesión de segmento inicial+final
+ if((inter!=GEOC_SEG_INTERSEC_MISMO_SEG)&&
+ (inter!=GEOC_SEG_INTERSEC_COLIN))
+ {
+ //en este caso, no hay intersección
+ inter = GEOC_DPEUCKER_NO_INTERSEC;
+ }
+ }
+ else
+ {
+ //compruebo intersección con la función simple (rápida)
+ inter = IntersecSegmentos2DSimple(xA,yA,xB,yB,xC,yC,xD,yD);
+ }
+ //unificamos los identificadores de intersección
+ if(!((inter==GEOC_SEG_NO_INTERSEC)||(inter==GEOC_DPEUCKER_NO_INTERSEC)))
+ {
+ //hay intersección
+ corte = 1;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return corte;
+}
+/******************************************************************************/
+/******************************************************************************/
+double DouglasPeuckerDistMaxPlano(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const size_t posFin,
+ size_t* pos)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //coordenadas de los extremos del segmento base y del punto de trabajo
+ double xIni=0.0,yIni=0.0,xFin=0.0,yFin=0.0,xP=0.0,yP=0.0;
+ //razones trigonométricas del ángulo de giro del sistema de coordenadas
+ double sA=0.0,cA=0.0;
+ //longitudes auxiliares
+ double dx=0.0,lonAux=0.0;
+ //variable de salida
+ double lon=-1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si los dos puntos están seguidos
+ if((posIni+1)==posFin)
+ {
+ //la posición que devolvemos es la del punto inicial
+ *pos = posIni;
+ //la distancia devuelta es -1.0
+ return lon;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //coordenadas del primer punto de la base
+ xIni = x[posIni*incX];
+ yIni = y[posIni*incY];
+ //coordenadas del segundo punto de la base, referidas al primero
+ xFin = x[posFin*incX]-xIni;
+ yFin = y[posFin*incY]-yIni;
+ //calculamos la longitud de la base y la rotación
+ DouglasPeuckerParamRotaBase(xFin,yFin,&sA,&cA,&dx);
+ //recorremos los puntos entre los extremos
+ for(i=posIni+1;i<posFin;i++)
+ {
+ //coordenadas del punto de trabajo referidas al punto inicial de la base
+ xP = x[i*incX]-xIni;
+ yP = y[i*incY]-yIni;
+ //calculamos la distancia del punto de trabajo al segmento base
+ lonAux = DouglasPeuckerDistMaxPlanoAux(dx,sA,cA,xP,yP);
+ //comprobamos si la distancia calculada es mayor que la anterior
+ if(lonAux>lon)
+ {
+ //actualizamos la distancia máxima
+ lon = lonAux;
+ //guardamos la posición del punto
+ *pos = i;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return lon;
+}
+/******************************************************************************/
+/******************************************************************************/
+void DouglasPeuckerParamRotaBase(const double xBase2RB1,
+ const double yBase2RB1,
+ double* sAlfa,
+ double* cAlfa,
+ double* lonBase)
+{
+ //álgulo de rotación
+ double alfa=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ángulo a rotar el sistema de coordenadas para llevar el eje X a coincidir
+ //con el segmento base
+ alfa = atan2(yBase2RB1,xBase2RB1);
+ //calculamos las razones trigonométricas del ángulo de rotación
+ *sAlfa = sin(alfa);
+ *cAlfa = cos(alfa);
+ //la longitud del segmento base será el valor absoluto de la coordenada X
+ //del extremo final del segmento base en el sistema de coordenadas rotado
+ *lonBase = fabs((*cAlfa)*xBase2RB1+(*sAlfa)*yBase2RB1);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+double DouglasPeuckerDistMaxPlanoAux(const double lonBase,
+ const double sAlfa,
+ const double cAlfa,
+ const double xVertRB1,
+ const double yVertRB1)
+{
+ //coordenadas del vértice de trabajo en el sistema rotado
+ double xVert1=0.0,yVert1=0.0;
+ //variable de salida
+ double lon=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //transformamos el vértice de trabajo al nuevo sistema de coordenadas
+ xVert1 = cAlfa*xVertRB1+sAlfa*yVertRB1;
+ yVert1 = -sAlfa*xVertRB1+cAlfa*yVertRB1;
+ //comprobamos la posición del punto con respecto al segmento base
+ if((xVert1>=0.0)&&(xVert1<=lonBase))
+ {
+ //el punto de trabajo está entre los extremos del segmento base
+ //su distancia hasta él es el valor absoluto de su coordenada Y en
+ //el sistema rotado
+ lon = fabs(yVert1);
+ }
+ else if(xVert1<0.0)
+ {
+ //el punto de trabajo está a la izquierda del punto inicial de la
+ //base, luego su distancia hasta el segmento será la distancia
+ //hasta dicho punto inicial
+ //Konrad Ebisch (2002), A correction to the Douglas-Peucker line
+ //generalization algorithm, Computers and Geosciences, vol. 28,
+ //págs. 995 a 997
+ lon = sqrt(xVert1*xVert1+yVert1*yVert1);
+ }
+ else
+ {
+ //el punto de trabajo está a la derecha del punto final de la base,
+ //luego su distancia hasta el segmento será la distancia hasta dicho
+ //punto final
+ //Konrad Ebisch (2002), A correction to the Douglas-Peucker line
+ //generalization algorithm, Computers and Geosciences, vol. 28,
+ //págs. 995 a 997
+ lon = sqrt((xVert1-lonBase)*(xVert1-lonBase)+yVert1*yVert1);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return lon;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* 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 100644
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@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 100644
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@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 100644
index 0000000..1479d5f
--- /dev/null
+++ b/src/fgeneral.c
@@ -0,0 +1,884 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 10 de octubre de 2009
+\version 1.0
+\copyright
+Copyright (c) 2009-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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(nDatos,incDatos,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(nDatos,incDatos,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(nDatos,incDatos,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(nDatos,incDatos,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
+#if defined(SIZE_MAX)
+ size_t salida=SIZE_MAX;
+#else
+ size_t salida=(size_t)ULONG_MAX;
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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(nDatos,incDatos,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(nDatos,incDatos,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 100644
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@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@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 100644
index 0000000..6075c3a
--- /dev/null
+++ b/src/greiner.c
@@ -0,0 +1,1922 @@
+/* -*- 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@gmail.com
+\date 14 de mayo de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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_EXTREMOS_NO_COLIN)||
+ (intersec==GEOC_SEG_INTERSEC_EXTREMOS_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,
+ const int compruebaHuecosUnion,
+ size_t* nIntersec,
+ size_t* nPerturb)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //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;
+ //variables auxiliares
+ int enPol1=GEOC_PTO_FUERA_POLIG,enPol2=GEOC_PTO_FUERA_POLIG;
+ size_t posIni=0;
+ double xAux=0.0,yAux=0.0;
+ //polígonos auxiliares
+ polig* ba=NULL;
+ polig* aux1=NULL;
+ polig* aux2=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);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializo los atributos a 1
+ for(i=0;i<resultado->nPolig;i++)
+ {
+ resultado->atr[i] = 1;
+ }
+ //compruebo si hemos trabajado con unión
+ if(compruebaHuecosUnion&&(op==GeocOpBoolUnion))
+ {
+ //convierto los polígonos de trabajo en estructuras polig
+ aux1 = CreaPoligPoliClip(poliBas,1);
+ aux2 = CreaPoligPoliClip(poliRec,1);
+ //comprobamos los posibles errores
+ if((aux1==NULL)||(aux2==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(resultado);
+ LibMemPolig(aux1);
+ LibMemPolig(aux2);
+ //mensaje de error
+ GEOC_ERROR("Error de asignación de memoria en la llamada a "
+ "'CreaPoligPoliClip' para la comprobación de huecos en "
+ "la operación OR");
+ //salimos de la función
+ return NULL;
+ }
+ //recorro todos los polígonos generados en la unión
+ for(i=0;i<resultado->nPolig;i++)
+ {
+ //posición de inicio del polígono
+ posIni = resultado->posIni[i];
+ //genero un punto dentro del polígono
+ GeneraPtoEnPoligono(&(resultado->x[posIni]),&(resultado->y[posIni]),
+ resultado->nVert[i],1,1,0.0,1,&xAux,&yAux);
+ //comprobamos las coordenadas de salida
+ if (EsGeocNan(xAux)||EsGeocNan(yAux))
+ {
+ //digo que es un hueco
+ resultado->atr[i] = 0;
+ }
+ else
+ {
+ //compruebo si el punto está dentro de alguno de los dos
+ //polígonos de trabajo
+ posIni = aux1->posIni[0];
+ enPol1 = PtoEnPoligonoVerticeBordeDouble(xAux,yAux,
+ &(aux1->x[posIni]),
+ &(aux1->y[posIni]),
+ aux1->nVert[0],1,1,
+ 0.0,1);
+ posIni = aux2->posIni[0];
+ enPol2 = PtoEnPoligonoVerticeBordeDouble(xAux,yAux,
+ &(aux2->x[posIni]),
+ &(aux2->y[posIni]),
+ aux2->nVert[0],1,1,
+ 0.0,1);
+ //si el polígono no pertenece a ninguno de los dos originales es
+ //un hueco
+ if((!enPol1)&&(!enPol2))
+ {
+ //lo marco como hueco
+ resultado->atr[i] = 0;
+ }
+ }
+ }
+ //liberamos la memoria asignada
+ LibMemPolig(aux1);
+ LibMemPolig(aux2);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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,
+ const int compruebaHuecosUnion,
+ 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 = GEOC_RECT_DISJUNTOS(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,
+ compruebaHuecosUnion,&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/arco.h b/src/libgeoc/arco.h
new file mode 100644
index 0000000..a5a7b8c
--- /dev/null
+++ b/src/libgeoc/arco.h
@@ -0,0 +1,617 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file arco.h
+\brief Declaración de funciones para la realización de cálculos con arcos de
+ circunferencia.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 08 de agosto de 2013
+\copyright
+Copyright (c) 2013-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _ARCO_H_
+#define _ARCO_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<math.h>
+#include"libgeoc/constantes.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/mate.h"
+#include"libgeoc/ptopol.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_RES_ANG
+\brief Resolución angular por debajo de la cual no se distinguirán dos valores
+ angulares en radianes.
+\note Esta constante ha de ser \b SIEMPRE positiva.
+\date 14 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_RES_ANG (1.0e-12)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_NO_INTERSEC
+\brief Identificador de que dos arcos no se cortan.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_NO_INTERSEC 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC
+\brief Identificador de que dos arcos se cortan en un punto, pero no son
+ colineales.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC 1
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN
+\brief Identificador de que dos arcos se cortan en un punto, el cual es un
+ extremo que está encima del otro arco, pero no son colineales.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN 2
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN
+\brief Identificador de que dos arcos tienen un extremo común, pero no son
+ colineales.
+\date 13 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN 3
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC_EXTREMOS_COLIN
+\brief Identificador de que dos arcos tienen un punto común y son colineales.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC_EXTREMOS_COLIN 4
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC_MISMO_ARC
+\brief Identificador de que dos arcos tienen todos sus puntos extremos en común.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC_MISMO_ARC 5
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_ARC_INTERSEC_COLIN
+\brief Identificador de que dos arcos tienen más de un punto en común, es decir,
+ se solapan, pero no son el mismo arco.
+\date 08 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_ARC_INTERSEC_COLIN 6
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si dos rectángulos sobre la superficie de la esfera son
+ disjuntos, atendiendo únicamente a la coordenada longitud geodésica.
+\param[in] tol Tolerancia angular, en radianes. Indica el valor por debajo del
+ cual dos ángulos se consideran iguales. Este argumento ha de ser un
+ número \b POSITIVO (no se comprueba internamente).
+\param[in] lonMin1 Longitud mínima del rectángulo 1, en radianes.
+\param[in] lonMax1 Longitud máxima del rectángulo 1, en radianes.
+\param[in] lonMin2 Longitud mínima del rectángulo 2, en radianes.
+\param[in] lonMax2 Longitud máxima del rectángulo 2, en radianes.
+\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 lonMin1<lonyMax1 y \em lonMin2<lonMax2.
+\note Hay casos sobre la superficie de la esfera en los que el solapamiento de
+ rectángulos es muy difícil de determinar, como aquéllos en que algún
+ rectángulo tiene incrementos de longitud mayores que \f$\pi\f$ o los que
+ alguno de los lados tiene igual latitud. Por todo ello, esta función sólo
+ tiene en cuenta longitudes. Si hay solapamiento en longitud, se considera
+ que los rectángulos no son disjuntos.
+\date 09 de junio de 2012: Creación de la función.
+\date 23 de septiembre de 2013: Adición del argumento \em tol.
+\todo Esta función no está probada.
+*/
+int ArcosCircMaxDisjuntos(const double tol,
+ const double lonMin1,
+ const double lonMax1,
+ const double lonMin2,
+ const double lonMax2);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el acimut de un arco de círculo máximo AB sobre la esfera.
+\param[in] tol Tolerancia angular, en radianes. Indica el valor por debajo del
+ cual dos ángulos se consideran iguales. Este argumento ha de ser un
+ número \b POSITIVO (no se comprueba internamente).
+\param[in] latA Latitud del punto A, en radianes.
+\param[in] lonA Longitud del punto A, en radianes.
+\param[in] latB Latitud del punto B, en radianes.
+\param[in] lonB Longitud del punto B, en radianes.
+\param[out] mRot Matriz de rotación aplicada al arco AB para llevar el punto A
+ al punto de coordenadas \f$(\varphi=0,\lambda=0)\f$. Este
+ argumento ha de ser una matriz de 3x3 almacenada en el formato de C.
+\return Acimut del arco AB, en radianes.
+\note El argumento \em mRot ha de ser pasado como una matriz en formato de C;
+ esto es, se accederá a sus elementos como <em>mRot[fil][com]</em>.
+\note El dominio de salida del acimut es \f$[0,2\pi[\f$.
+\date 13 de agosto de 2013: Creación de la función.
+\date 23 de septiembre de 2013: Adición del argumento \em tol.
+\todo Esta función no está probada.
+*/
+double AcimutArcoCircMaxEsf(const double tol,
+ const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ double mRot[][3]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula una matriz de rotación tal que, aplicada a un arco de círculo
+ máximo AB sobre la esfera, el punto A sea el punto de coordenadas
+ \f$(\varphi=0,\lambda=0)\f$ y el B esté contenido en el ecuador.
+\param[in] tol Tolerancia angular, en radianes. Indica el valor por debajo del
+ cual dos ángulos se consideran iguales. Este argumento ha de ser un
+ número \b POSITIVO (no se comprueba internamente).
+\param[in] latA Latitud del punto A, en radianes.
+\param[in] lonA Longitud del punto A, en radianes.
+\param[in] latB Latitud del punto B, en radianes.
+\param[in] lonB Longitud del punto B, en radianes.
+\param[out] mRot Matriz de rotación para aplicar a las coordenadas cartesianas
+ tridimensionales geocéntricas de los extremos de un segmento para
+ llevarlos al sistema descrito anteriormente. Este argumento ha de
+ ser una matriz de 3x3, almacenada en el formato de C.
+\param[out] lonBR Longitud del punto B en el sistema rotado, en el dominio
+ \f$]-\pi,\pi]\f$, en radianes. Este argumento sólo es tenido en
+ cuenta si se pasa un puntero distinto de \p NULL.
+\note El argumento \em mRot ha de ser pasado como una matriz en formato de C;
+ esto es, se accederá a sus elementos como <em>mRot[fil][com]</em>.
+\date 13 de agosto de 2013: Creación de la función.
+\date 23 de septiembre de 2013: Adición del argumento \em tol.
+\todo Esta función no está probada.
+*/
+void RotaArco00Ecuador(const double tol,
+ const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ double mRot[][3],
+ double* lonBR);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica una matriz de rotación a un punto en coordenadas cartesianas
+ tridimensionales geocéntricas.
+\param[in] sentido Identificador para realizar la rotación directa o la inversa.
+ Dos posibilidades:
+ - Mayor o igual que 0: Se realiza la transformación directa.
+ - Menor que 0: Re realiza la transformación inversa.
+\param[in] x Coordenada X del punto.
+\param[in] y Coordenada Y del punto.
+\param[in] z Coordenada Z del punto.
+\param[in] mRot Matriz de rotación de 3x3, almacenada en el formato de C.
+\param[out] xR Coordenada X rotada. Este argumento sólo es tenido en cuenta si
+ se pasa un puntero distinto de \p NULL.
+\param[out] yR Coordenada Y rotada. Este argumento sólo es tenido en cuenta si
+ se pasa un puntero distinto de \p NULL.
+\param[out] zR Coordenada Z rotada. Este argumento sólo es tenido en cuenta si
+ se pasa un puntero distinto de \p NULL.
+\note El argumento \em mRot ha de ser pasado como una matriz en formato de C;
+ esto es, se accederá a sus elementos como <em>mRot[fil][com]</em>.
+\date 13 de agosto de 2013: Creación de la función.
+\todo Esta función no está probada.
+*/
+void AplicaMatrizRotacionCoorCart(const int sentido,
+ const double x,
+ const double y,
+ const double z,
+ double mRot[][3],
+ double* xR,
+ double* yR,
+ double* zR);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aplica una matriz de rotación a un punto en coordenadas geodésicas.
+\param[in] sentido Identificador para realizar la rotación directa o la inversa.
+ Dos posibilidades:
+ - Mayor o igual que 0: Se realiza la transformación directa.
+ - Menor que 0: Re realiza la transformación inversa.
+\param[in] lat Latitud del punto, en radianes.
+\param[in] lon Longitud del punto, en radianes.
+\param[in] mRot Matriz de rotación de 3x3, almacenada en el formato de C.
+\param[out] latR Latitud del punto en el sistema rotado, en radianes. Este
+ argumento sólo es tenido en cuenta si se pasa un puntero distinto de
+ \p NULL.
+\param[out] lonR Longitud del punto en el sistema rotado, en radianes. Este
+ argumento sólo es tenido en cuenta si se pasa un puntero distinto de
+ \p NULL.
+\note El argumento \em mRot ha de ser pasado como una matriz en formato de C;
+ esto es, se accederá a sus elementos como <em>mRot[fil][com]</em>.
+\note El dominio de la variable de salida \em lat1 es
+ \f$[-\frac{\pi}{2},\frac{\pi}{2}]\f$.
+\note El dominio de la variable de salida \em lon1 es \f$]-\pi,\pi]\f$.
+\date 13 de agosto de 2013: Creación de la función.
+\todo Esta función no está probada.
+*/
+void AplicaMatrizRotacionCoorGeod(const int sentido,
+ const double lat,
+ const double lon,
+ double mRot[][3],
+ double* latR,
+ double* lonR);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los puntos de intersección de dos círculos máximos sobre la
+ superfice de la esfera, estando uno de ellos, que se omite, contenido en
+ el ecuador.
+\param[in] tol Tolerancia. Indica el valor por debajo del cual la componente de
+ un vector se considera igual a 0.0. Este argumento ha de ser un
+ número \b POSITIVO (no se comprueba internamente).
+\param[in] xC Coordenada X cartesiana geocéntrica del primer extremo del arco.
+\param[in] yC Coordenada Y cartesiana geocéntrica del primer extremo del arco.
+\param[in] zC Coordenada Z cartesiana geocéntrica del primer extremo del arco.
+\param[in] xD Coordenada X cartesiana geocéntrica del segundo extremo del arco.
+\param[in] yD Coordenada Y cartesiana geocéntrica del segundo extremo del arco.
+\param[in] zD Coordenada Z cartesiana geocéntrica del segundo extremo del arco.
+\param[out] xP Coordenada X cartesiana geocéntrica de uno de los puntos de
+ intersección, sobre la esfera de radio unidad. La coordenada del
+ otro punto será -\em xP.
+\param[out] yP Coordenada Y cartesiana geocéntrica de uno de los puntos de
+ intersección, sobre la esfera de radio unidad. La coordenada del
+ otro punto será -\em yP.
+\param[out] zP Coordenada Z cartesiana geocéntrica de uno de los puntos de
+ intersección, sobre la esfera de radio unidad. La coordenada del
+ otro punto será -\em zP.
+\return Dos posibilidades:
+ - #GEOC_ARC_INTERSEC: Hay intersección.
+ - #GEOC_ARC_NO_INTERSEC: No se ha podido calcular intersección, por lo
+ que \em xP, \em yP y \em zP no se utilizan internamente. Las razones
+ pueden ser:
+ - El arco CD es coindidente con el ecuador.
+ - Los vectores OC y OD forman un ángulo de \f$0\f$ o \f$\pi\f$, y no
+ se puede calcular su vector normal.
+\note Esta función no es robusta, es decir, puede dar resultados incorrectos
+ debido a errores de redondeo.
+\note Aunque los puntos C y D pertenezcan a una esfera de radio arbitrario, las
+ coordenadas de los puntos de intersección de los círculos máximos se dan
+ sobre la esfera de radio unidad.
+\note Para que se devuelvan las coordnadas del punto intersección, los
+ argumentos \em xP, \em yP y \em zP han de ser, \b TODOS, distintos de
+ \p NULL.
+\date 13 de agosto de 2013: Creación de la función.
+\date 22 de septirmbre de 2013: Adición del argumento \em tol.
+*/
+int IntersecCircMaxEsfAux(const double tol,
+ const double xC,
+ const double yC,
+ const double zC,
+ const double xD,
+ const double yD,
+ const double zD,
+ double* xP,
+ double* yP,
+ double* zP);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos arcos de círculo máximo sobre la
+ superfice de la esfera que tienen, al menos, un extremo común. Uno de los
+ arcos, que se omite, está en el ecuador, con su extremo inicial en el
+ punto \f$(\varphi=0,\lambda=0)\f$.
+\param[in] tol Tolerancia, en radianes. Indica el valor por debajo del cual la
+ diferencia entre dos ángulos se considera igual a 0.0. Este argumento
+ ha de ser un número \b POSITIVO (no se comprueba internamente).
+\param[in] lonB Longitud, en radianes, del segundo extremo del arco AB, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latC Latitud, en radianes, del primer extremo del arco CD.
+\param[in] lonC Longitud, en radianes, del primer extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latD Latitud, en radianes, del segundo extremo del arco CD.
+\param[in] lonD Longitud, en radianes, del segundo extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[out] latP Latitud, en radianes, del punto de intersección. Siempre 0.0.
+\param[out] lonP Longitud, en radianes, del punto de intersección, en el
+ dominio \f$]-\pi,\pi]\f$.
+\return Cinco posibilidades:
+ - #GEOC_ARC_NO_INTERSEC: Los arcos no tienen ningún punto en común.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN: Los arcos tienen un extremo
+ común, pero no son colineales.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_COLIN: Los arcos tienen un extremo común y
+ son colineales.
+ - #GEOC_ARC_INTERSEC_COLIN: Los arcos tienen más de un punto en común.
+ - #GEOC_ARC_INTERSEC_MISMO_ARC: Los dos arcos son idénticos.
+\note Para que se devuelvan las coordnadas del punto intersección, los
+ argumentos \em latP y \em lonP han de ser, \b TODOS, distintos de \p NULL.
+\note Si los arcos no se tocan, las variables devueltos en \em latP y \em lonP
+ almacenan 0.0.
+\note Los arcos implicados no pueden subtender un ángulo mayor o igual que
+ \f$\pi\f$. Esta condición no se comprueba internamente, por lo que \b NO
+ se informa de su posible inclumplimiento, y la función se ejecutará
+ normalmente.
+\note Esta función no es robusta, es decir, puede dar resultados incorrectos
+ debido a errores de redondeo.
+\note Si hay intersección, las coordenadas devueltas coinciden exactamente con
+ las del vértice implicado, A, B, C o D.
+\note Si los arcos se tocan en los dos extremos (son el mismo arco), las
+ coordenadas devueltas son siempre las del vértice A.
+\note Un buen valor para \em tol puede ser #GEOC_ARC_RES_ANG.
+\note Las longitudes de trabajo han de estar, obligatoriamente, en el dominio
+ \f$]-\pi,\pi]\f$.
+\date 22 de septiembre de 2013: Creación de la función.
+*/
+int IntersecArcCirMaxEsferaVertComunAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos arcos de círculo máximo sobre la
+ superfice de la esfera que tienen partes en común (se solapan
+ parcialmente o el vértice de uno está apoyado en el otro arco-pero no en
+ un vértice del segundo-). Uno de los arcos, que se omite, está en el
+ ecuador, con su extremo inicial en el punto \f$(\varphi=0,\lambda=0)\f$.
+\param[in] tol Tolerancia, en radianes. Indica el valor por debajo del cual la
+ diferencia entre dos ángulos se considera igual a 0.0. Este argumento
+ ha de ser un número \b POSITIVO (no se comprueba internamente).
+\param[in] lonB Longitud, en radianes, del segundo extremo del arco AB, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latC Latitud, en radianes, del primer extremo del arco CD.
+\param[in] lonC Longitud, en radianes, del primer extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latD Latitud, en radianes, del segundo extremo del arco CD.
+\param[in] lonD Longitud, en radianes, del segundo extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[out] latP Latitud, en radianes, del punto de intersección. Siempre 0.0.
+\param[out] lonP Longitud, en radianes, del punto de intersección, en el
+ dominio \f$]-\pi,\pi]\f$.
+\return Tres posibilidades:
+ - #GEOC_ARC_NO_INTERSEC: Los arcos no tienen ningún punto en común.
+ - #GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN: El extremo de un arco toca al
+ otro arco en un punto (excluidos los extremos del segundo), pero los
+ arcos no son colineales.
+ - #GEOC_ARC_INTERSEC_COLIN: Los arcos tienen más de un punto en común.
+\note Esta función considera los casos de arcos colineales que sólo coincidan en
+ un vértice como #GEOC_ARC_INTERSEC_COLIN. Para tratar correctamente esos
+ casos especiales, se recomienda ejecutar antes la función
+ \ref IntersecArcCirMaxEsferaVertComunAux.
+\note Para que se devuelvan las coordnadas del punto intersección, los
+ argumentos \em latP y \em lonP han de ser, \b TODOS, distintos de \p NULL.
+\note Si los arcos no se tocan, las variables devueltos en \em latP y \em lonP
+ almacenan 0.0.
+\note Los arcos implicados no pueden subtender un ángulo mayor o igual que
+ \f$\pi\f$. Esta condición no se comprueba internamente, por lo que \b NO
+ se informa de su posible inclumplimiento, y la función se ejecutará
+ normalmente.
+\note Esta función no es robusta, es decir, puede dar resultados incorrectos
+ debido a errores de redondeo.
+\note Si hay intersección, las coordenadas devueltas coinciden exactamente con
+ las del vértice implicado, A, B, C o D.
+\note Un buen valor para \em tol puede ser #GEOC_ARC_RES_ANG.
+\note Las longitudes de trabajo han de estar, obligatoriamente, en el dominio
+ \f$]-\pi,\pi]\f$.
+\date 22 de septiembre de 2013: Creación de la función.
+*/
+int IntersecArcCirMaxEsferaVertApoyadoAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos arcos de círculo máximo sobre la
+ superfice de la esfera, uno de los cuales, que se omite, está en el
+ ecuador, con su extremo inicial en el punto \f$(\varphi=0,\lambda=0)\f$.
+\param[in] tol Tolerancia, en radianes. Indica el valor por debajo del cual la
+ diferencia entre dos ángulos se considera igual a 0.0. Este argumento
+ ha de ser un número \b POSITIVO (no se comprueba internamente).
+\param[in] lonB Longitud, en radianes, del segundo extremo del arco AB, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latC Latitud, en radianes, del primer extremo del arco CD.
+\param[in] lonC Longitud, en radianes, del primer extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] latD Latitud, en radianes, del segundo extremo del arco CD.
+\param[in] lonD Longitud, en radianes, del segundo extremo del arco CD, en el
+ dominio \f$]-\pi,\pi]\f$.
+\param[in] xGC Coordenada X cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] yGC Coordenada Y cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] zGC Coordenada Z cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] xGD Coordenada X cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] yGD Coordenada Y cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] zGD Coordenada Z cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[out] latP Latitud, en radianes, del punto de intersección. Siempre 0.0.
+\param[out] lonP Longitud, en radianes, del punto de intersección, en el
+ dominio \f$]-\pi,\pi]\f$.
+\return Siete posibilidades:
+ - #GEOC_ARC_NO_INTERSEC: Los arcos no tienen ningún punto en común.
+ - #GEOC_ARC_INTERSEC: Los arcos se cortan en un punto.
+ - #GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN: El extremo de un arco toca al
+ otro arco en un punto (excluidos los extremos del segungo), pero los
+ arcos no son colineales.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN: Los arcos tienen un extremo
+ común, pero no son colineales.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_COLIN: Los arcos tienen un extremo común y
+ son colineales.
+ - #GEOC_ARC_INTERSEC_MISMO_ARC: Los dos arcos son idénticos.
+ - #GEOC_ARC_INTERSEC_COLIN: Los arcos tienen más de un punto en común.
+\note Para que se devuelvan las coordnadas del punto intersección, los
+ argumentos \em latP y \em lonP han de ser, \b TODOS, distintos de \p NULL.
+\note Si los arcos no se tocan, las variables devueltos en \em latP y \em lonP
+ almacenan 0.0.
+\note Los arcos implicados no pueden subtender un ángulo mayor o igual que
+ \f$\pi\f$. Esta condición no se comprueba internamente, por lo que \b NO
+ se informa de su posible inclumplimiento, y la función se ejecutará
+ normalmente.
+\note Esta función no es robusta, es decir, puede dar resultados incorrectos
+ debido a errores de redondeo.
+\note Un buen valor para \em tol puede ser #GEOC_ARC_RES_ANG.
+\note Las longitudes de trabajo han de estar, obligatoriamente, en el dominio
+ \f$]-\pi,\pi]\f$.
+\note Los argumentos \em xGC, \em yGC, \em zGC, \em xGD, \em yGD y \em zGD sólo
+ son tenidos en cuenta si se trabaja sobre la esfera y cada tríada es
+ distinta de \ref GeocNan, en cuyo caso las coordenadas cartesianas
+ tridimensionales geocéntricas, necesarias para los cálculos llevados a
+ cabo por la función, son calculadas internamente a partir de los
+ argumentos \em latC, \em lonC, \em latD y \em latD.
+\date 22 de septiembre de 2013: Creación de la función.
+\date 28 de marzo de 2014: Adición de los argumentos \em xGC, \em yGC, \em zGC,
+ \em xGD, \em yGD y \em zGD.
+*/
+int IntersecArcCircMaxEsferaAux(const double tol,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ const double xGC,
+ const double yGC,
+ const double zGC,
+ const double xGD,
+ const double yGD,
+ const double zGD,
+ double* latP,
+ double* lonP);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos arcos de círculo máximo sobre la
+ superfice de la esfera.
+\param[in] latA Latitud, en radianes, del primer extremo del arco AB.
+\param[in] lonA Longitud, en radianes, del primer extremo del arco AB.
+\param[in] latB Latitud, en radianes, del segundo extremo del arco AB.
+\param[in] lonB Longitud, en radianes, del segundo extremo del arco AB.
+\param[in] latC Latitud, en radianes, del primer extremo del arco CD.
+\param[in] lonC Longitud, en radianes, del primer extremo del arco CD.
+\param[in] latD Latitud, en radianes, del segundo extremo del arco CD.
+\param[in] lonD Longitud, en radianes, del segundo extremo del arco CD.
+\param[out] latP Latitud, en radianes, del punto de intersección. El dominio de
+ la latitud utilizado es, independientemente del usado en las
+ variables de entrada, \f$[-\frac{\pi}{2},\frac{\pi}{2}]\f$.
+\param[out] lonP Longitud, en radianes, del punto de intersección. El dominio de
+ la longitud utilizado es, independientemente del usado en las
+ variables de entrada, \f$]-\pi,\pi]\f$.
+\return Siete posibilidades:
+ - #GEOC_ARC_NO_INTERSEC: Los arcos no tienen ningún punto en común.
+ - #GEOC_ARC_INTERSEC: Los arcos se cortan en un punto.
+ - #GEOC_ARC_INTERSEC_EXTREMO_NO_COLIN: El extremo de un arco toca al
+ otro arco en un punto (excluidos los extremos del segungo), pero los
+ arcos no son colineales.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_NO_COLIN: Los arcos tienen un extremo
+ común, pero no son colineales.
+ - #GEOC_ARC_INTERSEC_EXTREMOS_COLIN: Los arcos tienen un extremo común y
+ son colineales.
+ - #GEOC_ARC_INTERSEC_MISMO_ARC: Los dos arcos son idénticos.
+ - #GEOC_ARC_INTERSEC_COLIN: Los arcos tienen más de un punto en común.
+\note Para que se devuelvan las coordnadas del punto intersección, los
+ argumentos \em latP y \em lonP han de ser, \b TODOS, distintos de \p NULL.
+\note Si los arcos no se tocan, las variables devueltos en \em latP y \em lonP
+ almacenan 0.0.
+\note Los arcos implicados no pueden subtender un ángulo mayor o igual que
+ \f$\pi\f$. Esta condición no se comprueba internamente, por lo que \b NO
+ se informa de su posible inclumplimiento, y la función se ejecutará
+ normalmente.
+\note Esta función no es robusta, es decir, puede dar resultados incorrectos
+ debido a errores de redondeo.
+\note Esta función considera dos puntos iguales a aquellos que estén en un
+ entorno de #GEOC_ARC_RES_ANG radianes.
+\note Si los arcos se tocan en los dos extremos (son el mismo arco), las
+ coordenadas devueltas son siempre las del vértice A.
+\note Si los arcos tienen más de un punto en común, pero no son el mismo arco,
+ las coordenadas de salida siempre son las de un punto extremo de un arco.
+ Este punto extremo se intentará que sea uno de los puntos iniciales de
+ algún arco, anque no se puede asegurar.
+\date 13 de agosto de 2013: Creación de la función.
+*/
+int IntersecArcCircMaxEsfera(const double latA,
+ const double lonA,
+ const double latB,
+ const double lonB,
+ const double latC,
+ const double lonC,
+ const double latD,
+ const double lonD,
+ double* latP,
+ double* lonP);
+/******************************************************************************/
+/******************************************************************************/
+#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/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@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 100644
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@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 100644
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@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..4d79318
--- /dev/null
+++ b/src/libgeoc/dpeucker.h
@@ -0,0 +1,333 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 17 de agosto de 2013
+\copyright
+Copyright (c) 2013-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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"libgeoc/dpeuckera.h"
+#include"libgeoc/dpeuckere.h"
+#include"libgeoc/dpeuckerp.h"
+#include"libgeoc/errores.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea mediante una familia de algoritmos
+ basados en el de Douglas-Peucker.
+\param[in] x Vector que contiene las coordenadas X o las longitudes, en
+ radianes, de los vértices de la polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
+ 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. Dos posibilidades:
+ - Si se trabaja en coordenadas planas, este argumento ha de estar en
+ las mismas unidades que las coordenadas de los vértices.
+ - Si se trabaja sobre la esfera, este argumento ha de ser una
+ longitud de arco de círculo máximo sobre la esfera de radio unidad.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: Utiliza el algoritmo de Douglas-Peucker
+ original, que no es robusto.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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/arcos de la polilínea
+ aligerada que se van creando no intersectarán con ninguno de los
+ segmentos/arcos 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/arcos de la polilínea
+ aligerada que se van creando no intersectarán con ninguno de los
+ segmentos/arcos de la polilínea aligerada creados con anterioridad.
+ En casos muy especiales, este algoritmo puede seguir dando lugar a
+ auto intersecciones.
+\param[in] nSegRobOrig Número de segmentos/arcos 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 segmentos/arcos hasta el final de la polilínea
+ original.
+\param[in] nSegRobAuto 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[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
+ posibilidades:
+ - 0: No se trabaja sobre la superficie de la esfera, sino en el
+ plano.
+ - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
+ unidad.
+\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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función comprueba los casos especiales con
+ \ref CasosEspecialesAligeraPolilinea.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\date 25 de mayo de 2012: Creación de la función.
+\date 08 de agosto de 2013: Comprobación de casos especiales.
+\date 17 de agosto de 2013: Unificación de las funciones de aligerado en el
+ plano y en la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\date 21 de septiembre de 2013: Adición de la capacidad de trabajar sobre la
+ esfera con el algoritmo de Douglas-Peucker original.
+\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 int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const int esf,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea mediante el algoritmo original de
+ Douglas-Peucker.
+\param[in] x Vector que contiene las coordenadas X o las longitudes, en
+ radianes, de los vértices de la polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
+ 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. Dos posibilidades:
+ - Si se trabaja en coordenadas planas, este argumento ha de estar en
+ las mismas unidades que las coordenadas de los vértices.
+ - Si se trabaja sobre la esfera, este argumento ha de ser una
+ longitud de arco de círculo máximo sobre la esfera de radio unidad.
+\param[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
+ posibilidades:
+ - 0: No se trabaja sobre la superficie de la esfera, sino en el
+ plano.
+ - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
+ unidad.
+\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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función puede devolver resultados erróneos si algún segmento base es
+ mayor o igual que \f$\pi\f$.
+\date 21 de septiembre de 2013: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+size_t* DouglasPeuckerOriginal(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int esf,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea mediante un algoritmo no recursivo,
+ inspirado en el de Douglas-Peucker.
+\brief Este algoritmo, comenzando por el primer punto de la polilínea, va
+ uniendo puntos en segmentos/arcos de tal forma que se eliminan todos
+ aquellos puntos que queden a una distancia menor o igual a \em tol del
+ segmento/arco 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 o las longitudes, en
+ radianes, de los vértices de la polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y o las latitudes, en radianes,
+ 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. Dos posibilidades:
+ - Si se trabaja en coordenadas planas, este argumento ha de estar en
+ las mismas unidades que las coordenadas de los vértices.
+ - Si se trabaja sobre la esfera, este argumento ha de ser una
+ longitud de arco de círculo máximo sobre la esfera de radio unidad.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: En este caso esta opción es equivalente a
+ pasar #GeocDPeuckerRobNo.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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/arcos de la polilínea
+ aligerada que se van creando no intersectarán con ninguno de los
+ segmentos/arcos 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/arcos de la polilínea
+ aligerada que se van creando no intersectarán con ninguno de los
+ segmentos/arcos de la polilínea aligerada creados con anterioridad.
+ En casos muy especiales, este algoritmo puede seguir dando lugar a
+ auto intersecciones.
+\param[in] nSegRobOrig Número de segmentos/arcos 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 segmentos/arcos hasta el final de la polilínea
+ original.
+\param[in] nSegRobAuto 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[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
+ posibilidades:
+ - 0: No se trabaja sobre la superficie de la esfera, sino en el
+ plano.
+ - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
+ unidad.
+\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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función comprueba los casos especiales con
+ \ref CasosEspecialesAligeraPolilinea.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\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.
+\date 14 de mayo de 2012: Corregido bug que hacía que no se escogiese bien el
+ vértice a añadir a la polilínea aligerada.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 17 de agosto de 2013: Comprobación de casos especiales y unificación de
+ las funciones de aligerado en el plano y en la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\todo Esta función todavía no está probada.
+*/
+size_t* DouglasPeuckerRobusto(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const int esf,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+#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/dpeuckera.h b/src/libgeoc/dpeuckera.h
new file mode 100644
index 0000000..7750e80
--- /dev/null
+++ b/src/libgeoc/dpeuckera.h
@@ -0,0 +1,210 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckera.h
+\brief Declaración de elementos y funciones auxiliares para el uso de la familia
+ de algoritmos de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 18 de agosto de 2013
+\copyright
+Copyright (c) 2013-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _DPEUCKERA_H_
+#define _DPEUCKERA_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<math.h>
+#include"libgeoc/arco.h"
+#include"libgeoc/errores.h"
+#include"libgeoc/ptopol.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 de las funciones de aligerado de polilíneas.
+\date 17 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_DPEUCKER_BUFFER_PTOS 1000
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_DPEUCKER_NO_INTERSEC
+\brief Identificador de que dos segmentos o arcos no se cortan.
+\date 18 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_DPEUCKER_NO_INTERSEC 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_DP_RECT_DISJ
+\brief Comprueba si dos rectángulos son disjuntos.
+\param[in] esf Identificador de trabajo sobre la superficie de la esfera. Dos
+ posibilidades:
+ - 0: No se trabaja sobre la superficie de la esfere, sino en el
+ plano.
+ - Distinto de 0: Se trabaja sobre la superficie de la esfera de radio
+ unidad.
+\param[in] tol Tolerancia angular, en radianes. Indica el valor por debajo del
+ cual dos ángulos se consideran iguales. Este argumento ha de ser un
+ número \b POSITIVO (no se comprueba internamente).
+\param[in] xMin1 Coordenada X o longitud, en radianes, mínima del rectángulo 1.
+\param[in] xMax1 Coordenada X o longitud, en radianes, máxima del rectángulo 1.
+\param[in] yMin1 Coordenada Y o latitud, en radianes, mínima del rectángulo 1.
+\param[in] yMax1 Coordenada Y o latitud, en radianes, máxima del rectángulo 1.
+\param[in] xMin2 Coordenada X o longitud, en radianes, mínima del rectángulo 2.
+\param[in] xMax2 Coordenada X o longitud, en radianes, máxima del rectángulo 2.
+\param[in] yMin2 Coordenada Y o latitud, en radianes, mínima del rectángulo 2.
+\param[in] yMax2 Coordenada Y o latitud, en radianes, 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.
+\note Si se trabaja sobre la esfera, esta macro utiliza internamente la función
+ \ref ArcosCircMaxDisjuntos, mientras que si estamos en el plano se usa la
+ macro \ref GEOC_RECT_DISJUNTOS.
+\date 18 de agosto de 2013: Creación de la macro.
+\date 23 de septiembre de 2013: Adición del argumento \em tol.
+\todo Esta macro no está probada.
+*/
+#define GEOC_DP_RECT_DISJ(esf,tol, \
+ xMin1,xMax1,yMin1,yMax1,xMin2,xMax2,yMin2,yMax2) \
+((esf) \
+? (ArcosCircMaxDisjuntos(tol,xMin1,xMax1,xMin2,xMax2)) \
+: (GEOC_RECT_DISJUNTOS(xMin1,xMax1,yMin1,yMax1,xMin2,xMax2,yMin2,yMax2)))
+/******************************************************************************/
+/******************************************************************************/
+/** \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.
+\date 24 de mayo de 2011: Adición del la opción \em GeocDPeuckerOriginal.
+*/
+enum GEOC_DPEUCKER_ROBUSTO
+{
+ /** \brief Se usa el algoritmo original de Douglas-Peucker (no robusto). */
+ GeocDPeuckerOriginal=111,
+ /** \brief \b *NO* se realiza aligerado robusto (con mi algoritmo). */
+ GeocDPeuckerRobNo=112,
+ /** \brief \b *SÍ* se realiza aligerado robusto. */
+ GeocDPeuckerRobSi=113,
+ /** \brief Aligerado semi robusto con
+ \ref DouglasPeuckerRobIntersecOrigPlano y
+ \ref DouglasPeuckerRobIntersecOrigEsfera. */
+ GeocDPeuckerRobOrig=114,
+ /** \brief Aligerado semi robusto con
+ \ref DouglasPeuckerRobAutoIntersecPlano y
+ \ref DouglasPeuckerRobAutoIntersecEsfera. */
+ GeocDPeuckerRobAuto=115
+};
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba algunos casos especiales antes del aligerado de vértices de una
+ polilínea.
+\param[in] x Vector que contiene las coordenadas X o las longitudes de los
+ vértices de la polilínea de trabajo.
+\param[in] y Vector que contiene las coordenadas Y o las latitudes 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. Este argumento sólo se tiene
+ internamente en cuenta si vale 0.0.
+\param[out] nPtosSal Número de puntos de la polilínea aligerada, si se ha
+ encontrado algún caso especial.
+\param[out] hayCasoEspecial Identificador de caso especial. Dos posibilidades:
+ - 0: No se ha encontrado ningún caso especial.
+ - Distinto de 0: Sí se ha encontrado algún caso especial.
+\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, en el caso de que se haya encontrado algún caso especial. Si
+ ocurre algún error de asignación de memoria se devuelve el valor
+ \p NULL. Este argumento sólo tiene sentido si se ha devuelto un valor de
+ \em hayCasoEspecial distinto de 0.
+\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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función comprueba los siguientes casos especiales:
+ - Si sólo hay un punto de entrada: En este caso, \em nPtosSal vale 1 y el
+ vector de salida contiene la posición de ese único punto.
+ - Si hay dos puntos de entrada, y estos son el mismo: En este caso,
+ \em nPtosSal vale 1 y el vector de salida contiene la posición
+ únicamente del primero de ellos.
+ - Si hay dos puntos de entrada, y estos son distintos: En este caso,
+ \em nPtosSal vale 2 y el vector de salida contiene la posición de los
+ dos puntos, aunque la distancia entre ellos sea menor que \em tol.
+ - Si hay tres puntos de entrada, y el primero es el mismo que el tercero:
+ En este caso, \em nPtosSal vale 2 y el vector de salida contiene la
+ posición de los dos primeros.
+ - En el caso en que el segundo punto también sea igual al primero,
+ \em nPtosSal vale 1 y el vector de salida contiene la posición
+ únicamente del primero.
+ - Si \em tol vale 0.0: En este caso, se eliminan los posibles puntos
+ repetidos en los vectores de coordenadas de entrada.
+\date 08 de agosto de 2013: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+size_t* CasosEspecialesAligeraPolilinea(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ size_t* nPtosSal,
+ int* hayCasoEspecial);
+/******************************************************************************/
+/******************************************************************************/
+#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/dpeuckere.h b/src/libgeoc/dpeuckere.h
new file mode 100644
index 0000000..46ead43
--- /dev/null
+++ b/src/libgeoc/dpeuckere.h
@@ -0,0 +1,1002 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckere.h
+\brief Declaración de funciones auxiliares para el aligerado de polilíneas sobre
+ la superficie de la esfera, basadas en el algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 15 de agosto de 2013
+\copyright
+Copyright (c) 2013-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _DPEUCKERE_H_
+#define _DPEUCKERE_H_
+/******************************************************************************/
+/******************************************************************************/
+#if defined(_OPENMP)
+#include<omp.h>
+#endif
+#include<math.h>
+#include"libgeoc/constantes.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/dpeuckera.h"
+#include"libgeoc/arco.h"
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref dpeuckerp.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 17 de agosto de 2013: Creación de la función.
+\date 03 de abril de 2014: Particularización de la función sólo para la esfera.
+*/
+int GeocParOmpDpeuckere(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea sobre la superficie de una esfera
+ mediante una modificación del algoritmo de Douglas-Peucker.
+\brief El algoritmo original, a partir del cual se ha hecho esta modificación,
+ está documentado en:
+
+\brief James E. Burt, 1989. Line Generalization on the Sphere. Geographical
+ Analysis 21 (1), 68-74.
+
+ También se utiliza una adaptación del criterio apuntado en:
+ Ebisch, K., October 2002. A correction to the Douglas–Peucker line
+ generalization algorithm. Computers and Geosciences 28 (8), 995–997.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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: longitud de arco de círculo
+ máximo sobre la esfera de radio unidad.
+\param[in] posIni Posición en los vectores de coordenadas del punto inicial del
+ segmento base para añadir puntos a la línea simplificada.
+\param[in] posFin Posición en los vectores de coordenadas del punto final del
+ segmento base para añadir puntos a la línea simplificada.
+\param[out] usados Vector de \em nPtos elementos para indicar los puntos que
+ finalmente se usan en la polilínea simplificada. En la entrada,
+ todos sus elementos han de contener el valor 0, excepto las
+ posiciones \em 0 y \em nPtos-1, que han de contener el valor 1. En
+ la salida, las posiciones correspondientes a los puntos de la línea
+ inicial no utilizados almacenarán el valor \em 0, mientras que las
+ posiciones de los puntos utilizados almacenarán el valor \em 1.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función es recursiva.
+\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 los valores \em posIni y \em posFin son posiciones
+ válidas.
+\note Esta función asume que el vector \em usados contiene suficiente memoria
+ asignada.
+\date 21 de septiembre de 2013: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerOriginalEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posIni,
+ const size_t posFin,
+ char* usados);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea sobre la superficie de la esfera
+ mediante un algoritmo no recursivo, inspirado en el de Douglas-Peucker.
+\brief Este algoritmo, comenzando por el primer punto de la polilínea, va
+ uniendo puntos en arcos de tal forma que se eliminan todos aquellos
+ puntos que queden a una distancia menor o igual a \em tol del arco 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 longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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, como longitud de arco de
+ círculo máximo sobre la esfera de radio unidad.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: En este caso esta opción es equivalente a
+ pasar #GeocDPeuckerRobNo.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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/arcos de la polilínea
+ aligerada que se van creando no intersectarán con ninguno de los
+ arcos 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 arcos de la polilínea aligerada que
+ se van creando no intersectarán con ninguno de los arcos de la
+ polilínea aligerada creados con anterioridad. En casos muy
+ especiales, este algoritmo puede seguir dando lugar a auto
+ intersecciones.
+\param[in] nSegRobOrig Número de arcos 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
+ arcos hasta el final de la polilínea original.
+\param[in] nSegRobAuto 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
+ arcos 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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función comprueba los casos especiales con
+ \ref CasosEspecialesAligeraPolilinea.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\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.
+\date 14 de mayo de 2012: Corregido bug que hacía que no se escogiese bien el
+ vértice a añadir a la polilínea aligerada.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 17 de agosto de 2013: Comprobación de casos especiales y unificación de
+ las funciones de aligerado en el plano y en la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+size_t* DouglasPeuckerRobustoEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo, con OpenMP, si una serie
+ de puntos entre los extremos de un arco base están en tolerancia, según
+ el criterio de la familia de algoritmos de Douglas-Peucker.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] tol Tolerancia para eliminar vértices, como longitud de arco de
+ círculo máximo sobre la esfera de radio unidad.
+\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
+ del arco base.
+\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
+ arco base.
+\param[in] posPtoIni Posición en los vectores \em x, \em y, \em xG, \em yG y
+ \em zG del punto inicial a partir del cual (incluido) se chequeará la
+ tolerancia.
+\param[in] posPtoFin Posición en los vectores \em x, \em y, \em xG, \em yG y
+ \em zG del punto inicial hasta el cual (incluido) se chequeará la
+ tolerancia.
+\param[in] lonFinR Longitud del punto final del arco base en el sistema rotado.
+\param[in] mRot Matriz de rotación aplicada a la base del triángulo para
+ llevarla al ecuador, con el punto inicial en
+ \f$(\varphi=0,\lambda=0)\f$. Este argumento ha de ser una matriz de
+ 3x3 almacenada en el formato de C.
+\return Identificador de que los puntos intermedios están o no en tolerancia.
+ Dos posibilidades:
+ - 0: Hay algún punto que se sale de tolerancia.
+ - Distinto de 0: Todos los puntos están en tolerancia.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
+ \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
+ número de elementos de los vectores \em x, \em y y, en su caso \em xG,
+ \em yG y \em zG.
+\note Esta función asume que
+ \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\date 18 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerPuntosEnTolEsferaOMP(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin,
+ const double lonFinR,
+ double mRot[][3]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de puntos entre
+ los extremos de un arco base están en tolerancia, según el criterio de la
+ familia de algoritmos de Douglas-Peucker.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] tol Tolerancia para eliminar vértices, como longitud de arco de
+ círculo máximo sobre la esfera de radio unidad.
+\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
+ del arco base.
+\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
+ arco base.
+\param[in] posPtoIni Posición en los vectores \em x, \em y, \em xG, \em yG y
+ \em zG del punto inicial a partir del cual (incluido) se chequeará la
+ tolerancia.
+\param[in] posPtoFin Posición en los vectores \em x, \em y, \em xG, \em yG y
+ \em zG del punto inicial hasta el cual (incluido) se chequeará la
+ tolerancia.
+\param[in] lonFinR Longitud del punto final del arco base en el sistema rotado.
+\param[in] mRot Matriz de rotación aplicada a la base del triángulo para
+ llevarla al ecuador, con el punto inicial en
+ \f$(\varphi=0,\lambda=0)\f$. Este argumento ha de ser una matriz de
+ 3x3 almacenada en el formato de C.
+\return Identificador de que los puntos intermedios están o no en tolerancia.
+ Dos posibilidades:
+ - 0: Hay algún punto que se sale de tolerancia.
+ - Distinto de 0: Todos los puntos están en tolerancia.
+\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
+ \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
+ número de elementos de los vectores \em x, \em y y, en su caso \em xG,
+ \em yG y \em zG.
+\note Esta función asume que
+ \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL y se trabaja sobre la esfera.
+\date 18 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerPuntosEnTolEsferaSerie(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin,
+ const double lonFinR,
+ double mRot[][3]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
+ arcos creados intersecten con los de la polilínea original a partir del
+ punto de trabajo actual.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] segAUsar Número de arcos a utilizar de la polilínea original. Si se
+ pasa el valor 0 se utilizan todos los arcos que quedan desde el punto
+ de trabajo hasta el final.
+\param[in] posIni Posición inicial del arco a chequear.
+\param[in,out] posFin Posición final del arco a chequear. Al término de la
+ ejecución de la función almacena la posición del punto que hace
+ que el arco 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,
+ \em y, \em xG, \em yG y \em zG, 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 Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\date 07 de julio de 2011: Creación de la función.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
+ esfera.
+\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
+ paralelo de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerRobIntersecOrigEsfera(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
+ arcos se cortan con un arco base AB, a partir de éste en adelante.
+\param[in] xA Longitud, en radianes, del punto A.
+\param[in] yA Latitud, en radianes, del punto A.
+\param[in] xB Longitud, en radianes, del punto B.
+\param[in] yB Latitud, en radianes, del punto B.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] posIni Posición en los vectores \em x, \em y, \em xG, \em yG y \em zG
+ del punto inicial a partir del cual (incluido) se comenzarán a
+ chequear arcos.
+\param[in] posFin Posición en los vectores \em x, \em y, \em xG, \em yG y \em zG
+ del punto final hasta el cual (incluido) se chequearán arcos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los arcos desde \em posIni
+ hasta \em posFin.
+ - Distinto de 0: Hay al menos una intersección entre AB y los arcos
+ desde \em posIni hasta \em posFin.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
+ congruentes con las dimensiones de los vectores \em x \em y, \em xG,
+ \em yG y \em zG.
+\note Esta función asume que \em posIni<\em posFin.
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecEsfera, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecOrigEsferaOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de arcos se
+ cortan con un arco base AB, a partir de éste en adelante.
+\param[in] xA Longitud, en radianes, del punto A.
+\param[in] yA Latitud, en radianes, del punto A.
+\param[in] xB Longitud, en radianes, del punto B.
+\param[in] yB Latitud, en radianes, del punto B.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] posIni Posición en los vectores \em x, \em y, \em xG, \em yG y \em zG
+ del punto inicial a partir del cual (incluido) se comenzarán a
+ chequear arcos.
+\param[in] posFin Posición en los vectores \em x, \em y, \em xG, \em yG y \em zG
+ del punto final hasta el cual (incluido) se chequearán arcos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los arcos desde \em posIni
+ hasta \em posFin.
+ - Distinto de 0: Hay al menos una intersección entre AB y los arcos
+ desde \em posIni hasta \em posFin.
+\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
+ congruentes con las dimensiones de los vectores \em x \em y, \em xG,
+ \em yG y \em zG.
+\note Esta función asume que \em posIni<\em posFin.
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecEsfera, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecOrigEsferaSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Aproximación robusta al aligerado de líneas consistente en evitar que los
+ arcos creados intersecten con los anteriores de la polilínea aligerada.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] posIni Posición (en los vectores \em x e \em y) inicial del arco a
+ chequear.
+\param[in,out] posFin Posición (en los vectores \em x e \em y) final del arco a
+ chequear. Al término de la ejecución de la función almacena la
+ posición del punto que hace que el arco de la polilínea aligerada
+ no intersecte con ninguno de los anteriormente calculados.
+\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.
+\param[in] segAUsar Número de arcos a utilizar de la polilínea aligerada. Si se
+ pasa el valor 0 se utilizan todos los arcos anteriores.
+\note Esta función no comprueba si el número de elementos de los vectores \em x,
+ \em y, \em xG, \em yG y \em zG, 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 si los índices almacenados en \em posAlig son
+ congruentes con el tamaño de los vectores \em x e \em y.
+\note Esta función no comprueba si el valor pasado en \em nPosAlig es congruente
+ con el tamaño del vector \em posAlig.
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\date 05 de julio de 2011: Creación de la función.
+\date 14 de mayo de 2012: Modificación del argumento \em nPosAlig para que
+ contenga el tamaño real del vector \em posAlig.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
+ esfera.
+\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
+ paralelo de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerRobAutoIntersecEsfera(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t posIni,
+ size_t* posFin,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
+ arcos de la polilínea ya aligerada se cortan con un arco base AB, a
+ partir de éste hacia atrás.
+\param[in] xA Longitud, en radianes, del punto A.
+\param[in] yA Latitud, en radianes, del punto A.
+\param[in] xB Longitud, en radianes, del punto B.
+\param[in] yB Latitud, en radianes, del punto B.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\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.
+\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
+ del cual (incluido) se comenzarán a chequear arcos.
+\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
+ cual (incluido) se chequearán arcos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los arcos.
+ - Distinto de 0: Hay al menos una intersección entre AB y los arcos.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si los índices almacenados en \em posAlig son
+ congruentes con las dimensiones de los vectores \em x \em y, \em xG,
+ \em yG y \em zG.
+\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
+ y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
+\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecEsfera, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobAutoIntersecEsferaOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de arcos de la
+ polilínea ya aligerada se cortan con un arco base AB, a partir de éste
+ hacia atrás.
+\param[in] xA Longitud, en radianes, del punto A.
+\param[in] yA Latitud, en radianes, del punto A.
+\param[in] xB Longitud, en radianes, del punto B.
+\param[in] yB Latitud, en radianes, del punto B.
+\param[in] x Vector que contiene las longitudes, en radianes, de los vértices de
+ la polilínea de trabajo.
+\param[in] y Vector que contiene las latitudes, en radianes, 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] xG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas X cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] yG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Y cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\param[in] zG Vector de las mismas dimensiones que \em x e \em y que contiene
+ las coordenadas Z cartesianas geocéntricas con esfera de radio unidad
+ de los puntos de trabajo. Sus elementos han de estar situados de
+ forma contigua en memoria. Este argumento sólo se tiene en cuenta si
+ es distinto de \p NULL.
+\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.
+\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
+ del cual (incluido) se comenzarán a chequear arcos.
+\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
+ cual (incluido) se chequearán arcos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los arcos.
+ - Distinto de 0: Hay al menos una intersección entre AB y los arcos.
+\note Esta función no comprueba si los índices almacenados en \em posAlig son
+ congruentes con las dimensiones de los vectores \em x \em y, \em xG,
+ \em yG y \em zG.
+\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
+ y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
+\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
+\note Los argumentos \em xG, \em yG y \em zG sólo son tenidos en cuenta si los
+ tres son distintos de \p NULL.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecEsfera, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobAutoIntersecEsferaSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double* xG,
+ const double* yG,
+ const double* zG,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección de dos arcos AB y CD en la esfera. Se asume que
+ el arco AB está contenido en el ecuador, con el punto A de coordenadas
+ \f$(\varphi=0,\lambda=0)\f$.
+\param[in] xB Longitud, en radianes, del punto B.
+\param[in] xC Longitud, en radianes, del punto C.
+\param[in] yC Latitud, en radianes, del punto C.
+\param[in] xD Longitud, en radianes, del punto D.
+\param[in] yD Latitud, en radianes, del punto D.
+\param[in] xGC Coordenada X cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] yGC Coordenada Y cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] zGC Coordenada Z cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] xGD Coordenada X cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] yGD Coordenada Y cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] zGD Coordenada Z cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto C. Este
+ argumento sólo se tiene en cuenta si es distinto del valor devuelto
+ por \ref GeocNan.
+\param[in] posFinAB Posición del punto final del arco AB en los vectores
+ originales de coordenadas.
+\param[in] posIniCD Posición del punto inicial del arco CD en los vectores
+ originales de coordenadas.
+\return Dos posibilidades:
+ - 0: No hay intersección entre AB y CD.
+ - Distinto de 0: Sí hay intersección entre AB y CD.
+\note El dominio de las longitudes pasadas ha de ser \f$]-\pi,\pi]\f$.
+\note Los argumentos \em xGC, \em yGC, \em zGC, \em xGD, \em yGD y \em zGD sólo
+ son tenidos en cuenta si cada tríada es distinta de \ref GeocNan, en cuyo
+ caso las coordenadas cartesianas tridimensionales geocéntricas, necesarias
+ para los cálculos llevados a cabo por la función, son calculadas
+ internamente a partir de los argumentos \em xC, \em yC, \em xD e \em yD.
+\note Esta función utiliza internamente las funciones
+ \ref IntersecArcCircMaxEsferaAux, que no es robusta. En consecuencia, los
+ resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 28 de marzo de 2014: Adición de los argumentos \em xGC, \em yGC, \em zGC,
+ \em xGD, \em yGD y \em zGD.
+\date 02 de abril de 2014: Particularización de la función sólo para la esfera.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecEsfera(const double xB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ const double xGC,
+ const double yGC,
+ const double zGC,
+ const double xGD,
+ const double yGD,
+ const double zGD,
+ const size_t posFinAB,
+ const size_t posIniCD);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el seno en valor absoluto de la distancia sobre un círculo máximo
+ del punto más alejado de un conjunto de puntos candidatos a un arco de
+ círculo máximo para su uso en el aligerado de polilíneas mediante el
+ algoritmo de Douglas-Peucker.
+\brief Esta función trabaja en un sistema de referencia esférico tal que la base
+ del triángulo está situada en el ecuador, con su punto inicial el de
+ coordenadas \f$(\varphi=0,\lambda=0)\f$.
+\param[in] lat Vector que contiene las latitudes, en radianes, de los vértices
+ de la polilínea de trabajo.
+\param[in] lon Vector que contiene las longitudes, en radianes, de los vértices
+ de la polilínea de trabajo.
+\param[in] incLat Posiciones de separación entre los elementos del vector
+ \em lat. Este argumento siempre ha de ser un número positivo.
+\param[in] incLon Posiciones de separación entre los elementos del vector
+ \em lon. Este argumento siempre ha de ser un número positivo.
+\param[in] posIni Posición en los vectores de coordenadas del punto inicial del
+ segmento base.
+\param[in] posFin Posición en los vectores de coordenadas del punto final del
+ segmento base.
+\param[out] pos Posición en los vectores de coordenadas del punto situado entre
+ \em posIni y \em posFin más alejado de la línea base. Si \em posFin
+ es el punto inmediatamente posterior a \em posIni, esta variable
+ devuelve \em posIni.
+\return Seno en valor absoluto de la distancia angular sobre un círculo máximo
+ del punto más alejado a la línea base. Si \em posFin es el punto
+ inmediatamente posterior a \em posIni, se devuelve el valor -1.0.
+\note Esta función no comprueba si el número de elementos de los vectores
+ \em lat y \em lon es congruente con los valores pasados en \em posIni y
+ \em posFin.
+\note En el caso de que el arco \f$\alpha\f$ de trabajo sea mayor que
+ \f$\frac{\pi}{2}\f$, esta función devuelve el valor \f$1+\cos(\alpha)\f$,
+ en lugar del seno.
+\note Esta función puede devolver resultados erróneos si algún segmento base es
+ mayor o igual que \f$\pi\f$.
+\date 21 de septiembre de 2013: Creación de la función.
+\date 26 de marzo de 2014: La función ahora devuelve el valor absoluto del seno
+ de la distancia angular.
+\todo Esta función todavía no está probada.
+*/
+double DouglasPeuckerSenDistMaxEsfera(const double* lat,
+ const double* lon,
+ const size_t incLat,
+ const size_t incLon,
+ const size_t posIni,
+ const size_t posFin,
+ size_t* pos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el seno en valor absoluto de la distancia sobre un círculo máximo
+ de un punto a un arco para su uso en el aligerado de polilíneas mediante
+ mi modificación del algoritmo de Douglas-Peucker.
+\brief Esta función trabaja en un sistema de referencia esférico tal que la base
+ del triángulo está situada en el ecuador, con su punto inicial el de
+ coordenadas \f$(\varphi=0,\lambda=0)\f$.
+\param[in] latVert Latitud del punto de trabajo, en el sistema original, en
+ radianes.
+\param[in] lonVert Longitud del punto de trabajo, en el sistema original, en
+ radianes.
+\param[in] xVert Coordenada X cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto de trabajo.
+ Este argumento sólo se tiene en cuenta si es distinto del valor
+ devuelto por \ref GeocNan.
+\param[in] yVert Coordenada Y cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto de trabajo.
+ Este argumento sólo se tiene en cuenta si es distinto del valor
+ devuelto por \ref GeocNan.
+\param[in] zVert Coordenada Z cartesiana geocéntrica para esfera de radio
+ unidad, en el sistema original, correspondiente al punto de trabajo.
+ Este argumento sólo se tiene en cuenta si es distinto del valor
+ devuelto por \ref GeocNan.
+\param[in] lonBase2R Longiud del punto final de la base del triángulo, en el
+ sistema rotado, en radianes.
+\param[out] mRot Matriz de rotación aplicada a la base del triángulo para
+ llevarla al sistema descrito. Este argumento ha de ser una matriz de
+ 3x3 almacenada en el formato de C.
+\return Seno en valor absoluto de la distancia angular sobre un círculo máximo
+ del punto al arco base.
+\note En el caso de que el arco \f$\alpha\f$ de trabajo sea mayor que
+ \f$\frac{\pi}{2}\f$, esta función devuelve el valor \f$1+\cos(\alpha)\f$,
+ en lugar del seno.
+\note Ninguno de los lados ni ángulos del triángulo puede ser mayor de
+ \f$\pi\f$, hecho que no se comprueba internamente.
+\note Los argumentos \em xVert, \em yVert y \em zVert sólo son tenidos en cuenta
+ si los tres son distintos de \ref GeocNan, en cuyo caso las coordenadas
+ cartesianas tridimensionales geocéntricas, necesarias para los cálculos
+ llevados a cabo por la función, son calculadas internamente a partir de
+ los argumentos \em latVert y \em lonVert.
+\date 15 de agosto de 2013: Creación de la función.
+\date 26 de marzo de 2014: La función ahora devuelve el valor absoluto del seno
+ de la distancia angular.
+\todo Esta función todavía no está probada.
+*/
+double DouglasPeuckerSenDistMaxEsferaAux(const double latVert,
+ const double lonVert,
+ const double xVert,
+ const double yVert,
+ const double zVert,
+ const double lonBase2R,
+ double mRot[][3]);
+/******************************************************************************/
+/******************************************************************************/
+#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/dpeuckerp.h b/src/libgeoc/dpeuckerp.h
new file mode 100644
index 0000000..d43e31e
--- /dev/null
+++ b/src/libgeoc/dpeuckerp.h
@@ -0,0 +1,774 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup geom
+@{
+\file dpeuckerp.h
+\brief Declaración de funciones para el aligerado de polilíneas en el plano
+ basadas en el algoritmo de Douglas-Peucker.
+\author José Luis García Pallero, jgpallero@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 04 de julio de 2011
+\copyright
+Copyright (c) 2011-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _DPEUCKERP_H_
+#define _DPEUCKERP_H_
+/******************************************************************************/
+/******************************************************************************/
+#if defined(_OPENMP)
+#include<omp.h>
+#endif
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/dpeuckera.h"
+#include"libgeoc/segmento.h"
+#include"libgeoc/geocomp.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica si hay alguna función compilada en paralelo con OpenMP en el
+ fichero \ref dpeuckerp.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 17 de agosto de 2013: Creación de la función.
+\date 03 de abril de 2014: Particularización de la función sólo para el plano.
+*/
+int GeocParOmpDpeuckerp(char version[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea en el plano mediante el algoritmo de
+ Douglas-Peucker.
+\brief El algoritmo original está documentado en:
+
+\brief Douglas, D. H., Peucker, T. K., 1973. Algorithms for the reduction of the
+ number of points required to represent a digitized line or its
+ caricature. The Canadian Cartographer 10 (2), 112–122.
+
+ También se utiliza el criterio apuntado en:
+ Ebisch, K., October 2002. A correction to the Douglas–Peucker line
+ generalization algorithm. Computers and Geosciences 28 (8), 995–997.
+\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] posIni Posición en los vectores de coordenadas del punto inicial del
+ segmento base para añadir puntos a la línea simplificada.
+\param[in] posFin Posición en los vectores de coordenadas del punto final del
+ segmento base para añadir puntos a la línea simplificada.
+\param[out] usados Vector de \em nPtos elementos para indicar los puntos que
+ finalmente se usan en la polilínea simplificada. En la entrada,
+ todos sus elementos han de contener el valor 0, excepto las
+ posiciones \em 0 y \em nPtos-1, que han de contener el valor 1. En
+ la salida, las posiciones correspondientes a los puntos de la línea
+ inicial no utilizados almacenarán el valor \em 0, mientras que las
+ posiciones de los puntos utilizados almacenarán el valor \em 1.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función es recursiva.
+\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 los valores \em posIni y \em posFin son posiciones
+ válidas.
+\note Esta función asume que el vector \em usados contiene suficiente memoria
+ asignada.
+\date 25 de mayo de 2012: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerOriginalPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posIni,
+ const size_t posFin,
+ char* usados);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Elimina vértices de una polilínea en el plano mediante un algoritmo no
+ recursivo, inspirado en el de Douglas-Peucker.
+\brief 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 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 éstos.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: En este caso esta opción es equivalente a
+ pasar #GeocDPeuckerRobNo.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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] nSegRobOrig Número de segmentos 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
+ segmentos hasta el final de la polilínea original.
+\param[in] nSegRobAuto 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, por lo que un valor de retorno igual a \p NULL sólo es
+ indicativo de error cuando \em nPtos es mayor que 0.
+\note Esta función comprueba los casos especiales con
+ \ref CasosEspecialesAligeraPolilinea.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\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.
+\date 14 de mayo de 2012: Corregido bug que hacía que no se escogiese bien el
+ vértice a añadir a la polilínea aligerada.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 17 de agosto de 2013: Comprobación de casos especiales y unificación de
+ las funciones de aligerado en el plano y en la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+size_t* DouglasPeuckerRobustoPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ size_t* nPtosSal);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo, con OpenMP, si una serie
+ de puntos entre los extremos de un segmento base están en tolerancia,
+ según el criterio de la familia de algoritmos de Douglas-Peucker.
+\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] tol Tolerancia para eliminar vértices, en las mismas unidades que las
+ coordenadas de éstos.
+\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
+ del segmento base.
+\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
+ segmento base.
+\param[in] posPtoIni Posición en los vectores \em x e \em y del punto inicial a
+ partir del cual (incluido) se chequeará la tolerancia.
+\param[in] posPtoFin Posición en los vectores \em x e \em y del punto inicial
+ hasta el cual (incluido) se chequeará la tolerancia.
+\return Identificador de que los puntos intermedios están o no en tolerancia.
+ Dos posibilidades:
+ - 0: Hay algún punto que se sale de tolerancia.
+ - Distinto de 0: Todos los puntos están en tolerancia.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
+ \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
+ número de elementos de los vectores \em x e \em y.
+\note Esta función asume que
+ \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
+\date 18 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerPuntosEnTolPlanoOMP(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de puntos entre
+ los extremos de un segmento base están en tolerancia, según el criterio
+ de la familia de algoritmos de Douglas-Peucker.
+\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] tol Tolerancia para eliminar vértices, en las mismas unidades que las
+ coordenadas de éstos.
+\param[in] posBaseIni Posición en los vectores \em x e \em y del punto inicial
+ del segmento/arco base.
+\param[in] posBaseFin Posición en los vectores \em x e \em y del punto final del
+ segmento/arco base.
+\param[in] posPtoIni Posición en los vectores \em x e \em y del punto inicial a
+ partir del cual (incluido) se chequeará la tolerancia.
+\param[in] posPtoFin Posición en los vectores \em x e \em y del punto inicial
+ hasta el cual (incluido) se chequeará la tolerancia.
+\return Identificador de que los puntos intermedios están o no en tolerancia.
+ Dos posibilidades:
+ - 0: Hay algún punto que se sale de tolerancia.
+ - Distinto de 0: Todos los puntos están en tolerancia.
+\note Esta función no comprueba si las posiciones pasadas en \em posBaseIni,
+ \em posBaseFin, \em posPtoIni y \em posPtoFin son congruentes con el
+ número de elementos de los vectores \em x e \em y.
+\note Esta función asume que
+ \em posBaseIni < \em posPtoIni <= \em posPtoFin < \em posBaseFin.
+\date 18 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerPuntosEnTolPlanoSerie(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const double tol,
+ const size_t posBaseIni,
+ const size_t posBaseFin,
+ const size_t posPtoIni,
+ const size_t posPtoFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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] segAUsar Número de segmentos a utilizar de la polilínea original. Si
+ se pasa el valor 0 se utilizan todos los segmentos 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.
+\date 07 de julio de 2011: Creación de la función.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
+ esfera.
+\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
+ paralelo de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerRobIntersecOrigPlano(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const size_t segAUsar,
+ const size_t posIni,
+ size_t* posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
+ segmentos se cortan con un segmento/arco base AB, a partir de éste en
+ adelante.
+\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] 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] posIni Posición en los vectores \em x e \em y del punto inicial a
+ partir del cual (incluido) se comenzarán a chequear segmentos.
+\param[in] posFin Posición en los vectores \em x e \em y del punto final hasta
+ el cual (incluido) se chequearán segmentos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los segmentos desde
+ \em posIni hasta \em posFin.
+ - Distinto de 0: Hay al menos una intersección entre AB y los segmentos
+ desde \em posIni hasta \em posFin.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
+ congruentes con las dimensiones de los vectores \em x e \em y.
+\note Esta función asume que \em posIni<\em posFin.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecPlano, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecOrigPlanoOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de segmentos
+ se cortan con un segmento base AB, a partir de éste en adelante.
+\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] 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] posIni Posición en los vectores \em x e \em y del punto inicial a
+ partir del cual (incluido) se comenzarán a chequear segmentos.
+\param[in] posFin Posición en los vectores \em x e \em y del punto final hasta
+ el cual (incluido) se chequearán segmentos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los segmentos desde
+ \em posIni hasta \em posFin.
+ - Distinto de 0: Hay al menos una intersección entre AB y los segmentos
+ desde \em posIni hasta \em posFin.
+\note Esta función no comprueba si los argumentos \em posIni y \em posFin son
+ congruentes con las dimensiones de los vectores \em x e \em y.
+\note Esta función asume que \em posIni<\em posFin.
+\note Esta función utiliza internamente la función
+ \ref DouglasPeuckerRobIntersecPlano, que no es robusta. En consecuencia,
+ los resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecOrigPlanoSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const 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] posIni Posición (en los vectores \em x e \em y) inicial del
+ segmento a chequear.
+\param[in,out] posFin Posición (en los vectores \em x e \em y) 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.
+\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.
+\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.
+\note Esta función no comprueba si el número de elementos de los vectores \em x
+ e \em y.
+\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 si los índices almacenados en \em posAlig son
+ congruentes con el tamaño de los vectores \em x e \em y.
+\note Esta función no comprueba si el valor pasado en \em nPosAlig es congruente
+ con el tamaño del vector \em posAlig.
+\date 05 de julio de 2011: Creación de la función.
+\date 14 de mayo de 2012: Modificación del argumento \em nPosAlig para que
+ contenga el tamaño real del vector \em posAlig.
+\date 25 de mayo de 2012: Cambio de nombre de la función.
+\date 18 de agosto de 2013: Unificación para el uso sobre el plano y sobre la
+ esfera.
+\date 20 de agosto de 2013: Reorganización interna de la ejecución en serie y en
+ paralelo de la función.
+\date 27 de marzo de 2014: Adición de los argumentos \em xG, \em yG y \em zG.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerRobAutoIntersecPlano(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ size_t* posFin,
+ const size_t* posAlig,
+ const size_t nPosAlig,
+ const size_t segAUsar);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en paralelo con OpenMP, si una serie de
+ segmentos de la polilínea ya aligerada se cortan con un segmento base AB,
+ a partir de éste hacia atrás.
+\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] 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.
+\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
+ del cual (incluido) se comenzarán a chequear segmentos.
+\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
+ cual (incluido) se chequearán segmentos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los segmentos.
+ - Distinto de 0: Hay al menos una intersección entre AB y los segmentos.
+\note Esta función está paralelizada con OpenMP.
+\note Esta función no comprueba si los índices almacenados en \em posAlig son
+ congruentes con el tamaño de los vectores \em x e \em y.
+\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
+ y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
+\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
+\date 20 de agosto de 2013: Creación de la función.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobAutoIntersecPlanoOMP(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ 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 posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba, mediante una ejecución en serie, si una serie de segmentos de
+ la polilínea ya aligerada se cortan con un segmento base AB, a partir de
+ éste hacia atrás.
+\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] 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.
+\param[in] posIni Posición en el vector \em posAlig del punto inicial a partir
+ del cual (incluido) se comenzarán a chequear segmentos.
+\param[in] posFin Posición en el vector \em posAlig del punto final hasta el
+ cual (incluido) se chequearán segmentos.
+\return Dos posibilidades:
+ - 0: No hay ninguna intersección entre AB y los segmentos.
+ - Distinto de 0: Hay al menos una intersección entre AB y los segmentos.
+\note Esta función no comprueba si los índices almacenados en \em posAlig son
+ congruentes con el tamaño de los vectores \em x e \em y.
+\note Esta función no comprueba si los valores pasados en \em posIni, \em posFin
+ y \em nPosAlig son congruentes con el tamaño del vector \em posAlig.
+\note Esta función asume que \em posIni>\em posFin (ya que vamos hacia atrás).
+\date 20 de agosto de 2013: Creación de la función.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobAutoIntersecPlanoSerie(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ 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 posIni,
+ const size_t posFin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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[in] posFinAB Posición del punto final del segmento AB en los vectores
+ originales de coordenadas.
+\param[in] posIniCD Posición del punto inicial del segmento CD en los vectores
+ originales de coordenadas.
+\return Dos posibilidades:
+ - 0: No hay intersección entre AB y CD.
+ - Distinto de 0: Sí hay intersección entre AB y CD.
+\note Esta función utiliza internamente las funciones \ref IntersecSegmentos2D o
+ \ref IntersecSegmentos2DSimple, que no son robustas. En consecuencia, los
+ resultados de esta función tampoco lo son.
+\date 20 de agosto de 2013: Creación de la función.
+\date 28 de marzo de 2014: Adición de los argumentos \em xGC, \em yGC, \em zGC,
+ \em xGD, \em yGD y \em zGD.
+\date 01 de abril de 2014: Particularización de la función sólo para el plano.
+\todo Esta función todavía no está probada.
+*/
+int DouglasPeuckerRobIntersecPlano(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD,
+ const size_t posFinAB,
+ const size_t posIniCD);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia a un segmento del punto más alejado de un conjunto
+ de puntos candidatos para su uso en el aligerado de polilíneas mediante
+ el algoritmo de Douglas-Peucker.
+\brief Esta función implementa el criterio apuntado en:
+
+\brief Ebisch, K., October 2002. A correction to the Douglas–Peucker line
+ generalization algorithm. Computers and Geosciences 28 (8), 995–997.
+\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] posIni Posición en los vectores de coordenadas del punto inicial del
+ segmento base.
+\param[in] posFin Posición en los vectores de coordenadas del punto final del
+ segmento base.
+\param[out] pos Posición en los vectores de coordenadas del punto más alejado de
+ la línea base. Si \em posFin es el punto inmediatamente posterior a
+ \em posIni, esta variable devuelve \em posIni.
+\return Distancia del punto más alejado a la línea base. Si \em posFin es el
+ punto inmediatamente posterior a \em posIni, se devuelve el valor -1.0.
+\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 posIni y \em posFin.
+\date 25 de mayo de 2012: Creación de la función.
+\date 16 de marzo de 2014: Reestructuración de la función para el cálculo de la
+ distancia de una forma más eficiente por medio de la transformación del
+ sistema de coordenadas original.
+\todo Esta función todavía no está probada.
+*/
+double DouglasPeuckerDistMaxPlano(const double* x,
+ const double* y,
+ const size_t incX,
+ const size_t incY,
+ const size_t posIni,
+ const size_t posFin,
+ size_t* pos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los parámetros de rotación para girar el sistema de coordenadas
+ con origen en el punto inicial de la base y llevar el eje X a coincidir
+ con ella, para su uso en el aligerado de polilíneas mediante el algoritmo
+ de Douglas-Peucker.
+\param[in] xBase2RB1 Coordenada X del punto final de la base en el sistema de
+ coordenadas original, reducida al punto inicial.
+\param[in] yBase2RB1 Coordenada Y del punto final de la base en el sistema de
+ coordenadas original, reducida al punto inicial.
+\param[out] sAlfa Seno del ángulo de rotación para llevar el eje X del sistema
+ de coordenadas (con origen en el punto inicial de la base) a
+ coincidir con el segmento base.
+\param[out] cAlfa Coseno del ángulo de rotación para llevar el eje X del sistema
+ de coordenadas (con origen en el punto inicial de la base) a
+ coincidir con el segmento base.
+\param[out] lonBase Longitud de la base.
+\date 16 de marzo de 2014: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+void DouglasPeuckerParamRotaBase(const double xBase2RB1,
+ const double yBase2RB1,
+ double* sAlfa,
+ double* cAlfa,
+ double* lonBase);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la distancia de un punto a un segmento AB para su uso en el
+ aligerado de polilíneas mediante el algoritmo de Douglas-Peucker.
+\brief Esta función implementa el criterio apuntado en:
+
+\brief Ebisch, K., October 2002. A correction to the Douglas–Peucker line
+ generalization algorithm. Computers and Geosciences 28 (8), 995–997.
+\param[in] lonBase Longitud de la base.
+\param[in] sAlfa Seno del ángulo de rotación para llevar el eje X del sistema de
+ coordenadas (con origen en el punto inicial de la base) a coincidir
+ con el segmento base.
+\param[in] cAlfa Coseno del ángulo de rotación para llevar el eje X del sistema
+ de coordenadas (con origen en el punto inicial de la base) a
+ coincidir con el segmento base.
+\param[in] xVertRB1 Coordenada X del punto de trabajo en el sistema de
+ coordenadas original, reducida al punto inicial de la base.
+\param[in] yVertRB1 Coordenada Y del punto de trabajo en el sistema de
+ coordenadas original, reducida al punto inicial de la base.
+\return Distancia del punto a la línea base.
+\note Los argumentos \em lonBase, \em sAlfa y \em cAlfa son los parámetros
+ calculados por la función \ref DouglasPeuckerParamRotaBase.
+\date 16 de marzo de 2014: Creación de la función.
+\todo Esta función todavía no está probada.
+*/
+double DouglasPeuckerDistMaxPlanoAux(const double lonBase,
+ const double sAlfa,
+ const double cAlfa,
+ const double xVertRB1,
+ const double yVertRB1);
+/******************************************************************************/
+/******************************************************************************/
+#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 100644
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@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 100644
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@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 100644
index 0000000..8634583
--- /dev/null
+++ b/src/libgeoc/fgeneral.h
@@ -0,0 +1,736 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 25 de septiembre de 2009
+\version 1.0
+\copyright
+Copyright (c) 2009-2018, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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<limits.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_UNIX
+\brief Comprueba si estamos en un entorno UNIX o compatible.
+\return Dos posibilidades:
+ - 1: Estamos en un entorno UNIX o compatible.
+ - 0: No estamos en un entorno UNIX o compatible.
+\note Esta variable sólo se puede usar en sentencias condicionales del
+ preprocesador.
+\date 03 de enero de 2013: Creación de la constante.
+\note Esta macro todavía no está probada.
+*/
+#define GEOC_UNIX 0
+#if (!defined(_WIN32)&&(defined(__unix__)||defined(__unix)||defined(unix)|| \
+ (defined(__APPLE__)&&defined(__MACH__))))
+ #undef GEOC_UNIX
+ #define GEOC_UNIX 1
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SUNOS
+\brief Comprueba si estamos en un entorno de sistema operativo de Oracle
+ (antigua Sun).
+\return Dos posibilidades:
+ - 1: Estamos en un entorno de Oracle.
+ - 0: No estamos en un entorno de Oracle.
+\note Esta variable sólo se puede usar en sentencias condicionales del
+ preprocesador.
+\date 18 de enero de 2013: Creación de la constante.
+\note Esta macro todavía no está probada.
+*/
+#define GEOC_SUNOS 0
+#if (defined(__sun__)||defined(__sun)||defined(__SunOS))
+ #undef GEOC_SUNOS
+ #define GEOC_SUNOS 1
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_WINDOWS
+\brief Comprueba si estamos en un entorno Microsoft Windows de 32 ó 64 bits.
+\return Dos posibilidades:
+ - 1: Estamos en un entorno MS Windows.
+ - 0: No estamos en un entorno MS Windows.
+\note Esta variable sólo se puede usar en sentencias condicionales del
+ preprocesador.
+\date 07 de enero de 2013: Creación de la constante.
+\note Esta macro todavía no está probada.
+*/
+#define GEOC_WINDOWS 0
+#if (defined(__WIN32__)||defined(__WIN32)||defined(_WIN32)||defined(WIN32)|| \
+ defined(__WIN64__)||defined(__WIN64)||defined(_WIN64)||defined(WIN64))
+ #undef GEOC_WINDOWS
+ #define GEOC_WINDOWS 1
+#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_ES_PAR
+\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.
+\date 11 de septiembre de 2012: Renombrado de la macro.
+*/
+#define GEOC_ES_PAR(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))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_COMPARA_VERSIONES
+\brief Compara dos números de versión.
+\param[in] vMay1 Número de versión mayor de la versión 1 a comparar.
+\param[in] vMen1 Número de versión menor de la versión 1 a comparar.
+\param[in] vMic1 Número de versión micro de la versión 1 a comparar.
+\param[in] vMay2 Número de versión mayor de la versión 2 a comparar.
+\param[in] vMen2 Número de versión menor de la versión 2 a comparar.
+\param[in] vMic2 Número de versión micro de la versión 2 a comparar.
+\return Dos posibilidades:
+ - 1: Si la versión 1 es mayor (posterior) o igual que la versión 2.
+ - 0: Si la versión 1 es menor (anterior) que la versión 2.
+\date 05 de agosto de 2012: Creación de la constante.
+\note Esta macro todavía no está probada.
+*/
+#define GEOC_COMPARA_VERSIONES(vMay1,vMen1,vMic1,vMay2,vMen2,vMic2) \
+(((vMay1)>(vMay2))|| \
+ (((vMay1)==(vMay2))&&((vMen1)>(vMen2)))|| \
+ (((vMay1)==(vMay2))&&((vMen1)==(vMen2))&&((vMic1)>=(vMic2))))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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.
+\brief <ul>
+ <li>Para un vector de datos [1,2,2,3,4,4] se devuelve el vector de
+ posiciones [0,1,3,4].
+ </li>
+ <li>Para un vector de datos [1,2,2,3,4] se devuelve el vector de
+ posiciones [0,1,3,4].
+ </li>
+ <li>Para un vector de datos [1,1,1,1,1] se devuelve el vector de
+ posiciones [0].
+ </li>
+ <li>Para un vector de datos [1] se devuelve el vector de posiciones [0].
+ </li>
+ </ul>
+\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.
+\brief <ul>
+ <li>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].
+ </li>
+ <li>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].
+ </li>
+ <li>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].
+ </li>
+ <li>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].
+ </li>
+ </ul>
+\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 100644
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@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 100644
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@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@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 100644
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@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 100644
index 0000000..2a36011
--- /dev/null
+++ b/src/libgeoc/greiner.h
@@ -0,0 +1,855 @@
+/* -*- 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@gmail.com
+\date 14 de mayo de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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.
+\brief 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 \b*NO* serán considerados como separadores de múltiples polígonos,
+ por lo que en la estructura de salida se asumirá que se almacena un
+ polígono único cuyos vértices son los pasados sin tener en cuenta los
+ pares (#GEOC_NAN,#GEOC_NAN).
+\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.
+\brief 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[in] compruebaHuecosUnion Identificador para comprobar si alguno de los
+ polígonos generados en la operación #GeocOpBoolUnion es es realidad
+ un elemento que no pertenece a ninguno de los polígonos originales,
+ caso que puede darse en algunas situaciones con polígonos de trabajo
+ no convexos. Esta opción sólo es tenida en cuenta si \em op vale
+ #GeocOpBoolUnion Dos posibles valores:
+ - 0: No se comprueba.
+ - Distinto de 0: Sí se comprueba.
+\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. Cada
+ elemento del campo polig::atr puede tener dos posibles valores:
+ - 0: El polígono correspondiente es un agujero, luego no es un resultado
+ válido para la operación solicitada en \em op. Este valor sólo
+ puede darse si \em op vale #GeocOpBoolUnion y si se ha pasado un
+ valor de \em compruebaHuecosOr distinto de 0.
+ - 1: El polígono correspondiente es válido para la operación solicitada
+ en \em op.
+\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.
+\note Esta función asume que tanto \em poliBas como \em poliRec almacenan cada
+ una un polígono único.
+\note Los polígonos pueden tener autointersecciones.
+\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.
+\date 11 de mayo de 2011: Adición del atributo polig::atr y del argumento de
+ entrada \em compruebaHuecosUnion.
+\todo Esta función no está probada.
+*/
+polig* PoliBoolGreiner(vertPoliClip* poliBas,
+ vertPoliClip* poliRec,
+ const enum GEOC_OP_BOOL_POLIG op,
+ const double facPer,
+ const int compruebaHuecosUnion,
+ 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[in] compruebaHuecosUnion Identificador para comprobar si alguno de los
+ polígonos generados en la operación #GeocOpBoolUnion es es realidad
+ un elemento que no pertenece a ninguno de los polígonos originales,
+ caso que puede darse en algunas situaciones con polígonos de trabajo
+ no convexos. Esta opción sólo es tenida en cuenta si \em op vale
+ #GeocOpBoolUnion Dos posibles valores:
+ - 0: No se comprueba.
+ - Distinto de 0: Sí se comprueba.
+\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.
+\note Los polígonos pueden tener autointersecciones.
+\date 07 de junio de 2011: Creación de la función.
+\date 11 de mayo de 2011: Adición del atributo polig::atr y del argumento de
+ entrada \em compruebaHuecosUnion.
+\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,
+ const int compruebaHuecosUnion,
+ 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/mate.h b/src/libgeoc/mate.h
new file mode 100644
index 0000000..b546574
--- /dev/null
+++ b/src/libgeoc/mate.h
@@ -0,0 +1,482 @@
+/* -*- coding: utf-8 -*- */
+/**
+\defgroup mate Módulo MATEMATICAS
+\ingroup anespec gshhs legendre
+\brief En este módulo se reúnen las funciones necesarias para la realización de
+ cálculos matemáticos generales.
+@{
+\file mate.h
+\brief Declaración de funciones para la realización de cálculos matemáticos
+ generales.
+
+En el momento de la compilación de las funciones que dan el factorial de un
+número y el producto de una serie de números ha de seleccionarse el tipo de
+cálculo a utilizar (para números mayores que #GEOC_MATE_CONST_DBL_NMAXFAC y
+#GEOC_MATE_CONST_LDBL_NMAXFAC). Para realizar el cálculo es necesario definir la
+variable \em CALCULO_PRODUCTO_MULT si se quiere utilizar el producto o
+\em CALCULO_PRODUCTO_LOG si se quieren utilizar logaritmos. 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@gmail.com
+\date 17 de mayo de 2010
+\copyright
+Copyright (c) 2009-2014, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _MATE_H_
+#define _MATE_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<math.h>
+#include"libgeoc/constantes.h"
+#include"libgeoc/posmatvec.h"
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PROD_MULT
+\brief Identificador de cálculo de productos de series de números correlativos
+ por multiplicación directa.
+\date 30 de diciembre de 2010: Creación de la constante.
+*/
+#define GEOC_PROD_MULT 0
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PROD_LOG
+\brief Identificador de cálculo de productos de series de números correlativos
+ por logaritmos.
+\date 30 de diciembre de 2010: Creación de la constante.
+*/
+#define GEOC_PROD_LOG 1
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MATE_CONST_DBL_NMAXFAC
+\brief Número más alto para el que se almacena su factorial de manera explícita
+ para tipo de dato \p double.
+\date 03 de octubre de 2010: Creación de la constante.
+*/
+#define GEOC_MATE_CONST_DBL_NMAXFAC (170)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MATE_CONST_LDBL_NMAXFAC
+\brief Número más alto para el que se almacena su factorial de manera explícita
+ para tipo de dato \p long \p double.
+\date 03 de octubre de 2010: Creación de la constante.
+*/
+#define GEOC_MATE_CONST_LDBL_NMAXFAC (200)
+/******************************************************************************/
+/******************************************************************************/
+/** \struct __mateFactExpl
+\brief Estructura contenedora de valores explícitos de algunos factoriales.
+\brief Esta estructura se basa en la que se puede encontrar en el fichero
+ \p gamma.c, de la biblioteca GSL.
+\date 03 de octubre de 2010: Creación de la estructura.
+*/
+typedef struct
+{
+ /** \brief Número. */
+ size_t numero;
+ /** \brief Factorial del número almacenado en __mateFacExpl::numero. */
+ long double valor;
+}__mateFactExpl;
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Indica el tipo de cálculo del producto de una serie de números
+ correlativos.
+\return Dos posibles valores:
+ - #GEOC_PROD_MULT: Cálculo por multiplicación directa.
+ - #GEOC_PROD_LOG: Cálculo mediante logaritmos.
+\date 30 de diciembre de 2010: Creación de la función.
+*/
+int GeocTipoCalcProd(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la media de una serie de valores de tipo \p double.
+\param[in] datos Dirección de comienzo del vector que almacena los datos.
+\param[in] nDatos Número de datos que contiene el vector.
+\param[in] inc Posiciones de separación entre los elementos del vector de datos.
+ Si es un número negativo, el vector se recorre desde el final hasta
+ el principio.
+\return Valor medio de la serie de datos.
+\note Esta función asume que \em nDatos>0.
+\date 19 de noviembre de 2009: Creación de la función.
+*/
+double Media(const double* datos,
+ const size_t nDatos,
+ const int inc);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la varianza de una serie de valores de tipo \p double.
+\brief Esta función calcula la varianza mediante la fórmula
+ \f$
+ \sigma^2_x=\frac{\sum_{i=1}^{N}(x_i-\bar{x})^2}{N-1},
+ \f$
+ donde \f$N\f$ es el número de elementos de trabajo y \f$\bar{x}\f$ es la
+ media.
+\param[in] datos Dirección de comienzo del vector que almacena los datos.
+\param[in] nDatos Número de datos que contiene el vector.
+\param[in] inc Posiciones de separación entre los elementos del vector de datos.
+ Si es un número negativo, el vector se recorre desde el final hasta
+ el principio.
+\param[in] media Valor medio de la serie de datos.
+\note Esta función asume que \em nDatos>1.
+\return Varianza de la serie de datos.
+\date 09 de marzo de 2011: Creación de la función.
+*/
+double Varianza(const double* datos,
+ const size_t nDatos,
+ const int inc,
+ const double media);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la media ponderada de una serie de valores de tipo \p double.
+\param[in] datos Dirección de comienzo del vector que almacena los datos.
+\param[in] nDatos Número de datos que contienen los vectores \em datos y
+ \em pesos.
+\param[in] incDatos Posiciones de separación entre los elementos del vector
+ \em datos. Si es un número negativo, el vector se recorre desde el
+ final hasta el principio.
+\param[in] pesos Dirección de comienzo del vector que almacena los pesos.
+\param[in] incPesos Posiciones de separación entre los elementos del vector
+ \em pesos. Si es un número negativo, el vector se recorre desde el
+ final hasta el principio.
+\return Valor medio de la serie de datos.
+\note Esta función asume que \em nDatos>0.
+\date 23 de abril de 2010: Creación de la función.
+\todo Esta función no está probada.
+*/
+double MediaPonderada(const double* datos,
+ const size_t nDatos,
+ const int incDatos,
+ const double* pesos,
+ const int incPesos);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la mediana de una serie de valores de tipo \p double.
+\param[in] datos Dirección de comienzo del vector que almacena los datos, que ha
+ de estar ordenado (en orden ascendente o descendente, da igual).
+\param[in] nDatos Número de datos que contiene el vector.
+\param[in] inc Posiciones de separación entre los elementos del vector de datos.
+ Si es un número negativo, el vector se recorre desde el final hasta
+ el principio.
+\date 19 de noviembre de 2009: Creación de la función.
+*/
+double Mediana(const double* datos,
+ const size_t nDatos,
+ const int inc);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números mediante multiplicaciones.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie, calculado mediante
+ multiplicaciones.
+\date 03 de octubre de 2010: Creación de la función.
+*/
+double ProductoMult(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números mediante multiplicaciones.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie, calculado mediante
+ multiplicaciones.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double ProductoMultLD(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números mediante logaritmos.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie, calculado mediante
+ logaritmos.
+\date 03 de octubre de 2010: Creación de la función.
+*/
+double ProductoLog(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números mediante logaritmos.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie, calculado mediante
+ logaritmos.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double ProductoLogLD(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie.
+\date 03 de octubre de 2010: Creación de la función.
+*/
+double Producto(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto de una serie de números.
+\param[in] inicio Número inicial de la serie.
+\param[in] fin Número final de la serie.
+\return Producto acumulado de los números de la serie.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double ProductoLD(size_t inicio,
+ size_t fin);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número mediante productos.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\date 03 de octubre de 2010: Creación de la función.
+*/
+double FactorialMult(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número mediante productos.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double FactorialMultLD(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número como el antilogaritmo de la suma de
+ logaritmos.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\date 03 de octubre de 2010: Creación de la función.
+*/
+double FactorialLog(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número como el antilogaritmo de la suma de
+ logaritmos.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double FactorialLogLD(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\note Si el número es menor o igual que #GEOC_MATE_CONST_DBL_NMAXFAC, el
+ factorial se toma de un array donde están almacenados de manera explícita
+ los resultados. Si es mayor que #GEOC_MATE_CONST_DBL_NMAXFAC, el factorial
+ se calcula.
+\date 02 de marzo de 2009: Creación de la función.
+\date 03 de octubre de 2010: Reprogramación de la función como llamada a las
+ funciones \ref FactorialMult o \ref FactorialLog y cambio del tipo de dato
+ devuelto de \p size_t a \p double.
+*/
+double Factorial(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el factorial de un número.
+\param[in] numero Número.
+\return Factorial del número pasado.
+\note Si el número es menor o igual que #GEOC_MATE_CONST_LDBL_NMAXFAC, el
+ factorial se toma de un array donde están almacenados de manera explícita
+ los resultados. Si es mayor que #GEOC_MATE_CONST_LDBL_NMAXFAC, el
+ factorial se calcula.
+\note Los cálculos intermedios y el resultado se almacenan en datos de tipo
+ \p long \p double, para prevenir desbordamientos (el tipo de dato
+ \p double -8 bytes- sólo es capaz de almacenar los rangos -1.79769e308 a
+ -2.22507e-308 y 2.22507e-308 a 1.79769e308).
+\date 03 de octubre de 2010: Creación de la función.
+*/
+long double FactorialLD(size_t numero);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula el producto vectorial de dos vectores.
+\param[in] x1 Coordenada X del primer vector.
+\param[in] y1 Coordenada Y del primer vector.
+\param[in] z1 Coordenada Z del primer vector.
+\param[in] x2 Coordenada X del segundo vector.
+\param[in] y2 Coordenada Y del segundo vector.
+\param[in] z2 Coordenada Z del segundo vector.
+\param[out] x Coordenada X del vector producto vectorial de 1 y 2.
+\param[out] y Coordenada Y del vector producto vectorial de 1 y 2.
+\param[out] z Coordenada Z del vector producto vectorial de 1 y 2.
+\date 08 de agosto de 2013: Creación de la función.
+\todo Esta función no está probada.
+*/
+void ProductoVectorial(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2,
+ double* x,
+ double* y,
+ double* z);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula los senos y cosenos de una serie de ángulos equiespaciados.
+\brief Esta función utiliza en el cálculo las expresiones (ecuacies número 5.4.6
+ y 5.4.7, pág. 219) que se puede encontrar en:
+
+ William H. Press, Saul A. Teukolsky, William T. Vetterling y Brian P.
+ Flannery, 2007, Numerical recipes. The Art of Scientific Computing, 3a
+ edición. Cambridge University Press, ISBN: 978-0-521-88068-8.
+\param[in] anguloIni Ángulo inicial de la serie, en radianes.
+\param[in] incAngulo Incremento entre los valores algulares de la serie, en
+ radianes.
+\param[in] numValores Número de valores angulares de la serie, incluido
+ \em anguloIni.
+\param[out] seno Vector para almacenar el seno de los valores angulares de la
+ serie.
+\param[in] incSeno Posiciones de separación entre los elementos del vector de
+ salida \em seno. Este argumento siempre ha de ser un número positivo.
+\param[out] coseno Vector para almacenar el coseno de los valores angulares de
+ la serie.
+\param[in] incCoseno Posiciones de separación entre los elementos del vector de
+ salida \em coseno. Este argumento siempre ha de ser un número
+ positivo.
+\note Esta función no comprueba internamente si los vectores pasados contienen
+ suficiente memoria.
+\note Según pruebas realizadas, para una serie de 1000000 de elementos con
+ incremento angular de 50 grados, las diferencias con respecto a los senos
+ y cosenos calculados con las funciones de math.h están en el entorno de
+ 1e-10. Para incrementos de 1 grado, en el entorno de 1e-12.
+\date 27 de diciembre de 2014: Creación de la función.
+\todo Esta función no está probada.
+*/
+void SinCosRecurrencia(const double anguloIni,
+ const double incAngulo,
+ const size_t numValores,
+ double* seno,
+ const size_t incSeno,
+ double* coseno,
+ const size_t incCoseno);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Construye un \em spline cúbico natural para una serie de puntos e
+ interpola el valor de la función para una posición dada.
+\param[in] x Puntero a la dirección de memoria donde comienza el vector que
+ almacena las coordenadas X de los puntos dato.
+\param[in] y Puntero a la dirección de memoria donde comienza el vector que
+ almacena los valores de la función a interpolar, correspondientes a
+ cada posición del vector pasado en el argumento \em x.
+\param[in] nDatos Tamaño de los vectores \em x e \em y.
+\param[in,out] xInterp Puntero a la dirección de memoria donde comienza el
+ vector que almacena las coordenadas X de los puntos a interpolar.
+ Al término de la ejecución de la función, este argumento almacena
+ las coordenadas Y interpoladas.
+\param[in] nInterp Tamaño del vector \em xInterp.
+\note El código de esta función es una modificación de la versión que se puede
+ encontrar en:
+ http://koders.com/cpp/fid16BE3A5D46A7AC7BF84EECB1ADBF99B913A8F610.aspx
+\note El código original está acogido a la GNU Lesser General Public License
+ Version 2.1
+\note Esta función no controla internamente si los vectores \em x e \em y son
+ del tamaño especificado en \em nDatos.
+\note Esta función no controla internamente si el vector \em xInterp es del
+ tamaño especificado en \em nInterp.
+\note Esta función no controla internamente si las coordenadas X de los puntos a
+ interpolar están dentro o fuera de los límites de los puntos dato.
+\date 02 de marzo de 2009: Creación de la función.
+\todo Esta función todavía no está programada.
+*/
+void SplineCubicoNatural(double* x,
+ double* y,
+ size_t nDatos,
+ double* xInterp,
+ size_t nInterp);
+/******************************************************************************/
+/******************************************************************************/
+#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 100644
index 0000000..50f8812
--- /dev/null
+++ b/src/libgeoc/polig.h
@@ -0,0 +1,1215 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 20 de abril de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/arco.h"
+#include"libgeoc/constantes.h"
+#include"libgeoc/dpeucker.h"
+#include"libgeoc/dpeuckera.h"
+#include"libgeoc/errores.h"
+#include"libgeoc/fgeneral.h"
+#include"libgeoc/geocnan.h"
+#include"libgeoc/geocomp.h"
+#include"libgeoc/proyecaux.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.
+\date 10 de mayo de 2020: Adición del campo polig::atr.
+*/
+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;
+ /**
+ \brief Vector de polig::nPolig elementos, que almacena un atributo
+ cualquiera elegido por el usuario referido a cada polígono. Este
+ campo sólo sirve para posibles manejos del usuario en el empleo de
+ la estructura. Los elementos se inicializan con el valor 0.
+ */
+ int* atr;
+}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.
+\brief 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.
+\brief 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.
+\brief 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, pero sea cual sea la elección ha de ser la misma para
+ los dos vectores.
+\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.
+\param[in] facCoor Factor a aplicar a las coordenadas antes del cálculo de las
+ superficies. Si los cálculos se van a hacer sobre el elipsoide, este
+ argumento debe llevar las coordenadas a radianes, si no lo están.
+\param[in] geo Identificador de que el polígono está sobre la superficie del
+ elipsoide. Dos posibilidades:
+ - 0: El polígono está en el plano euclideo.
+ - Distinto de 0: El polígono está sobre la superficie del elipsoide.
+\param[in] a Semieje mayor del elipsoide. Este argumento sólo es tenido en
+ cuenta si se ha indicado trabajo sobre el elipsoide mediante el
+ argumento \em geo.
+\param[in] f Aplanamiento del elipsoide. Este argumento sólo es tenido en
+ cuenta si se ha indicado trabajo sobre el elipsoide mediante el
+ argumento \em geo.
+\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 El área calculada sólo es correcta si el polígono es simple, esto es, si
+ sus lados no se cortan entre ellos mismos (ver la documentación de
+ polig::area).
+\note Se asume que \em facCoor>0.0, condición que no se controla internamente.
+\note En caso de error de asignación de memoria, la memoria de la estructura de
+ entrada no se libera.
+\note El cálculo del área sobre el elipsoide se realiza proyectando los puntos
+ mediante una proyección cilíndrica equivalente de Lambert.
+\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.
+\date 16 de agosto de 2013: Adición de la capacidad de cálculo de áreas para
+ polígonos sobre la superficie del elipsoide.
+\date 17 de agosto de 2013: Modificación de la función para que el área se
+ calcule siempre, aunque la estructura ya la contenga. Se dota de esta
+ capacidad por si se llama repetidas veces a la función con valores
+ distintos de \em facCoor.
+\note Esta función todavía no está probada.
+*/
+int CalcAreaPolig(polig* poli,
+ const double facCoor,
+ const int geo,
+ const double a,
+ const double f);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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] esf Identificador de que el polígono está sobre la superficie de la
+ esfera. Dos posibilidades:
+ - 0: El polígono está en el plano euclideo.
+ - Distinto de 0: El polígono está sobre la esfera.
+\param[in] facCoor Factor de escala a aplicar a las coordenadas del polígono
+ para realizar el aligerado. Si se trabaja sobre la esfera, este
+ argumento ha de llevar las coordenadas de los puntos de trabajo a
+ radianes. Las coordenadas devueltas al término de la ejecución de
+ está función no se verán afectadas por este factor.
+\param[in] tol Tolerancia para eliminar vértices. Si se trabaja sobre la
+ superficie de la esfera, este valor ha de estar en radianes, es
+ decir, será una distancia sobre la superficie de la esfera de radio
+ unidad. Ver la ayuda de la función \ref AligeraPolilinea.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: Utiliza el algoritmo de Douglas-Peucker
+ original, que no es robusto.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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] nSegRobOrig Número de segmentos/arcos 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 segmentos/arcos hasta el final de la polilínea
+ original.
+\param[in] nSegRobAuto 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[in] a Semieje mayor del elipsoide. Este argumento sólo es tenido en
+ cuenta si se ha indicado trabajo sobre el elipsoide mediante el
+ argumento \em geo.
+\param[in] f Aplanamiento del elipsoide. Este argumento sólo es tenido en
+ cuenta si se ha indicado trabajo sobre el elipsoide mediante el
+ argumento \em geo.
+\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 Si \em poli está sobre la superficie de la esfera, el campo polig::x
+ almacenará la longitud, mientras que polig::y almacenará la latitud. Del
+ mismo modo, los límites polig::xMin y polig::xMax almacenarán longitudes y
+ polig::yMin y polig::yMax, latitudes.
+\note Se asume que \em facCoor>0.0, condición que no se controla internamente.
+\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.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\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.
+\date 25 de mayo de 2012: Adición de la posibilidad de usar el algoritmo de
+ Douglas-Peucker original.
+\date 16 de agosto de 2013: Adición de la capacidad de trabajar con polígonos en
+ la superficie de la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\date 21 de septiembre de 2013: Adición de la capacidad de trabajar sobre la
+ esfera con el algoritmo de Douglas-Peucker original.
+\todo Esta función todavía no está probada.
+*/
+int AligeraPolig(polig* poli,
+ const int esf,
+ const double facCoor,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const double a,
+ const double f);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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 caracteres 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 caracteres 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] impAtr Identificador para imprimir o no el atributo almacenado en
+ polig::atr. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formAtr Cadena de caracteres indicadora del formato para escribir el
+ valor del atributo. Este argumento sólo se usa internamente si se
+ ha indicado la impresión del atributo.
+\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 atributo</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 El área imprimida sólo es correcta si el polígono es simple, esto es, si
+ sus lados no se cortan entre ellos mismos (ver la documentación de
+ polig::area).
+\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.
+\date 10 de mayo de 2020: Adición de los argumentos \em impAtr y \em formAtr.
+\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 int impAtr,
+ const char formAtr[],
+ 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 caracteres 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 caracteres 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] impAtr Identificador para imprimir o no el atributo almacenado en
+ polig::atr. Dos posibles valores:
+ - 0: No se imprime.
+ - Distinto de 0: Sí se imprime.
+\param[in] formAtr Cadena de caracteres indicadora del formato para escribir el
+ valor del atributo. Este argumento sólo se usa internamente si se
+ ha indicado la impresión del atributo.
+\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 atributo</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 El área imprimida sólo es correcta si el polígono es simple, esto es, si
+ sus lados no se cortan entre ellos mismos (ver la documentación de
+ polig::area).
+\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.
+\date 10 de mayo de 2020: Adición de los argumentos \em impAtr y \em formAtr.
+\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[],
+ const int impAtr,
+ const char formAtr[],
+ 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 100644
index 0000000..8c9a73d
--- /dev/null
+++ b/src/libgeoc/polil.h
@@ -0,0 +1,836 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 03 de junio de 2011
+\copyright
+Copyright (c) 2011-2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/dpeuckera.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.
+\brief 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.
+\brief 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.
+\brief 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] esf Identificador de que la polilínea está sobre la superficie de la
+ esfera. Dos posibilidades:
+ - 0: La polilínea está en el plano euclideo.
+ - Distinto de 0: La polilínea está sobre la esfera.
+\param[in] facCoor Factor de escala a aplicar a las coordenadas de la polilínea
+ para realizar el aligerado. Si se trabaja sobre la esfera, este
+ argumento ha de llevar las coordenadas de los puntos de trabajo a
+ radianes. Las coordenadas devueltas al término de la ejecución de
+ está función no se verán afectadas por este factor.
+\param[in] tol Tolerancia para eliminar vértices. Si se trabaja sobre la
+ superficie de la esfera, este valor ha de estar en radianes, es
+ decir, será una distancia sobre la superficie de la esfera de radio
+ unidad. Ver la ayuda de la función \ref AligeraPolilinea.
+\param[in] paralelizaTol Identificador para evaluar o no en paralelo si los
+ puntos candidatos están en tolerancia. Dos posibilidades:
+ - 0: Se evalúa en serie (aunque la compilación se haya hecho en
+ paralelo) si los puntos están en tolerancia.
+ - Distinto de 0: Se evalúa en paralelo (sólo si se ha compilado en
+ paralelo) si los puntos están en tolerancia.
+\param[in] robusto Identificador para realizar o no un aligerado robusto. Ha de
+ ser un elemento del tipo enumerado #GEOC_DPEUCKER_ROBUSTO. Varias
+ posibilidades:
+ - #GeocDPeuckerOriginal: Utiliza el algoritmo de Douglas-Peucker
+ original, que no es robusto.
+ - #GeocDPeuckerRobNo: Utiliza la variación no recursiva del algoritmo
+ de Douglas-Peucker, que no es robusta.
+ - #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] nSegRobOrig Número de segmentos/arcos 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 segmentos/arcos hasta el final de la polilínea
+ original.
+\param[in] nSegRobAuto 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 Si \em poli está sobre la superficie de la esfera, el campo polil::x
+ almacenará la longitud, mientras que polil::y almacenará la latitud. Del
+ mismo modo, los límites polil::xMin y polil::xMax almacenarán longitudes y
+ polil::yMin y polil::yMax, latitudes.
+\note Se asume que \em facCoor>0.0, condición que no se controla internamente.
+\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. Al término de la ejecución de esta función, el resultado puede
+ ser una estructura \ref polil vacía.
+\note El argumento \em paralelizaTol \b SÓLO afecta a la paralelización de la
+ comprobación de puntos en tolerancia. Los chequeos de intersección de
+ segmentos/arcos siempre se hacen en paralelo (si el código ha sido
+ compilado al efecto).
+\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.
+\date 25 de mayo de 2012: Adición de la posibilidad de usar el algoritmo de
+ Douglas-Peucker original.
+\date 16 de agosto de 2013: Adición de la capacidad de trabajar con polilíneas
+ en la superficie de la esfera.
+\date 20 de agosto de 2013: Sustitución de las antiguas variables de entrada
+ \em nPtosRobusto y \em nSegRobusto por \em nSegRobOrig y \em nSegRobAuto.
+\date 23 de agosto de 2013: Adición del argumento de entrada \em paralelizaTol.
+\date 21 de septiembre de 2013: Adición de la capacidad de trabajar sobre la
+ esfera con el algoritmo de Douglas-Peucker original.
+\todo Esta función todavía no está probada.
+*/
+int AligeraPolil(polil* poli,
+ const int esf,
+ const double facCoor,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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 caracteres 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 caracteres 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/posmatvec.h b/src/libgeoc/posmatvec.h
new file mode 100644
index 0000000..126ffa8
--- /dev/null
+++ b/src/libgeoc/posmatvec.h
@@ -0,0 +1,512 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup algebra anespec geopot gshhs matriz mmcc snx
+@{
+\file posmatvec.h
+\brief Declaración de funciones para realizar cálculos de posiciones de
+ elementos en matrices almacenadas en formato vector.
+
+En el momento de la compilación de las funciones de cálculo de posición ha de
+seleccionarse el tipo de almacenamiento matricial. Para realizar la selección es
+necesario definir la variable \em ROW_MAJOR_ORDER_MATVEC si se quiere
+almacenamiento de tipo ROW MAJOR ORDER o \em COLUMN_MAJOR_ORDER_MATVEC si se
+quiere almacenamiento de tipo COLUMN MAJOR ORDER. En \p gcc, las variables para
+el preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
+introducir.
+
+Una matriz puede ser almacenada en formato vector de dos formas distintas: ROW
+MAJOR ORDER y COLUMN MAJOR ORDER. En la primera, la matriz es almacenada por
+filas, mientras que en la segunda lo es por columnas. Por ejemplo, la matriz
+\code
+m = [1 2 3 4
+ 5 6 7 8]
+\endcode
+será almacenada en ROW MAJOR ORDER como
+\code
+m = [1 2 3 4 5 6 7 8]
+\endcode
+y en COLUMN MAJOR ORDER como
+\code
+m = [1 5 2 6 3 7 4 8]
+\endcode
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 14 de enero de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2013, 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 _POSMATVEC_H_
+#define _POSMATVEC_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<stdlib.h>
+#include<string.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_LON_CAD_COD_ALM
+\brief Longitud máxima de una cadena para almacenar el código identificador de
+ tipo de almacenamiento matricial.
+\date 25 de septiembre de 2009: Creación de la constante.
+*/
+#define GEOC_LON_CAD_COD_ALM 25
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MATR_COD_ALM_RMO
+\brief Código identificador de almacenamiento como ROW MAJOR ORDER.
+\date 14 de enero de 2009: Creación de la constante.
+*/
+#define GEOC_MATR_COD_ALM_RMO "ROW-MAJOR-ORDER"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_MATR_COD_ALM_CMO
+\brief Código identificador de almacenamiento como COLUMN MAJOR ORDER.
+\date 14 de enero de 2009: Creación de la constante.
+*/
+#define GEOC_MATR_COD_ALM_CMO "COLUMN-MAJOR-ORDER"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_INICIO_VEC
+\brief Macro para seleccionar el índice correspondiente al primer elemento de un
+ vector dependiendo del valor de las posiciones de separación entre sus
+ elementos. El índice buscado será diferente de 0 cuando el valor de
+ posiciones de separación sea menor que 0.
+\param[in] n Número de elementos del vector. Ha de ser una variable de tipo
+ \p size_t.
+\param[in] inc Posiciones de separación entre los elementos del vector.
+\return Índice del primer elemento del vector.
+\note Esta macro ha sido copiada (sólo se le ha cambiado el nombre) del fichero
+ \em cblas.h del código fuente de la biblioteca \p gsl \p v.1.12, que se
+ distribuye bajo licencia GPL v.3 o posterior.
+\date 19 de noviembre de 2009: Creación de la macro.
+*/
+#define GEOC_INICIO_VEC(n,inc) ((inc) >= 0 ? 0 : ((n)-1)*(size_t)(-(inc)))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_LMFC_RMO
+\brief Devuelve las columnas almacenadas en memoria de una matriz.
+\param[in] filMem Filas de la matriz almacenada en memoria.
+\param[in] colMem Columnas de la matriz almacenada en memoria.
+\return Número de columnas almacenadas en memoria.
+\date 25 de noviembre de 2009: Creación de la macro.
+*/
+//se añade 0*filMem para que el compilador no dé warning por variable no usada
+#define GEOC_LMFC_RMO(filMem,colMem) ((colMem)+0*(filMem))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_LMFC_CMO
+\brief Devuelve las filas almacenadas en memoria de una matriz.
+\param[in] filMem Filas de la matriz almacenada en memoria.
+\param[in] colMem Columnas de la matriz almacenada en memoria.
+\return Número de filas almacenadas en memoria.
+\date 25 de noviembre de 2009: Creación de la macro.
+*/
+//se añade 0*colMem para que el compilador no dé warning por variable no usada
+#define GEOC_LMFC_CMO(filMem,colMem) ((filMem)+0*(colMem))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_RMO
+\brief Calcula la posición de un elemento de una matriz almacenada en ROW MAJOR
+ ORDER en el vector que la contiene.
+\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
+\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 25 de noviembre de 2009: Creación de la macro.
+\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
+ realmente almacenadas en memoria.
+*/
+//se añade 0*filMem para que el compilador no dé warning por variable no usada
+#define GEOC_POSMATVEC_RMO(filMem,colMem,fil,col) \
+((fil)*(colMem)+(col)+0*(filMem))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_CMO
+\brief Calcula la posición de un elemento de una matriz almacenada en COLUMN
+ MAJOR ORDER en el vector que la contiene.
+\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
+\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 25 de noviembre de 2009: Creación de la macro.
+\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
+ realmente almacenadas en memoria.
+*/
+//se añade 0*colMem para que el compilador no dé warning por variable no usada
+#define GEOC_POSMATVEC_CMO(filMem,colMem,fil,col) \
+((col)*(filMem)+(fil)+0*(colMem))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_TRIEM_INF_RMO
+\brief Calcula la posición de un elemento de una matriz triangular inferior
+ empaquetada en ROW MAJOR ORDER en el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 29 de enero de 2011: Creación de la macro.
+*/
+//se añade 0*dim para que el compilador no dé warning por variable no usada
+#define GEOC_POSMATVEC_TRIEM_INF_RMO(dim,fil,col) \
+((col)+(fil)*((fil)+1)/2+0*(dim))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_TRIEM_SUP_RMO
+\brief Calcula la posición de un elemento de una matriz triangular superior
+ empaquetada en ROW MAJOR ORDER en el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 29 de enero de 2011: Creación de la macro.
+*/
+#define GEOC_POSMATVEC_TRIEM_SUP_RMO(dim,fil,col) \
+((col)-(fil)+(fil)*(2*(dim)-(fil)+1)/2)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_TRIEM_INF_CMO
+\brief Calcula la posición de un elemento de una matriz triangular inferior
+ empaquetada en COLUMN MAJOR ORDER en el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 29 de enero de 2011: Creación de la macro.
+*/
+#define GEOC_POSMATVEC_TRIEM_INF_CMO(dim,fil,col) \
+((fil)-(col)+(col)*(2*(dim)-(col)+1)/2)
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_POSMATVEC_TRIEM_SUP_CMO
+\brief Calcula la posición de un elemento de una matriz triangular superior
+ empaquetada en COLUMN MAJOR ORDER en el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 29 de enero de 2011: Creación de la macro.
+*/
+//se añade 0*dim para que el compilador no dé warning por variable no usada
+#define GEOC_POSMATVEC_TRIEM_SUP_CMO(dim,fil,col) \
+((fil)+(col)*((col)+1)/2+0*(dim))
+/******************************************************************************/
+/******************************************************************************/
+/** \enum GEOC_MATR_ID_TRI
+\brief Indicador de parte de triangular de matriz.
+\date 26 de julio de 2009: Creación del tipo.
+*/
+enum GEOC_MATR_ID_TRI
+{
+ /** \brief Indicador de parte triangular superior. */
+ GeocMatTriSup=121,
+ /** \brief Indicador de parte triangular inferior. */
+ GeocMatTriInf=122
+};
+/******************************************************************************/
+/******************************************************************************/
+/** \enum GEOC_MATR_ID_DIAG
+\brief Indicador del contenido de la diagonal de una matriz triangular.
+\date 26 de septiembre de 2009: Creación del tipo.
+*/
+enum GEOC_MATR_ID_DIAG
+{
+ /** \brief Indicador de diagonal con algún elemento distinto de 1. */
+ GeocMatDiagNoUnos=131,
+ /** \brief Indicador de diagonal cuyos elementos son 1. */
+ GeocMatDiagUnos=132
+};
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si el tipo de almacenamiento utilizado es COLUMN-MAJOR-ORDER.
+\return Dos posibilidades:
+ - 0: El tipo de almacenamiento es ROW-MAJOR-ORDER.
+ - Distinto de 0: El tipo de almacenamiento es COLUMN-MAJOR-ORDER.
+\note El tipo de almacenamiento se selecciona en el momento de la compilación
+ mediante la definición de una de las siguientes variables:
+ \em ROW_MAJOR_ORDER_MATVEC (para un almacenamiento de tipo
+ ROW MAJOR ORDER) o \em COLUMN_MAJOR_ORDER_MATVEC (para un almacenamiento
+ de tipo COLUMN MAJOR ORDER). En \p gcc, las variables para el
+ preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
+ introducir.
+\date 29 de julio de 2013: Creación de la función.
+*/
+int EsAlmMatVecCMO(void);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Devuelve el código de almacenamiento utilizado.
+\param[out] tipo Cadena de texto identificadora del tipo de almacenamiento. Una
+ de las almacenadas en #GEOC_MATR_COD_ALM_RMO o
+ #GEOC_MATR_COD_ALM_CMO.
+\note El tipo de almacenamiento se selecciona en el momento de la compilación
+ mediante la definición de una de las siguientes variables:
+ \em ROW_MAJOR_ORDER_MATVEC (para un almacenamiento de tipo
+ ROW MAJOR ORDER) o \em COLUMN_MAJOR_ORDER_MATVEC (para un almacenamiento
+ de tipo COLUMN MAJOR ORDER). En \p gcc, las variables para el
+ preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
+ introducir.
+\date 14 de enero de 2009: Creación de la función.
+*/
+void TipoAlmMatVec(char tipo[]);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Devuelve la longitud de las filas o columnas almacenadas en memoria de
+ una matriz, según el tipo de almacenamiento utilizado.
+\param[in] filMem Filas de la matriz almacenada en memoria.
+\param[in] colMem Columnas de la matriz almacenada en memoria.
+\return Filas o columnas almacenadas en memoria. Si el tipo de almacenamiento es
+ \em ROW_MAJOR_ORDER_MATVEC se devuelve \em colMem, mientras que si es
+ \em COLUMN_MAJOR_ORDER_MATVEC se devuelve \em filMem.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\date 19 de noviembre de 2009: Creación de la función.
+\date 25 de noviembre de 2009: Cálculos internos mediante macros.
+\date 30 de enero de 2011: Añado el identificador \p const a los argumentos de
+ entrada.
+*/
+size_t Lmfc(const size_t filMem,
+ const size_t colMem);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Devuelve las posiciones entre cada elemento de una fila de una matriz
+ densa.
+\param[in] filMem Filas de la matriz realmente almacenadas en memoria.
+\return Posiciones entre cada elemento de las filas de la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\date 30 de enero de 2011: Creación de la función.
+*/
+size_t IncElemFil(const size_t filMem);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Devuelve las posiciones entre cada elemento de una columna de una matriz
+ densa.
+\param[in] colMem Columnas de la matriz realmente almacenadas en memoria.
+\return Posiciones entre cada elemento de las columnas de la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\date 30 de enero de 2011: Creación de la función.
+*/
+size_t IncElemCol(const size_t colMem);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz en el vector en el que
+ está almacenada.
+\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
+\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 14 de enero de 2009: Creación de la función.
+\date 25 de noviembre de 2009: Cálculos internos mediante macros.
+\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
+ realmente almacenadas en memoria.
+*/
+size_t PosMatVec(const size_t filMem,
+ const size_t colMem,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición en una matriz a partir de la posición en el vector en
+ que está almacenada.
+\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
+\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
+\param[in] posVec Posición en el vector.
+\param[out] fil Columna del elemento de trabajo.
+\param[out] col Columna del elemento de trabajo.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones de la matriz.
+\date 14 de enero de 2009: Creación de la función.
+\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
+ realmente almacenadas en memoria.
+*/
+void PosVecMat(const size_t filMem,
+ const size_t colMem,
+ const size_t posVec,
+ size_t* fil,
+ size_t* col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz general banda en el
+ vector en el que está almacenada.
+\param[in] diagInf Número de subdiagonales de la matriz.
+\param[in] diagSup Número de superdiagonales de la matriz.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones y la parte que contiene datos de la matriz.
+\date 21 de agosto de 2009: Creación de la función.
+*/
+size_t PosMatGenBanVec(const size_t diagInf,
+ const size_t diagSup,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz triangular empaquetada
+ en el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] supInf Identificador de matriz triangular superior o inferior. Ha de
+ ser un elemento perteneciente al tipo enumerado #GEOC_MATR_ID_TRI.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si el argumento \em supInf es correcto.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones y la parte triangular de la matriz.
+\date 26 de julio de 2009: Creación de la función.
+*/
+size_t PosMatTriEmVec(const size_t dim,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz triangular banda en el
+ vector en el que está almacenada.
+\param[in] diag Número de superdiagonales o subdiagonales de la matriz.
+\param[in] supInf Identificador de matriz triangular superior o inferior. Ha de
+ ser un elemento perteneciente al tipo enumerado #GEOC_MATR_ID_TRI.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si el argumento \em supInf es correcto.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones y la parte que contiene datos de la matriz.
+\date 27 de septiembre de 2009: Creación de la función.
+*/
+size_t PosMatTriBanVec(const size_t diag,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz simétrica empaquetada en
+ el vector en el que está almacenada.
+\param[in] dim Dimensiones de la matriz (filas==columnas).
+\param[in] supInf Identificador de la parte de matriz simétrica almacenada:
+ superior o inferior. Ha de ser un elemento perteneciente al tipo
+ enumerado #GEOC_MATR_ID_TRI.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si el argumento \em supInf es correcto.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones y la parte triangular de la matriz.
+\date 30 de enero de 2010: Creación de la función.
+*/
+size_t PosMatSimEmVec(const size_t dim,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la posición de un elemento de una matriz simétrica banda en el
+ vector en el que está almacenada.
+\param[in] diag Número de superdiagonales o subdiagonales de la matriz.
+\param[in] supInf Identificador de la parte de matriz simétrica almacenada:
+ superior o inferior. Ha de ser un elemento perteneciente al tipo
+ enumerado #GEOC_MATR_ID_TRI.
+\param[in] fil Fila del elemento de trabajo.
+\param[in] col Columna del elemento de trabajo.
+\return Posición del elemento de trabajo en el vector que almacena la matriz.
+\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
+\note Esta función no comprueba si el argumento \em supInf es correcto.
+\note Esta función no comprueba si la posición del elemento de trabajo concuerda
+ con las dimensiones y la parte que contiene datos de la matriz.
+\date 27 de septiembre de 2009: Creación de la función.
+*/
+size_t PosMatSimBanVec(const size_t diag,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col);
+/******************************************************************************/
+/******************************************************************************/
+#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/proyecaux.h b/src/libgeoc/proyecaux.h
new file mode 100644
index 0000000..85d00b8
--- /dev/null
+++ b/src/libgeoc/proyecaux.h
@@ -0,0 +1,90 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup gshhs geom proyec
+@{
+\file proyecaux.h
+\brief Declaración de funciones de algunas proyecciones cartográficas para no
+ usar PROJ.4.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 16 de agosto de 2013
+\copyright
+Copyright (c) 2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 _PROYECAUX_H_
+#define _PROYECAUX_H_
+/******************************************************************************/
+/******************************************************************************/
+#include<math.h>
+/******************************************************************************/
+/******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Proyecta un punto según la proyección cilíndrica equivalente de Lambert,
+ siendo el paralelo origen el ecuador.
+\param[in] lat Latitud geodésica del punto de trabajo, en radianes.
+\param[in] lon Longitud geodésica del punto de trabajo, en radianes.
+\param[in] lon0 Longitud geodésica origen, en radianes.
+\param[in] a Semieje mayor del elipsoide, en metros.
+\param[in] f Aplanamiento del elipsoide.
+\param[out] x Coordenada X proyectada.
+\param[out] y Coordenada Y proyectada.
+\note El incremento \em lon-lon0 no puede estar fuera del intervalo
+ \f$[-\pi,\pi]\f$.
+\date 22 de junio de 2011: Creación de la función.
+\date 15 de noviembre de 2013: Adición de la capacidad de cálculo con puntos
+ sobre la esfera.
+*/
+void ProjCilinEquivLambertLat0Ec(const double lat,
+ const double lon,
+ const double lon0,
+ const double a,
+ const double f,
+ 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/ptopol.h b/src/libgeoc/ptopol.h
new file mode 100644
index 0000000..a884db0
--- /dev/null
+++ b/src/libgeoc/ptopol.h
@@ -0,0 +1,1377 @@
+/* -*- 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 #GEOC_PTO_POLIG_LEJOS_32
+unidades. Con cálculos de 64 bits, los polígonos pueden estar alejados de los
+puntos de trabajo unas #GEOC_PTO_POLIG_LEJOS_64 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 05 de abril de 2010
+\copyright
+Copyright (c) 2010-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_POLIG_LEJOS_32
+\brief Número de unidades máximas que puede estar alejado un punto de un
+ polígono trabajando con variables reales de 32 bits para que los cálculos
+ de inclusión en polígonos de forma arbitraria seas correctos.
+\date 11 de mayo de 2020: Creación de la constante.
+*/
+#define GEOC_PTO_POLIG_LEJOS_32 40000
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_POLIG_LEJOS_64
+\brief Número de unidades máximas que puede estar alejado un punto de un
+ polígono trabajando con variables reales de 64 bits para que los cálculos
+ de inclusión en polígonos de forma arbitraria seas correctos.
+\date 11 de mayo de 2020: Creación de la constante.
+*/
+#define GEOC_PTO_POLIG_LEJOS_64 3000000000
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_PTO_POLIG_LEJOS_ESCALA_DIST
+\brief Factor de escala a aplicar a #GEOC_PTO_POLIG_LEJOS_32 o
+ #GEOC_PTO_POLIG_LEJOS_64 para calcular el factor de multiplicación para
+ el escalado de puntos y polígonos automáticaente.
+\date 11 de mayo de 2020: Creación de la constante.
+*/
+#define GEOC_PTO_POLIG_LEJOS_ESCALA_DIST 0.75
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_RECT_DISJUNTOS
+\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 09 de junio de 2012: Creación de la macro.
+\todo Esta macro no está probada.
+*/
+#define GEOC_RECT_DISJUNTOS(xMin1,xMax1,yMin1,yMax1,xMin2,xMax2,yMin2,yMax2) \
+(!(((xMin1)<=(xMax2))&&((xMax1)>=(xMin2))&& \
+((yMin1)<=(yMax2))&&((yMax1)>=(yMin2))))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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 un punto está contenido en un polígono o polígonos 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 de los polígonos.
+\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 (ver la nota al respecto).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Puede contener varios polígonos (ver la nota al respecto).
+\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 de los polígonos de trabajo
+ o pertenece a un hueco.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de alguno de los
+ polígonos de trabajo.
+\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 y se ha
+ sustituido el separador de polígonos O=(0,0) por
+ NaN=(#GEOC_NAN, #GEOC_NAN) que, a efectos de código, produce el mismo
+ resultado.
+\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, ni
+ si la definición de estos está hecha de manera correcta.
+\note Esta función no detecta el caso de que el punto de trabajo esté en el
+ borde o en un vértice de los polígonos. 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 o huecos de la siguiente manera:
+ -# Los vectores de vértices pasados pueden 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 una serie de puntos están contenidos en un polígono o
+ polígonos 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 de los
+ polígonos.
+\param[in] x Vector que contiene las coordenadas X de los puntos de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los puntos de trabajo.
+\param[in] nPtos 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[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incCoorX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incCoorY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[out] situacion Vector de \em nPtos elementos que almacena la situación
+ de los puntos con respecto a los polígonos de trabajo. Cada posición
+ del vector se refiere a un punto de trabajo y puede almacenar dos
+ valores:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de los polígonos de
+ trabajo o pertenece a un hueco.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de alguno de los
+ polígonos de trabajo.
+\param[in] incSituacion Posiciones de separación entre los elementos del vector
+ \em situacion. Este argumento siempre ha de ser un número positivo.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función utiliza internamente la función \ref PtoEnPoligono, por lo
+ que todos sus casos especiales lo serán también de la nueva función.
+\note Esta función no comprueba si el número de elementos de los vectores \em X,
+ \em Y y \em situacion es congruente con los valores padados en \em nPtos,
+ \em incX, \em incY e \em incSituacion. Tampoco 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, ni si la definición de estos está hecha de manera
+ correcta.
+\date 22 de enero de 2015: Creación de la función.
+\todo Esta función no está probada.
+*/
+void PtosEnPoligono(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Comprueba si un punto está contenido o es un vértice de un polígono o
+ polígonos 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. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\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 Tres posibilidades:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de los polígonos de trabajo
+ o pertenece a un hueco.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de alguno de los
+ polígonos de trabajo.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice de alguno de los
+ polígonos de trabajo o de un hueco.
+\note Esta función utiliza internamente la función \ref PtoEnPoligono, por lo
+ que todos sus casos especiales lo serán también de la nueva función.
+\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.
+\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.
+\date 22 de enero de 2015: Los vectores de definición de polígonos pueden ahora
+ contener varios elementos y huecos.
+\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 una serie de puntos están contenidos o son un vértice en un
+ polígono o polígonos de un número arbitrario de lados. Esta función puede
+ no dar resultados correctos para puntos en los bordes de los polígonos.
+\param[in] x Vector que contiene las coordenadas X de los puntos de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los puntos de trabajo.
+\param[in] nPtos 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[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. Puede contener varios polígonos (en el mismo formato que el
+ argumento correspondiente de la función \ref PtoEnPoligono).
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incCoorX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incCoorY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[out] situacion Vector de \em nPtos elementos que almacena la situación
+ de los puntos con respecto a los polígonos de trabajo. Cada posición
+ del vector se refiere a un punto de trabajo y puede almacenar tres
+ valores:
+ - #GEOC_PTO_FUERA_POLIG: El punto está fuera de los polígonos de
+ trabajo o pertenece a un hueco.
+ - #GEOC_PTO_DENTRO_POLIG: El punto está dentro de alguno de los
+ polígonos de trabajo.
+ - #GEOC_PTO_VERTICE_POLIG: El punto es un vértice de alguno de los
+ polígonos de trabajo o de un hueco.
+\param[in] incSituacion Posiciones de separación entre los elementos del vector
+ \em situacion. Este argumento siempre ha de ser un número positivo.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\note Esta función utiliza internamente la función \ref PtoEnPoligonoVertice,
+ por lo que todos sus casos especiales lo serán también de la nueva
+ función.
+\note Esta función no comprueba si el número de elementos de los vectores \em X,
+ \em Y y \em situacion es congruente con los valores padados en \em nPtos,
+ \em incX, \em incY e \em incSituacion. Tampoco 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, ni si la definición de estos está hecha de manera
+ correcta.
+\date 22 de enero de 2015: Creación de la función.
+\todo Esta función no está probada.
+*/
+void PtosEnPoligonoVertice(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits, los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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 una serie de puntos están contenidos 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 Vector que contiene las coordenadas X de los puntos de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los puntos de trabajo.
+\param[in] nPtos 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[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. <b> Sólo puede contener un polígono. </b>
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. <b> Sólo puede contener un polígono. </b>
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incCoorX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incCoorY Posiciones de separación entre los elementos del vector
+ \em coorY. Este argumento siempre ha de ser un número positivo.
+\param[out] situacion Vector de \em nPtos elementos que almacena la situación
+ de los puntos con respecto al polígono de trabajo. Cada posición del
+ vector se refiere a un punto de trabajo y puede almacenar cuatro
+ valores:
+ - #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.
+\param[in] incSituacion Posiciones de separación entre los elementos del vector
+ \em situacion. Este argumento siempre ha de ser un número positivo.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\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 utiliza internamente la función
+ \ref PtoEnPoligonoVerticeBorde, por lo que todos sus casos especiales lo
+ serán también de la nueva función.
+\note Esta función no comprueba si el número de elementos de los vectores \em X,
+ \em Y y \em situacion es congruente con los valores padados en \em nPtos,
+ \em incX, \em incY e \em incSituacion. Tampoco 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, ni si la definición de éste está hecha de manera
+ correcta.
+\note <b>El polígono de trabajo ha de ser único, sin huecos. Es opcional repetir
+ las coordenadas del primer punto al final del listado.</b>
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits, los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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 22 de enero de 2015: Creación de la función.
+*/
+void PtosEnPoligonoVerticeBorde(const long* x,
+ const long* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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. Si se pasa el valor \p 0 el factor de
+ escala se calcula automáticamente, lo que puede hacer a la función un
+ poco más lenta.
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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. El cálculo automático del factor de escala
+ si se pasa el valor \p 0 a \em factor se realiza de tal modo que la
+ distancia entre el punto de trabajo y el vértice más alejado del polígono
+ se ajuste lo más posible a los límites indicados para cada tipo de
+ variable multiplicados por #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST (se hace para
+ ser conservador y asegurar, por eso el valor de
+ #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST es recomendable que sea menor que 1).
+\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.
+\date 11 de mayo de 2020:Adición de la capacidad de cálculo automático del
+ factor de multiplicación.
+\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 Comprueba si una serie de puntos están contenidos 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 Vector que contiene las coordenadas X de los puntos de trabajo.
+\param[in] y Vector que contiene las coordenadas Y de los puntos de trabajo.
+\param[in] nPtos 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[in] coorX Vector que contiene las coordenadas X de los vértices del
+ polígono. <b> Sólo puede contener un polígono. </b>
+\param[in] coorY Vector que contiene las coordenadas Y de los vértices del
+ polígono. <b> Sólo puede contener un polígono. </b>
+\param[in] N Número de elementos que contienen los vectores \em coorX y
+ \em coorY.
+\param[in] incCoorX Posiciones de separación entre los elementos del vector
+ \em coorX. Este argumento siempre ha de ser un número positivo.
+\param[in] incCoorY 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 de los
+ puntos 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. Si se pasa el valor \p 0 el factor de
+ escala se calcula automáticamente, lo que puede hacer a la función un
+ poco más lenta.
+\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[out] situacion Vector de \em nPtos elementos que almacena la situación
+ de los puntos con respecto al polígono de trabajo. Cada posición del
+ vector se refiere a un punto de trabajo y puede almacenar cuatro
+ valores:
+ - #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.
+\param[in] incSituacion Posiciones de separación entre los elementos del vector
+ \em situacion. Este argumento siempre ha de ser un número positivo.
+\note Esta función se puede ejecutar en paralelo con OpenMP.
+\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 utiliza internamente la función
+ \ref PtoEnPoligonoVerticeBordeDouble, por lo que todos sus casos
+ especiales lo serán también de la nueva función.
+\note Esta función no comprueba si el número de elementos de los vectores \em X,
+ \em Y y \em situacion es congruente con los valores padados en \em nPtos,
+ \em incX, \em incY e \em incSituacion. Tampoco 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, ni si la definición de éste está hecha de manera
+ correcta.
+\note <b>El polígono de trabajo ha de ser único, sin huecos. Es opcional repetir
+ las coordenadas del primer punto al final del listado.</b>
+\note Los vértices del polígono pueden listarse en sentido dextrógiro o
+ levógiro.
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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. El cálculo automático del factor de escala
+ si se pasa el valor \p 0 a \em factor se realiza de tal modo que la
+ distancia entre el punto de trabajo y el vértice más alejado del polígono
+ se ajuste lo más posible a los límites indicados para cada tipo de
+ variable multiplicados por #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST (se hace para
+ ser conservador y asegurar, por eso el valor de
+ #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST es recomendable que sea menor que 1).
+\date 22 de enero de 2015: Creación de la función.
+\date 11 de mayo de 2020:Adición de la capacidad de cálculo automático del
+ factor de multiplicación.
+*/
+void PtosEnPoligonoVerticeBordeDouble(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ const double factor,
+ const int redondeo,
+ int* situacion,
+ const size_t incSituacion);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits, los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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. Si se pasa el valor \p 0 el factor de
+ escala se calcula automáticamente, lo que puede hacer a la función un
+ poco más lenta.
+\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
+ #GEOC_PTO_POLIG_LEJOS_32 unidades. Con cálculos de 64 bits los polígonos
+ pueden estar alejados de los puntos de trabajo unas
+ #GEOC_PTO_POLIG_LEJOS_64 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. El cálculo automático del factor de escala
+ si se pasa el valor \p 0 a \em factor se realiza de tal modo que la
+ distancia entre el punto de trabajo y el vértice más alejado del polígono
+ se ajuste lo más posible a los límites indicados para cada tipo de
+ variable multiplicados por #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST (se hace para
+ ser conservador y asegurar, por eso el valor de
+ #GEOC_PTO_POLIG_LEJOS_ESCALA_DIST es recomendable que sea menor que 1).
+\date 14 de abril de 2011: Creación de la función.
+\date 11 de mayo de 2020:Adición de la capacidad de cálculo automático del
+ factor de multiplicació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);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Genera un punto en el interior de un polígono simple (sin huecos).
+\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 interno para aplicar a las
+ coordenadas de puntos y vértices en el chequeo de inclusión de punto
+ en polígono. Ver la ayuda de la función
+ \ref PtoEnPoligonoVerticeBordeDouble para más informació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.
+ Ver la ayuda de la función \ref PtoEnPoligonoVerticeBordeDouble para
+ más información.
+\param[out] x Coordenada X de un punto situado estrictamente en el interior (no
+ en un vértice o borde) del polígono de trabajo. Si ha ocurrido algún
+ error o no se han podido determinar coordenadas contiene #GEOC_NAN.
+\param[out] y Coordenada Y de un punto situado estrictamente en el interior (no
+ en un vértice o borde) del polígono de trabajo. Si ha ocurrido algún
+ error o no se han podido determinar coordenadas contiene #GEOC_NAN.
+\note El polígono ha de ser único, sin huecos. Es opcional repetir las
+ coordenadas del primer punto al final del listado
+\note Esta función asume que el polígono está correctamente definido (que tiene
+ los vértices suficientes para considerarse tal) Puede tener
+ autointersecciones.
+\note El punto generado \b*NO* es aleatorio, sino que se busca a partir de la
+ generación de triángulos con los vértices del polígono. Queda garantizado
+ que ejecuciones con los mismos parámetros producirán siempre idéntico
+ resultado.
+\note Los vértices del polígono pueden listarse en sentido dextrógiro o
+ levógiro.
+\date 11 de mayo de 2020: Creación de la función.
+\todo Esta función no está probada.
+*/
+void GeneraPtoEnPoligono(const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo,
+ 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/recpolil.h b/src/libgeoc/recpolil.h
new file mode 100644
index 0000000..188f934
--- /dev/null
+++ b/src/libgeoc/recpolil.h
@@ -0,0 +1,440 @@
+/* -*- 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@gmail.com
+\date 04 de junio de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 \b*NO* serán considerados como separadores de múltiples polilíneas,
+ por lo que en la estructura de salida se asumirá que se almacena una
+ polilínea única cuyos vértices son los pasados sin tener en cuenta los
+ pares (#GEOC_NAN,#GEOC_NAN).
+\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.
+\brief 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.
+\note Esta función asume que tanto \em poli como \em poliRec almacenan cada una
+ un elemento único (polilínea y polígono respectivamente).
+\note La polilínea y el polígono pueden tener autointersecciones.
+\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.
+\note Las polilíneas y los polígonos pueden tener autointersecciones.
+\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 100644
index 0000000..7ec3dab
--- /dev/null
+++ b/src/libgeoc/segmento.h
@@ -0,0 +1,377 @@
+/* -*- 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@gmail.com
+\date 22 de abril de 2011
+\copyright
+Copyright (c) 2011-2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 (excluidos los extremos de este
+ 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_EXTREMOS_NO_COLIN
+\brief Identificador de que dos segmentos tienen un extremo común, pero no son
+ colineales.
+\date 10 de agosto de 2013: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN 3
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_EXTREMOS_COLIN
+\brief Identificador de que dos segmentos tienen un solo extremo común y son
+ colineales.
+\date 14 de mayo de 2011: Creación de la constante.
+\date 10 de agosto de 2013: Cambio de nombre de la constante.
+*/
+#define GEOC_SEG_INTERSEC_EXTREMOS_COLIN 4
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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 5
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def GEOC_SEG_INTERSEC_COLIN
+\brief Identificador de que dos segmentos tienen más de un punto en común, es
+ decir, se solapan, pero no son el mismo segmento.
+\date 14 de mayo de 2011: Creación de la constante.
+*/
+#define GEOC_SEG_INTERSEC_COLIN 6
+/******************************************************************************/
+/******************************************************************************/
+/**
+\def POS_PTO_RECTA_2D
+\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 macro 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 Para evitar errores por desbordamiento, es conveniente utilizar esta macro
+ con las coordenadas de los argumentos de entrada reducidas al centroide.
+\note El código de esta macro 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.
+\date 10 de agosto de 2013: Conversión de la antigua función en esta macro.
+*/
+#define POS_PTO_RECTA_2D(x,y,xIni,yIni,xFin,yFin) \
+(((xIni)-(x))*((yFin)-(y))-((xFin)-(x))*((yIni)-(y)))
+/******************************************************************************/
+/******************************************************************************/
+/**
+\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 macro \ref POS_PTO_RECTA_2D, que no
+ es robusta. En consecuencia, los resultados de esta función tampoco lo
+ son.
+\note Esta función sirve de apoyo para \ref PtoComunSegmParalelos2D.
+\note Para evitar errores por desbordamiento, es conveniente utilizar esta
+ función con las coordenadas de los argumentos de entrada reducidas al
+ centroide.
+\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 son
+ 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_EXTREMOS_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.
+\note Para evitar errores por desbordamiento, es conveniente utilizar esta
+ función con las coordenadas de los argumentos de entrada reducidas al
+ centroide.
+\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_EXTREMOS_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 Siete 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 en un punto (excluidos los extremos del segungo), pero
+ los segmentos no son colineales.
+ - #GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN: Los segmentos tienen un extremo
+ común, pero no son colineales.
+ - #GEOC_SEG_INTERSEC_EXTREMOS_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.
+\note Si los segmentos no se tocan, los valores devueltos en \em x e \em y no
+ tienen sentido.
+\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.
+\date 10 de agosto de 2013: Adición de un nuevo valor de salida:
+ #GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN.
+*/
+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);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Calcula la intersección, de manera simplificada, 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.
+\return Dos posibilidades:
+ - #GEOC_SEG_NO_INTERSEC: No hay intersección, los segmentos no tienen
+ ningún punto en común.
+ - #GEOC_SEG_INTERSEC: Los segmentos se cortan; tienen, al menos, un
+ punto en común.
+\note Esta función utiliza internamente la macro \ref POS_PTO_RECTA_2D y la
+ función \ref PuntoEntreDosPuntos2DColin, las cuales no son robustas. En
+ consecuencia, los resultados de esta función tampoco lo son.
+\note Para casos de intersección limpia, esta función es, como término medio, un
+ 20% más rápida que \ref IntersecSegmentos2D. El hardware en el que se han
+ hecho las pruebas es Intel Pentium M 1.3 GHz.
+\date 10 de agosto de 2013: Creación de la función.
+*/
+int IntersecSegmentos2DSimple(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD);
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Convierte el valor de salida de la función \ref IntersecSegmentos2D en el
+ equivalente de la función \ref IntersecSegmentos2DSimple.
+\param[in] cod2D Código de salida de la función \ref IntersecSegmentos2D.
+\return Código de salida equivalente de la función
+ \ref IntersecSegmentos2DSimple. Las equivalencias son:
+ - #GEOC_SEG_NO_INTERSEC -> #GEOC_SEG_NO_INTERSEC.
+ - #GEOC_SEG_INTERSEC -> #GEOC_SEG_INTERSEC.
+ - #GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN -> #GEOC_SEG_INTERSEC.
+ - #GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN -> #GEOC_SEG_INTERSEC.
+ - #GEOC_SEG_INTERSEC_EXTREMOS_COLIN -> #GEOC_SEG_INTERSEC.
+ - #GEOC_SEG_INTERSEC_MISMO_SEG -> #GEOC_SEG_INTERSEC.
+ - #GEOC_SEG_INTERSEC_COLIN -> #GEOC_SEG_INTERSEC.
+ - Otro valor cualquiera -> #GEOC_SEG_NO_INTERSEC.
+\date 10 de agosto de 2013: Creación de la función.
+*/
+int CodIntSeg2DCodIntSeg2DSimple(const int cod2D);
+/******************************************************************************/
+/******************************************************************************/
+#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 100644
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@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/mate.c b/src/mate.c
new file mode 100644
index 0000000..a87f82f
--- /dev/null
+++ b/src/mate.c
@@ -0,0 +1,813 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup anespec gshhs mate legendre
+@{
+\file mate.c
+\brief Definición de funciones para la realización de cálculos matemáticos
+ generales.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 17 de mayo de 2010
+\copyright
+Copyright (c) 2009-2016, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/mate.h"
+/******************************************************************************/
+/******************************************************************************/
+/**
+\brief Array que almacena de manera explícita los factoriales de los números que
+ van de \em 0 a #GEOC_MATE_CONST_LDBL_NMAXFAC.
+
+ Este array se basa en el array \p fact_table, que se puede encontrar en
+ el fichero \p gamma.c, de la biblioteca GSL.
+*/
+static __mateFactExpl __tablaFacExpl[GEOC_MATE_CONST_LDBL_NMAXFAC+1]=
+{
+ { 0, 1.0 },
+ { 1, 1.0 },
+ { 2, 2.0 },
+ { 3, 6.0 },
+ { 4, 24.0 },
+ { 5, 120.0 },
+ { 6, 720.0 },
+ { 7, 5040.0 },
+ { 8, 40320.0 },
+ { 9, 362880.0 },
+ { 10, 3628800.0 },
+ { 11, 39916800.0 },
+ { 12, 479001600.0 },
+ { 13, 6227020800.0 },
+ { 14, 87178291200.0 },
+ { 15, 1307674368000.0 },
+ { 16, 20922789888000.0 },
+ { 17, 355687428096000.0 },
+ { 18, 6402373705728000.0 },
+ { 19, 121645100408832000.0 },
+ { 20, 2432902008176640000.0 },
+ { 21, 51090942171709440000.0 },
+ { 22, 1124000727777607680000.0 },
+ { 23, 25852016738884976640000.0 },
+ { 24, 620448401733239439360000.0 },
+ { 25, 15511210043330985984000000.0 },
+ { 26, 403291461126605635584000000.0 },
+ { 27, 10888869450418352160768000000.0 },
+ { 28, 304888344611713860501504000000.0 },
+ { 29, 8841761993739701954543616000000.0 },
+ { 30, 265252859812191058636308480000000.0 },
+ { 31, 8222838654177922817725562880000000.0 },
+ { 32, 263130836933693530167218012160000000.0 },
+ { 33, 8683317618811886495518194401280000000.0 },
+ { 34, 2.95232799039604140847618609644e38 },
+ { 35, 1.03331479663861449296666513375e40 },
+ { 36, 3.71993326789901217467999448151e41 },
+ { 37, 1.37637530912263450463159795816e43 },
+ { 38, 5.23022617466601111760007224100e44 },
+ { 39, 2.03978820811974433586402817399e46 },
+ { 40, 8.15915283247897734345611269600e47 },
+ { 41, 3.34525266131638071081700620534e49 },
+ { 42, 1.40500611775287989854314260624e51 },
+ { 43, 6.04152630633738356373551320685e52 },
+ { 44, 2.65827157478844876804362581101e54 },
+ { 45, 1.19622220865480194561963161496e56 },
+ { 46, 5.50262215981208894985030542880e57 },
+ { 47, 2.58623241511168180642964355154e59 },
+ { 48, 1.24139155925360726708622890474e61 },
+ { 49, 6.08281864034267560872252163321e62 },
+ { 50, 3.04140932017133780436126081661e64 },
+ { 51, 1.55111875328738228022424301647e66 },
+ { 52, 8.06581751709438785716606368564e67 },
+ { 53, 4.27488328406002556429801375339e69 },
+ { 54, 2.30843697339241380472092742683e71 },
+ { 55, 1.26964033536582759259651008476e73 },
+ { 56, 7.10998587804863451854045647464e74 },
+ { 57, 4.05269195048772167556806019054e76 },
+ { 58, 2.35056133128287857182947491052e78 },
+ { 59, 1.38683118545689835737939019720e80 },
+ { 60, 8.32098711274139014427634118320e81 },
+ { 61, 5.07580213877224798800856812177e83 },
+ { 62, 3.14699732603879375256531223550e85 },
+ { 63, 1.982608315404440064116146708360e87 },
+ { 64, 1.268869321858841641034333893350e89 },
+ { 65, 8.247650592082470666723170306800e90 },
+ { 66, 5.443449390774430640037292402480e92 },
+ { 67, 3.647111091818868528824985909660e94 },
+ { 68, 2.480035542436830599600990418570e96 },
+ { 69, 1.711224524281413113724683388810e98 },
+ { 70, 1.197857166996989179607278372170e100 },
+ { 71, 8.504785885678623175211676442400e101 },
+ { 72, 6.123445837688608686152407038530e103 },
+ { 73, 4.470115461512684340891257138130e105 },
+ { 74, 3.307885441519386412259530282210e107 },
+ { 75, 2.480914081139539809194647711660e109 },
+ { 76, 1.885494701666050254987932260860e111 },
+ { 77, 1.451830920282858696340707840860e113 },
+ { 78, 1.132428117820629783145752115870e115 },
+ { 79, 8.946182130782975286851441715400e116 },
+ { 80, 7.156945704626380229481153372320e118 },
+ { 81, 5.797126020747367985879734231580e120 },
+ { 82, 4.753643337012841748421382069890e122 },
+ { 83, 3.945523969720658651189747118010e124 },
+ { 84, 3.314240134565353266999387579130e126 },
+ { 85, 2.817104114380550276949479442260e128 },
+ { 86, 2.422709538367273238176552320340e130 },
+ { 87, 2.107757298379527717213600518700e132 },
+ { 88, 1.854826422573984391147968456460e134 },
+ { 89, 1.650795516090846108121691926250e136 },
+ { 90, 1.485715964481761497309522733620e138 },
+ { 91, 1.352001527678402962551665687590e140 },
+ { 92, 1.243841405464130725547532432590e142 },
+ { 93, 1.156772507081641574759205162310e144 },
+ { 94, 1.087366156656743080273652852570e146 },
+ { 95, 1.032997848823905926259970209940e148 },
+ { 96, 9.916779348709496892095714015400e149 },
+ { 97, 9.619275968248211985332842594960e151 },
+ { 98, 9.426890448883247745626185743100e153 },
+ { 99, 9.332621544394415268169923885600e155 },
+ { 100,9.33262154439441526816992388563e157 },
+ { 101,9.42594775983835942085162312450e159 },
+ { 102,9.61446671503512660926865558700e161 },
+ { 103,9.90290071648618040754671525458e163 },
+ { 104,1.02990167451456276238485838648e166 },
+ { 105,1.08139675824029090050410130580e168 },
+ { 106,1.146280563734708354534347384148e170 },
+ { 107,1.226520203196137939351751701040e172 },
+ { 108,1.324641819451828974499891837120e174 },
+ { 109,1.443859583202493582204882102460e176 },
+ { 110,1.588245541522742940425370312710e178 },
+ { 111,1.762952551090244663872161047110e180 },
+ { 112,1.974506857221074023536820372760e182 },
+ { 113,2.231192748659813646596607021220e184 },
+ { 114,2.543559733472187557120132004190e186 },
+ { 115,2.925093693493015690688151804820e188 },
+ { 116,3.393108684451898201198256093590e190 },
+ { 117,3.96993716080872089540195962950e192 },
+ { 118,4.68452584975429065657431236281e194 },
+ { 119,5.57458576120760588132343171174e196 },
+ { 120,6.68950291344912705758811805409e198 },
+ { 121,8.09429852527344373968162284545e200 },
+ { 122,9.87504420083360136241157987140e202 },
+ { 123,1.21463043670253296757662432419e205 },
+ { 124,1.50614174151114087979501416199e207 },
+ { 125,1.88267717688892609974376770249e209 },
+ { 126,2.37217324288004688567714730514e211 },
+ { 127,3.01266001845765954480997707753e213 },
+ { 128,3.85620482362580421735677065923e215 },
+ { 129,4.97450422247728744039023415041e217 },
+ { 130,6.46685548922047367250730439554e219 },
+ { 131,8.47158069087882051098456875820e221 },
+ { 132,1.11824865119600430744996307608e224 },
+ { 133,1.48727070609068572890845089118e226 },
+ { 134,1.99294274616151887673732419418e228 },
+ { 135,2.69047270731805048359538766215e230 },
+ { 136,3.65904288195254865768972722052e232 },
+ { 137,5.01288874827499166103492629211e234 },
+ { 138,6.91778647261948849222819828311e236 },
+ { 139,9.61572319694108900419719561353e238 },
+ { 140,1.34620124757175246058760738589e241 },
+ { 141,1.89814375907617096942852641411e243 },
+ { 142,2.69536413788816277658850750804e245 },
+ { 143,3.85437071718007277052156573649e247 },
+ { 144,5.55029383273930478955105466055e249 },
+ { 145,8.04792605747199194484902925780e251 },
+ { 146,1.17499720439091082394795827164e254 },
+ { 147,1.72724589045463891120349865931e256 },
+ { 148,2.55632391787286558858117801578e258 },
+ { 149,3.80892263763056972698595524351e260 },
+ { 150,5.71338395644585459047893286526e262 },
+ { 151,8.62720977423324043162318862650e264 },
+ { 152,1.31133588568345254560672467123e267 },
+ { 153,2.00634390509568239477828874699e269 },
+ { 154,3.08976961384735088795856467036e271 },
+ { 155,4.78914290146339387633577523906e273 },
+ { 156,7.47106292628289444708380937294e275 },
+ { 157,1.17295687942641442819215807155e278 },
+ { 158,1.85327186949373479654360975305e280 },
+ { 159,2.94670227249503832650433950735e282 },
+ { 160,4.71472363599206132240694321176e284 },
+ { 161,7.59070505394721872907517857094e286 },
+ { 162,1.22969421873944943411017892849e289 },
+ { 163,2.00440157654530257759959165344e291 },
+ { 164,3.28721858553429622726333031164e293 },
+ { 165,5.42391066613158877498449501421e295 },
+ { 166,9.00369170577843736647426172359e297 },
+ { 167,1.50361651486499904020120170784e300 },
+ { 168,2.52607574497319838753801886917e302 },
+ { 169,4.26906800900470527493925188890e304 },
+ { 170,7.25741561530799896739672821113e306 },
+ { 171,1.24101807021766782342484052410e309L },
+ { 172,2.13455108077438865629072570146e311L },
+ { 173,3.69277336973969237538295546352e313L },
+ { 174,6.42542566334706473316634250653e315L },
+ { 175,1.12444949108573632830410993864e318L },
+ { 176,1.97903110431089593781523349201e320L },
+ { 177,3.50288505463028580993296328086e322L },
+ { 178,6.23513539724190874168067463993e324L },
+ { 179,1.11608923610630166476084076055e327L },
+ { 180,2.00896062499134299656951336898e329L },
+ { 181,3.63621873123433082379081919786e331L },
+ { 182,6.61791809084648209929929094011e333L },
+ { 183,1.21107901062490622417177024204e336L },
+ { 184,2.22838537954982745247605724535e338L },
+ { 185,4.12251295216718078708070590390e340L },
+ { 186,7.66787409103095626397011298130e342L },
+ { 187,1.43389245502278882136241112750e345L },
+ { 188,2.69571781544284298416133291969e347L },
+ { 189,5.09490667118697324006491921822e349L },
+ { 190,9.68032267525524915612334651460e351L },
+ { 191,1.84894163097375258881955918429e354L },
+ { 192,3.54996793146960497053355363384e356L },
+ { 193,6.85143810773633759312975851330e358L },
+ { 194,1.32917899290084949306717315158e361L },
+ { 195,2.59189903615665651148098764559e363L },
+ { 196,5.08012211086704676250273578535e365L },
+ { 197,1.00078405584080821221303894971e368L },
+ { 198,1.98155243056480026018181712043e370L },
+ { 199,3.94328933682395251776181606966e372L },
+ { 200,7.88657867364790503552363213932e374L }
+};
+/******************************************************************************/
+/******************************************************************************/
+int GeocTipoCalcProd(void)
+{
+ //distingimos los tipos de cálculo
+#if defined(CALCULO_PRODUCTO_MULT)
+ return GEOC_PROD_MULT;
+#elif defined(CALCULO_PRODUCTO_LOG)
+ return GEOC_PROD_LOG;
+#else
+ #error *****No se ha definido el método de cálculo de la función Producto()
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+double Media(const double* datos,
+ const size_t nDatos,
+ const int inc)
+{
+ //índice para recorrer un bucle
+ size_t i=0;
+ //posición del elemento de trabajo
+ size_t pos=0;
+ //variable para almacenar el resultado
+ double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición del elemento inicial del vector
+ pos = GEOC_INICIO_VEC(nDatos,inc);
+ //recorremos el vector
+ for(i=0;i<nDatos;i++)
+ {
+ //vamos sumando los valores del vector
+ resultado += datos[pos];
+ //aumentamos el contador de posiciones
+ pos = inc>0 ? pos+(size_t)inc : pos-(size_t)abs(inc);
+ }
+ //calculamos la media
+ resultado /= (double)nDatos;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Varianza(const double* datos,
+ const size_t nDatos,
+ const int inc,
+ const double media)
+{
+ //índice para recorrer un bucle
+ size_t i=0;
+ //posición del elemento de trabajo
+ size_t pos=0;
+ //residuo
+ double res=0.0;
+ //variable para almacenar el resultado
+ double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición del elemento inicial del vector
+ pos = GEOC_INICIO_VEC(nDatos,inc);
+ //recorremos el vector
+ for(i=0;i<nDatos;i++)
+ {
+ //calculamos el residuo
+ res = datos[pos]-media;
+ //vamos sumando los cuadrados del valor menos la media
+ resultado += res*res;
+ //aumentamos el contador de posiciones
+ pos = inc>0 ? pos+(size_t)inc : pos-(size_t)abs(inc);
+ }
+ //calculamos la varianza
+ resultado /= (double)(nDatos-1);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double MediaPonderada(const double* datos,
+ const size_t nDatos,
+ const int incDatos,
+ const double* pesos,
+ const int incPesos)
+{
+ //índice para recorrer un bucle
+ size_t i=0;
+ //posiciones de los elementos de trabajo
+ size_t posDatos=0,posPesos;
+ //variable auxiliar
+ double sumaPesos=0.0;
+ //variable para almacenar el resultado
+ double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición del elemento inicial de los vectores
+ posDatos = GEOC_INICIO_VEC(nDatos,incDatos);
+ posPesos = GEOC_INICIO_VEC(nDatos,incPesos);
+ //recorremos el vector
+ for(i=0;i<nDatos;i++)
+ {
+ //vamos sumando los valores del vector
+ resultado += datos[posDatos]*pesos[posPesos];
+ //aumentamos el contador de posiciones
+ posDatos = incDatos>0 ? posDatos+(size_t)incDatos
+ : posDatos-(size_t)abs(incDatos);
+ posPesos = incPesos>0 ? posPesos+(size_t)incPesos
+ : posPesos-(size_t)abs(incPesos);
+ //vamos sumando los pesos
+ sumaPesos += pesos[posPesos];
+ }
+ //calculamos la media
+ resultado /= sumaPesos;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Mediana(const double* datos,
+ const size_t nDatos,
+ const int inc)
+{
+ //posición del elemento central
+ size_t pos=0;
+ //posición de inicio del vector
+ size_t posInicio;
+ //variable auxiliar
+ size_t posAux=0;
+ //variable para almacenar el resultado
+ double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición del elemento inicial del vector
+ posInicio = GEOC_INICIO_VEC(nDatos,inc);
+ //distinguimos entre número par o impar de datos
+ if(nDatos%2)
+ {
+ //el número de datos es impar, calculamos la posición del punto medio
+ pos = (size_t)ceil((double)nDatos/2.0)-1;
+ //calculamos la posición en memoria
+ pos = inc>0 ? posInicio+pos*(size_t)inc
+ : posInicio-pos*(size_t)abs(inc);
+ //extraemos el dato
+ resultado = datos[pos];
+ }
+ else
+ {
+ //el número de datos es par, calculamos la posición de los puntos medios
+ pos = (size_t)((double)nDatos/2.0)-1;
+ //calculamos la posición en memoria
+ pos = inc>0 ? posInicio+pos*(size_t)inc
+ : posInicio-pos*(size_t)abs(inc);
+ //calculamos la posición del siguiente elemento del vector
+ posAux = inc>0 ? pos+(size_t)inc : pos-(size_t)abs(inc);
+ //calculamos la mediana
+ resultado = (datos[pos]+datos[posAux])/2.0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double ProductoMult(size_t inicio,
+ size_t fin)
+{
+ //variables intermedias
+ size_t menor=0.0,mayor=0.0;
+ //variable para almacenar el resultado
+ double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema de forma iterativa
+ if((inicio==0)||(fin==0))
+ {
+ resultado = 0.0;
+ }
+ else
+ {
+ //seleccionamos los elementos mayor y menor
+ menor = inicio<=fin ? inicio : fin;
+ mayor = inicio>fin ? inicio : fin;
+ //multiplicamos
+ while(menor<=mayor)
+ {
+ resultado *= (double)menor;
+ menor++;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+long double ProductoMultLD(size_t inicio,
+ size_t fin)
+{
+ //variables intermedias
+ size_t menor=0.0,mayor=0.0;
+ //variable para almacenar el resultado
+ long double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema de forma iterativa
+ if((inicio==0)||(fin==0))
+ {
+ resultado = 0.0;
+ }
+ else
+ {
+ //seleccionamos los elementos mayor y menor
+ menor = inicio<=fin ? inicio : fin;
+ mayor = inicio>fin ? inicio : fin;
+ //multiplicamos
+ while(menor<=mayor)
+ {
+ resultado *= (long double)menor;
+ menor++;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double ProductoLog(size_t inicio,
+ size_t fin)
+{
+ //variables intermedias
+ size_t menor=0.0,mayor=0.0;
+ //variable para almacenar el resultado
+ double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema de forma iterativa
+ if((inicio==0)||(fin==0))
+ {
+ resultado = 0.0;
+ }
+ else
+ {
+ //seleccionamos los elementos mayor y menor
+ menor = inicio<=fin ? inicio : fin;
+ mayor = inicio>fin ? inicio : fin;
+ //multiplicamos
+ while(menor<=mayor)
+ {
+ resultado += log((double)menor);
+ menor++;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return round(pow(GEOC_CONST_E,resultado));
+}
+/******************************************************************************/
+/******************************************************************************/
+long double ProductoLogLD(size_t inicio,
+ size_t fin)
+{
+ //variables intermedias
+ size_t menor=0.0,mayor=0.0;
+ //variable para almacenar el resultado
+ long double resultado=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema de forma iterativa
+ if((inicio==0)||(fin==0))
+ {
+ resultado = 0.0;
+ }
+ else
+ {
+ //seleccionamos los elementos mayor y menor
+ menor = inicio<=fin ? inicio : fin;
+ mayor = inicio>fin ? inicio : fin;
+ //multiplicamos
+ while(menor<=mayor)
+ {
+ resultado += (long double)log((double)menor);
+ menor++;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return roundl(powl((long double)GEOC_CONST_E,resultado));
+}
+/******************************************************************************/
+/******************************************************************************/
+double Producto(size_t inicio,
+ size_t fin)
+{
+ //variable para almacenar el resultado
+ double resultado=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //método de cálculo para números mayores que GEOC_MATE_CONST_NMAXFAC
+#if defined(CALCULO_PRODUCTO_MULT)
+ resultado = ProductoMult(inicio,fin);
+#elif defined(CALCULO_PRODUCTO_LOG)
+ resultado = ProductoLog(inicio,fin);
+#else
+ #error *****No se ha definido el método de cálculo de la función Producto()
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+long double ProductoLD(size_t inicio,
+ size_t fin)
+{
+ //variable para almacenar el resultado
+ long double resultado=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //método de cálculo para números mayores que GEOC_MATE_CONST_NMAXFAC
+#if defined(CALCULO_PRODUCTO_MULT)
+ resultado = ProductoMultLD(inicio,fin);
+#elif defined(CALCULO_PRODUCTO_LOG)
+ resultado = ProductoLogLD(inicio,fin);
+#else
+ #error *****No se ha definido el método de cálculo de la función Producto()
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double FactorialMult(size_t numero)
+{
+ //variable para almacenar el resultado
+ double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema
+ if(numero)
+ {
+ resultado = ProductoMult((size_t)1,numero);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+long double FactorialMultLD(size_t numero)
+{
+ //variable para almacenar el resultado
+ long double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema
+ if(numero)
+ {
+ resultado = ProductoMultLD((size_t)1,numero);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double FactorialLog(size_t numero)
+{
+ //variable para almacenar el resultado
+ double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema
+ if(numero)
+ {
+ resultado = ProductoLog((size_t)1,numero);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+long double FactorialLogLD(size_t numero)
+{
+ //variable para almacenar el resultado
+ long double resultado=1.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //resolvemos el problema
+ if(numero)
+ {
+ resultado = ProductoLogLD((size_t)1,numero);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+double Factorial(size_t numero)
+{
+ //variable para almacenar el resultado
+ double resultado=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el factorial
+ if(numero<=GEOC_MATE_CONST_DBL_NMAXFAC)
+ {
+ resultado = (double)__tablaFacExpl[numero].valor;
+ }
+ else
+ {
+ //método de cálculo para números mayores que GEOC_MATE_CONST_DBL_NMAXFAC
+#if defined(CALCULO_PRODUCTO_MULT)
+ resultado = FactorialMult(numero);
+#elif defined(CALCULO_PRODUCTO_LOG)
+ resultado = FactorialLog(numero);
+#else
+ #error *****No se ha definido el método de cálculo de la función Factorial()
+#endif
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+long double FactorialLD(size_t numero)
+{
+ //variable para almacenar el resultado
+ long double resultado=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el factorial
+ if(numero<=GEOC_MATE_CONST_LDBL_NMAXFAC)
+ {
+ resultado = __tablaFacExpl[numero].valor;
+ }
+ else
+ {
+ //cálculo para números mayores que GEOC_MATE_CONST_LDBL_NMAXFAC
+#if defined(CALCULO_PRODUCTO_MULT)
+ resultado = FactorialMultLD(numero);
+#elif defined(CALCULO_PRODUCTO_LOG)
+ resultado = FactorialLogLD(numero);
+#else
+ #error *****No se ha definido el método de cálculo de la función Factorial()
+#endif
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return resultado;
+}
+/******************************************************************************/
+/******************************************************************************/
+void ProductoVectorial(const double x1,
+ const double y1,
+ const double z1,
+ const double x2,
+ const double y2,
+ const double z2,
+ double* x,
+ double* y,
+ double* z)
+{
+ //calculamos las componentes
+ *x = y1*z2-y2*z1;
+ *y = x2*z1-x1*z2;
+ *z = x1*y2-x2*y1;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void SinCosRecurrencia(const double anguloIni,
+ const double incAngulo,
+ const size_t numValores,
+ double* seno,
+ const size_t incSeno,
+ double* coseno,
+ const size_t incCoseno)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ //posiciones en los vectores de trabajo
+ size_t pS=0,pC=0;
+ //variables auxiliares
+ double aux=sin(incAngulo/2.0);
+ double alfa=2.0*aux*aux,beta=sin(incAngulo);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //seno y coseno del primero elemento de la serie
+ seno[pS] = sin(anguloIni);
+ coseno[pC] = cos(anguloIni);
+ //recorremos el resto de valores
+ for(i=1;i<numValores;i++)
+ {
+ //calculamos las posiciones en los vectores de salida
+ pS += incSeno;
+ pC += incCoseno;
+ //vamos calculando los senos y los cosenos
+ seno[pS] = seno[pS-incSeno]-
+ (alfa*seno[pS-incSeno]-beta*coseno[pC-incCoseno]);
+ coseno[pC] = coseno[pC-incCoseno]-
+ (alfa*coseno[pC-incCoseno]+beta*seno[pS-incSeno]);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+void SplineCubicoNatural(double* x,
+ double* y,
+ size_t nDatos,
+ double* xInterp,
+ size_t nInterp)
+{
+ //sentencias para que no salgan avisos en la compilación
+ x = x;
+ y = y;
+ nDatos = nDatos;
+ xInterp = xInterp;
+ nInterp = nInterp;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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/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@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 100644
index 0000000..1252999
--- /dev/null
+++ b/src/polig.c
@@ -0,0 +1,2048 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 20 de abril de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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;
+ sal->atr = 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)
+{
+ //variable para recorrer bucles
+ size_t i=0;
+ //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,nElem,incX,x,nNanX,posNanY,incY,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;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializamos el vector de atributos
+ sal->atr = (int*)malloc(sal->nPolig*sizeof(int));
+ //comprobamos los posibles errores
+ if(sal->atr==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;
+ }
+ //Inicializamos el vector de atributos a 0
+ for(i=0;i<sal->nPolig;i++)
+ {
+ sal->atr[i] = 0;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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);
+ }
+ //compruebo si hay algún polígono en los vectores de posiciones y atributos
+ if(poliSal->nPolig)
+ {
+ free(poliSal->posIni);
+ free(poliSal->nVert);
+ free(poliSal->atr);
+ }
+ //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;
+ poliSal->atr = poliEnt->atr;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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,1.0,0,0.0,0.0);
+ //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));
+ poli->atr = (int*)realloc(poli->atr,nPolig*sizeof(int));
+ //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)||(poli->atr==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];
+ poli->atr[poli->nPolig+i] = anyade->atr[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 al vector de atributos
+ if(datos->atr!=NULL)
+ {
+ free(datos->atr);
+ }
+ //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(incX,x,nElem,posXMin,posXMax,incY,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(nPolig,posIni,restaPosIni,incX,x,incY,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,
+ const double facCoor,
+ const int geo,
+ const double a,
+ const double f)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //variable de posición
+ size_t pos=0;
+ //longitud origen
+ double lon0=0.0;
+ //coordenadas de trabajo
+ double* x=NULL;
+ double* y=NULL;
+ //variable de estado (salida)
+ int estado=GEOC_ERR_NO_ERROR;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos salida rápida
+ if(poli->nPolig==0)
+ {
+ //salimos de la función si la estructura
+ return estado;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si la estructura no contiene área calculada
+ if(!(poli->hayArea))
+ {
+ //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;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si trabajamos sobre la superficie del elipsoide
+ if(geo||(facCoor!=1.0))
+ {
+ //asignamos memoria para los vectores auxiliares
+ x = (double*)malloc((poli->nElem)*sizeof(double));
+ y = (double*)malloc((poli->nElem)*sizeof(double));
+ //comprobamos posibles errores
+ if((x==NULL)||(y==NULL))
+ {
+ //volvemos a indicar que no hay áreas
+ poli->hayArea = 0;
+ //liberamos la memoria asignada
+ free(poli->area);
+ 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;
+ }
+ //copiamos las coordenadas y aplicamos factor de escala
+ //si estamos sobre el elipsoide, este paso se hace luego
+ if(!geo)
+ {
+ for(i=0;i<poli->nElem;i++)
+ {
+ x[i] = poli->x[i]*facCoor;
+ y[i] = poli->y[i]*facCoor;
+ }
+ }
+ else
+ {
+ //recorremos los polígonos
+ for(i=0;i<poli->nPolig;i++)
+ {
+ //posición de inicio en los vectores de coordenadas
+ pos = poli->posIni[i];
+ //calculamos la longitud media del polígono de trabajo
+ lon0 = Media(&(poli->x[pos]),poli->nVert[i],1);
+ //recorremos los vértices del polígono
+ for(j=0;j<poli->nVert[i];j++)
+ {
+ //proyectamos, aplicando el factor de escala
+ ProjCilinEquivLambertLat0Ec(poli->y[pos+j]*facCoor,
+ poli->x[pos+j]*facCoor,
+ lon0*facCoor,a,f,&x[pos+j],
+ &y[pos+j]);
+ }
+ }
+ }
+ }
+ else
+ {
+ //no hace falta copiarlas a los vectores auxiliares, sólo enlazarlas
+ x = poli->x;
+ y = poli->y;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las superficies de todos los polígonos
+ AreaPoligonosSimplesPolig(x,y,1,1,poli->posIni,poli->nVert,poli->nPolig,0,
+ poli->area);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //liberamos la memoria utilizada
+ if(geo||(facCoor!=1.0))
+ {
+ free(x);
+ free(y);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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 primer 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(nPolig,posIni,restaPosIni,area,incX,x,incY,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,escalaX,trasladaX,escalaY,trasladaY)
+#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,escalaX,trasladaX,escalaY,trasladaY)
+#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 int esf,
+ const double facCoor,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto,
+ const double a,
+ const double f)
+{
+ //índices para recorrer bucles
+ size_t i=0,j=0;
+ //tolerancia angular
+ double tolAng=fabs(GEOC_ARC_RES_ANG);
+ //posición inicial del polígono de trabajo y número de puntos del aligerado
+ size_t posIni=0,nVert=0,nPtos=0;
+ //puntos colineales
+ int colin=0;
+ //coordenadas de los polígonos aligerados
+ double* x=NULL;
+ double* y=NULL;
+ double* xF=NULL;
+ double* yF=NULL;
+ //vértices del polígono de entrada más largo
+ size_t nVertMax=0;
+ //matriz de rotación y coordenadas en el sistema rotado
+ double mRot[3][3];
+ double latCR=0.0;
+ //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;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay factor de escala para las coordenadas
+ if(facCoor!=1.0)
+ {
+ //vértices del polígono más largo
+ nVertMax = MaximoSizeT(poli->nVert,poli->nPolig,1);
+ //asignamos memoria para las coordenadas con factor de escala
+ xF = (double*)malloc(nVertMax*sizeof(double));
+ yF = (double*)malloc(nVertMax*sizeof(double));
+ //comprobamos posibles errores
+ if((xF==NULL)||(yF==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ free(xF);
+ free(yF);
+ //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];
+ //número de vértices del polígono
+ nVert = poli->nVert[i];
+ //comprobamos si hay factor de escala para las coordenadas
+ if(facCoor!=1.0)
+ {
+ //copiamos las coordenadas y aplicamos el factor de escala
+ for(j=0;j<nVert;j++)
+ {
+ xF[j] = facCoor*(poli->x[posIni+j]);
+ yF[j] = facCoor*(poli->y[posIni+j]);
+ }
+ }
+ else
+ {
+ //las coordenadas del polígono se quedan como están
+ xF = &(poli->x[posIni]);
+ yF = &(poli->y[posIni]);
+ }
+ //aligeramos el polígono de trabajo
+ pos = AligeraPolilinea(xF,yF,nVert,1,1,tol,paralelizaTol,robusto,
+ nSegRobOrig,nSegRobAuto,esf,&nPtos);
+ //comprobamos posibles errores
+ if(pos==NULL)
+ {
+ //liberamos la memoria asignada
+ LibMemPolig(aux);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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)
+ {
+ //distinguimos entre trabajo sobre la esfera y sobre el plano
+ if(esf)
+ {
+ //calculamos la rotación para pasar a un sistema que contenga a
+ //los dos primeros puntos en el ecuador, con el primero en
+ //(lat=0,lon=0)
+ RotaArco00Ecuador(tolAng,
+ yF[pos[0]],xF[pos[0]],yF[pos[1]],xF[pos[1]],
+ mRot,NULL);
+ //calculamos la latitud del tercer punto
+ AplicaMatrizRotacionCoorGeod(1,yF[pos[2]],xF[pos[2]],mRot,
+ &latCR,NULL);
+ //comprobamos si la latitud es 0.0
+ if(GEOC_ES_CERO(latCR,GEOC_ARC_RES_ANG))
+ {
+ //los puntos son colineales
+ colin = 1;
+ }
+ }
+ else
+ {
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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,facCoor,esf,a,f);
+ //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
+ free(aux);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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 int impAtr,
+ const char formAtr[],
+ 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);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que imprimir los atributos
+ if(impAtr)
+ {
+ //imprimimos el valor del atributo
+ fprintf(idFich," ");
+ fprintf(idFich,formAtr,poli->atr[indice]);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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[],
+ const int impAtr,
+ const char formAtr[],
+ 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,impAtr,formAtr,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 100644
index 0000000..b819dc3
--- /dev/null
+++ b/src/polil.c
@@ -0,0 +1,1535 @@
+/* -*- 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 03 de junio de 2011
+\copyright
+Copyright (c) 2011-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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,nElem,incX,x,nNanX,posNanY,incY,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,escalaX,trasladaX,escalaY,trasladaY)
+#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,escalaX,trasladaX,escalaY,trasladaY)
+#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 int esf,
+ const double facCoor,
+ const double tol,
+ const int paralelizaTol,
+ const enum GEOC_DPEUCKER_ROBUSTO robusto,
+ const size_t nSegRobOrig,
+ const size_t nSegRobAuto)
+{
+ //í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,nVert=0,nPtos=0;
+ //polilínea que es un mismo punto
+ int pmp=0;
+ //coordenadas de trabajo
+ double* x=NULL;
+ double* y=NULL;
+ double* xF=NULL;
+ double* yF=NULL;
+ //vértices de la polilínea de entrada más larga
+ size_t nVertMax=0;
+ //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;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay factor de escala para las coordenadas
+ if(facCoor!=1.0)
+ {
+ //vértices de la polilínea más larga
+ nVertMax = MaximoSizeT(poli->nVert,poli->nPolil,1);
+ //asignamos memoria para las coordenadas con factor de escala
+ xF = (double*)malloc(nVertMax*sizeof(double));
+ yF = (double*)malloc(nVertMax*sizeof(double));
+ //comprobamos posibles errores
+ if((xF==NULL)||(yF==NULL))
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ free(xF);
+ free(yF);
+ //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];
+ //número de vértices de la polilínea
+ nVert = poli->nVert[i];
+ //comprobamos si hay factor de escala para las coordenadas
+ if(facCoor!=1.0)
+ {
+ //copiamos las coordenadas y aplicamos el factor de escala
+ for(j=0;j<nVert;j++)
+ {
+ xF[j] = facCoor*(poli->x[posIni+j]);
+ yF[j] = facCoor*(poli->y[posIni+j]);
+ }
+ }
+ else
+ {
+ //las coordenadas de la polilínea se quedan como están
+ xF = &(poli->x[posIni]);
+ yF = &(poli->y[posIni]);
+ }
+ //aligeramos la polilínea de trabajo
+ pos = AligeraPolilinea(xF,yF,nVert,1,1,tol,paralelizaTol,robusto,
+ nSegRobOrig,nSegRobAuto,esf,&nPtos);
+ //comprobamos posibles errores
+ if(pos==NULL)
+ {
+ //liberamos la memoria asignada
+ LibMemPolil(aux);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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 dos puntos son el mismo
+ 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)))
+ {
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ //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
+ free(aux);
+ if(facCoor!=1.0)
+ {
+ free(xF);
+ free(yF);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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/posmatvec.c b/src/posmatvec.c
new file mode 100644
index 0000000..9e5db45
--- /dev/null
+++ b/src/posmatvec.c
@@ -0,0 +1,292 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup algebra anespec geopot gshhs matriz mmcc snx
+@{
+\file posmatvec.c
+\brief Definición de funciones para realizar cálculos de posiciones de
+ elementos en matrices almacenadas en formato vector.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 14 de enero de 2009
+\section Licencia Licencia
+Copyright (c) 2009-2013, 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/posmatvec.h"
+/******************************************************************************/
+/******************************************************************************/
+int EsAlmMatVecCMO(void)
+{
+ //determinamos la salida dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //el almacenamiento no es column major order
+ return 0;
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //el almacenamiento es column major order
+ return 1;
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+void TipoAlmMatVec(char tipo[])
+{
+ //determinamos la cadena de código dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //asignamos la cadena correspondiente al tipo row major order
+ strcpy(tipo,GEOC_MATR_COD_ALM_RMO);
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //asignamos la cadena correspondiente al tipo column major order
+ strcpy(tipo,GEOC_MATR_COD_ALM_CMO);
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t Lmfc(const size_t filMem,
+ const size_t colMem)
+{
+ //distinguimos según el tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //almacenamiento row major order
+ return GEOC_LMFC_RMO(filMem,colMem);
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //almacenamiento column major order
+ return GEOC_LMFC_CMO(filMem,colMem);
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t IncElemFil(const size_t filMem)
+{
+ //distinguimos según el tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //almacenamiento row major order
+ //0*filMem para que el compilador no dé warning por variable no usada
+ return 1+0*filMem;
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //almacenamiento column major order
+ return filMem;
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t IncElemCol(const size_t colMem)
+{
+ //distinguimos según el tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //almacenamiento row major order
+ return colMem;
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //almacenamiento column major order
+ //0*colMem para que el compilador no dé warning por variable no usada
+ return 1+0*colMem;
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatVec(const size_t filMem,
+ const size_t colMem,
+ const size_t fil,
+ const size_t col)
+{
+ //calculamos la posición en el vector dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //almacenamiento row major order
+ return GEOC_POSMATVEC_RMO(filMem,colMem,fil,col);
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //almacenamiento column major order
+ return GEOC_POSMATVEC_CMO(filMem,colMem,fil,col);
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+void PosVecMat(const size_t filMem,
+ const size_t colMem,
+ const size_t posVec,
+ size_t* fil,
+ size_t* col)
+
+{
+ //calculamos la posición en la matriz dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //calculamos la fila
+ //la division se realiza entre elementos del mismo tipo, por lo que el
+ //resultado tambien lo es (el redondeo de la division se hace por
+ //truncamiento)
+ //se añade el factor 0*filMem para que el compilador no emita un warning por
+ //variable no usada
+ *fil = posVec/colMem+0*filMem;
+ //calculamos la columna
+ *col = posVec%colMem;
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //calculamos la fila
+ *fil = posVec%filMem;
+ //calculamos la columna
+ //la division se realiza entre elementos del mismo tipo, por lo que el
+ //resultado tambien lo es (el redondeo de la division se hace por
+ //truncamiento)
+ //se añade el factor 0*colMem para que el compilador no emita un warning por
+ //variable no usada
+ *col = posVec/filMem+0*colMem;
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatGenBanVec(const size_t diagInf,
+ const size_t diagSup,
+ const size_t fil,
+ const size_t col)
+{
+ //filas de la matriz empaquetada si el almacenamiento es COLUMN MAJOR ORDER
+ //y columnas si es ROW MAJOR ORDER
+ size_t lda=diagSup+diagInf+1;
+ //calculamos la posición en el vector dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //columna en la matriz empaquetada donde se encuentra el elemento de trabajo
+ size_t colAux=diagInf-fil+col;
+ //calculamos la posición en el vector
+ return fil*lda+colAux;
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //fila en la matriz empaquetada donde se encuentra el elemento de trabajo
+ size_t filAux=diagSup+fil-col;
+ //calculamos la posición en el vector
+ return col*lda+filAux;
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatTriEmVec(const size_t dim,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col)
+{
+ //calculamos la posición en el vector dependiendo del tipo de almacenamiento
+#if defined(ROW_MAJOR_ORDER_MATVEC)
+ //distinguimos entre matriz triangular superior e inferior
+ if(supInf==GeocMatTriSup)
+ {
+ //calculamos la posición
+ return GEOC_POSMATVEC_TRIEM_SUP_RMO(dim,fil,col);
+ }
+ else
+ {
+ //calculamos la posición
+ return GEOC_POSMATVEC_TRIEM_INF_RMO(dim,fil,col);
+ }
+#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
+ //distinguimos entre matriz triangular superior e inferior
+ if(supInf==GeocMatTriSup)
+ {
+ //calculamos la posición
+ return GEOC_POSMATVEC_TRIEM_SUP_CMO(dim,fil,col);
+ }
+ else
+ {
+ //calculamos la posición
+ return GEOC_POSMATVEC_TRIEM_INF_CMO(dim,fil,col);
+ }
+#else
+ #error *****No se ha definido el tipo de almacenamiento matricial
+#endif
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatTriBanVec(const size_t diag,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col)
+{
+ //diagonales de la matriz de trabajo
+ size_t diagInf=0,diagSup=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las diagonales de la matriz de trabajo
+ if(supInf==GeocMatTriSup)
+ {
+ diagSup = diag;
+ }
+ else if(supInf==GeocMatTriInf)
+ {
+ diagInf = diag;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posicion
+ return PosMatGenBanVec(diagInf,diagSup,fil,col);
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatSimEmVec(const size_t dim,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col)
+{
+ //calculamos y salimos de la función
+ return PosMatTriEmVec(dim,supInf,fil,col);
+}
+/******************************************************************************/
+/******************************************************************************/
+size_t PosMatSimBanVec(const size_t diag,
+ const enum GEOC_MATR_ID_TRI supInf,
+ const size_t fil,
+ const size_t col)
+{
+ //calculamos y salimos de la función
+ return PosMatTriBanVec(diag,supInf,fil,col);
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* 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/proyecaux.c b/src/proyecaux.c
new file mode 100644
index 0000000..9dc11d9
--- /dev/null
+++ b/src/proyecaux.c
@@ -0,0 +1,92 @@
+/* -*- coding: utf-8 -*- */
+/**
+\ingroup gshhs geom proyec
+@{
+\file proyecaux.c
+\brief Definición de funciones de algunas proyecciones cartográficas para no
+ usar PROJ.4.
+\author José Luis García Pallero, jgpallero@gmail.com
+\date 16 de agosto de 2013
+\copyright
+Copyright (c) 2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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/proyecaux.h"
+/******************************************************************************/
+/******************************************************************************/
+void ProjCilinEquivLambertLat0Ec(const double lat,
+ const double lon,
+ const double lon0,
+ const double a,
+ const double f,
+ double* x,
+ double* y)
+{
+ //variables auxiliares
+ double k0=0.0,q=0.0,sLat=0.0,e=0.0,e2=0.0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //ASUMIMOS QUE EL PARALELO ORIGEN ES EL ECUADOR
+ //distinguimos entre la esfera y el elipsoide
+ if(f==0.0)
+ {
+ //proyectamos
+ *x = a*(lon-lon0);
+ *y = a*sin(lat);
+ }
+ else
+ {
+ //calculamos el seno de la latitud geodésica
+ sLat = sin(lat);
+ //calculamos la primera excentricidad del elipsoide
+ e = sqrt(2.0*f-f*f);
+ e2 = e*e;
+ //el parámetro k0 porque el paralelo estándar es el ecuador
+ k0 = 1.0;
+ //calculamos el parámetro q
+ q = (1.0-e2)*
+ (sLat/(1.0-e2*sLat*sLat)-
+ 1.0/(2.0*e)*log((1.0-e*sLat)/(1.0+e*sLat)));
+ //proyectamos
+ *x = a*k0*(lon-lon0);
+ *y = a*q/(2.0*k0);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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 100644
index 0000000..035ac4b
--- /dev/null
+++ b/src/ptopol.c
@@ -0,0 +1,1332 @@
+/* -*- 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 #GEOC_PTO_POLIG_LEJOS_32
+unidades. Con cálculos de 64 bits, los polígonos pueden estar alejados de los
+puntos de trabajo unas #GEOC_PTO_POLIG_LEJOS_64 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@gmail.com
+\note Este fichero contiene funciones paralelizadas con OpenMP.
+\date 05 de abril de 2010
+\copyright
+Copyright (c) 2010-2020, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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 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;
+}
+/******************************************************************************/
+/******************************************************************************/
+void PtosEnPoligono(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(nPtos,incSituacion,situacion,incX,x,incY,y,N,incCoorX,coorX,incCoorY, \
+ coorY) \
+ private(i)
+#endif
+ //recorremos los puntos a chequear
+ for(i=0;i<nPtos;i++)
+ {
+ //compruebo la situación del punto de trabajo
+ situacion[i*incSituacion] = PtoEnPoligono(x[i*incX],y[i*incY],coorX,
+ coorY,N,incCoorX,incCoorY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+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;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos la posición general
+ pos = PtoEnPoligono(x,y,coorX,coorY,N,incX,incY);
+ //comprobamos si el polígono 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;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return pos;
+}
+/******************************************************************************/
+/******************************************************************************/
+void PtosEnPoligonoVertice(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(nPtos,incSituacion,situacion,incX,x,incY,y,N,incCoorX,coorX,incCoorY, \
+ coorY) \
+ private(i)
+#endif
+ //recorremos los puntos a chequear
+ for(i=0;i<nPtos;i++)
+ {
+ //compruebo la situación del punto de trabajo
+ situacion[i*incSituacion] = PtoEnPoligonoVertice(x[i*incX],y[i*incY],
+ coorX,coorY,N,
+ incCoorX,incCoorY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+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;
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+void PtosEnPoligonoVerticeBorde(const long* x,
+ const long* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const long* coorX,
+ const long* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ int* situacion,
+ const size_t incSituacion)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(nPtos,incSituacion,situacion,incX,x,incY,y,N,incCoorX,coorX,incCoorY, \
+ coorY) \
+ private(i)
+#endif
+ //recorremos los puntos a chequear
+ for(i=0;i<nPtos;i++)
+ {
+ //compruebo la situación del punto de trabajo
+ situacion[i*incSituacion] = PtoEnPoligonoVerticeBorde(x[i*incX],
+ y[i*incY],
+ coorX,coorY,N,
+ incCoorX,
+ incCoorY);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+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;
+ //factor de escala de trabajo
+ double fmult=1.0;
+ //variables auxiliares
+ double X=0.0,aux=0.0,dmax=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;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos si hay que calcular el factor de escala
+ if(factor==0.0)
+ {
+ //recorro todos los vértices del polígono
+ for(i=0;i<n;i++)
+ {
+ //calculo la distancia del punto al vértice
+ aux = sqrt(coorX[i*incX]*coorX[i*incX]+coorY[i*incY]*coorY[i*incY]);
+ //compruebo si es la máxima
+ if(aux>dmax)
+ {
+ dmax = aux;
+ }
+ }
+ //compruebo la precisión de trabajo
+ if(sizeof(ptopol_long)==4)
+ {
+ //precisión de 32 bits (4 bytes)
+ fmult = floor(GEOC_PTO_POLIG_LEJOS_ESCALA_DIST*
+ GEOC_PTO_POLIG_LEJOS_32/dmax);
+ }
+ else
+ {
+ //precisión de 64 bits (8 bytes)
+ fmult = floor(GEOC_PTO_POLIG_LEJOS_ESCALA_DIST*
+ GEOC_PTO_POLIG_LEJOS_64/dmax);
+ }
+ }
+ else
+ {
+ fmult = factor;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //pasamos a número entero el punto a evaluar
+ if(redondeo)
+ {
+ //redondeo
+ fX = (ptopol_long)(round(fmult*x));
+ fY = (ptopol_long)(round(fmult*y));
+ }
+ else
+ {
+ //truncamiento
+ fX = (ptopol_long)(fmult*x);
+ fY = (ptopol_long)(fmult*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(fmult*coorX[i*incX]))-fX;
+ cy = (ptopol_long)(round(fmult*coorY[i*incY]))-fY;
+ //redondeo del vértice anterior
+ cx1 = (ptopol_long)(round(fmult*coorX[i1*incX]))-fX;
+ cy1 = (ptopol_long)(round(fmult*coorY[i1*incY]))-fY;
+ }
+ else
+ {
+ //truncamiento del vértice actual
+ cx = (ptopol_long)(fmult*coorX[i*incX])-fX;
+ cy = (ptopol_long)(fmult*coorY[i*incY])-fY;
+ //redondeo del vértice anterior
+ cx1 = (ptopol_long)(fmult*coorX[i1*incX])-fX;
+ cy1 = (ptopol_long)(fmult*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;
+ }
+}
+/******************************************************************************/
+/******************************************************************************/
+void PtosEnPoligonoVerticeBordeDouble(const double* x,
+ const double* y,
+ const size_t nPtos,
+ const size_t incX,
+ const size_t incY,
+ const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incCoorX,
+ const size_t incCoorY,
+ const double factor,
+ const int redondeo,
+ int* situacion,
+ const size_t incSituacion)
+{
+ //índice para recorrer bucles
+ size_t i=0;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //paralelización con OpenMP
+#if defined(_OPENMP)
+#pragma omp parallel for default(none) \
+ shared(nPtos,incSituacion,situacion,incX,x,incY,y,N,incCoorX,coorX,incCoorY, \
+ coorY,factor,redondeo) \
+ private(i)
+#endif
+ //recorremos los puntos a chequear
+ for(i=0;i<nPtos;i++)
+ {
+ //compruebo la situación del punto de trabajo
+ situacion[i*incSituacion] = PtoEnPoligonoVerticeBordeDouble(x[i*incX],
+ y[i*incY],
+ coorX,coorY,
+ N,incCoorX,
+ incCoorY,
+ factor,
+ redondeo);
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return;
+}
+/******************************************************************************/
+/******************************************************************************/
+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
+ int 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)
+ {
+ //inicializamos el indicador de continuación de chequeos (si se compila
+ //versión en serie, esta sentencia sólo vale para que no dé warning en
+ //compilación por variable no usada)
+ continuar = 1;
+ //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(nNan,continuar,posNan,incX,x,coorX,incY,y,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++)
+ {
+ //si compilamos para OpenMP no podemos usar la sentencia break
+ //en cambio, comprobamos si hay que continuar o no haciendo pruebas
+ //para que las vueltas del bucle hagan todos los cálculos o no
+#if defined(_OPENMP)
+ //hacemos que todos los hilos vean la variable continuar actualizada
+#pragma omp flush(continuar)
+ //comprobamos si hay que continuar chequeando polígonos en OpenMP
+ if(continuar)
+ {
+#endif
+ //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);
+ //distinguimos entre algoritmo en serie y en paralelo
+#if !defined(_OPENMP)
+ //comprobamos si el punto no está fuera del polígono
+ if(posAux!=GEOC_PTO_FUERA_POLIG)
+ {
+ //asignamos la variable de salida
+ pos = posAux;
+ //asignamos el polígono que contiene al punto
+ *poli = i;
+ //esta asignación sólo está aquí para que no dé warning en
+ //la compilación
+ continuar = continuar;
+ //salimos del bucle
+ break;
+ }
+#else
+ //me aseguro de que las variables involucradas sean actualizadas
+ //por un hilo cada vez, sin posibilidad de modificación por
+ //varios al mismo tiempo
+#pragma omp critical(paraSiPuntoDentro)
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el chequear 'continuar' 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&&(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
+#pragma omp flush(continuar)
+ }
+}
+#endif
+ //llave de cierre del if(continuar) si compilamos para OpenMP
+#if defined(_OPENMP)
+ } // --> cierro el if(continuar) si compilamos para OpenMP
+#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(nNan,continuar,posNan,incX,x,coorX,incY,y,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(paraSiPuntoDentro)
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el chequear 'continuar' 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&&(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(nNan,continuar,posNan,incX,x,coorX,incY,y,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(paraSiPuntoDentro)
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el chequear 'continuar' 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&&(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(nNan,continuar,posNan,incX,x,coorX,incY,y,coorY,pos,factor,redondeo, \
+ 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(paraSiPuntoDentro)
+#endif
+{
+ //si el punto no está fuera, no se han de hacer más operaciones
+ //el chequear 'continuar' 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&&(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;
+}
+/******************************************************************************/
+/******************************************************************************/
+void GeneraPtoEnPoligono(const double* coorX,
+ const double* coorY,
+ const size_t N,
+ const size_t incX,
+ const size_t incY,
+ const double factor,
+ const int redondeo,
+ double* x,
+ double* y)
+{
+ //número de vértices de trabajo
+ size_t n=N;
+ //coordenadas de los vértices de un triángulo y centroide
+ double x1=0.0,y1=0.0,x2=0.0,y2=0.0,x3=0.0,y3=0.0,xc=0.0,yc=0.0;
+ //identificador de inclusión en polígono
+ int dentro=GEOC_PTO_FUERA_POLIG;
+ //variables auxiliares
+ int camina=0;
+ size_t pos1=0,pos2=0,pos3=0;
+ //inicializo las coordenadas de salida
+ *x = GeocNan();
+ *y = GeocNan();
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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;
+ }
+ //compruebo si hay un número suficiente de vértices
+ if(n<3)
+ {
+ //salimos de la función
+ return;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //inicializo el primer triángulo
+ x1 = coorX[0];
+ y1 = coorY[0];
+ x2 = coorX[incX];
+ y2 = coorY[incY];
+ x3 = coorX[2*incX];
+ y3 = coorY[2*incY];
+ //identificador de punto a mover y posiciones
+ camina = 3;
+ pos1 = 0;
+ pos2 = 1;
+ pos3 = 2;
+ //entramos en un bucle infinito
+ while(1)
+ {
+ //calculamos las coordenadas del centroide del triángulo, que siempre
+ //está dentro de él
+ xc = (x1+x2+x3)/3.0;
+ yc = (y1+y2+y3)/3.0;
+ //comprobamos si el punto está dentro del polígono
+ dentro = PtoEnPoligonoVerticeBordeDouble(xc,yc,coorX,coorY,N,incX,incY,
+ factor,redondeo);
+ //si está dentro salgo del bucle
+ if(dentro==GEOC_PTO_DENTRO_POLIG)
+ {
+ //asigno las coordenadas
+ *x = xc;
+ *y = yc;
+ //salgo del bucle
+ break;
+ }
+ //compruebo qué punto he de mover
+ if(camina==3)
+ {
+ //muevo el punto 3
+ pos3++;
+ //comprobamos si se ha llegado al final
+ if(pos3==n)
+ {
+ //hay que empezar a mover el punto 2
+ camina = 2;
+ //devuelvo la posición del tercer punto al último de la lista
+ pos3 = n-1;
+ //siguiente vuelta, aunque se repita el cálculo anterior
+ continue;
+ }
+ }
+ else if(camina==2)
+ {
+ //muevo el punto 2
+ pos2++;
+ //compruebo si he llegado al final para el punto 2
+ if(pos2==(n-1))
+ {
+ //hay que empezar a mover el punto 1
+ camina = 1;
+ //posición del segundo punto al penúltimo de la lista
+ pos2 = n-2;
+ //siguiente vuelta, aunque se repita el cálculo anterior
+ continue;
+ }
+ }
+ else
+ {
+ //nuevo punto 1
+ pos1++;
+ //los puntos 2 y 3 son los que vienen a continuación de él
+ pos2 = pos1+1;
+ pos3 = pos2+1;
+ //compruebo si he llegado al final para el punto 1
+ if(pos1==(n-2))
+ {
+ //salimos del bucle
+ break;
+ }
+ //en la siguiente vuelta moveremos el tercer vértice
+ camina = 3;
+ }
+ //extraigo las coordenadas de los puntos del triángulo
+ x1 = coorX[pos1*incX];
+ y1 = coorY[pos1*incY];
+ x2 = coorX[pos2*incX];
+ y2 = coorY[pos2*incY];
+ x3 = coorX[pos3*incX];
+ y3 = coorY[pos3*incY];
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //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/recpolil.c b/src/recpolil.c
new file mode 100644
index 0000000..c6cbe40
--- /dev/null
+++ b/src/recpolil.c
@@ -0,0 +1,1403 @@
+/* -*- 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@gmail.com
+\date 05 de junio de 2011
+\copyright
+Copyright (c) 2011, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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)||
+ (intersec==GEOC_SEG_INTERSEC_EXTREMOS_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_EXTREMOS_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 = GEOC_RECT_DISJUNTOS(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 100644
index 0000000..836b5cc
--- /dev/null
+++ b/src/segmento.c
@@ -0,0 +1,476 @@
+/* -*- 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@gmail.com
+\date 22 de abril de 2011
+\copyright
+Copyright (c) 2011-2013, José Luis García Pallero. All rights reserved.
+\par
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+\par
+- 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.
+\par
+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"
+/******************************************************************************/
+/******************************************************************************/
+int TresPuntosColineales2D(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC)
+{
+ //utilizamos la macro de posición de punto con respecto a una recta, aunque
+ //no es una macro robusta
+ //son colineales si el resultado es 0.0
+ //calculamos y salimos de la función
+ return (POS_PTO_RECTA_2D(xA,yA,xB,yB,xC,yC)==0.0);
+}
+/******************************************************************************/
+/******************************************************************************/
+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_EXTREMOS_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_EXTREMOS_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)
+{
+ //centroide del conjunto de puntos implicados
+ double xc=0.0,yc=0.0;
+ //coordenadas reducidas al centroide
+ double xAc=0.0,yAc=0.0,xBc=0.0,yBc=0.0,xCc=0.0,yCc=0.0,xDc=0.0,yDc=0.0;
+ //parámetros de las ecuaciones
+ double s=0.0,t=0.0,num=0.0,den=0.0;
+ //variable de salida
+ int cod=GEOC_SEG_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los rectángulos son disjuntos, los segmentos no se tocan
+ if(GEOC_RECT_DISJUNTOS(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)))
+ {
+ //código de salida
+ cod = GEOC_SEG_NO_INTERSEC;
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el centroide del conjunto de puntos de trabajo
+ xc = (xA+xB+xC+xD)/4.0;
+ yc = (yA+yB+yC+yD)/4.0;
+ //reducimos las coordenadas de trabajo al centroide, para que los números
+ //sean más pequeños y evitar posibles errores de desbordamiento
+ xAc = xA-xc;
+ xBc = xB-xc;
+ xCc = xC-xc;
+ xDc = xD-xc;
+ yAc = yA-yc;
+ yBc = yB-yc;
+ yCc = yC-yc;
+ yDc = yD-yc;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //a partir de aquí, trabajamos con las coordenadas reducidas al centroide
+ //calculamos el denominador
+ den = xAc*(yDc-yCc)+xBc*(yCc-yDc)+xDc*(yBc-yAc)+xCc*(yAc-yBc);
+ //si el denominador es 0.0, los segmentos son paralelos
+ if(den==0.0)
+ {
+ //calculamos el punto común
+ cod = PtoComunSegmParalelos2D(xAc,yAc,xBc,yBc,xCc,yCc,xDc,yDc,x,y);
+ //deshacemos el cambio del centroide
+ *x += xc;
+ *y += yc;
+ //salimos de la función
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el numerador
+ num = xAc*(yDc-yCc)+xCc*(yAc-yDc)+xDc*(yCc-yAc);
+ //un extremo de un segmento puede estar encima del otro segmento, pero los
+ //segmentos no son colineales
+ if((num==0.0)||(num==den))
+ {
+ //comprobamos si se tocan en un extremo
+ if(((xAc==xCc)&&(yAc==yCc))||((xAc==xDc)&&(yAc==yDc))||
+ ((xBc==xCc)&&(yBc==yCc))||((xBc==xDc)&&(yBc==yDc)))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ else
+ {
+ //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 = -(xAc*(yCc-yBc)+xBc*(yAc-yCc)+xCc*(yBc-yAc));
+ //un extremo de un segmento puede estar encima del otro segmento, pero los
+ //segmentos no son colineales
+ if((num==0.0)||(num==den))
+ {
+ //comprobamos si se tocan en un extremo
+ if(((xAc==xCc)&&(yAc==yCc))||((xAc==xDc)&&(yAc==yDc))||
+ ((xBc==xCc)&&(yBc==yCc))||((xBc==xDc)&&(yBc==yDc)))
+ {
+ //asignamos la variable de salida
+ cod = GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN;
+ }
+ else
+ {
+ //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 y deshacemos el cambio
+ //del centroide
+ *x = xc+xAc+s*(xBc-xAc);
+ *y = yc+yAc+s*(yBc-yAc);
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int IntersecSegmentos2DSimple(const double xA,
+ const double yA,
+ const double xB,
+ const double yB,
+ const double xC,
+ const double yC,
+ const double xD,
+ const double yD)
+{
+ //centroide del conjunto de puntos implicados
+ double xc=0.0,yc=0.0;
+ //coordenadas reducidas al centroide
+ double xAc=0.0,yAc=0.0,xBc=0.0,yBc=0.0,xCc=0.0,yCc=0.0,xDc=0.0,yDc=0.0;
+ //identificadores de posición
+ double posA=0.0,posB=0.0,posC=0.0,posD=0.0;
+ //identificadores de punto enmedio de un segmento
+ int enmA=0,enmB=0,enmC=0,enmD=0;
+ //variable de salida (por defecto, no hay intersección)
+ int cod=GEOC_SEG_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //si los rectángulos son disjuntos, los segmentos no se tocan
+ if(GEOC_RECT_DISJUNTOS(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)))
+ {
+ //salimos de la función (usamos el valor por defecto de no intersección
+ return cod;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos el centroide del conjunto de puntos de trabajo
+ xc = (xA+xB+xC+xD)/4.0;
+ yc = (yA+yB+yC+yD)/4.0;
+ //reducimos las coordenadas de trabajo al centroide, para que los números
+ //sean más pequeños y evitar posibles errores de desbordamiento
+ xAc = xA-xc;
+ xBc = xB-xc;
+ xCc = xC-xc;
+ xDc = xD-xc;
+ yAc = yA-yc;
+ yBc = yB-yc;
+ yCc = yC-yc;
+ yDc = yD-yc;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //calculamos las posiciones de los puntos con respecto a las rectas
+ posA = POS_PTO_RECTA_2D(xAc,yAc,xCc,yCc,xDc,yDc);
+ posB = POS_PTO_RECTA_2D(xBc,yBc,xCc,yCc,xDc,yDc);
+ posC = POS_PTO_RECTA_2D(xCc,yCc,xAc,yAc,xBc,yBc);
+ posD = POS_PTO_RECTA_2D(xDc,yDc,xAc,yAc,xBc,yBc);
+ //comprobamos si hay tres puntos alineados, que dan lugar a casos especiales
+ if((posA==0.0)||(posB==0.0)||(posC==0.0)||(posD==0.0))
+ {
+ //comprobamos si alguno de los extremos son coincidentes
+ if(((xA==xC)&&(yA==yC))||((xA==xD)&&(yA==yD))||
+ ((xB==xC)&&(yB==yC))||((xB==xD)&&(yB==yD)))
+ {
+ //código de salida
+ cod = GEOC_SEG_INTERSEC;
+ }
+ else
+ {
+ //comprobamos si A está en el segmento CD, pero no es un extremo
+ if(posA==0.0)
+ {
+ enmA = PuntoEntreDosPuntos2DColin(xAc,yAc,xCc,yCc,xDc,yDc);
+ }
+ //comprobamos si B está en el segmento CD, pero no es un extremo
+ if(posB==0.0)
+ {
+ enmB = PuntoEntreDosPuntos2DColin(xBc,yBc,xCc,yCc,xDc,yDc);
+ }
+ //comprobamos si C está en el segmento AB, pero no es un extremo
+ if(posC==0.0)
+ {
+ enmC = PuntoEntreDosPuntos2DColin(xCc,yCc,xAc,yAc,xBc,yBc);
+ }
+ //comprobamos si C está en el segmento AB, pero no es un extremo
+ if(posD==0.0)
+ {
+ enmD = PuntoEntreDosPuntos2DColin(xDc,yDc,xAc,yAc,xBc,yBc);
+ }
+ //si hay algún punto enmedio de algún segmento, existe intersección
+ if(enmA||enmB||enmC||enmD)
+ {
+ //código de salida
+ cod = GEOC_SEG_INTERSEC;
+ }
+ }
+ }
+ else
+ {
+ //para que ocurra intersección pura, las rectas han de dividirse
+ //mutuamente en dos, es decir, los puntos de cada una han de estar uno a
+ //cada lado de la otra
+ if((((posA<0.0)&&(posB>0.0))||((posA>0.0)&&(posB<0.0)))&&
+ (((posC<0.0)&&(posD>0.0))||((posC>0.0)&&(posD<0.0))))
+ {
+ //código de salida
+ cod = GEOC_SEG_INTERSEC;
+ }
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return cod;
+}
+/******************************************************************************/
+/******************************************************************************/
+int CodIntSeg2DCodIntSeg2DSimple(const int cod2D)
+{
+ //variable de salida
+ int sal=GEOC_SEG_NO_INTERSEC;
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //comprobamos los posibles valores de entrada
+ switch(cod2D)
+ {
+ case GEOC_SEG_NO_INTERSEC:
+ //no hay intersección
+ sal = GEOC_SEG_NO_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC:
+ //intersección pura
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC_EXTREMO_NO_COLIN:
+ //el vértice de un segmento se apoya en el otro segmento, aunque no
+ //en alguno de sus vértices
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC_EXTREMOS_NO_COLIN:
+ //los segmentos comparten un vértice, pero no son colineales
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC_EXTREMOS_COLIN:
+ //los segmentos comparten un vértice y son colineales
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC_MISMO_SEG:
+ //ambos son el mismo segmento
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ case GEOC_SEG_INTERSEC_COLIN:
+ //los segmentos se solapan
+ sal = GEOC_SEG_INTERSEC;
+ break;
+ default:
+ sal = GEOC_SEG_NO_INTERSEC;
+ break;
+ }
+ ////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////
+ //salimos de la función
+ return sal;
+}
+/******************************************************************************/
+/******************************************************************************/
+/** @} */
+/******************************************************************************/
+/******************************************************************************/
+/* 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 100644
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@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; */