├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
├── visilibity.cpp
├── visilibity.hpp
├── visilibity.i
├── visilibity.py
└── visilibity_test.py
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | env:
4 | CIBW_BEFORE_ALL_LINUX: yum install -y http://springdale.princeton.edu/data/springdale/6/x86_64/os/Computational/swig307-3.0.7-3.sdl6.x86_64.rpm && alias swig='swig307'
5 | CIBW_BEFORE_ALL_WINDOWS: choco install swig -f -y
6 | CIBW_BEFORE_ALL_MACOS: brew install swig
7 |
8 |
9 | on: [push, pull_request]
10 |
11 | jobs:
12 |
13 | build_wheels:
14 | name: Build wheels on ${{ matrix.os }}
15 | runs-on: ${{ matrix.os }}
16 | strategy:
17 | matrix:
18 | os: [ubuntu-18.04, windows-latest, macos-latest]
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 |
23 | - uses: actions/setup-python@v2
24 | name: Install Python
25 | with:
26 | python-version: '3.7'
27 |
28 | - name: Install cibuildwheel
29 | run: |
30 | python -m pip install cibuildwheel==1.5.5
31 |
32 | - name: Install Visual C++
33 | if: runner.os == 'Windows'
34 | run: |
35 | choco install vcpython27 -f -y
36 |
37 | - name: Build wheels
38 | run: |
39 | python -m cibuildwheel --output-dir wheelhouse
40 |
41 | - uses: actions/upload-artifact@v2
42 | with:
43 | path: ./wheelhouse/*.whl
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include visilibity.hpp
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PyVisiLibity
2 | Python binding of [VisiLibity 1](https://karlobermeyer.github.io/VisiLibity1/).
3 |
4 | Support both Python 2.7 and Python >= 3
5 |
6 |
7 | ## Installtion
8 |
9 |
10 | `swig` is required to build C++ extension.
11 | Check [here](https://github.com/swig/swig/wiki/Getting-Started) for the instruction.
12 |
13 |
14 | To install the Python package:
15 |
16 | `pip install visilibity`
17 |
18 | ## Run test with example
19 |
20 | After installation, it would possible to run the test example `visilibity_test.py`.
21 |
22 | Get a copy of test file from this [repository](https://github.com/tsaoyu/PyVisiLibity) and run
23 |
24 | `python visilibity_test.py`
25 |
26 | The test script is self-explanatory. If anything wrong make sure you have `matplotlib` installed and configured.
27 |
28 | ## Issue
29 |
30 | Please file me any issue related to the installtion and usage of PyVisiLibity in this repository.
31 | However any issue concerned about the core function of PyVisiLibity such as add new feature, bug report need to be raised at original VisiLibity [repository](https://github.com/karlobermeyer/VisiLibity1).
32 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # PyVisiLibity: a Python binding of VisiLibity1
3 | # Copyright (C) 2018 Yu Cao < University of Southampton> Yu.Cao at soton.ac.uk
4 | #
5 | # This program is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or
8 | # (at your option) any later version.
9 |
10 | # This program is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU Lesser General Public License for more details.
14 |
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with this program. If not, see .
17 |
18 | from distutils.core import setup, Extension
19 | from distutils.command.build import build
20 |
21 | class CustomBuild(build):
22 | sub_commands = [
23 | ('build_ext', build.has_ext_modules),
24 | ('build_py', build.has_pure_modules),
25 | ('build_clib', build.has_c_libraries),
26 | ('build_scripts', build.has_scripts),
27 | ]
28 |
29 | module = Extension('_visilibity', swig_opts = ['-c++'],
30 | sources = ['visilibity.i', 'visilibity.cpp'],
31 | headers = ['visilibity.hpp'], include = ['visilibity.hpp'])
32 |
33 | setup (name = 'VisiLibity',
34 | version = '1.0.10',
35 | cmdclass = {'build': CustomBuild},
36 | author = 'Yu Cao',
37 | author_email = 'yu.cao@soton.ac.uk',
38 | license = 'LGPL',
39 | url = 'https://github.com/tsaoyu/PyVisiLibity',
40 | description = 'Python bindings of VisiLibity1',
41 | py_modules = ['visilibity'],
42 | ext_modules = [module])
43 |
--------------------------------------------------------------------------------
/visilibity.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \file visilibity.hpp
3 | * \authors Karl J. Obermeyer
4 | * \date March 20, 2008
5 | *
6 | VisiLibity: A Floating-Point Visibility Algorithms Library,
7 | Copyright (C) 2008 Karl J. Obermeyer (karl.obermeyer [ at ] gmail.com)
8 |
9 | This file is part of VisiLibity.
10 |
11 | VisiLibity is free software: you can redistribute it and/or modify it under
12 | the terms of the GNU Lesser General Public License as published by the
13 | Free Software Foundation, either version 3 of the License, or (at your
14 | option) any later version.
15 |
16 | VisiLibity is distributed in the hope that it will be useful, but WITHOUT
17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 | License for more details.
20 |
21 | You should have received a copy of the GNU Lesser General Public
22 | License along with VisiLibity. If not, see .
23 | */
24 |
25 | /**
26 | * \mainpage
27 | *
28 | * see also the VisiLibity Project Page
29 | *
30 | * Authors: Karl J. Obermeyer
31 | *
32 | * \section developers For Developers
33 | * Coding Standards
34 | *
35 | * \section release_notes Release Notes
36 | * Current Functionality
37 | *
38 | * - visibility polygons in polygonal environments with holes
39 | * - visibility graphs
40 | * - shortest path planning for a point
41 | *
42 | */
43 |
44 | #ifndef VISILIBITY_H
45 | #define VISILIBITY_H
46 |
47 |
48 | //Uncomment these lines when compiling under
49 | //Microsoft Visual Studio
50 | /*
51 | #include
52 | #define NAN std::numeric_limits::quiet_NaN()
53 | #define INFINITY std::numeric_limits::infinity()
54 | #define M_PI 3.141592653589793238462643
55 | #define and &&
56 | #define or ||
57 | */
58 |
59 | #include //math functions in std namespace
60 | #include
61 | #include //queue and priority_queue.
62 | #include //priority queues with iteration,
63 | //integrated keys
64 | #include
65 | #include //sorting, min, max, reverse
66 | #include //rand and srand
67 | #include //Unix time
68 | #include //file I/O
69 | #include
70 | #include //C-string manipulation
71 | #include //string class
72 | #include //assertions
73 |
74 |
75 | /// VisiLibity's sole namespace
76 | namespace VisiLibity
77 | {
78 |
79 | //Fwd declaration of all classes and structs serves as index.
80 | struct Bounding_Box;
81 | class Point;
82 | class Line_Segment;
83 | class Angle;
84 | class Ray;
85 | class Polar_Point;
86 | class Polyline;
87 | class Polygon;
88 | class Environment;
89 | class Guards;
90 | class Visibility_Polygon;
91 | class Visibility_Graph;
92 |
93 |
94 | /** \brief floating-point display precision.
95 | *
96 | * This is the default precision with which floating point
97 | * numbers are displayed or written to files for classes with a
98 | * write_to_file() method.
99 | */
100 | const int FIOS_PRECISION = 10;
101 |
102 |
103 | /** \brief get a uniform random sample from an (inclusive) interval
104 | * on the real line
105 | *
106 | * \author Karl J. Obermeyer
107 | * \param lower_bound lower bound of the real interval
108 | * \param upper_bound upper bound of the real interval
109 | * \pre \a lower_bound <= \a upper_bound
110 | * \return a random sample from a uniform probability distribution
111 | * on the real interval [\a lower_bound, \a upper_bound]
112 | * \remarks Uses the Standard Library's rand() function. rand()
113 | * should be seeded (only necessary once at the beginning of the
114 | * program) using the command
115 | * std::srand( std::time( NULL ) ); rand();
116 | * \warning performance degrades as upper_bound - lower_bound
117 | * approaches RAND_MAX.
118 | */
119 | double uniform_random_sample(double lower_bound, double upper_bound);
120 |
121 |
122 | /** \brief rectangle with sides parallel to the x- and y-axes
123 | *
124 | * \author Karl J. Obermeyer
125 | * Useful for enclosing other geometric objects.
126 | */
127 | struct Bounding_Box { double x_min, x_max, y_min, y_max; };
128 |
129 |
130 | /// Point in the plane represented by Cartesian coordinates
131 | class Point
132 | {
133 | public:
134 | //Constructors
135 | /** \brief default
136 | *
137 | * \remarks Data defaults to NAN so that checking whether the
138 | * data are numbers can be used as a precondition in functions.
139 | */
140 | Point() : x_(NAN) , y_(NAN) { }
141 | /// costruct from raw coordinates
142 | Point(double x_temp, double y_temp)
143 | { x_=x_temp; y_=y_temp; }
144 | //Accessors
145 | /// get x coordinate
146 | double x () const { return x_; }
147 | /// get y coordinate
148 | double y () const { return y_; }
149 | /** \brief closest Point on \a line_segment_temp
150 | *
151 | * \author Karl J. Obermeyer
152 | * \pre the calling Point data are numbers
153 | * and \a line_segment_temp is nonempty
154 | * \return the Point on \a line_segment_temp which is the smallest
155 | * Euclidean distance from the calling Point
156 | */
157 | Point projection_onto(const Line_Segment& line_segment_temp) const;
158 | /** \brief closest Point on \a ray_temp
159 | *
160 | * \author Karl J. Obermeyer
161 | * \pre the calling Point and \a ray_temp data are numbers
162 | * \return the Point on \a ray_temp which is the smallest
163 | * Euclidean distance from the calling Point
164 | */
165 | Point projection_onto(const Ray& ray_temp) const;
166 | /** \brief closest Point on \a polyline_temp
167 | *
168 | * \pre the calling Point data are numbers and \a polyline_temp
169 | * is nonempty
170 | * \return the Point on \a polyline_temp which is the smallest
171 | * Euclidean distance from the calling Point
172 | */
173 | Point projection_onto(const Polyline& polyline_temp) const;
174 | /** \brief closest vertex of \a polygon_temp
175 | *
176 | * \author Karl J. Obermeyer
177 | * \pre the calling Point data are numbers and \a polygon_temp
178 | * is nonempty
179 | * \return the vertex of \a polygon_temp which is the
180 | * smallest Euclidean distance from the calling Point
181 | */
182 | Point projection_onto_vertices_of(const Polygon& polygon_temp) const;
183 | /** \brief closest vertex of \a environment_temp
184 | *
185 | * \author Karl J. Obermeyer
186 | * \pre the calling Point data are numbers and \a environment_temp
187 | * is nonempty
188 | * \return the vertex of \a environment_temp which is
189 | * the smallest Euclidean distance from the calling Point
190 | */
191 | Point projection_onto_vertices_of(const Environment&
192 | enviroment_temp) const;
193 | /** \brief closest Point on boundary of \a polygon_temp
194 | *
195 | * \author Karl J. Obermeyer
196 | * \pre the calling Point data are numbers and \a polygon_temp
197 | * is nonempty
198 | * \return the Point on the boundary of \a polygon_temp which is the
199 | * smallest Euclidean distance from the calling Point
200 | */
201 | Point projection_onto_boundary_of(const Polygon& polygon_temp) const;
202 | /** \brief closest Point on boundary of \a environment_temp
203 | *
204 | * \author Karl J. Obermeyer
205 | * \pre the calling Point data are numbers and \a environment_temp
206 | * is nonempty
207 | * \return the Point on the boundary of \a environment_temp which is
208 | * the smalles Euclidean distance from the calling Point
209 | */
210 | Point projection_onto_boundary_of(const Environment&
211 | enviroment_temp) const;
212 | /** \brief true iff w/in \a epsilon of boundary of \a polygon_temp
213 | *
214 | * \author Karl J. Obermeyer
215 | * \pre the calling Point data are numbers and \a polygon_temp
216 | * is nonempty
217 | * \return true iff the calling Point is within Euclidean distance
218 | * \a epsilon of \a polygon_temp 's boundary
219 | * \remarks O(n) time complexity, where n is the number
220 | * of vertices of \a polygon_temp
221 | */
222 | bool on_boundary_of(const Polygon& polygon_temp,
223 | double epsilon=0.0) const;
224 | /** \brief true iff w/in \a epsilon of boundary of \a environment_temp
225 | *
226 | * \author Karl J. Obermeyer
227 | * \pre the calling Point data are numbers and \a environment_temp
228 | * is nonempty
229 | * \return true iff the calling Point is within Euclidean distance
230 | * \a epsilon of \a environment_temp 's boundary
231 | * \remarks O(n) time complexity, where n is the number
232 | * of vertices of \a environment_temp
233 | */
234 | bool on_boundary_of(const Environment& environment_temp,
235 | double epsilon=0.0) const;
236 | /** \brief true iff w/in \a epsilon of \a line_segment_temp
237 | *
238 | * \author Karl J. Obermeyer
239 | * \pre the calling Point data are numbers and \a line_segment_temp
240 | * is nonempty
241 | * \return true iff the calling Point is within distance
242 | * \a epsilon of the (closed) Line_Segment \a line_segment_temp
243 | */
244 | bool in(const Line_Segment& line_segment_temp,
245 | double epsilon=0.0) const;
246 | /** \brief true iff w/in \a epsilon of interior but greater than
247 | * \a espilon away from endpoints of \a line_segment_temp
248 | *
249 | * \author Karl J. Obermeyer
250 | * \pre the calling Point data are numbers and \a line_segment_temp
251 | * is nonempty
252 | * \return true iff the calling Point is within distance \a
253 | * epsilon of \line_segment_temp, but distance (strictly) greater
254 | * than epsilon from \a line_segment_temp 's endpoints.
255 | */
256 | bool in_relative_interior_of(const Line_Segment& line_segment_temp,
257 | double epsilon=0.0) const;
258 | /** \brief true iff w/in \a epsilon of \a polygon_temp
259 | *
260 | * \author Karl J. Obermeyer
261 | *
262 | * \pre the calling Point data are numbers and \a polygon_temp is
263 | * \a epsilon -simple. Test simplicity with
264 | * Polygon::is_simple(epsilon)
265 | *
266 | * \return true iff the calling Point is a Euclidean distance no greater
267 | * than \a epsilon from the (closed) Polygon (with vertices listed
268 | * either cw or ccw) \a polygon_temp.
269 | * \remarks O(n) time complexity, where n is the number of vertices
270 | * in \a polygon_temp
271 | */
272 | bool in(const Polygon& polygon_temp,
273 | double epsilon=0.0) const;
274 | /** \brief true iff w/in \a epsilon of \a environment_temp
275 | *
276 | * \author Karl J. Obermeyer
277 | *
278 | * \pre the calling Point data are numbers and \a environment_temp
279 | * is nonempty and \a epsilon -valid. Test validity with
280 | * Enviroment::is_valid(epsilon)
281 | *
282 | * \return true iff the calling Point is a Euclidean distance no greater
283 | * than \a epsilon from the in the (closed) Environment \a environment_temp
284 | * \remarks O(n) time complexity, where n is the number of
285 | * vertices in \a environment_temp
286 | */
287 | bool in(const Environment& environment_temp,
288 | double epsilon=0.0) const;
289 | /** \brief true iff w/in \a epsilon of some endpoint
290 | * of \a line_segment_temp
291 | *
292 | * \pre the calling Point data are numbers and \a line_segment_temp
293 | * is nonempty
294 | * \return true iff calling Point is a Euclidean distance no greater
295 | * than \a epsilon from some endpoint of \a line_segment_temp
296 | */
297 | bool is_endpoint_of(const Line_Segment& line_segment_temp,
298 | double epsilon=0.0) const;
299 | //Mutators
300 | /// change x coordinate
301 | void set_x(double x_temp) { x_ = x_temp;}
302 | /// change y coordinate
303 | void set_y(double y_temp) { y_ = y_temp;}
304 | /** \brief relocate to closest vertex if w/in \a epsilon of some
305 | * vertex (of \a polygon_temp)
306 | *
307 | * \author Karl J. Obermeyer
308 | * \pre the calling Point data are numbers and \a polygon_temp
309 | * is nonempty
310 | * \post If the calling Point was a Euclidean distance no greater
311 | * than \a epsilon from any vertex of \a polygon_temp, then it
312 | * will be repositioned to coincide with the closest such vertex
313 | * \remarks O(n) time complexity, where n is the number of
314 | * vertices in \a polygon_temp.
315 | */
316 | void snap_to_vertices_of(const Polygon& polygon_temp,
317 | double epsilon=0.0);
318 | /** \brief relocate to closest vertex if w/in \a epsilon of some
319 | * vertex (of \a environment_temp)
320 | *
321 | * \author Karl J. Obermeyer
322 | * \pre the calling Point data are numbers and \a environment_temp
323 | * is nonempty
324 | * \post If the calling Point was a Euclidean distance no greater
325 | * than \a epsilon from any vertex of \a environment_temp, then it
326 | * will be repositioned to coincide with the closest such vertex
327 | * \remarks O(n) time complexity, where n is the number of
328 | * vertices in \a environment_temp.
329 | */
330 | void snap_to_vertices_of(const Environment& environment_temp,
331 | double epsilon=0.0);
332 | /** \brief relocate to closest Point on boundary if w/in \a epsilon
333 | * of the boundary (of \a polygon_temp)
334 | *
335 | * \author Karl J. Obermeyer
336 | * \pre the calling Point data are numbers and \a polygon_temp
337 | * is nonempty
338 | * \post if the calling Point was a Euclidean distance no greater
339 | * than \a epsilon from the boundary of \a polygon_temp, then it
340 | * will be repositioned to it's projection onto that boundary
341 | * \remarks O(n) time complexity, where n is the number of
342 | * vertices in \a polygon_temp.
343 | */
344 | void snap_to_boundary_of(const Polygon& polygon_temp,
345 | double epsilon=0.0);
346 | /** \brief relocate to closest Point on boundary if w/in \a epsilon
347 | * of the boundary (of \a environment_temp)
348 | *
349 | * \author Karl J. Obermeyer
350 | * \pre the calling Point data are numbers and \a environment_temp
351 | * is nonempty
352 | * \post if the calling Point was a Euclidean distance no greater
353 | * than \a epsilon from the boundary of \a environment_temp, then it
354 | * will be repositioned to it's projection onto that boundary
355 | * \remarks O(n) time complexity, where n is the number of
356 | * vertices in \a environment_temp.
357 | */
358 | void snap_to_boundary_of(const Environment& environment_temp,
359 | double epsilon=0.0);
360 | protected:
361 | double x_;
362 | double y_;
363 | };
364 |
365 |
366 | /** \brief True iff Points' coordinates are identical.
367 | *
368 | * \remarks NAN==NAN returns false, so if either point has
369 | * not been assigned real number coordinates, they will not be ==
370 | */
371 | bool operator == (const Point& point1, const Point& point2);
372 | /// True iff Points' coordinates are not identical.
373 | bool operator != (const Point& point1, const Point& point2);
374 |
375 |
376 | /** \brief compare lexicographic order of points
377 | *
378 | * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
379 | * p1.x()==p2.x() and p1.y() (const Point& point1, const Point& point2);
394 | /** \brief compare lexicographic order of points
395 | *
396 | * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
397 | * p1.x()==p2.x() and p1.y()= (const Point& point1, const Point& point2);
403 | /** \brief compare lexicographic order of points
404 | *
405 | * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
406 | * p1.x()==p2.x() and p1.y() 0
553 | * \return the first Point of the Line_Segment
554 | * \remarks If size() == 1, then both first() and second() are valid
555 | * and will return the same Point
556 | */
557 | Point first() const;
558 | /** \brief second endpoint
559 | *
560 | * \pre size() > 0
561 | * \return the second Point of the Line_Segment
562 | * \remarks If size() == 1, then both first() and second() are valid
563 | * and will return the same Point
564 | */
565 | Point second() const;
566 | /** \brief number of distinct endpoints
567 | *
568 | * \remarks
569 | * size 0 => empty line segment;
570 | * size 1 => degenerate (single point) line segment;
571 | * size 2 => full-fledged (bona fide) line segment
572 | */
573 | unsigned size() const { return size_; }
574 | /** \brief midpoint
575 | *
576 | * \pre size() > 0
577 | */
578 | Point midpoint() const;
579 | /** \brief Euclidean length
580 | *
581 | * \pre size() > 0
582 | */
583 | double length() const;
584 | /** \brief true iff vertices in lex. order
585 | *
586 | * \pre size() > 0
587 | * \return true iff vertices are listed beginning with the vertex
588 | * which is lexicographically smallest (lowest x, then lowest y)
589 | * \remarks lex. comparison is very sensitive to perturbations if
590 | * two Points nearly define a line parallel to one of the axes
591 | */
592 | bool is_in_standard_form() const;
593 | //Mutators
594 | /// assignment operator
595 | Line_Segment& operator = (const Line_Segment& line_segment_temp);
596 | /** \brief set first endpoint
597 | *
598 | * \remarks if \a point_temp is w/in a distance \a epsilon of an existing
599 | * endpoint, the coordinates of \a point_temp are used and size is set to
600 | * 1 as appropriate
601 | */
602 | void set_first(const Point& point_temp, double epsilon=0.0);
603 | /** \brief set second endpoint
604 | *
605 | * \remarks if \a point_temp is w/in a distance \a epsilon of an existing
606 | * endpoint, the coordinates of \a point_temp are used and size is set to
607 | * 1 as appropriate
608 | */
609 | void set_second(const Point& point_temp, double epsilon=0.0);
610 | /** \brief reverse order of endpoints
611 | *
612 | * \post order of endpoints is reversed.
613 | */
614 | void reverse();
615 | /** \brief enforce that lex. smallest endpoint first
616 | *
617 | * \post the lexicographically smallest endpoint (lowest x, then lowest y)
618 | * is first
619 | * \remarks lex. comparison is very sensitive to perturbations if
620 | * two Points nearly define a line parallel to one of the axes
621 | */
622 | void enforce_standard_form();
623 | /// erase both endpoints and set line segment empty (size 0)
624 | void clear();
625 | /// destructor
626 | virtual ~Line_Segment();
627 | protected:
628 | //Pointer to dynamic array of endpoints.
629 | Point *endpoints_;
630 | //See size() comments.
631 | unsigned size_;
632 | };
633 |
634 |
635 | /** \brief true iff endpoint coordinates are exactly equal, but
636 | * false if either Line_Segment has size 0
637 | *
638 | * \remarks respects ordering of vertices, i.e., even if the line segments
639 | * overlap exactly, they are not considered == unless the orientations are
640 | * the same
641 | */
642 | bool operator == (const Line_Segment& line_segment1,
643 | const Line_Segment& line_segment2);
644 | /// true iff endpoint coordinates are not ==
645 | bool operator != (const Line_Segment& line_segment1,
646 | const Line_Segment& line_segment2);
647 |
648 |
649 | /** \brief true iff line segments' endpoints match up w/in a (closed)
650 | * \a epsilon ball of each other, but false if either
651 | * Line_Segment has size 0
652 | *
653 | * \author Karl J. Obermeyer
654 | * \remarks this function will return true even if it has to flip
655 | * the orientation of one of the segments to get the vertices to
656 | * match up
657 | */
658 | bool equivalent(Line_Segment line_segment1,
659 | Line_Segment line_segment2, double epsilon=0);
660 |
661 |
662 | /** \brief Euclidean distance between Line_Segments
663 | *
664 | * \author Karl J. Obermeyer
665 | * \pre \a line_segment1.size() > 0 and \a line_segment2.size() > 0
666 | */
667 | double distance(const Line_Segment& line_segment1,
668 | const Line_Segment& line_segment2);
669 |
670 |
671 | /** \brief Euclidean distance between a Line_Segment and the
672 | * boundary of a Polygon
673 | *
674 | * \author Karl J. Obermeyer
675 | * \pre \a line_segment.size() > 0 and \a polygon.n() > 0
676 | */
677 | double boundary_distance(const Line_Segment& line_segment,
678 | const Polygon& polygon);
679 |
680 |
681 | /** \brief Euclidean distance between a Line_Segment and the
682 | * boundary of a Polygon
683 | *
684 | * \author Karl J. Obermeyer
685 | * \pre \a line_segment.size() > 0 and \a polygon.n() > 0
686 | */
687 | double boundary_distance(const Polygon& polygon,
688 | const Line_Segment& line_segment);
689 |
690 |
691 | /** \brief true iff the Euclidean distance between Line_Segments is
692 | * no greater than \a epsilon, false if either line segment
693 | * has size 0
694 | *
695 | * \author Karl J. Obermeyer
696 | */
697 | bool intersect(const Line_Segment& line_segment1,
698 | const Line_Segment& line_segment2,
699 | double epsilon=0.0);
700 |
701 |
702 | /** \brief true iff line segments intersect properly w/in epsilon,
703 | * false if either line segment has size 0
704 | *
705 | * \author Karl J. Obermeyer
706 | * \return true iff Line_Segments intersect exactly at a single
707 | * point in their relative interiors. For robustness, here the
708 | * relative interior of a Line_Segment is consider to be any Point
709 | * in the Line_Segment which is a distance greater than \a epsilon
710 | * from both endpoints.
711 | */
712 | bool intersect_proper(const Line_Segment& line_segment1,
713 | const Line_Segment& line_segment2,
714 | double epsilon=0.0);
715 |
716 |
717 | /** \brief intersection of Line_Segments
718 | *
719 | * \author Karl J. Obermeyer
720 | * \return a Line_Segment of size 0, 1, or 2
721 | * \remarks size 0 results if the distance (or at least the
722 | * floating-point computed distance) between line_segment1 and
723 | * line_segment2 is (strictly) greater than epsilon. size 1 results
724 | * if the segments intersect poperly, form a T intersection, or --
725 | * intersection. size 2 results when two or more endpoints are a
726 | * Euclidean distance no greater than \a epsilon from the opposite
727 | * segment, and the overlap of the segments has a length greater
728 | * than \a epsilon.
729 | */
730 | Line_Segment intersection(const Line_Segment& line_segment1,
731 | const Line_Segment& line_segment2,
732 | double epsilon=0.0);
733 |
734 |
735 | /// print a Line_Segment
736 | std::ostream& operator << (std::ostream& outs,
737 | const Line_Segment& line_segment_temp);
738 |
739 |
740 | /** \brief angle in radians represented by a value in
741 | * the interval [0,2*M_PI]
742 | *
743 | * \remarks the intended interpretation is that angles 0 and 2*M_PI
744 | * correspond to the positive x-axis of the coordinate system
745 | */
746 | class Angle
747 | {
748 | public:
749 | //Constructors
750 | /** \brief default
751 | *
752 | * \remarks data defaults to NAN so that checking whether the
753 | * data are numbers can be used as a precondition in functions
754 | */
755 | Angle() : angle_radians_(NAN) { }
756 | /// construct from real value, mod into interval [0, 2*M_PI)
757 | Angle(double data_temp);
758 | /** \brief construct using 4 quadrant inverse tangent into [0, 2*M_PI),
759 | * where 0 points along the x-axis
760 | */
761 | Angle(double rise_temp, double run_temp);
762 | //Accessors
763 | /// get radians
764 | double get() const { return angle_radians_; }
765 | //Mutators
766 | /// set angle, mod into interval [0, 2*PI)
767 | void set(double data_temp);
768 | /** \brief set angle data to 2*M_PI
769 | *
770 | * \remarks sometimes it is necessary to set the angle value to
771 | * 2*M_PI instead of 0, so that the lex. inequalities behave
772 | * appropriately during a radial line sweep
773 | */
774 | void set_to_2pi() { angle_radians_=2*M_PI; }
775 | /// set to new random angle in [0, 2*M_PI)
776 | void randomize();
777 | private:
778 | double angle_radians_;
779 | };
780 |
781 |
782 | /// compare angle radians
783 | bool operator == (const Angle& angle1, const Angle& angle2);
784 | /// compare angle radians
785 | bool operator != (const Angle& angle1, const Angle& angle2);
786 |
787 |
788 | /// compare angle radians
789 | bool operator > (const Angle& angle1, const Angle& angle2);
790 | /// compare angle radians
791 | bool operator < (const Angle& angle1, const Angle& angle2);
792 | /// compare angle radians
793 | bool operator >= (const Angle& angle1, const Angle& angle2);
794 | /// compare angle radians
795 | bool operator <= (const Angle& angle1, const Angle& angle2);
796 |
797 |
798 | /// add angles' radians and mod into [0, 2*M_PI)
799 | Angle operator + (const Angle& angle1, const Angle& angle2);
800 | /// subtract angles' radians and mod into [0, 2*M_PI)
801 | Angle operator - (const Angle& angle1, const Angle& angle2);
802 |
803 |
804 | /** \brief geodesic distance in radians between Angles
805 | *
806 | * \author Karl J. Obermeyer
807 | * \pre \a angle1 and \a angle2 data are numbers
808 | */
809 | double geodesic_distance(const Angle& angle1, const Angle& angle2);
810 |
811 |
812 | /** \brief 1.0 => geodesic path from angle1 to angle2
813 | * is couterclockwise, -1.0 => clockwise
814 | *
815 | * \author Karl J. Obermeyer
816 | * \pre \a angle1 and \a angle2 data are numbers
817 | */
818 | double geodesic_direction(const Angle& angle1, const Angle& angle2);
819 |
820 |
821 | /// print Angle
822 | std::ostream& operator << (std::ostream& outs, const Angle& angle_temp);
823 |
824 |
825 | /** \brief Point in the plane packaged together with polar
826 | * coordinates w.r.t. specified origin
827 | *
828 | * The origin of the polar coordinate system is stored with the
829 | * Polar_Point (in \a polar_origin_) and bearing is measured ccw from the
830 | * positive x-axis.
831 | * \remarks used, e.g., for radial line sweeps
832 | */
833 | class Polar_Point : public Point
834 | {
835 | public:
836 | //Constructors
837 | /** \brief default
838 | *
839 | * \remarks Data defaults to NAN so that checking whether the
840 | * data are numbers can be used as a precondition in functions.
841 | */
842 | Polar_Point() : Point(), range_(NAN), bearing_(NAN) { }
843 | /** \brief construct from (Cartesian) Points
844 | *
845 | * \pre member data of \a polar_origin_temp and \a point_temp have
846 | * been assigned (numbers)
847 | * \param polar_origin_temp the origin of the polar coordinate system
848 | * \param point_temp the point to be represented
849 | * \remarks if polar_origin_temp == point_temp, the default
850 | * bearing is Angle(0.0)
851 | */
852 | Polar_Point(const Point& polar_origin_temp,
853 | const Point& point_temp,
854 | double epsilon=0.0);
855 | //Accessors
856 | /** \brief origin of the polar coordinate system in which the point is
857 | * represented
858 | */
859 | Point polar_origin() const { return polar_origin_; }
860 | /// Euclidean distance from the point represented to the origin of
861 | /// the polar coordinate system
862 | double range() const { return range_; }
863 | /// bearing from polar origin w.r.t. direction parallel to x-axis
864 | Angle bearing() const { return bearing_; }
865 | //Mutators
866 | /** \brief set the origin of the polar coordinate system
867 | *
868 | * \remarks x and y held constant, bearing and range modified
869 | * accordingly
870 | */
871 | void set_polar_origin(const Point& polar_origin_temp);
872 | /** \brief set x
873 | *
874 | * \remarks polar_origin held constant, bearing and range modified
875 | * accordingly
876 | */
877 | void set_x(double x_temp);
878 | /** \brief set y
879 | *
880 | * \remarks polar_origin held constant, bearing and range modified
881 | * accordingly
882 | */
883 | void set_y(double y_temp);
884 | /** \brief set range
885 | *
886 | * \remarks polar_origin held constant, x and y modified
887 | * accordingly
888 | */
889 | void set_range(double range_temp);
890 | /** \brief set bearing
891 | *
892 | * \remarks polar_origin and range held constant, x and y modified
893 | * accordingly
894 | */
895 | void set_bearing(const Angle& bearing_temp);
896 | /** \brief set bearing Angle data to 2*M_PI
897 | *
898 | * \remarks Special function for use in computations involving a
899 | * radial line sweep; sometimes it is necessary to set the angle
900 | * value to 2*PI instead of 0, so that the lex. inequalities
901 | * behave appropriately
902 | */
903 | void set_bearing_to_2pi() { bearing_.set_to_2pi(); }
904 | protected:
905 | //Origin of the polar coordinate system in world coordinates.
906 | Point polar_origin_;
907 | //Polar coordinates where radius always positive, and angle
908 | //measured ccw from the world coordinate system's x-axis.
909 | double range_;
910 | Angle bearing_;
911 | };
912 |
913 |
914 | /** \brief compare member data
915 | *
916 | * \remarks returns false if any member data are NaN
917 | */
918 | bool operator == (const Polar_Point& polar_point1,
919 | const Polar_Point& polar_point2);
920 | bool operator != (const Polar_Point& polar_point1,
921 | const Polar_Point& polar_point2);
922 |
923 |
924 | /** \brief compare according to polar lexicographic order
925 | * (smaller bearing, then smaller range)
926 | *
927 | * false if any member data have not been assigned (numbers)
928 | * \remarks lex. comparison is very sensitive to perturbations if
929 | * two Points nearly define a radial line
930 | */
931 | bool operator > (const Polar_Point& polar_point1,
932 | const Polar_Point& polar_point2);
933 | /** \brief compare according to polar lexicographic order
934 | * (smaller bearing, then smaller range)
935 | *
936 | * false if any member data have not been assigned (numbers)
937 | * \remarks lex. comparison is very sensitive to perturbations if
938 | * two Points nearly define a radial line
939 | */
940 | bool operator < (const Polar_Point& polar_point1,
941 | const Polar_Point& polar_point2);
942 | /** \brief compare according to polar lexicographic order
943 | * (smaller bearing, then smaller range)
944 | *
945 | * false if any member data have not been assigned (numbers)
946 | * \remarks lex. comparison is very sensitive to perturbations if
947 | * two Points nearly define a radial line
948 | */
949 | bool operator >= (const Polar_Point& polar_point1,
950 | const Polar_Point& polar_point2);
951 | /** \brief compare according to polar lexicographic order
952 | * (smaller bearing, then smaller range)
953 | *
954 | * false if any member data have not been assigned (numbers)
955 | * \remarks lex. comparison is very sensitive to perturbations if
956 | * two Points nearly define a radial line
957 | */
958 | bool operator <= (const Polar_Point& polar_point1,
959 | const Polar_Point& polar_point2);
960 |
961 |
962 | /// print Polar_Point
963 | std::ostream& operator << (std::ostream& outs,
964 | const Polar_Point& polar_point_temp);
965 |
966 |
967 | /// ray in the plane represented by base Point and bearing Angle
968 | class Ray
969 | {
970 | public:
971 | //Constructors
972 | /** \brief default
973 | *
974 | * \remarks data defaults to NAN so that checking whether the data
975 | * are numbers can be used as a precondition in functions
976 | */
977 | Ray() { }
978 | /// construct ray emanating from \a base_point_temp in the direction
979 | /// \a bearing_temp
980 | Ray(Point base_point_temp, Angle bearing_temp) :
981 | base_point_(base_point_temp) , bearing_(bearing_temp) {}
982 | /// construct ray emanating from \a base_point_temp towards
983 | /// \a bearing_point
984 | Ray(Point base_point_temp, Point bearing_point);
985 | //Accessors
986 | /// get base point
987 | Point base_point() const { return base_point_; }
988 | /// get bearing
989 | Angle bearing() const { return bearing_; }
990 | //Mutators
991 | /// set base point
992 | void set_base_point(const Point& point_temp)
993 | { base_point_ = point_temp; }
994 | /// set bearing
995 | void set_bearing(const Angle& angle_temp)
996 | { bearing_ = angle_temp; }
997 | private:
998 | Point base_point_;
999 | Angle bearing_;
1000 | };
1001 |
1002 |
1003 | /** \brief compare member data
1004 | *
1005 | * \remarks returns false if any member data are NaN
1006 | */
1007 | bool operator == (const Ray& ray1,
1008 | const Ray& ray2);
1009 | /** \brief compare member data
1010 | *
1011 | * \remarks negation of ==
1012 | */
1013 | bool operator != (const Ray& ray1,
1014 | const Ray& ray2);
1015 |
1016 |
1017 | /** \brief compute the intersection of a Line_Segment with a Ray
1018 | *
1019 | * \author Karl J. Obermeyer
1020 | * \pre member data of \a ray_temp has been assigned (numbers) and
1021 | * \a line_segment_temp has size greater than 0
1022 | * \remarks as a convention, if the intersection has positive
1023 | * length, the Line_Segment returned has the first point closest to
1024 | * the Ray's base point
1025 | */
1026 | Line_Segment intersection(const Ray ray_temp,
1027 | const Line_Segment& line_segment_temp,
1028 | double epsilon=0.0);
1029 | /** \brief compute the intersection of a Line_Segment with a Ray
1030 | *
1031 | * \author Karl J. Obermeyer
1032 | * \pre member data of \a ray_temp has been assigned (numbers) and
1033 | * \a line_segment_temp has size greater than 0
1034 | * \remarks as a convention, if the intersection has positive
1035 | * length, the Line_Segment returned has the first point closest to
1036 | * the Ray's base point
1037 | */
1038 | Line_Segment intersection(const Line_Segment& line_segment_temp,
1039 | const Ray& ray_temp,
1040 | double epsilon=0.0);
1041 |
1042 |
1043 | ///oriented polyline in the plane represented by list of vertices
1044 | class Polyline
1045 | {
1046 | public:
1047 | friend class Point;
1048 | //Constructors
1049 | /// default to empty
1050 | Polyline() { }
1051 | /// construct from vector of vertices
1052 | Polyline(const std::vector& vertices_temp)
1053 | { vertices_ = vertices_temp; }
1054 | //Accessors
1055 | /** \brief raw access
1056 | *
1057 | * \remarks for efficiency, no bounds checks; usually trying to
1058 | * access out of bounds causes a bus error
1059 | */
1060 | Point operator [] (unsigned i) const
1061 | { return vertices_[i]; }
1062 | /// vertex count
1063 | unsigned size() const
1064 | { return vertices_.size(); }
1065 | /// Euclidean length of the Polyline
1066 | double length() const;
1067 | /** \brief Euclidean diameter
1068 | *
1069 | * \pre Polyline has greater than 0 vertices
1070 | * \return the maximum Euclidean distance between all pairs of
1071 | * vertices
1072 | * \remarks time complexity O(n^2), where n is the number of
1073 | * vertices representing the Polyline
1074 | */
1075 | double diameter() const;
1076 | //a box which fits snugly around the Polyline
1077 | Bounding_Box bbox() const;
1078 | //Mutators
1079 | /** \brief raw access
1080 | *
1081 | * \remarks for efficiency, no bounds checks; usually trying to
1082 | * access out of bounds causes a bus error
1083 | */
1084 | Point& operator [] (unsigned i)
1085 | { return vertices_[i]; }
1086 | /// erase all points
1087 | void clear()
1088 | { vertices_.clear(); }
1089 | /// add a vertex to the back (end) of the list
1090 | void push_back(const Point& point_temp)
1091 | { vertices_.push_back(point_temp); }
1092 | /// delete a vertex to the back (end) of the list
1093 | void pop_back()
1094 | { vertices_.pop_back(); }
1095 | /// reset the whole list of vertices at once
1096 | void set_vertices(const std::vector& vertices_temp)
1097 | { vertices_ = vertices_temp; }
1098 | /** \brief eliminates vertices which are (\a epsilon) - colinear
1099 | * with their respective neighbors
1100 | *
1101 | * \author Karl J. Obermeyer
1102 | * \post the Euclidean distance between each vertex and the line
1103 | * segment connecting its neighbors is at least \a epsilon
1104 | * \remarks time complexity O(n), where n is the number of
1105 | * vertices representing the Polyline.
1106 | */
1107 | void eliminate_redundant_vertices(double epsilon=0.0);
1108 | //Reduce number of vertices in representation...
1109 | //void smooth(double epsilon);
1110 | /// reverse order of vertices
1111 | void reverse();
1112 | /// append the points from another polyline
1113 | std::vector path();
1114 | /// show all vertices of the polyline
1115 | void append( const Polyline& polyline );
1116 | private:
1117 | std::vector vertices_;
1118 | };
1119 |
1120 |
1121 | //print Polyline
1122 | std::ostream& operator << (std::ostream& outs,
1123 | const Polyline& polyline_temp);
1124 |
1125 |
1126 | /** \brief simple polygon in the plane represented by list of vertices
1127 | *
1128 | * Simple here means non-self-intersecting. More precisely, edges
1129 | * should not (i) intersect with an edge not adjacent to it, nor
1130 | * (ii) intersect at more than one Point with an adjacent edge.
1131 | * \remarks vertices may be listed cw or ccw
1132 | */
1133 | class Polygon
1134 | {
1135 | public:
1136 | friend class Point;
1137 | //Constructors
1138 | ///default to empty
1139 | Polygon() { }
1140 | /** \brief construct from *.polygon file
1141 | *
1142 | * \author Karl J. Obermeyer
1143 | * \remarks for efficiency, simplicity check not called here
1144 | */
1145 | Polygon(const std::string& filename);
1146 | /** \brief construct from vector of vertices
1147 | *
1148 | * \remarks for efficiency, simplicity check not called here
1149 | */
1150 | Polygon(const std::vector& vertices_temp);
1151 | /** \brief construct triangle from 3 Points
1152 | *
1153 | * \remarks for efficiency, simplicity check not called here
1154 | */
1155 | Polygon(const Point& point0, const Point& point1, const Point& point2);
1156 | //Accessors
1157 | /** \brief access with automatic wrap-around in forward direction
1158 | *
1159 | * \remarks For efficiency, no bounds check; usually trying to
1160 | * access out of bounds causes a bus error
1161 | */
1162 | const Point& operator [] (unsigned i) const
1163 | { return vertices_[i % vertices_.size()]; }
1164 | /** \brief vertex count
1165 | *
1166 | * \remarks O(1) time complexity
1167 | */
1168 | unsigned n() const { return vertices_.size(); }
1169 | /** \brief reflex vertex count (nonconvex vertices)
1170 | *
1171 | * \author Karl J. Obermeyer
1172 | * \remarks Works regardless of polygon orientation (ccw vs cw),
1173 | * but assumes no redundant vertices. Time complexity O(n), where
1174 | * n is the number of vertices representing the Polygon
1175 | */
1176 | unsigned r() const;
1177 | /** \brief true iff Polygon is (\a epsilon) simple
1178 | *
1179 | * \author Karl J. Obermeyer
1180 | *
1181 | * \remarks A Polygon is considered \a epsilon -simple iff (i) the
1182 | * Euclidean distance between nonadjacent edges is no greater than
1183 | * \a epsilon, (ii) adjacent edges intersect only at their single
1184 | * shared Point, (iii) and it has at least 3 vertices. One
1185 | * consequence of these conditions is that there can be no
1186 | * redundant vertices.
1187 | */
1188 | bool is_simple(double epsilon=0.0) const;
1189 | /** \brief true iff lexicographically smallest vertex is first in
1190 | * the list of vertices representing the Polygon
1191 | *
1192 | * \author Karl J. Obermeyer
1193 | * \remarks lex. comparison is very sensitive to perturbations if
1194 | * two Points nearly define a line parallel to one of the axes
1195 | */
1196 | bool is_in_standard_form() const;
1197 | /// perimeter length
1198 | double boundary_length() const;
1199 | /** oriented area of the Polygon
1200 | *
1201 | * \author Karl J. Obermeyer
1202 | * \pre Polygon is simple, but for efficiency simplicity is not asserted.
1203 | * area > 0 => vertices listed ccw,
1204 | * area < 0 => cw
1205 | * \remarks O(n) time complexity, where n is the number
1206 | * of vertices representing the Polygon
1207 | */
1208 | double area() const;
1209 | /** \brief Polygon's centroid (center of mass)
1210 | *
1211 | * \author Karl J. Obermeyer
1212 | * \pre Polygon has greater than 0 vertices and is simple,
1213 | * but for efficiency simplicity is not asserted
1214 | */
1215 | Point centroid() const;
1216 | /** \brief Euclidean diameter
1217 | *
1218 | * \pre Polygon has greater than 0 vertices
1219 | * \return maximum Euclidean distance between all pairs of
1220 | * vertices
1221 | * \remarks time complexity O(n^2), where n is the number of
1222 | * vertices representing the Polygon
1223 | */
1224 | double diameter() const;
1225 | /** \brief box which fits snugly around the Polygon
1226 | *
1227 | * \author Karl J. Obermeyer
1228 | * \pre Polygon has greater than 0 vertices
1229 | */
1230 | Bounding_Box bbox() const;
1231 | // Returns a vector of n pts randomly situated in the polygon.
1232 | std::vector random_points(const unsigned& count,
1233 | double epsilon=0.0) const;
1234 | /** \brief write list of vertices to *.polygon file
1235 | *
1236 | * \author Karl J. Obermeyer
1237 | * Uses intuitive human and computer readable decimal format with
1238 | * display precision \a fios_precision_temp.
1239 | * \pre \a fios_precision_temp >=1
1240 | */
1241 | void write_to_file(const std::string& filename,
1242 | int fios_precision_temp=FIOS_PRECISION);
1243 | //Mutators
1244 | /** \brief access with automatic wrap-around in forward direction
1245 | *
1246 | * \remarks for efficiency, no bounds check; usually trying to
1247 | * access out of bounds causes a bus error
1248 | */
1249 | Point& operator [] (unsigned i) { return vertices_[i % vertices_.size()]; }
1250 | /// set vertices using STL vector of Points
1251 | void set_vertices(const std::vector& vertices_temp)
1252 | { vertices_ = vertices_temp; }
1253 | /// push a Point onto the back of the vertex list
1254 | void push_back(const Point& vertex_temp )
1255 | { vertices_.push_back( vertex_temp ); }
1256 | /// erase all vertices
1257 | void clear()
1258 | { vertices_.clear(); }
1259 | /** \brief enforces that the lexicographically smallest vertex is first
1260 | * in the list of vertices representing the Polygon
1261 | *
1262 | * \author Karl J. Obermeyer
1263 | * \remarks O(n) time complexity, where n is the number of
1264 | * vertices representing the Polygon. Lex. comparison is very
1265 | * sensitive to perturbations if two Points nearly define a line
1266 | * parallel to one of the axes
1267 | */
1268 | void enforce_standard_form();
1269 | /** \brief eliminates vertices which are (\a epsilon) - colinear
1270 | * with their respective neighbors
1271 | *
1272 | * \author Karl J. Obermeyer
1273 | * \post the Euclidean distance between each vertex and the line
1274 | * segment connecting its neighbors is at least \a epsilon, and the
1275 | * Polygon is in standard form
1276 | * \remarks time complexity O(n), where n is the number of
1277 | * vertices representing the the Polygon
1278 | */
1279 | void eliminate_redundant_vertices(double epsilon=0.0);
1280 | /** \brief reverse (cyclic) order of vertices
1281 | *
1282 | * \remarks vertex first in list is held first
1283 | */
1284 | void reverse();
1285 | protected:
1286 | std::vector vertices_;
1287 | };
1288 |
1289 |
1290 | /** \brief true iff vertex lists are identical, but false if either
1291 | * Polygon has size 0
1292 | *
1293 | * \remarks returns false if either Polygon has size 0
1294 | * \remarks O(n) time complexity
1295 | */
1296 | bool operator == (Polygon polygon1, Polygon polygon2);
1297 | bool operator != (Polygon polygon1, Polygon polygon2);
1298 | /** \brief true iff the Polygon's vertices match up w/in a (closed)
1299 | * epsilon ball of each other, but false if either Polygon
1300 | * has size 0
1301 | *
1302 | * Respects number, ordering, and orientation of vertices, i.e.,
1303 | * even if the (conceptual) polygons represented by two Polygons are
1304 | * identical, they are not considered \a epsilon - equivalent unless
1305 | * the number of vertices is the same, the orientations are the same
1306 | * (cw vs. ccw list), and the Points of the vertex lists match up
1307 | * within epsilon. This function does attempt to match the polygons
1308 | * for all possible cyclic permutations, hence the quadratic time
1309 | * complexity.
1310 | * \author Karl J. Obermeyer
1311 | * \remarks O(n^2) time complexity, where n is the number of
1312 | * vertices representing the polygon
1313 | */
1314 | bool equivalent(Polygon polygon1, Polygon polygon2,
1315 | double epsilon=0.0);
1316 |
1317 |
1318 | /** \brief Euclidean distance between Polygons' boundaries
1319 | *
1320 | * \author Karl J. Obermeyer
1321 | * \pre \a polygon1 and \a polygon2 each have greater than 0 vertices
1322 | */
1323 | double boundary_distance( const Polygon& polygon1,
1324 | const Polygon& polygon2 );
1325 |
1326 |
1327 | //print Polygon
1328 | std::ostream& operator << (std::ostream& outs,
1329 | const Polygon& polygon_temp);
1330 |
1331 |
1332 | /** \brief environment represented by simple polygonal outer boundary
1333 | * with simple polygonal holes
1334 | *
1335 | * \remarks For methods to work correctly, the outer boundary vertices must
1336 | * be listed ccw and the hole vertices cw
1337 | */
1338 | class Environment
1339 | {
1340 | public:
1341 | friend class Point;
1342 | //Constructors
1343 | /// default to empty
1344 | Environment() { }
1345 | /** \brief construct Environment without holes
1346 | *
1347 | * \remarks time complexity O(n), where n is the number of vertices
1348 | * representing the Environment
1349 | */
1350 | Environment(const Polygon& polygon_temp)
1351 | { outer_boundary_=polygon_temp; update_flattened_index_key(); }
1352 | /** \brief construct Environment with holes from STL vector of Polygons
1353 | *
1354 | * the first Polygon in the vector becomes the outer boundary,
1355 | * the rest become the holes
1356 | * \remarks time complexity O(n), where n is the number of vertices
1357 | * representing the Environment
1358 | */
1359 | Environment(const std::vector& polygons);
1360 | /** construct from *.environment file.
1361 | *
1362 | * \author Karl J. Obermeyer
1363 | * \remarks time complexity O(n), where n is the number of vertices
1364 | * representing the Environment
1365 | */
1366 | Environment(const std::string& filename);
1367 | //Accessors
1368 | /** \brief raw access to Polygons
1369 | *
1370 | * An argument of 0 accesses the outer boundary, 1 and above
1371 | * access the holes.
1372 | * \remarks for efficiency, no bounds check; usually trying to
1373 | * access out of bounds causes a bus error
1374 | */
1375 | const Polygon& operator [] (unsigned i) const
1376 | { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
1377 | /** \brief raw access to vertices via flattened index
1378 | *
1379 | * By flattened index is intended the label given to a vertex if
1380 | * you were to label all the vertices from 0 to n-1 (where n is
1381 | * the number of vertices representing the Environment) starting
1382 | * with the first vertex of the outer boundary and progressing in
1383 | * order through all the remaining vertices of the outer boundary
1384 | * and holes.
1385 | *
1386 | * \remarks Time complexity O(1). For efficiency, no bounds
1387 | * check; usually trying to access out of bounds causes a bus
1388 | * error.
1389 | */
1390 | const Point& operator () (unsigned k) const;
1391 | /// hole count
1392 | unsigned h() const { return holes_.size(); }
1393 | /** \brief vertex count
1394 | *
1395 | * \remarks time complexity O(h)
1396 | */
1397 | unsigned n() const;
1398 | /** \brief total reflex vertex count (nonconvex vertices)
1399 | *
1400 | * \author Karl J. Obermeyer
1401 | * \remarks time complexity O(n), where n is the number of
1402 | * vertices representing the Environment
1403 | */
1404 | unsigned r() const;
1405 | /** \brief true iff lexicographically smallest vertex is first in
1406 | * each list of vertices representing a Polygon of the
1407 | * Environment
1408 | *
1409 | * \author Karl J. Obermeyer
1410 | * \remarks lex. comparison is very sensitive to perturbations if
1411 | * two Points nearly define a line parallel to one of the axes
1412 | */
1413 | bool is_in_standard_form() const;
1414 | /** \brief true iff \a epsilon -valid
1415 | *
1416 | * \a epsilon -valid means (i) the outer boundary and holes are
1417 | * pairwise \a epsilon -disjoint (no two features should come
1418 | * within \a epsilon of each other) simple polygons, (ii) outer
1419 | * boundary is oriented ccw, and (iii) holes are oriented cw.
1420 | *
1421 | * \author Karl J. Obermeyer
1422 | *
1423 | * \pre Environment has greater than 2 vertices
1424 | * (otherwise it can't even have nonzero area)
1425 | * \remarks time complexity O(h^2*n^2), where h is the number of
1426 | * holes and n is the number of vertices representing the
1427 | * Environment
1428 | */
1429 | bool is_valid(double epsilon=0.0) const;
1430 | /** \brief sum of perimeter lengths of outer boundary and holes
1431 | *
1432 | * \author Karl J. Obermeyer
1433 | * \remarks O(n) time complexity, where n is the number of
1434 | * vertices representing the Environment
1435 | */
1436 | double boundary_length() const;
1437 | /** \brief (obstacle/hole free) area of the Environment
1438 | *
1439 | * \author Karl J. Obermeyer
1440 | * \remarks O(n) time complexity, where n is the number of
1441 | * vertices representing the Environment
1442 | */
1443 | double area() const;
1444 | /** \brief Euclidean diameter
1445 | *
1446 | * \author Karl J. Obermeyer
1447 | * \pre Environment has greater than 0 vertices
1448 | * \return maximum Euclidean distance between all pairs of
1449 | * vertices
1450 | * \remarks time complexity O(n^2), where n is the number of
1451 | * vertices representing the Environment
1452 | */
1453 | double diameter() const { return outer_boundary_.diameter(); }
1454 | /** \brief box which fits snugly around the Environment
1455 | *
1456 | * \author Karl J. Obermeyer
1457 | * \pre Environment has greater than 0 vertices
1458 | */
1459 | Bounding_Box bbox() const { return outer_boundary_.bbox(); }
1460 | /** \brief get STL vector of \a count Points randomly situated
1461 | * within \a epsilon of the Environment
1462 | *
1463 | * \author Karl J. Obermeyer
1464 | * \pre the Environment has positive area
1465 | */
1466 | std::vector random_points(const unsigned& count,
1467 | double epsilon=0.0) const;
1468 | /** \brief compute a shortest path between 2 Points
1469 | *
1470 | * Uses the classical visibility graph method as described, e.g.,
1471 | * in ``Robot Motion Planning" (Ch. 4 Sec. 1) by J.C. Latombe.
1472 | * Specifically, an A* search is performed on the visibility graph
1473 | * using the Euclidean distance as the heuristic function.
1474 | *
1475 | * \author Karl J. Obermeyer
1476 | *
1477 | * \pre \a start and \a finish must be in the environment.
1478 | * Environment must be \a epsilon -valid. Test with
1479 | * Environment::is_valid(epsilon).
1480 | *
1481 | * \remarks If multiple shortest path queries are made for the
1482 | * same Envrionment, it is better to precompute the
1483 | * Visibility_Graph. For a precomputed Visibility_Graph, the time
1484 | * complexity of a shortest_path() query is O(n^2), where n is the
1485 | * number of vertices representing the Environment.
1486 | *
1487 | * \todo return not just one, but all shortest paths (w/in
1488 | * epsilon), e.g., returning a std::vector)
1489 | */
1490 | Polyline shortest_path(const Point& start,
1491 | const Point& finish,
1492 | const Visibility_Graph& visibility_graph,
1493 | double epsilon=0.0);
1494 | /** \brief compute shortest path between 2 Points
1495 | *
1496 | * \author Karl J. Obermeyer
1497 | *
1498 | * \pre \a start and \a finish must be in the environment.
1499 | * Environment must be \a epsilon -valid. Test with
1500 | * Environment::is_valid(epsilon).
1501 | *
1502 | * \remarks For single shortest path query, visibility graph is
1503 | * not precomputed. Time complexity O(n^3), where n is the number
1504 | * of vertices representing the Environment.
1505 | */
1506 | Polyline shortest_path(const Point& start,
1507 | const Point& finish,
1508 | double epsilon=0.0);
1509 | /** \brief compute the faces (partition cells) of an arrangement
1510 | * of Line_Segments inside the Environment
1511 | *
1512 | * \author Karl J. Obermeyer
1513 | * \todo finish this
1514 | */
1515 | std::vector compute_partition_cells( std::vector
1516 | partition_inducing_segments,
1517 | double epsilon=0.0 )
1518 | {
1519 | std::vector cells;
1520 | return cells;
1521 | }
1522 | /** \brief write lists of vertices to *.environment file
1523 | *
1524 | * uses intuitive human and computer readable decimal format with
1525 | * display precision \a fios_precision_temp
1526 | * \author Karl J. Obermeyer
1527 | * \pre \a fios_precision_temp >=1
1528 | */
1529 | void write_to_file(const std::string& filename,
1530 | int fios_precision_temp=FIOS_PRECISION);
1531 | //Mutators
1532 | /** \brief raw access to Polygons
1533 | *
1534 | * An argument of 0 accesses the outer boundary, 1 and above
1535 | * access the holes.
1536 | * \author Karl J. Obermeyer
1537 | * \remarks for efficiency, no bounds check; usually trying to
1538 | * access out of bounds causes a bus error
1539 | */
1540 | Polygon& operator [] (unsigned i)
1541 | { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
1542 | //Mutators
1543 | /** \brief raw access to vertices via flattened index
1544 | *
1545 | * By flattened index is intended the label given to a vertex if
1546 | * you were to label all the vertices from 0 to n-1 (where n is
1547 | * the number of vertices representing the Environment) starting
1548 | * with the first vertex of the outer boundary and progressing in
1549 | * order through all the remaining vertices of the outer boundary
1550 | * and holes.
1551 | * \author Karl J. Obermeyer
1552 | * \remarks for efficiency, no bounds check; usually trying to
1553 | * access out of bounds causes a bus error.
1554 | */
1555 | Point& operator () (unsigned k);
1556 | /// set outer boundary
1557 | void set_outer_boundary(const Polygon& polygon_temp)
1558 | { outer_boundary_ = polygon_temp; update_flattened_index_key(); }
1559 | /// add hole
1560 | void add_hole(const Polygon& polygon_temp)
1561 | { holes_.push_back(polygon_temp); update_flattened_index_key(); }
1562 | /** \brief enforces outer boundary vertices are listed ccw and
1563 | * holes listed cw, and that these lists begin with respective
1564 | * lexicographically smallest vertex
1565 | *
1566 | * \author Karl J. Obermeyer
1567 | * \remarks O(n) time complexity, where n is the number of
1568 | * vertices representing the Environment. Lex. comparison is very
1569 | * sensitive to perturbations if two Points nearly define a line
1570 | * parallel to one of the axes.
1571 | */
1572 | void enforce_standard_form();
1573 | /** \brief eliminates vertices which are (\a epsilon) - colinear
1574 | * with their respective neighbors
1575 | *
1576 | * \author Karl J. Obermeyer
1577 | * \post the Euclidean distance between each vertex and the line
1578 | * segment connecting its neighbors is at least \a epsilon
1579 | * \remarks time complexity O(n), where n is the number of
1580 | * vertices representing the the Environment
1581 | */
1582 | void eliminate_redundant_vertices(double epsilon=0.0);
1583 | /** \brief reverse (cyclic) order of vertices belonging to holes
1584 | * only
1585 | *
1586 | * \remarks vertex first in each hole's list is held first
1587 | */
1588 | void reverse_holes();
1589 | private:
1590 | Polygon outer_boundary_;
1591 | //obstacles
1592 | std::vector holes_;
1593 | //allows constant time access to vertices via operator () with
1594 | //flattened index as argument
1595 | std::vector< std::pair > flattened_index_key_;
1596 | //Must call if size of outer_boundary and/or holes_ changes. Time
1597 | //complexity O(n), where n is the number of vertices representing
1598 | //the Environment.
1599 | void update_flattened_index_key();
1600 | //converts flattened index to index pair (hole #, vertex #) in
1601 | //time O(n), where n is the number of vertices representing the
1602 | //Environment
1603 | std::pair one_to_two(unsigned k) const;
1604 | //node used for search tree of A* search in shortest_path() method
1605 | class Shortest_Path_Node
1606 | {
1607 | public:
1608 | //flattened index of corresponding Environment vertex
1609 | //convention vertex_index = n() => corresponds to start Point
1610 | //vertex_index = n() + 1 => corresponds to finish Point
1611 | unsigned vertex_index;
1612 | //pointer to self in search tree.
1613 | std::list::iterator search_tree_location;
1614 | //pointer to parent in search tree.
1615 | std::list::iterator parent_search_tree_location;
1616 | //Geodesic distance from start Point.
1617 | double cost_to_come;
1618 | //Euclidean distance to finish Point.
1619 | double estimated_cost_to_go;
1620 | //std::vector expand();
1621 | bool operator < (const Shortest_Path_Node& spn2) const
1622 | {
1623 | double f1 = this->cost_to_come + this->estimated_cost_to_go;
1624 | double f2 = spn2.cost_to_come + spn2.estimated_cost_to_go;
1625 | if( f1 < f2 )
1626 | return true;
1627 | else if( f2 < f1 )
1628 | return false;
1629 | else if( this->vertex_index < spn2.vertex_index )
1630 | return true;
1631 | else if( this->vertex_index > spn2.vertex_index )
1632 | return false;
1633 | else if( &(*(this->parent_search_tree_location))
1634 | < &(*(spn2.parent_search_tree_location)) )
1635 | return true;
1636 | else
1637 | return false;
1638 | }
1639 | // print member data for debugging
1640 | void print() const
1641 | {
1642 | std::cout << " vertex_index = " << vertex_index << std::endl
1643 | << "parent's vertex_index = "
1644 | << parent_search_tree_location->vertex_index
1645 | << std::endl
1646 | << " cost_to_come = " << cost_to_come << std::endl
1647 | << " estimated_cost_to_go = "
1648 | << estimated_cost_to_go << std::endl;
1649 | }
1650 | };
1651 | };
1652 |
1653 |
1654 | /// printing Environment
1655 | std::ostream& operator << (std::ostream& outs,
1656 | const Environment& environment_temp);
1657 |
1658 |
1659 | /** \brief set of Guards represented by a list of Points
1660 | */
1661 | class Guards
1662 | {
1663 | public:
1664 | friend class Visibility_Graph;
1665 | //Constructors
1666 | /// default to empty
1667 | Guards() { }
1668 | /** \brief construct from *.guards file
1669 | *
1670 | * \author Karl J. Obermeyer
1671 | */
1672 | Guards(const std::string& filename);
1673 | /// construct from STL vector of Points
1674 | Guards(const std::vector& positions)
1675 | { positions_ = positions; }
1676 | //Accessors
1677 | /** \brief raw access to guard position Points
1678 | *
1679 | * \author Karl J. Obermeyer
1680 | * \remarks for efficiency, no bounds check; usually trying to
1681 | * access out of bounds causes a bus error
1682 | */
1683 | const Point& operator [] (unsigned i) const { return positions_[i]; }
1684 | /// guard count
1685 | unsigned N() const { return positions_.size(); }
1686 | /// true iff positions are lexicographically ordered
1687 | bool are_lex_ordered() const;
1688 | /// true iff no two guards are w/in epsilon of each other
1689 | bool noncolocated(double epsilon=0.0) const;
1690 | /// true iff all guards are located in \a polygon_temp
1691 | bool in(const Polygon& polygon_temp, double epsilon=0.0) const;
1692 | /// true iff all guards are located in \a environment_temp
1693 | bool in(const Environment& environment_temp, double epsilon=0.0) const;
1694 | /** \brief Euclidean diameter
1695 | *
1696 | * \author Karl J. Obermeyer
1697 | * \pre greater than 0 guards
1698 | * \return maximum Euclidean distance between all pairs of
1699 | * vertices
1700 | * \remarks time complexity O(N^2), where N is the number of
1701 | * guards
1702 | */
1703 | double diameter() const;
1704 | /** \brief box which fits snugly around the Guards
1705 | *
1706 | * \author Karl J. Obermeyer
1707 | * \pre greater than 0 guards
1708 | */
1709 | Bounding_Box bbox() const;
1710 | /** \brief write list of positions to *.guards file
1711 | *
1712 | * Uses intuitive human and computer readable decimal format with
1713 | * display precision \a fios_precision_temp.
1714 | * \author Karl J. Obermeyer
1715 | * \pre \a fios_precision_temp >=1
1716 | */
1717 | void write_to_file(const std::string& filename,
1718 | int fios_precision_temp=FIOS_PRECISION);
1719 | //Mutators
1720 | /** \brief raw access to guard position Points
1721 | *
1722 | * \author Karl J. Obermeyer
1723 | * \remarks for efficiency, no bounds check; usually trying to
1724 | * access out of bounds causes a bus error
1725 | */
1726 | Point& operator [] (unsigned i) { return positions_[i]; }
1727 | /// add a guard
1728 | void push_back(const Point& point_temp)
1729 | { positions_.push_back(point_temp); }
1730 | /// set positions with STL vector of Points
1731 | void set_positions(const std::vector& positions_temp)
1732 | { positions_ = positions_temp; }
1733 | /** \brief sort positions in lexicographic order
1734 | *
1735 | * from (lowest x, then lowest y) to (highest x, then highest y)
1736 | * \author Karl J. Obermeyer
1737 | * \remarks time complexity O(N logN), where N is the guard count.
1738 | * Lex. comparison is very sensitive to perturbations if two
1739 | * Points nearly define a line parallel to one of the axes.
1740 | */
1741 | void enforce_lex_order();
1742 | /// reverse order of positions
1743 | void reverse();
1744 | /** \brief relocate each guard to closest vertex if within
1745 | * \a epsilon of some vertex (of \a environment_temp)
1746 | *
1747 | * \author Karl J. Obermeyer
1748 | * \pre the guards' position data are numbers and \a environment_temp
1749 | * is nonempty
1750 | * \post if a guard was a Euclidean distance no greater
1751 | * than \a epsilon from any vertex of \a environment_temp, then it
1752 | * will be repositioned to coincide with the closest such vertex
1753 | * \remarks O(N*n) time complexity, where N is the guard count
1754 | * and n is the number of vertices in \a environment_temp.
1755 | */
1756 | void snap_to_vertices_of(const Environment& environment_temp,
1757 | double epsilon=0.0);
1758 |
1759 | /** \brief relocate each guard to closest vertex if within
1760 | * \a epsilon of some vertex (of \a environment_temp)
1761 | *
1762 | * \author Karl J. Obermeyer
1763 | * \pre the guards' position data are numbers and \a polygon_temp
1764 | * is nonempty
1765 | * \post if a guard was a Euclidean distance no greater
1766 | * than \a epsilon from any vertex of \a polygon_temp, then it
1767 | * will be repositioned to coincide with the closest such vertex
1768 | * \remarks O(N*n) time complexity, where N is the guard count
1769 | * and n is the number of vertices in \a polygon_temp
1770 | */
1771 | void snap_to_vertices_of(const Polygon& polygon_temp,
1772 | double epsilon=0.0);
1773 | /** \brief relocate each guard to closest Point on boundary if
1774 | * within \a epsilon of the boundary (of \a environment_temp)
1775 | *
1776 | * \author Karl J. Obermeyer
1777 | * \pre the guards' position data are numbers and \a environment_temp
1778 | * is nonempty
1779 | * \post If the calling Point was a Euclidean distance no greater
1780 | * than \a epsilon from the boundary of \a environment_temp, then it
1781 | * will be repositioned to it's projection onto that boundary
1782 | * \remarks O(N*n) time complexity, where N is the guard count and
1783 | * n is the number of vertices in \a environment_temp
1784 | */
1785 | void snap_to_boundary_of(const Environment& environment_temp,
1786 | double epsilon=0.0);
1787 | /** \brief relocate each guard to closest Point on boundary if
1788 | * within \a epsilon of the boundary (of \a polygon_temp)
1789 | *
1790 | * \author Karl J. Obermeyer
1791 | * \pre the guards' position data are numbers and \a polygon_temp
1792 | * is nonempty
1793 | * \post If the calling Point was a Euclidean distance no greater
1794 | * than \a epsilon from the boundary of \a polygon_temp, then it
1795 | * will be repositioned to it's projection onto that boundary
1796 | * \remarks O(N*n) time complexity, where N is the guard count and
1797 | * n is the number of vertices in \a polygon_temp
1798 | */
1799 | void snap_to_boundary_of(const Polygon& polygon_temp,
1800 | double epsilon=0.0);
1801 | private:
1802 | std::vector positions_;
1803 | };
1804 |
1805 |
1806 | /// print Guards
1807 | std::ostream& operator << (std::ostream& outs,
1808 | const Guards& guards);
1809 |
1810 |
1811 | /** \brief visibility polygon of a Point in an Environment or Polygon
1812 | *
1813 | * A Visibility_Polygon represents the closure of the set of all
1814 | * points in an environment which are {\it clearly visible} from a
1815 | * point (the observer). Two Points p1 and p2 are (mutually) {\it
1816 | * clearly visible} in an environment iff the relative interior of
1817 | * the line segment connecting p1 and p2 does not intersect the
1818 | * boundary of the environment.
1819 | *
1820 | * \remarks average case time complexity O(n log(n)), where n is the
1821 | * number of vertices in the Evironment (resp. Polygon). Note the
1822 | * Standard Library's sort() function performs O(n log(n))
1823 | * comparisons (both average and worst-case) and the sort() member
1824 | * function of an STL list performs "approximately O(n log(n))
1825 | * comparisons". For robustness, any Point (observer) should be \a
1826 | * epsilon -snapped to the environment boundary and vertices before
1827 | * computing its Visibility_Polygon (use the Point methods
1828 | * snap_to_vertices_of(...) and snap_to_boundary_of(...) ).
1829 | */
1830 | class Visibility_Polygon : public Polygon
1831 | {
1832 | public:
1833 | //Constructors
1834 | /// default to empty
1835 | Visibility_Polygon() { }
1836 | //:TRICKY:
1837 | /** \brief visibility set of a Point in an Environment
1838 | *
1839 | * \author Karl J. Obermeyer
1840 | *
1841 | * \pre \a observer is in \a environment_temp (w/in \a epsilon )
1842 | * and has been epsilon-snapped to the Environment using the
1843 | * method Point::snap_to_boundary_of() followed by (order is
1844 | * important) Point::snap_to_vertices_of(). \a environment_temp
1845 | * must be \a epsilon -valid. Test with
1846 | * Environment::is_valid(epsilon).
1847 | *
1848 | * \remarks O(n log(n)) average case time complexity, where n is the
1849 | * number of vertices in the Evironment (resp. Polygon).
1850 | */
1851 | Visibility_Polygon(const Point& observer,
1852 | const Environment& environment_temp,
1853 | double epsilon=0.0);
1854 | /** \brief visibility set of a Point in a Polygon
1855 | *
1856 | * \pre \a observer is in \a polygon_temp (w/in \a epsilon ) and
1857 | * has been epsilon-snapped to the Polygon using the methods
1858 | * Point::snap_to_vertices_of() and Point::snap_to_boundary_of().
1859 | * \a environment_temp must be \a epsilon -valid. Test with
1860 | * Environment::is_valid(epsilon).
1861 | *
1862 | * \remarks less efficient because constructs an Environment from
1863 | * a Polygon and then calls the other Visibility_Polygon constructor.
1864 | * O(n log(n)) average case time complexity, where n is the
1865 | * number of vertices in the Evironment (resp. Polygon).
1866 | */
1867 | Visibility_Polygon(const Point& observer,
1868 | const Polygon& polygon_temp,
1869 | double epsilon=0.0);
1870 | //Accessors
1871 | //std::vector get_gap_edges(double epsilon=0.0) { return gap_edges_; }
1872 | /// location of observer which induced the visibility polygon
1873 | Point observer() const
1874 | { return observer_; }
1875 | //Mutators
1876 | private:
1877 | //ith entry of gap_edges is true iff the edge following ith vertex
1878 | //is a gap edge (not solid).
1879 | //std::vector gap_edges_;
1880 | Point observer_;
1881 |
1882 | struct Polar_Edge
1883 | {
1884 | Polar_Point first;
1885 | Polar_Point second;
1886 | Polar_Edge() { }
1887 | Polar_Edge(const Polar_Point& ppoint1,
1888 | const Polar_Point& ppoint2) :
1889 | first(ppoint1), second(ppoint2) {}
1890 | };
1891 |
1892 | class Polar_Point_With_Edge_Info : public Polar_Point
1893 | {
1894 | public:
1895 | std::list::iterator incident_edge;
1896 | bool is_first; //True iff polar_point is the first_point of the
1897 | //Polar_Edge pointed to by
1898 | //incident_edge.
1899 | void set_polar_point(const Polar_Point& ppoint_temp)
1900 | {
1901 | set_polar_origin( ppoint_temp.polar_origin() );
1902 | set_x( ppoint_temp.x() );
1903 | set_y( ppoint_temp.y() );
1904 | set_range( ppoint_temp.range() );
1905 | set_bearing( ppoint_temp.bearing() );
1906 | }
1907 | //The operator < is the same as for Polar_Point with one
1908 | //exception. If two vertices have equal coordinates, but one is
1909 | //the first point of its respecitve edge and the other is the
1910 | //second point of its respective edge, then the vertex which is
1911 | //the second point of its respective edge is considered
1912 | //lexicographically smaller.
1913 | friend bool operator < (const Polar_Point_With_Edge_Info& ppwei1,
1914 | const Polar_Point_With_Edge_Info& ppwei2)
1915 | {
1916 | if( Polar_Point(ppwei1) == Polar_Point(ppwei2)
1917 | and !ppwei1.is_first and ppwei2.is_first )
1918 | return true;
1919 | else
1920 | return Polar_Point(ppwei1) < Polar_Point(ppwei2);
1921 | }
1922 | };
1923 |
1924 | //Strict weak ordering (acts like <) for pointers to Polar_Edges.
1925 | //Used to sort the priority_queue q2 used in the radial line sweep
1926 | //of Visibility_Polygon constructors. Let p1 be a pointer to
1927 | //Polar_Edge e1 and p2 be a pointer to Polar_Edge e2. Then p1 is
1928 | //considered greater (higher priority) than p2 if the distance
1929 | //from the observer (pointed to by observer_pointer) to e1 along
1930 | //the direction to current_vertex is smaller than the distance
1931 | //from the observer to e2 along the direction to current_vertex.
1932 | class Incident_Edge_Compare
1933 | {
1934 | const Point *const observer_pointer;
1935 | const Polar_Point_With_Edge_Info *const current_vertex_pointer;
1936 | double epsilon;
1937 | public:
1938 | Incident_Edge_Compare(const Point& observer,
1939 | const Polar_Point_With_Edge_Info& current_vertex,
1940 | double epsilon_temp) :
1941 | observer_pointer(&observer),
1942 | current_vertex_pointer(¤t_vertex),
1943 | epsilon(epsilon_temp) { }
1944 | bool operator () (std::list::iterator e1,
1945 | std::list::iterator e2) const
1946 | {
1947 | Polar_Point k1, k2;
1948 | Line_Segment xing1 = intersection( Ray(*observer_pointer,
1949 | current_vertex_pointer->bearing()),
1950 | Line_Segment(e1->first,
1951 | e1->second),
1952 | epsilon);
1953 | Line_Segment xing2 = intersection( Ray(*observer_pointer,
1954 | current_vertex_pointer->bearing()),
1955 | Line_Segment(e2->first,
1956 | e2->second),
1957 | epsilon);
1958 | if( xing1.size() > 0 and xing2.size() > 0 ){
1959 | k1 = Polar_Point( *observer_pointer,
1960 | xing1.first() );
1961 | k2 = Polar_Point( *observer_pointer,
1962 | xing2.first() );
1963 | if( k1.range() <= k2.range() )
1964 | return false;
1965 | return true;
1966 | }
1967 | //Otherwise infeasible edges are given higher priority, so they
1968 | //get pushed out the top of the priority_queue's (q2's)
1969 | //heap.
1970 | else if( xing1.size() == 0 and xing2.size() > 0 )
1971 | return false;
1972 | else if( xing1.size() > 0 and xing2.size() == 0 )
1973 | return true;
1974 | else
1975 | return true;
1976 | }
1977 | };
1978 |
1979 | bool is_spike( const Point& observer,
1980 | const Point& point1,
1981 | const Point& point2,
1982 | const Point& point3,
1983 | double epsilon=0.0 ) const;
1984 |
1985 | //For eliminating spikes as they appear. In the
1986 | //Visibility_Polygon constructors, these are checked every time a
1987 | //Point is added to vertices.
1988 | void chop_spikes_at_back(const Point& observer,
1989 | double epsilon);
1990 | void chop_spikes_at_wrap_around(const Point& observer,
1991 | double epsilon);
1992 | void chop_spikes(const Point& observer,
1993 | double epsilon);
1994 | //For debugging Visibility_Polygon constructors.
1995 | //Prints current_vertex and active_edge data to screen.
1996 | void print_cv_and_ae(const Polar_Point_With_Edge_Info& current_vertex,
1997 | const std::list::iterator&
1998 | active_edge);
1999 | };
2000 |
2001 |
2002 | /** \brief visibility graph of points in an Environment,
2003 | * represented by adjacency matrix
2004 | *
2005 | * \remarks used for shortest path planning in the
2006 | * Environment::shortest_path() method
2007 | *
2008 | * \todo Add method to prune edges for faster shortest path
2009 | * calculation, e.g., exclude concave vertices and only include
2010 | * tangent edges as described in ``Robot Motion Planning" (Ch. 4
2011 | * Sec. 1) by J.C. Latombe.
2012 | */
2013 | class Visibility_Graph
2014 | {
2015 | public:
2016 | //Constructors
2017 | /// default to empty
2018 | Visibility_Graph() { n_=0; adjacency_matrix_ = NULL; }
2019 | /// copy
2020 | Visibility_Graph( const Visibility_Graph& vg2 );
2021 | /** \brief construct the visibility graph of Environment vertices
2022 | *
2023 | * \author Karl J. Obermeyer
2024 | *
2025 | * \pre \a environment must be \a epsilon -valid. Test with
2026 | * Environment::is_valid(epsilon).
2027 | *
2028 | * \remarks Currently this constructor simply computes the
2029 | * Visibility_Polygon of each vertex and checks inclusion of the
2030 | * other vertices, taking time complexity O(n^3), where n is the
2031 | * number of vertices representing the Environment. This time
2032 | * complexity is not optimal. As mentioned in ``Robot Motion
2033 | * Planning" by J.C. Latombe p.157, there are algorithms able to
2034 | * construct a visibility graph for a polygonal environment with
2035 | * holes in time O(n^2). The nonoptimal algorithm is being used
2036 | * temporarily because of (1) its ease to implement using the
2037 | * Visibility_Polygon class, and (2) its apparent robustness.
2038 | * Implementing the optimal algorithm robustly is future work.
2039 | */
2040 | Visibility_Graph(const Environment& environment, double epsilon=0.0);
2041 | //Constructors
2042 | /** \brief construct the visibility graph of Points in an Environment
2043 | *
2044 | * \pre \a environment must be \a epsilon -valid. Test with
2045 | * Environment::is_valid(epsilon).
2046 | *
2047 | * \author Karl J. Obermeyer \remarks Currently this constructor
2048 | * simply computes the Visibility_Polygon of each Point and checks
2049 | * inclusion of the other Points, taking time complexity
2050 | * O(N n log(n) + N^2 n), where N is the number of Points and n is
2051 | * the number of vertices representing the Environment. This time
2052 | * complexity is not optimal, but has been used for
2053 | * simplicity. More efficient algorithms are discussed in ``Robot
2054 | * Motion Planning" by J.C. Latombe p.157.
2055 | */
2056 | Visibility_Graph(const std::vector points,
2057 | const Environment& environment, double epsilon=0.0);
2058 | //Constructors
2059 | /** \brief construct the visibility graph of Guards in an Environment
2060 | *
2061 | * \pre \a start and \a finish must be in the environment.
2062 | * Environment must be \a epsilon -valid. Test with
2063 | * Environment::is_valid(epsilon).
2064 | *
2065 | * \author Karl J. Obermeyer
2066 | * \remarks Currently this constructor simply computes the
2067 | * Visibility_Polygon of each guard and checks inclusion of the
2068 | * other guards, taking time complexity O(N n log(n) + N^2 n),
2069 | * where N is the number of guards and n is the number of vertices
2070 | * representing the Environment. This time complexity is not
2071 | * optimal, but has been used for simplicity. More efficient
2072 | * algorithms are discussed in ``Robot Motion Planning" by
2073 | * J.C. Latombe p.157.
2074 | */
2075 | Visibility_Graph(const Guards& guards,
2076 | const Environment& environment, double epsilon=0.0);
2077 | //Accessors
2078 | /** \brief raw access to adjacency matrix data
2079 | *
2080 | * \author Karl J. Obermeyer
2081 | * \param i1 Polygon index of first vertex
2082 | * \param j1 index of first vertex within its Polygon
2083 | * \param i2 Polygon index of second vertex
2084 | * \param j2 index of second vertex within its Polygon
2085 | * \return true iff first vertex is visible from second vertex
2086 | * \remarks for efficiency, no bounds check; usually trying to
2087 | * access out of bounds causes a bus error
2088 | */
2089 | bool operator () (unsigned i1,
2090 | unsigned j1,
2091 | unsigned i2,
2092 | unsigned j2) const;
2093 | /** \brief raw access to adjacency matrix data via flattened
2094 | * indices
2095 | *
2096 | * By flattened index is intended the label given to a vertex if
2097 | * you were to label all the vertices from 0 to n-1 (where n is
2098 | * the number of vertices representing the Environment) starting
2099 | * with the first vertex of the outer boundary and progressing in
2100 | * order through all the remaining vertices of the outer boundary
2101 | * and holes.
2102 | * \author Karl J. Obermeyer
2103 | * \param k1 flattened index of first vertex
2104 | * \param k1 flattened index of second vertex
2105 | * \return true iff first vertex is visible from second vertex
2106 | * \remarks for efficiency, no bounds check; usually trying to
2107 | * access out of bounds causes a bus error
2108 | */
2109 | bool operator () (unsigned k1,
2110 | unsigned k2) const;
2111 | /// \brief total number of vertices in corresponding Environment
2112 | unsigned n() const { return n_; }
2113 | //Mutators
2114 | /** \brief raw access to adjacency matrix data
2115 | *
2116 | * \author Karl J. Obermeyer
2117 | * \param i1 Polygon index of first vertex
2118 | * \param j1 index of first vertex within its Polygon
2119 | * \param i2 Polygon index of second vertex
2120 | * \param j2 index of second vertex within its Polygon
2121 | * \return true iff first vertex is visible from second vertex
2122 | * \remarks for efficiency, no bounds check; usually trying to
2123 | * access out of bounds causes a bus error
2124 | */
2125 | bool& operator () (unsigned i1,
2126 | unsigned j1,
2127 | unsigned i2,
2128 | unsigned j2);
2129 | /** \brief raw access to adjacency matrix data via flattened
2130 | * indices
2131 | *
2132 | * By flattened index is intended the label given to a vertex if
2133 | * you were to label all the vertices from 0 to n-1 (where n is
2134 | * the number of vertices representing the Environment) starting
2135 | * with the first vertex of the outer boundary and progressing in
2136 | * order through all the remaining vertices of the outer boundary
2137 | * and holes.
2138 | * \author Karl J. Obermeyer
2139 | * \param k1 flattened index of first vertex
2140 | * \param k1 flattened index of second vertex
2141 | * \return true iff first vertex is visible from second vertex
2142 | * \remarks for efficiency, no bounds check; usually trying to
2143 | * access out of bounds causes a bus error
2144 | */
2145 | bool& operator () (unsigned k1,
2146 | unsigned k2);
2147 | /// assignment operator
2148 | Visibility_Graph& operator =
2149 | (const Visibility_Graph& visibility_graph_temp);
2150 | /// destructor
2151 | virtual ~Visibility_Graph();
2152 | private:
2153 | //total number of vertices of corresponding Environment
2154 | unsigned n_;
2155 | //the number of vertices in each Polygon of corresponding Environment
2156 | std::vector vertex_counts_;
2157 | // n_-by-n_ adjacency matrix data stored as 2D dynamic array
2158 | bool **adjacency_matrix_;
2159 | //converts vertex pairs (hole #, vertex #) to flattened index
2160 | unsigned two_to_one(unsigned i,
2161 | unsigned j) const;
2162 | };
2163 |
2164 |
2165 | /// print Visibility_Graph adjacency matrix
2166 | std::ostream& operator << (std::ostream& outs,
2167 | const Visibility_Graph& visibility_graph);
2168 |
2169 | }
2170 |
2171 | #endif //VISILIBITY_H
2172 |
--------------------------------------------------------------------------------
/visilibity.i:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | PyVisiLibity: a Python binding of VisiLibity1
4 | Copyright (C) 2018 Yu Cao < University of Southampton> Yu.Cao at soton.ac.uk
5 | Originally by Stefanie T. of MIT, United States
6 |
7 | PyVisiLibity is free software: you can redistribute it and/or modify it under
8 | the terms of the GNU Lesser General Public License as published by the
9 | Free Software Foundation, either version 3 of the License, or (at your
10 | option) any later version.
11 | PyVisiLibity is distributed in the hope that it will be useful, but WITHOUT
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 | License for more details.
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with PyVisiLibity. If not, see .
17 |
18 |
19 | */
20 | %module visilibity
21 | #pragma SWIG nowarn=501
22 | #pragma SWIG nowarn=501,505,401
23 | %{
24 |
25 | #include "visilibity.hpp"
26 | %}
27 | %include std_vector.i
28 | namespace std {
29 | %template(pointList) vector;
30 | %template(polygonList) vector;
31 | }
32 |
33 |
34 | %include visilibity.hpp
35 |
36 |
37 | %extend VisiLibity::Polygon {
38 | Point __getitem__(unsigned i) {
39 | return (*self)[i];
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/visilibity.py:
--------------------------------------------------------------------------------
1 | # This file was automatically generated by SWIG (http://www.swig.org).
2 | # Version 3.0.12
3 | #
4 | # Do not make changes to this file unless you know what you are doing--modify
5 | # the SWIG interface file instead.
6 |
7 | from sys import version_info as _swig_python_version_info
8 | if _swig_python_version_info >= (2, 7, 0):
9 | def swig_import_helper():
10 | import importlib
11 | pkg = __name__.rpartition('.')[0]
12 | mname = '.'.join((pkg, '_visilibity')).lstrip('.')
13 | try:
14 | return importlib.import_module(mname)
15 | except ImportError:
16 | return importlib.import_module('_visilibity')
17 | _visilibity = swig_import_helper()
18 | del swig_import_helper
19 | elif _swig_python_version_info >= (2, 6, 0):
20 | def swig_import_helper():
21 | from os.path import dirname
22 | import imp
23 | fp = None
24 | try:
25 | fp, pathname, description = imp.find_module('_visilibity', [dirname(__file__)])
26 | except ImportError:
27 | import _visilibity
28 | return _visilibity
29 | try:
30 | _mod = imp.load_module('_visilibity', fp, pathname, description)
31 | finally:
32 | if fp is not None:
33 | fp.close()
34 | return _mod
35 | _visilibity = swig_import_helper()
36 | del swig_import_helper
37 | else:
38 | import _visilibity
39 | del _swig_python_version_info
40 |
41 | try:
42 | _swig_property = property
43 | except NameError:
44 | pass # Python < 2.2 doesn't have 'property'.
45 |
46 | try:
47 | import builtins as __builtin__
48 | except ImportError:
49 | import __builtin__
50 |
51 | def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
52 | if (name == "thisown"):
53 | return self.this.own(value)
54 | if (name == "this"):
55 | if type(value).__name__ == 'SwigPyObject':
56 | self.__dict__[name] = value
57 | return
58 | method = class_type.__swig_setmethods__.get(name, None)
59 | if method:
60 | return method(self, value)
61 | if (not static):
62 | if _newclass:
63 | object.__setattr__(self, name, value)
64 | else:
65 | self.__dict__[name] = value
66 | else:
67 | raise AttributeError("You cannot add attributes to %s" % self)
68 |
69 |
70 | def _swig_setattr(self, class_type, name, value):
71 | return _swig_setattr_nondynamic(self, class_type, name, value, 0)
72 |
73 |
74 | def _swig_getattr(self, class_type, name):
75 | if (name == "thisown"):
76 | return self.this.own()
77 | method = class_type.__swig_getmethods__.get(name, None)
78 | if method:
79 | return method(self)
80 | raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name))
81 |
82 |
83 | def _swig_repr(self):
84 | try:
85 | strthis = "proxy of " + self.this.__repr__()
86 | except __builtin__.Exception:
87 | strthis = ""
88 | return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
89 |
90 | try:
91 | _object = object
92 | _newclass = 1
93 | except __builtin__.Exception:
94 | class _object:
95 | pass
96 | _newclass = 0
97 |
98 | class SwigPyIterator(_object):
99 | __swig_setmethods__ = {}
100 | __setattr__ = lambda self, name, value: _swig_setattr(self, SwigPyIterator, name, value)
101 | __swig_getmethods__ = {}
102 | __getattr__ = lambda self, name: _swig_getattr(self, SwigPyIterator, name)
103 |
104 | def __init__(self, *args, **kwargs):
105 | raise AttributeError("No constructor defined - class is abstract")
106 | __repr__ = _swig_repr
107 | __swig_destroy__ = _visilibity.delete_SwigPyIterator
108 | __del__ = lambda self: None
109 |
110 | def value(self):
111 | return _visilibity.SwigPyIterator_value(self)
112 |
113 | def incr(self, n=1):
114 | return _visilibity.SwigPyIterator_incr(self, n)
115 |
116 | def decr(self, n=1):
117 | return _visilibity.SwigPyIterator_decr(self, n)
118 |
119 | def distance(self, x):
120 | return _visilibity.SwigPyIterator_distance(self, x)
121 |
122 | def equal(self, x):
123 | return _visilibity.SwigPyIterator_equal(self, x)
124 |
125 | def copy(self):
126 | return _visilibity.SwigPyIterator_copy(self)
127 |
128 | def next(self):
129 | return _visilibity.SwigPyIterator_next(self)
130 |
131 | def __next__(self):
132 | return _visilibity.SwigPyIterator___next__(self)
133 |
134 | def previous(self):
135 | return _visilibity.SwigPyIterator_previous(self)
136 |
137 | def advance(self, n):
138 | return _visilibity.SwigPyIterator_advance(self, n)
139 |
140 | def __eq__(self, x):
141 | return _visilibity.SwigPyIterator___eq__(self, x)
142 |
143 | def __ne__(self, x):
144 | return _visilibity.SwigPyIterator___ne__(self, x)
145 |
146 | def __iadd__(self, n):
147 | return _visilibity.SwigPyIterator___iadd__(self, n)
148 |
149 | def __isub__(self, n):
150 | return _visilibity.SwigPyIterator___isub__(self, n)
151 |
152 | def __add__(self, n):
153 | return _visilibity.SwigPyIterator___add__(self, n)
154 |
155 | def __sub__(self, *args):
156 | return _visilibity.SwigPyIterator___sub__(self, *args)
157 | def __iter__(self):
158 | return self
159 | SwigPyIterator_swigregister = _visilibity.SwigPyIterator_swigregister
160 | SwigPyIterator_swigregister(SwigPyIterator)
161 |
162 | class pointList(_object):
163 | __swig_setmethods__ = {}
164 | __setattr__ = lambda self, name, value: _swig_setattr(self, pointList, name, value)
165 | __swig_getmethods__ = {}
166 | __getattr__ = lambda self, name: _swig_getattr(self, pointList, name)
167 | __repr__ = _swig_repr
168 |
169 | def iterator(self):
170 | return _visilibity.pointList_iterator(self)
171 | def __iter__(self):
172 | return self.iterator()
173 |
174 | def __nonzero__(self):
175 | return _visilibity.pointList___nonzero__(self)
176 |
177 | def __bool__(self):
178 | return _visilibity.pointList___bool__(self)
179 |
180 | def __len__(self):
181 | return _visilibity.pointList___len__(self)
182 |
183 | def __getslice__(self, i, j):
184 | return _visilibity.pointList___getslice__(self, i, j)
185 |
186 | def __setslice__(self, *args):
187 | return _visilibity.pointList___setslice__(self, *args)
188 |
189 | def __delslice__(self, i, j):
190 | return _visilibity.pointList___delslice__(self, i, j)
191 |
192 | def __delitem__(self, *args):
193 | return _visilibity.pointList___delitem__(self, *args)
194 |
195 | def __getitem__(self, *args):
196 | return _visilibity.pointList___getitem__(self, *args)
197 |
198 | def __setitem__(self, *args):
199 | return _visilibity.pointList___setitem__(self, *args)
200 |
201 | def pop(self):
202 | return _visilibity.pointList_pop(self)
203 |
204 | def append(self, x):
205 | return _visilibity.pointList_append(self, x)
206 |
207 | def empty(self):
208 | return _visilibity.pointList_empty(self)
209 |
210 | def size(self):
211 | return _visilibity.pointList_size(self)
212 |
213 | def swap(self, v):
214 | return _visilibity.pointList_swap(self, v)
215 |
216 | def begin(self):
217 | return _visilibity.pointList_begin(self)
218 |
219 | def end(self):
220 | return _visilibity.pointList_end(self)
221 |
222 | def rbegin(self):
223 | return _visilibity.pointList_rbegin(self)
224 |
225 | def rend(self):
226 | return _visilibity.pointList_rend(self)
227 |
228 | def clear(self):
229 | return _visilibity.pointList_clear(self)
230 |
231 | def get_allocator(self):
232 | return _visilibity.pointList_get_allocator(self)
233 |
234 | def pop_back(self):
235 | return _visilibity.pointList_pop_back(self)
236 |
237 | def erase(self, *args):
238 | return _visilibity.pointList_erase(self, *args)
239 |
240 | def __init__(self, *args):
241 | this = _visilibity.new_pointList(*args)
242 | try:
243 | self.this.append(this)
244 | except __builtin__.Exception:
245 | self.this = this
246 |
247 | def push_back(self, x):
248 | return _visilibity.pointList_push_back(self, x)
249 |
250 | def front(self):
251 | return _visilibity.pointList_front(self)
252 |
253 | def back(self):
254 | return _visilibity.pointList_back(self)
255 |
256 | def assign(self, n, x):
257 | return _visilibity.pointList_assign(self, n, x)
258 |
259 | def resize(self, *args):
260 | return _visilibity.pointList_resize(self, *args)
261 |
262 | def insert(self, *args):
263 | return _visilibity.pointList_insert(self, *args)
264 |
265 | def reserve(self, n):
266 | return _visilibity.pointList_reserve(self, n)
267 |
268 | def capacity(self):
269 | return _visilibity.pointList_capacity(self)
270 | __swig_destroy__ = _visilibity.delete_pointList
271 | __del__ = lambda self: None
272 | pointList_swigregister = _visilibity.pointList_swigregister
273 | pointList_swigregister(pointList)
274 |
275 | class polygonList(_object):
276 | __swig_setmethods__ = {}
277 | __setattr__ = lambda self, name, value: _swig_setattr(self, polygonList, name, value)
278 | __swig_getmethods__ = {}
279 | __getattr__ = lambda self, name: _swig_getattr(self, polygonList, name)
280 | __repr__ = _swig_repr
281 |
282 | def iterator(self):
283 | return _visilibity.polygonList_iterator(self)
284 | def __iter__(self):
285 | return self.iterator()
286 |
287 | def __nonzero__(self):
288 | return _visilibity.polygonList___nonzero__(self)
289 |
290 | def __bool__(self):
291 | return _visilibity.polygonList___bool__(self)
292 |
293 | def __len__(self):
294 | return _visilibity.polygonList___len__(self)
295 |
296 | def __getslice__(self, i, j):
297 | return _visilibity.polygonList___getslice__(self, i, j)
298 |
299 | def __setslice__(self, *args):
300 | return _visilibity.polygonList___setslice__(self, *args)
301 |
302 | def __delslice__(self, i, j):
303 | return _visilibity.polygonList___delslice__(self, i, j)
304 |
305 | def __delitem__(self, *args):
306 | return _visilibity.polygonList___delitem__(self, *args)
307 |
308 | def __getitem__(self, *args):
309 | return _visilibity.polygonList___getitem__(self, *args)
310 |
311 | def __setitem__(self, *args):
312 | return _visilibity.polygonList___setitem__(self, *args)
313 |
314 | def pop(self):
315 | return _visilibity.polygonList_pop(self)
316 |
317 | def append(self, x):
318 | return _visilibity.polygonList_append(self, x)
319 |
320 | def empty(self):
321 | return _visilibity.polygonList_empty(self)
322 |
323 | def size(self):
324 | return _visilibity.polygonList_size(self)
325 |
326 | def swap(self, v):
327 | return _visilibity.polygonList_swap(self, v)
328 |
329 | def begin(self):
330 | return _visilibity.polygonList_begin(self)
331 |
332 | def end(self):
333 | return _visilibity.polygonList_end(self)
334 |
335 | def rbegin(self):
336 | return _visilibity.polygonList_rbegin(self)
337 |
338 | def rend(self):
339 | return _visilibity.polygonList_rend(self)
340 |
341 | def clear(self):
342 | return _visilibity.polygonList_clear(self)
343 |
344 | def get_allocator(self):
345 | return _visilibity.polygonList_get_allocator(self)
346 |
347 | def pop_back(self):
348 | return _visilibity.polygonList_pop_back(self)
349 |
350 | def erase(self, *args):
351 | return _visilibity.polygonList_erase(self, *args)
352 |
353 | def __init__(self, *args):
354 | this = _visilibity.new_polygonList(*args)
355 | try:
356 | self.this.append(this)
357 | except __builtin__.Exception:
358 | self.this = this
359 |
360 | def push_back(self, x):
361 | return _visilibity.polygonList_push_back(self, x)
362 |
363 | def front(self):
364 | return _visilibity.polygonList_front(self)
365 |
366 | def back(self):
367 | return _visilibity.polygonList_back(self)
368 |
369 | def assign(self, n, x):
370 | return _visilibity.polygonList_assign(self, n, x)
371 |
372 | def resize(self, *args):
373 | return _visilibity.polygonList_resize(self, *args)
374 |
375 | def insert(self, *args):
376 | return _visilibity.polygonList_insert(self, *args)
377 |
378 | def reserve(self, n):
379 | return _visilibity.polygonList_reserve(self, n)
380 |
381 | def capacity(self):
382 | return _visilibity.polygonList_capacity(self)
383 | __swig_destroy__ = _visilibity.delete_polygonList
384 | __del__ = lambda self: None
385 | polygonList_swigregister = _visilibity.polygonList_swigregister
386 | polygonList_swigregister(polygonList)
387 |
388 |
389 | def uniform_random_sample(lower_bound, upper_bound):
390 | return _visilibity.uniform_random_sample(lower_bound, upper_bound)
391 | uniform_random_sample = _visilibity.uniform_random_sample
392 | class Bounding_Box(_object):
393 | __swig_setmethods__ = {}
394 | __setattr__ = lambda self, name, value: _swig_setattr(self, Bounding_Box, name, value)
395 | __swig_getmethods__ = {}
396 | __getattr__ = lambda self, name: _swig_getattr(self, Bounding_Box, name)
397 | __repr__ = _swig_repr
398 | __swig_setmethods__["x_min"] = _visilibity.Bounding_Box_x_min_set
399 | __swig_getmethods__["x_min"] = _visilibity.Bounding_Box_x_min_get
400 | if _newclass:
401 | x_min = _swig_property(_visilibity.Bounding_Box_x_min_get, _visilibity.Bounding_Box_x_min_set)
402 | __swig_setmethods__["x_max"] = _visilibity.Bounding_Box_x_max_set
403 | __swig_getmethods__["x_max"] = _visilibity.Bounding_Box_x_max_get
404 | if _newclass:
405 | x_max = _swig_property(_visilibity.Bounding_Box_x_max_get, _visilibity.Bounding_Box_x_max_set)
406 | __swig_setmethods__["y_min"] = _visilibity.Bounding_Box_y_min_set
407 | __swig_getmethods__["y_min"] = _visilibity.Bounding_Box_y_min_get
408 | if _newclass:
409 | y_min = _swig_property(_visilibity.Bounding_Box_y_min_get, _visilibity.Bounding_Box_y_min_set)
410 | __swig_setmethods__["y_max"] = _visilibity.Bounding_Box_y_max_set
411 | __swig_getmethods__["y_max"] = _visilibity.Bounding_Box_y_max_get
412 | if _newclass:
413 | y_max = _swig_property(_visilibity.Bounding_Box_y_max_get, _visilibity.Bounding_Box_y_max_set)
414 |
415 | def __init__(self):
416 | this = _visilibity.new_Bounding_Box()
417 | try:
418 | self.this.append(this)
419 | except __builtin__.Exception:
420 | self.this = this
421 | __swig_destroy__ = _visilibity.delete_Bounding_Box
422 | __del__ = lambda self: None
423 | Bounding_Box_swigregister = _visilibity.Bounding_Box_swigregister
424 | Bounding_Box_swigregister(Bounding_Box)
425 | cvar = _visilibity.cvar
426 | FIOS_PRECISION = cvar.FIOS_PRECISION
427 |
428 | class Point(_object):
429 | __swig_setmethods__ = {}
430 | __setattr__ = lambda self, name, value: _swig_setattr(self, Point, name, value)
431 | __swig_getmethods__ = {}
432 | __getattr__ = lambda self, name: _swig_getattr(self, Point, name)
433 | __repr__ = _swig_repr
434 |
435 | def __init__(self, *args):
436 | this = _visilibity.new_Point(*args)
437 | try:
438 | self.this.append(this)
439 | except __builtin__.Exception:
440 | self.this = this
441 |
442 | def x(self):
443 | return _visilibity.Point_x(self)
444 |
445 | def y(self):
446 | return _visilibity.Point_y(self)
447 |
448 | def projection_onto(self, *args):
449 | return _visilibity.Point_projection_onto(self, *args)
450 |
451 | def projection_onto_vertices_of(self, *args):
452 | return _visilibity.Point_projection_onto_vertices_of(self, *args)
453 |
454 | def projection_onto_boundary_of(self, *args):
455 | return _visilibity.Point_projection_onto_boundary_of(self, *args)
456 |
457 | def on_boundary_of(self, *args):
458 | return _visilibity.Point_on_boundary_of(self, *args)
459 |
460 | def in_relative_interior_of(self, line_segment_temp, epsilon=0.0):
461 | return _visilibity.Point_in_relative_interior_of(self, line_segment_temp, epsilon)
462 |
463 | def _in(self, *args):
464 | return _visilibity.Point__in(self, *args)
465 |
466 | def is_endpoint_of(self, line_segment_temp, epsilon=0.0):
467 | return _visilibity.Point_is_endpoint_of(self, line_segment_temp, epsilon)
468 |
469 | def set_x(self, x_temp):
470 | return _visilibity.Point_set_x(self, x_temp)
471 |
472 | def set_y(self, y_temp):
473 | return _visilibity.Point_set_y(self, y_temp)
474 |
475 | def snap_to_vertices_of(self, *args):
476 | return _visilibity.Point_snap_to_vertices_of(self, *args)
477 |
478 | def snap_to_boundary_of(self, *args):
479 | return _visilibity.Point_snap_to_boundary_of(self, *args)
480 | __swig_destroy__ = _visilibity.delete_Point
481 | __del__ = lambda self: None
482 | Point_swigregister = _visilibity.Point_swigregister
483 | Point_swigregister(Point)
484 |
485 |
486 | def __mul__(*args):
487 | return _visilibity.__mul__(*args)
488 | __mul__ = _visilibity.__mul__
489 |
490 | def cross(point1, point2):
491 | return _visilibity.cross(point1, point2)
492 | cross = _visilibity.cross
493 | class Line_Segment(_object):
494 | __swig_setmethods__ = {}
495 | __setattr__ = lambda self, name, value: _swig_setattr(self, Line_Segment, name, value)
496 | __swig_getmethods__ = {}
497 | __getattr__ = lambda self, name: _swig_getattr(self, Line_Segment, name)
498 | __repr__ = _swig_repr
499 |
500 | def __init__(self, *args):
501 | this = _visilibity.new_Line_Segment(*args)
502 | try:
503 | self.this.append(this)
504 | except __builtin__.Exception:
505 | self.this = this
506 |
507 | def first(self):
508 | return _visilibity.Line_Segment_first(self)
509 |
510 | def second(self):
511 | return _visilibity.Line_Segment_second(self)
512 |
513 | def size(self):
514 | return _visilibity.Line_Segment_size(self)
515 |
516 | def midpoint(self):
517 | return _visilibity.Line_Segment_midpoint(self)
518 |
519 | def length(self):
520 | return _visilibity.Line_Segment_length(self)
521 |
522 | def is_in_standard_form(self):
523 | return _visilibity.Line_Segment_is_in_standard_form(self)
524 |
525 | def set_first(self, point_temp, epsilon=0.0):
526 | return _visilibity.Line_Segment_set_first(self, point_temp, epsilon)
527 |
528 | def set_second(self, point_temp, epsilon=0.0):
529 | return _visilibity.Line_Segment_set_second(self, point_temp, epsilon)
530 |
531 | def reverse(self):
532 | return _visilibity.Line_Segment_reverse(self)
533 |
534 | def enforce_standard_form(self):
535 | return _visilibity.Line_Segment_enforce_standard_form(self)
536 |
537 | def clear(self):
538 | return _visilibity.Line_Segment_clear(self)
539 | __swig_destroy__ = _visilibity.delete_Line_Segment
540 | __del__ = lambda self: None
541 | Line_Segment_swigregister = _visilibity.Line_Segment_swigregister
542 | Line_Segment_swigregister(Line_Segment)
543 |
544 |
545 | def distance(*args):
546 | return _visilibity.distance(*args)
547 | distance = _visilibity.distance
548 |
549 | def intersect(line_segment1, line_segment2, epsilon=0.0):
550 | return _visilibity.intersect(line_segment1, line_segment2, epsilon)
551 | intersect = _visilibity.intersect
552 |
553 | def intersect_proper(line_segment1, line_segment2, epsilon=0.0):
554 | return _visilibity.intersect_proper(line_segment1, line_segment2, epsilon)
555 | intersect_proper = _visilibity.intersect_proper
556 | class Angle(_object):
557 | __swig_setmethods__ = {}
558 | __setattr__ = lambda self, name, value: _swig_setattr(self, Angle, name, value)
559 | __swig_getmethods__ = {}
560 | __getattr__ = lambda self, name: _swig_getattr(self, Angle, name)
561 | __repr__ = _swig_repr
562 |
563 | def __init__(self, *args):
564 | this = _visilibity.new_Angle(*args)
565 | try:
566 | self.this.append(this)
567 | except __builtin__.Exception:
568 | self.this = this
569 |
570 | def get(self):
571 | return _visilibity.Angle_get(self)
572 |
573 | def set(self, data_temp):
574 | return _visilibity.Angle_set(self, data_temp)
575 |
576 | def set_to_2pi(self):
577 | return _visilibity.Angle_set_to_2pi(self)
578 |
579 | def randomize(self):
580 | return _visilibity.Angle_randomize(self)
581 | __swig_destroy__ = _visilibity.delete_Angle
582 | __del__ = lambda self: None
583 | Angle_swigregister = _visilibity.Angle_swigregister
584 | Angle_swigregister(Angle)
585 |
586 |
587 | def __add__(*args):
588 | return _visilibity.__add__(*args)
589 | __add__ = _visilibity.__add__
590 |
591 | def __sub__(*args):
592 | return _visilibity.__sub__(*args)
593 | __sub__ = _visilibity.__sub__
594 |
595 | def geodesic_distance(angle1, angle2):
596 | return _visilibity.geodesic_distance(angle1, angle2)
597 | geodesic_distance = _visilibity.geodesic_distance
598 |
599 | def geodesic_direction(angle1, angle2):
600 | return _visilibity.geodesic_direction(angle1, angle2)
601 | geodesic_direction = _visilibity.geodesic_direction
602 | class Polar_Point(Point):
603 | __swig_setmethods__ = {}
604 | for _s in [Point]:
605 | __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
606 | __setattr__ = lambda self, name, value: _swig_setattr(self, Polar_Point, name, value)
607 | __swig_getmethods__ = {}
608 | for _s in [Point]:
609 | __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
610 | __getattr__ = lambda self, name: _swig_getattr(self, Polar_Point, name)
611 | __repr__ = _swig_repr
612 |
613 | def __init__(self, *args):
614 | this = _visilibity.new_Polar_Point(*args)
615 | try:
616 | self.this.append(this)
617 | except __builtin__.Exception:
618 | self.this = this
619 |
620 | def polar_origin(self):
621 | return _visilibity.Polar_Point_polar_origin(self)
622 |
623 | def range(self):
624 | return _visilibity.Polar_Point_range(self)
625 |
626 | def bearing(self):
627 | return _visilibity.Polar_Point_bearing(self)
628 |
629 | def set_polar_origin(self, polar_origin_temp):
630 | return _visilibity.Polar_Point_set_polar_origin(self, polar_origin_temp)
631 |
632 | def set_x(self, x_temp):
633 | return _visilibity.Polar_Point_set_x(self, x_temp)
634 |
635 | def set_y(self, y_temp):
636 | return _visilibity.Polar_Point_set_y(self, y_temp)
637 |
638 | def set_range(self, range_temp):
639 | return _visilibity.Polar_Point_set_range(self, range_temp)
640 |
641 | def set_bearing(self, bearing_temp):
642 | return _visilibity.Polar_Point_set_bearing(self, bearing_temp)
643 |
644 | def set_bearing_to_2pi(self):
645 | return _visilibity.Polar_Point_set_bearing_to_2pi(self)
646 | __swig_destroy__ = _visilibity.delete_Polar_Point
647 | __del__ = lambda self: None
648 | Polar_Point_swigregister = _visilibity.Polar_Point_swigregister
649 | Polar_Point_swigregister(Polar_Point)
650 |
651 |
652 | def __gt__(*args):
653 | return _visilibity.__gt__(*args)
654 | __gt__ = _visilibity.__gt__
655 |
656 | def __lt__(*args):
657 | return _visilibity.__lt__(*args)
658 | __lt__ = _visilibity.__lt__
659 |
660 | def __ge__(*args):
661 | return _visilibity.__ge__(*args)
662 | __ge__ = _visilibity.__ge__
663 |
664 | def __le__(*args):
665 | return _visilibity.__le__(*args)
666 | __le__ = _visilibity.__le__
667 | class Ray(_object):
668 | __swig_setmethods__ = {}
669 | __setattr__ = lambda self, name, value: _swig_setattr(self, Ray, name, value)
670 | __swig_getmethods__ = {}
671 | __getattr__ = lambda self, name: _swig_getattr(self, Ray, name)
672 | __repr__ = _swig_repr
673 |
674 | def __init__(self, *args):
675 | this = _visilibity.new_Ray(*args)
676 | try:
677 | self.this.append(this)
678 | except __builtin__.Exception:
679 | self.this = this
680 |
681 | def base_point(self):
682 | return _visilibity.Ray_base_point(self)
683 |
684 | def bearing(self):
685 | return _visilibity.Ray_bearing(self)
686 |
687 | def set_base_point(self, point_temp):
688 | return _visilibity.Ray_set_base_point(self, point_temp)
689 |
690 | def set_bearing(self, angle_temp):
691 | return _visilibity.Ray_set_bearing(self, angle_temp)
692 | __swig_destroy__ = _visilibity.delete_Ray
693 | __del__ = lambda self: None
694 | Ray_swigregister = _visilibity.Ray_swigregister
695 | Ray_swigregister(Ray)
696 |
697 |
698 | def intersection(*args):
699 | return _visilibity.intersection(*args)
700 | intersection = _visilibity.intersection
701 | class Polyline(_object):
702 | __swig_setmethods__ = {}
703 | __setattr__ = lambda self, name, value: _swig_setattr(self, Polyline, name, value)
704 | __swig_getmethods__ = {}
705 | __getattr__ = lambda self, name: _swig_getattr(self, Polyline, name)
706 | __repr__ = _swig_repr
707 |
708 | def __init__(self, *args):
709 | this = _visilibity.new_Polyline(*args)
710 | try:
711 | self.this.append(this)
712 | except __builtin__.Exception:
713 | self.this = this
714 |
715 | def size(self):
716 | return _visilibity.Polyline_size(self)
717 |
718 | def length(self):
719 | return _visilibity.Polyline_length(self)
720 |
721 | def diameter(self):
722 | return _visilibity.Polyline_diameter(self)
723 |
724 | def bbox(self):
725 | return _visilibity.Polyline_bbox(self)
726 |
727 | def clear(self):
728 | return _visilibity.Polyline_clear(self)
729 |
730 | def push_back(self, point_temp):
731 | return _visilibity.Polyline_push_back(self, point_temp)
732 |
733 | def pop_back(self):
734 | return _visilibity.Polyline_pop_back(self)
735 |
736 | def set_vertices(self, vertices_temp):
737 | return _visilibity.Polyline_set_vertices(self, vertices_temp)
738 |
739 | def eliminate_redundant_vertices(self, epsilon=0.0):
740 | return _visilibity.Polyline_eliminate_redundant_vertices(self, epsilon)
741 |
742 | def reverse(self):
743 | return _visilibity.Polyline_reverse(self)
744 |
745 | def path(self):
746 | return _visilibity.Polyline_path(self)
747 |
748 | def append(self, polyline):
749 | return _visilibity.Polyline_append(self, polyline)
750 | __swig_destroy__ = _visilibity.delete_Polyline
751 | __del__ = lambda self: None
752 | Polyline_swigregister = _visilibity.Polyline_swigregister
753 | Polyline_swigregister(Polyline)
754 |
755 | class Polygon(_object):
756 | __swig_setmethods__ = {}
757 | __setattr__ = lambda self, name, value: _swig_setattr(self, Polygon, name, value)
758 | __swig_getmethods__ = {}
759 | __getattr__ = lambda self, name: _swig_getattr(self, Polygon, name)
760 | __repr__ = _swig_repr
761 |
762 | def __init__(self, *args):
763 | this = _visilibity.new_Polygon(*args)
764 | try:
765 | self.this.append(this)
766 | except __builtin__.Exception:
767 | self.this = this
768 |
769 | def n(self):
770 | return _visilibity.Polygon_n(self)
771 |
772 | def r(self):
773 | return _visilibity.Polygon_r(self)
774 |
775 | def is_simple(self, epsilon=0.0):
776 | return _visilibity.Polygon_is_simple(self, epsilon)
777 |
778 | def is_in_standard_form(self):
779 | return _visilibity.Polygon_is_in_standard_form(self)
780 |
781 | def boundary_length(self):
782 | return _visilibity.Polygon_boundary_length(self)
783 |
784 | def area(self):
785 | return _visilibity.Polygon_area(self)
786 |
787 | def centroid(self):
788 | return _visilibity.Polygon_centroid(self)
789 |
790 | def diameter(self):
791 | return _visilibity.Polygon_diameter(self)
792 |
793 | def bbox(self):
794 | return _visilibity.Polygon_bbox(self)
795 |
796 | def random_points(self, count, epsilon=0.0):
797 | return _visilibity.Polygon_random_points(self, count, epsilon)
798 |
799 | def write_to_file(self, *args):
800 | return _visilibity.Polygon_write_to_file(self, *args)
801 |
802 | def set_vertices(self, vertices_temp):
803 | return _visilibity.Polygon_set_vertices(self, vertices_temp)
804 |
805 | def push_back(self, vertex_temp):
806 | return _visilibity.Polygon_push_back(self, vertex_temp)
807 |
808 | def clear(self):
809 | return _visilibity.Polygon_clear(self)
810 |
811 | def enforce_standard_form(self):
812 | return _visilibity.Polygon_enforce_standard_form(self)
813 |
814 | def eliminate_redundant_vertices(self, epsilon=0.0):
815 | return _visilibity.Polygon_eliminate_redundant_vertices(self, epsilon)
816 |
817 | def reverse(self):
818 | return _visilibity.Polygon_reverse(self)
819 |
820 | def __getitem__(self, i):
821 | return _visilibity.Polygon___getitem__(self, i)
822 | __swig_destroy__ = _visilibity.delete_Polygon
823 | __del__ = lambda self: None
824 | Polygon_swigregister = _visilibity.Polygon_swigregister
825 | Polygon_swigregister(Polygon)
826 |
827 |
828 | def __eq__(*args):
829 | return _visilibity.__eq__(*args)
830 | __eq__ = _visilibity.__eq__
831 |
832 | def __ne__(*args):
833 | return _visilibity.__ne__(*args)
834 | __ne__ = _visilibity.__ne__
835 |
836 | def equivalent(*args):
837 | return _visilibity.equivalent(*args)
838 | equivalent = _visilibity.equivalent
839 |
840 | def boundary_distance(*args):
841 | return _visilibity.boundary_distance(*args)
842 | boundary_distance = _visilibity.boundary_distance
843 | class Environment(_object):
844 | __swig_setmethods__ = {}
845 | __setattr__ = lambda self, name, value: _swig_setattr(self, Environment, name, value)
846 | __swig_getmethods__ = {}
847 | __getattr__ = lambda self, name: _swig_getattr(self, Environment, name)
848 | __repr__ = _swig_repr
849 |
850 | def __init__(self, *args):
851 | this = _visilibity.new_Environment(*args)
852 | try:
853 | self.this.append(this)
854 | except __builtin__.Exception:
855 | self.this = this
856 |
857 | def h(self):
858 | return _visilibity.Environment_h(self)
859 |
860 | def n(self):
861 | return _visilibity.Environment_n(self)
862 |
863 | def r(self):
864 | return _visilibity.Environment_r(self)
865 |
866 | def is_in_standard_form(self):
867 | return _visilibity.Environment_is_in_standard_form(self)
868 |
869 | def is_valid(self, epsilon=0.0):
870 | return _visilibity.Environment_is_valid(self, epsilon)
871 |
872 | def boundary_length(self):
873 | return _visilibity.Environment_boundary_length(self)
874 |
875 | def area(self):
876 | return _visilibity.Environment_area(self)
877 |
878 | def diameter(self):
879 | return _visilibity.Environment_diameter(self)
880 |
881 | def bbox(self):
882 | return _visilibity.Environment_bbox(self)
883 |
884 | def random_points(self, count, epsilon=0.0):
885 | return _visilibity.Environment_random_points(self, count, epsilon)
886 |
887 | def shortest_path(self, *args):
888 | return _visilibity.Environment_shortest_path(self, *args)
889 |
890 | def compute_partition_cells(self, partition_inducing_segments, epsilon=0.0):
891 | return _visilibity.Environment_compute_partition_cells(self, partition_inducing_segments, epsilon)
892 |
893 | def write_to_file(self, *args):
894 | return _visilibity.Environment_write_to_file(self, *args)
895 |
896 | def __call__(self, *args):
897 | return _visilibity.Environment___call__(self, *args)
898 |
899 | def set_outer_boundary(self, polygon_temp):
900 | return _visilibity.Environment_set_outer_boundary(self, polygon_temp)
901 |
902 | def add_hole(self, polygon_temp):
903 | return _visilibity.Environment_add_hole(self, polygon_temp)
904 |
905 | def enforce_standard_form(self):
906 | return _visilibity.Environment_enforce_standard_form(self)
907 |
908 | def eliminate_redundant_vertices(self, epsilon=0.0):
909 | return _visilibity.Environment_eliminate_redundant_vertices(self, epsilon)
910 |
911 | def reverse_holes(self):
912 | return _visilibity.Environment_reverse_holes(self)
913 | __swig_destroy__ = _visilibity.delete_Environment
914 | __del__ = lambda self: None
915 | Environment_swigregister = _visilibity.Environment_swigregister
916 | Environment_swigregister(Environment)
917 |
918 | class Guards(_object):
919 | __swig_setmethods__ = {}
920 | __setattr__ = lambda self, name, value: _swig_setattr(self, Guards, name, value)
921 | __swig_getmethods__ = {}
922 | __getattr__ = lambda self, name: _swig_getattr(self, Guards, name)
923 | __repr__ = _swig_repr
924 |
925 | def __init__(self, *args):
926 | this = _visilibity.new_Guards(*args)
927 | try:
928 | self.this.append(this)
929 | except __builtin__.Exception:
930 | self.this = this
931 |
932 | def N(self):
933 | return _visilibity.Guards_N(self)
934 |
935 | def are_lex_ordered(self):
936 | return _visilibity.Guards_are_lex_ordered(self)
937 |
938 | def noncolocated(self, epsilon=0.0):
939 | return _visilibity.Guards_noncolocated(self, epsilon)
940 |
941 | def _in(self, *args):
942 | return _visilibity.Guards__in(self, *args)
943 |
944 | def diameter(self):
945 | return _visilibity.Guards_diameter(self)
946 |
947 | def bbox(self):
948 | return _visilibity.Guards_bbox(self)
949 |
950 | def write_to_file(self, *args):
951 | return _visilibity.Guards_write_to_file(self, *args)
952 |
953 | def push_back(self, point_temp):
954 | return _visilibity.Guards_push_back(self, point_temp)
955 |
956 | def set_positions(self, positions_temp):
957 | return _visilibity.Guards_set_positions(self, positions_temp)
958 |
959 | def enforce_lex_order(self):
960 | return _visilibity.Guards_enforce_lex_order(self)
961 |
962 | def reverse(self):
963 | return _visilibity.Guards_reverse(self)
964 |
965 | def snap_to_vertices_of(self, *args):
966 | return _visilibity.Guards_snap_to_vertices_of(self, *args)
967 |
968 | def snap_to_boundary_of(self, *args):
969 | return _visilibity.Guards_snap_to_boundary_of(self, *args)
970 | __swig_destroy__ = _visilibity.delete_Guards
971 | __del__ = lambda self: None
972 | Guards_swigregister = _visilibity.Guards_swigregister
973 | Guards_swigregister(Guards)
974 |
975 | class Visibility_Polygon(Polygon):
976 | __swig_setmethods__ = {}
977 | for _s in [Polygon]:
978 | __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
979 | __setattr__ = lambda self, name, value: _swig_setattr(self, Visibility_Polygon, name, value)
980 | __swig_getmethods__ = {}
981 | for _s in [Polygon]:
982 | __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
983 | __getattr__ = lambda self, name: _swig_getattr(self, Visibility_Polygon, name)
984 | __repr__ = _swig_repr
985 |
986 | def __init__(self, *args):
987 | this = _visilibity.new_Visibility_Polygon(*args)
988 | try:
989 | self.this.append(this)
990 | except __builtin__.Exception:
991 | self.this = this
992 |
993 | def observer(self):
994 | return _visilibity.Visibility_Polygon_observer(self)
995 | __swig_destroy__ = _visilibity.delete_Visibility_Polygon
996 | __del__ = lambda self: None
997 | Visibility_Polygon_swigregister = _visilibity.Visibility_Polygon_swigregister
998 | Visibility_Polygon_swigregister(Visibility_Polygon)
999 |
1000 | class Visibility_Graph(_object):
1001 | __swig_setmethods__ = {}
1002 | __setattr__ = lambda self, name, value: _swig_setattr(self, Visibility_Graph, name, value)
1003 | __swig_getmethods__ = {}
1004 | __getattr__ = lambda self, name: _swig_getattr(self, Visibility_Graph, name)
1005 | __repr__ = _swig_repr
1006 |
1007 | def __init__(self, *args):
1008 | this = _visilibity.new_Visibility_Graph(*args)
1009 | try:
1010 | self.this.append(this)
1011 | except __builtin__.Exception:
1012 | self.this = this
1013 |
1014 | def n(self):
1015 | return _visilibity.Visibility_Graph_n(self)
1016 |
1017 | def __call__(self, *args):
1018 | return _visilibity.Visibility_Graph___call__(self, *args)
1019 | __swig_destroy__ = _visilibity.delete_Visibility_Graph
1020 | __del__ = lambda self: None
1021 | Visibility_Graph_swigregister = _visilibity.Visibility_Graph_swigregister
1022 | Visibility_Graph_swigregister(Visibility_Graph)
1023 |
1024 |
1025 | def __lshift__(*args):
1026 | return _visilibity.__lshift__(*args)
1027 | __lshift__ = _visilibity.__lshift__
1028 | # This file is compatible with both classic and new-style classes.
1029 |
1030 |
1031 |
--------------------------------------------------------------------------------
/visilibity_test.py:
--------------------------------------------------------------------------------
1 | # PyVisiLibity: a Python binding of VisiLibity1
2 | # Copyright (C) 2018 Yu Cao < University of Southampton> Yu.Cao at soton.ac.uk
3 | # Originally by Ramiro C. of UNC, Argentina
4 | #
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU Lesser General Public License as published by
8 | # the Free Software Foundation; either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU Lesser General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU Lesser General Public License
17 | # along with this program; if not, write to the Free Software Foundation,
18 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 |
20 |
21 | from __future__ import print_function
22 | import visilibity as vis
23 |
24 | # Used to plot the example
25 | import matplotlib.pylab as p
26 |
27 | # Used in the create_cone function
28 | import math
29 |
30 | def testVisilibity():
31 |
32 | # Define an epsilon value (should be != 0.0)
33 | epsilon = 0.0000001
34 |
35 | # Define the points which will be the outer boundary of the environment
36 | # Must be COUNTER-CLOCK-WISE(ccw)
37 | p1 = vis.Point(0,0)
38 | p2 = vis.Point(700,0)
39 | p3 = vis.Point(700,900)
40 | p4 = vis.Point(0,900)
41 |
42 | # Load the values of the outer boundary polygon in order to draw it later
43 | wall_x = [p1.x(), p2.x(), p3.x(), p4.x(), p1.x()]
44 | wall_y = [p1.y(), p2.y(), p3.y(), p4.y(), p1.y()]
45 |
46 | # Outer boundary polygon must be COUNTER-CLOCK-WISE(ccw)
47 | # Create the outer boundary polygon
48 | walls = vis.Polygon([p1, p2, p3, p4])
49 |
50 | # Define the point of the "observer"
51 | observer = vis.Point(235,400)
52 |
53 | # Uncomment the following line in order to create a cone polygon
54 | #walls = create_cone((observer.x(), observer.y()), 500, 270, 30, quality= 3)
55 |
56 | # Walls should be in standard form
57 | print('Walls in standard form : ',walls.is_in_standard_form())
58 |
59 | # Now we define some holes for our environment. The holes must be inside
60 | # our outer boundary polygon. A hole blocks the observer vision, it works as
61 | # an obstacle in his vision sensor.
62 |
63 |
64 | # We define some point for a hole. You can add more points in order to get
65 | # the shape you want.
66 | # The smalles point should be first
67 | p2 =vis.Point(100, 300)
68 | p3 =vis.Point(100, 500)
69 | p4 =vis.Point(150, 500)
70 | p1 =vis.Point(150, 300)
71 |
72 | # Load the values of the hole polygon in order to draw it later
73 | hole_x = [p1.x(), p2.x(), p3.x(), p4.x(),p1.x()]
74 | hole_y = [p1.y(), p2.y(), p3.y(), p4.y(),p1.y()]
75 |
76 | # Note: The point of a hole must be in CLOCK-WISE(cw) order.
77 | # Create the hole polygon
78 | hole = vis.Polygon([p2,p3,p4,p1])
79 |
80 | # Check if the hole is in standard form
81 | print('Hole in standard form: ',hole.is_in_standard_form())
82 |
83 |
84 | # Define another point of a hole polygon
85 | # Remember: the list of points must be CLOCK-WISE(cw)
86 | p1 =vis.Point(300, 300)
87 | p2 =vis.Point(300, 500)
88 | p3 =vis.Point(400, 550)
89 | p4 =vis.Point(400, 300)
90 |
91 | # Load the values of the hole polygon in order to draw it later
92 | hole1_x = [p1.x(), p2.x(), p3.x(), p4.x(),p1.x()]
93 | hole1_y = [p1.y(), p2.y(), p3.y(), p4.y(),p1.y()]
94 |
95 | # Create the hole polygon
96 | hole1 = vis.Polygon([p1,p2,p3,p4])
97 |
98 | # Check if the hole is in standard form
99 | print('Hole in standard form: ',hole1.is_in_standard_form())
100 |
101 | # Define another point of a hole polygon
102 | # Remember: the list of points must be CLOCK-WISE(cw)
103 | p2 =vis.Point(90, 700)
104 | p3 =vis.Point(250, 750)
105 | p4 =vis.Point(220, 600)
106 | p1 =vis.Point(150, 600)
107 |
108 | # Load the values of the hole polygon in order to draw it later
109 | hole2_x = [p1.x(), p2.x(), p3.x(), p4.x(),p1.x()]
110 | hole2_y = [p1.y(), p2.y(), p3.y(), p4.y(),p1.y()]
111 |
112 | # Create the hole polygon
113 | hole2 = vis.Polygon([p2,p3,p4,p1])
114 |
115 | # Check if the hole is in standard form
116 | print('Hole in standard form: ',hole2.is_in_standard_form())
117 |
118 | # Define another point of a hole polygon
119 | # Remember: the list of points must be CLOCK-WISE(cw)
120 | p1 =vis.Point(330, 700)
121 | p2 =vis.Point(330, 800)
122 | p3 =vis.Point(530, 850)
123 | p4 =vis.Point(530, 790)
124 |
125 | # Load the values of the hole polygon in order to draw it later
126 | hole3_x = [p1.x(), p2.x(), p3.x(), p4.x(),p1.x()]
127 | hole3_y = [p1.y(), p2.y(), p3.y(), p4.y(),p1.y()]
128 |
129 | # Create the hole polygon
130 | hole3 = vis.Polygon([p1,p2,p3,p4])
131 |
132 | # Check if the hole is in standard form
133 | print('Hole in standard form: ',hole3.is_in_standard_form())
134 |
135 | # Define another point of a hole polygon
136 | # Remember: the list of points must be CLOCK-WISE(cw)
137 | p1 =vis.Point(230, 50)
138 | p2 =vis.Point(250, 90)
139 | p3 =vis.Point(390, 90)
140 | p4 =vis.Point(390, 50)
141 |
142 | # Load the values of the hole polygon in order to draw it later
143 | hole4_x = [p1.x(), p2.x(), p3.x(), p4.x(),p1.x()]
144 | hole4_y = [p1.y(), p2.y(), p3.y(), p4.y(),p1.y()]
145 |
146 | # Create the hole polygon
147 | hole4 = vis.Polygon([p1,p2,p3,p4])
148 |
149 | # Check if the hole is in standard form
150 | print('Hole in standard form: ',hole4.is_in_standard_form())
151 |
152 |
153 | # Create environment, wall will be the outer boundary because
154 | # is the first polygon in the list. The other polygons will be holes
155 | env = vis.Environment([walls, hole,hole2, hole1, hole3, hole4])
156 |
157 |
158 | # Check if the environment is valid
159 | print('Environment is valid : ',env.is_valid(epsilon))
160 |
161 |
162 | # Define another point, could be used to check if the observer see it, to
163 | # check the shortest path from one point to the other, etc.
164 | end = vis.Point(330, 525)
165 |
166 | # Define another point that the 'observer' will see
167 | end_visible = vis.Point(415,45)
168 |
169 | # Necesary to generate the visibility polygon
170 | observer.snap_to_boundary_of(env, epsilon)
171 | observer.snap_to_vertices_of(env, epsilon)
172 |
173 | # Obtein the visibility polygon of the 'observer' in the environmente
174 | # previously define
175 | isovist = vis.Visibility_Polygon(observer, env, epsilon)
176 |
177 | # Uncomment the following line to obtein the visibility polygon
178 | # of 'end' in the environmente previously define
179 | #polygon_vis = vis.Visibility_Polygon(end, env, epsilon)
180 |
181 | # Obtein the shortest path from 'observer' to 'end' and 'end_visible'
182 | # in the environment previously define
183 | shortest_path = env.shortest_path(observer, end, epsilon)
184 | shortest_path1 = env.shortest_path(observer, end_visible, epsilon)
185 |
186 | # Print the length of the path
187 | print("Shortest Path length from observer to end: ", shortest_path.length())
188 | print( "Shortest Path length from observer to end_visible: ", shortest_path1.length())
189 |
190 |
191 | # Check if 'observer' can see 'end', i.e., check if 'end' point is in
192 | # the visibility polygon of 'observer'
193 | print( "Can observer see end? ", end._in(isovist, epsilon))
194 |
195 | print( "Can observer see end_visible? ", end_visible._in(isovist, epsilon))
196 |
197 | # Print the point of the visibility polygon of 'observer' and save them
198 | # in two arrays in order to draw the polygon later
199 | point_x , point_y = save_print(isovist)
200 |
201 | # Add the first point again because the function to draw, draw a line from
202 | # one point to the next one and to close the figure we need the last line
203 | # from the last point to the first one
204 | point_x.append(isovist[0].x())
205 | point_y.append(isovist[0].y())
206 |
207 | # Set the title
208 | p.title('VisiLibity Test')
209 |
210 | # Set the labels for the axis
211 | p.xlabel('X Position')
212 | p.ylabel('Y Position')
213 |
214 | # Plot the outer boundary with black color
215 | p.plot(wall_x, wall_y, 'black')
216 |
217 | # Plot the position of the observer with a green dot ('go')
218 | p.plot([observer.x()], [observer.y()], 'go')
219 |
220 | # Plot the position of 'end' with a green dot ('go')
221 | p.plot([end.x()],[end.y()], 'go')
222 |
223 | # Plot the position of 'end_visible' with a green dot ('go')
224 | p.plot([end_visible.x()],[end_visible.y()], 'go')
225 |
226 | # Plot the visibility polygon of 'observer'
227 | p.plot(point_x, point_y)
228 |
229 | # Plot the hole polygon with red color
230 | p.plot(hole_x, hole_y, 'r')
231 |
232 | # Plot the hole polygon with red color
233 | p.plot(hole1_x, hole1_y, 'r')
234 |
235 | # Plot the hole polygon with red color
236 | p.plot(hole2_x, hole2_y, 'r')
237 |
238 | # Plot the hole polygon with red color
239 | p.plot(hole3_x, hole3_y, 'r')
240 |
241 | # Plot the hole polygon with red color
242 | p.plot(hole4_x, hole4_y, 'r')
243 |
244 | # Example of a cone-shape polygon
245 | cone_point = vis.Point(440,420)
246 | cone = create_cone([cone_point.x(),cone_point.y()], 150, 0, 45, 3)
247 | cone_x, cone_y = save_print(cone)
248 | cone_x.append(cone_x[0])
249 | cone_y.append(cone_y[0])
250 | p.plot([cone_point.x()], [cone_point.y()], 'go')
251 | p.plot(cone_x, cone_y)
252 |
253 | # Show the plot
254 | p.show()
255 |
256 |
257 | def save_print(polygon):
258 | end_pos_x = []
259 | end_pos_y = []
260 | print ('Points of Polygon: ')
261 | for i in range(polygon.n()):
262 | x = polygon[i].x()
263 | y = polygon[i].y()
264 |
265 | end_pos_x.append(x)
266 | end_pos_y.append(y)
267 |
268 | print( x,y)
269 |
270 | return end_pos_x, end_pos_y
271 |
272 |
273 | # Desc: This function creates a cone-shape polygon. To do that it use
274 | # five inputs(point, radius, angle, opening, resolution).
275 | # 'point': is the vertex of the cone.
276 | # 'radius': is the longitude from 'point' to any point in the arc.
277 | # 'angle': is the direcction of the cone.
278 | # 'resolution': is the number of degrees one point and the next in the arc.
279 | # Return: The function returns a Polygon object with the shape of
280 | # a cone with the above characteristics.
281 | def create_cone(point, radio, angle, opening, resolution=1):
282 |
283 | # Define the list for the points of the cone-shape polygon
284 | p=[]
285 |
286 | # The fisrt point will be the vertex of the cone
287 | p.append(vis.Point(point[0], point[1]))
288 |
289 | # Define the start and end of the arc
290 | start = angle - opening
291 | end = angle + opening
292 |
293 | for i in range(start, end, resolution):
294 |
295 | # Convert start angle from degrees to radians
296 | rad = math.radians(i)
297 |
298 | # Calculate the off-set of the first point of the arc
299 | x = radio*math.cos(rad)
300 | y = radio*math.sin(rad)
301 |
302 | # Add the off-set to the vertex point
303 | new_x = point[0] + x
304 | new_y = point[1] + y
305 |
306 | # Add the first point of the arc to the list
307 | p.append( vis.Point(new_x, new_y) )
308 |
309 | # Add the last point of the arc
310 | rad = math.radians(end)
311 | x = radio*math.cos(rad)
312 | y = radio*math.sin(rad)
313 | new_x = point[0] + x
314 | new_y = point[1] + y
315 | p.append( vis.Point(new_x, new_y) )
316 |
317 | return vis.Polygon(p)
318 |
319 | if __name__ == "__main__":
320 | testVisilibity()
321 |
--------------------------------------------------------------------------------