From 088ef9a0c6d705b6c57a465b8b2fe87805136033 Mon Sep 17 00:00:00 2001 From: isucan <isucan@253336fb-580f-4252-a368-f3cef5a2a82b> Date: Thu, 26 Jan 2012 06:03:30 +0000 Subject: [PATCH] adding fcl_test package git-svn-id: https://kforge.ros.org/fcl/fcl_ros@67 253336fb-580f-4252-a368-f3cef5a2a82b --- trunk/fcl/manifest.xml | 2 - trunk/fcl_test/CMakeLists.txt | 43 + trunk/fcl_test/Makefile | 1 + trunk/fcl_test/mainpage.dox | 26 + trunk/fcl_test/manifest.xml | 19 + trunk/fcl_test/test/env.obj | 8721 +++++++++++++++++ trunk/fcl_test/test/rob.obj | 865 ++ trunk/fcl_test/test/test_core_broad_phase.cpp | 247 + trunk/fcl_test/test/test_core_collision.cpp | 847 ++ .../test/test_core_collision_point.cpp | 516 + ..._core_collision_shape_mesh_consistency.cpp | 1187 +++ .../test_core_conservative_advancement.cpp | 538 + .../test/test_core_continuous_collision.cpp | 296 + .../test/test_core_deformable_object.cpp | 357 + trunk/fcl_test/test/test_core_distance.cpp | 329 + trunk/fcl_test/test/test_core_front_list.cpp | 412 + .../test/test_core_geometric_shapes.cpp | 500 + trunk/fcl_test/test/test_core_utility.h | 665 ++ trunk/fcl_test/test/timer.cpp | 121 + trunk/fcl_test/test/timer.h | 70 + trunk/fcl_test/test/timing_test.cpp | 247 + 21 files changed, 16007 insertions(+), 2 deletions(-) create mode 100644 trunk/fcl_test/CMakeLists.txt create mode 100644 trunk/fcl_test/Makefile create mode 100644 trunk/fcl_test/mainpage.dox create mode 100644 trunk/fcl_test/manifest.xml create mode 100644 trunk/fcl_test/test/env.obj create mode 100644 trunk/fcl_test/test/rob.obj create mode 100644 trunk/fcl_test/test/test_core_broad_phase.cpp create mode 100644 trunk/fcl_test/test/test_core_collision.cpp create mode 100644 trunk/fcl_test/test/test_core_collision_point.cpp create mode 100644 trunk/fcl_test/test/test_core_collision_shape_mesh_consistency.cpp create mode 100644 trunk/fcl_test/test/test_core_conservative_advancement.cpp create mode 100644 trunk/fcl_test/test/test_core_continuous_collision.cpp create mode 100644 trunk/fcl_test/test/test_core_deformable_object.cpp create mode 100644 trunk/fcl_test/test/test_core_distance.cpp create mode 100644 trunk/fcl_test/test/test_core_front_list.cpp create mode 100644 trunk/fcl_test/test/test_core_geometric_shapes.cpp create mode 100644 trunk/fcl_test/test/test_core_utility.h create mode 100644 trunk/fcl_test/test/timer.cpp create mode 100644 trunk/fcl_test/test/timer.h create mode 100644 trunk/fcl_test/test/timing_test.cpp diff --git a/trunk/fcl/manifest.xml b/trunk/fcl/manifest.xml index 9434d81f..bc894938 100644 --- a/trunk/fcl/manifest.xml +++ b/trunk/fcl/manifest.xml @@ -12,8 +12,6 @@ <depend package="ann"/> <depend package="common_rosdeps"/> - <rosdep name="assimp"/> - <export> <cpp cflags="-I${prefix}/include" lflags="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -lfcl"/> </export> diff --git a/trunk/fcl_test/CMakeLists.txt b/trunk/fcl_test/CMakeLists.txt new file mode 100644 index 00000000..3c70b463 --- /dev/null +++ b/trunk/fcl_test/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 2.4.6) +include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) + +# Set the build type. Options are: +# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage +# Debug : w/ debug symbols, w/o optimization +# Release : w/o debug symbols, w/ optimization +# RelWithDebInfo : w/ debug symbols, w/ optimization +# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries +#set(ROS_BUILD_TYPE RelWithDebInfo) +set(ROS_BUILD_TYPE Release) + +rosbuild_init() + +add_definitions(-DUSE_PQP=1) +add_definitions(-DUSE_SVMLIGHT=0) + +#set the default path for built executables to the "bin" directory +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) +#set the default path for built libraries to the "lib" directory +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) + +rosbuild_add_gtest(test_core_collision test/test_core_collision.cpp) + +rosbuild_add_gtest(test_core_distance test/test_core_distance.cpp) + +rosbuild_add_executable(test_core_collision_point test/test_core_collision_point.cpp) + +rosbuild_add_gtest(test_core_geometric_shapes test/test_core_geometric_shapes.cpp) + +rosbuild_add_gtest(test_core_collision_shape_mesh_consistency test/test_core_collision_shape_mesh_consistency.cpp) + +rosbuild_add_gtest(test_core_broad_phase test/test_core_broad_phase.cpp) + +rosbuild_add_gtest(test_core_front_list test/test_core_front_list.cpp) + +rosbuild_add_gtest(test_core_continuous_collision test/test_core_continuous_collision.cpp) + +rosbuild_add_executable(test_core_deformable_object test/test_core_deformable_object.cpp) + +rosbuild_add_executable(test_core_conservative_advancement test/test_core_conservative_advancement.cpp) + +rosbuild_add_executable(timing_test test/timing_test.cpp test/timer.cpp) diff --git a/trunk/fcl_test/Makefile b/trunk/fcl_test/Makefile new file mode 100644 index 00000000..b75b928f --- /dev/null +++ b/trunk/fcl_test/Makefile @@ -0,0 +1 @@ +include $(shell rospack find mk)/cmake.mk \ No newline at end of file diff --git a/trunk/fcl_test/mainpage.dox b/trunk/fcl_test/mainpage.dox new file mode 100644 index 00000000..b84671b9 --- /dev/null +++ b/trunk/fcl_test/mainpage.dox @@ -0,0 +1,26 @@ +/** +\mainpage +\htmlinclude manifest.html + +\b fcl_test is ... + +<!-- +Provide an overview of your package. +--> + + +\section codeapi Code API + +<!-- +Provide links to specific auto-generated API documentation within your +package that is of particular interest to a reader. Doxygen will +document pretty much every part of your code, so do your best here to +point the reader to the actual API. + +If your codebase is fairly large or has different sets of APIs, you +should use the doxygen 'group' tag to keep these APIs together. For +example, the roscpp documentation has 'libros' group. +--> + + +*/ diff --git a/trunk/fcl_test/manifest.xml b/trunk/fcl_test/manifest.xml new file mode 100644 index 00000000..7002c2ed --- /dev/null +++ b/trunk/fcl_test/manifest.xml @@ -0,0 +1,19 @@ +<package> + <description brief="fcl_test"> + + fcl_test + + </description> + <author>Ioan Sucan</author> + <license>BSD</license> + <review status="unreviewed" notes=""/> + <url>http://ros.org/wiki/fcl_test</url> + <depend package="fcl"/> + <depend package="PQP"/> + <depend package="svm_light"/> + + <rosdep name="assimp"/> + +</package> + + diff --git a/trunk/fcl_test/test/env.obj b/trunk/fcl_test/test/env.obj new file mode 100644 index 00000000..1aeb971d --- /dev/null +++ b/trunk/fcl_test/test/env.obj @@ -0,0 +1,8721 @@ +6540 2180 +v -2987.5 -3004.5 2987.5 +v 987.5 -3004.5 2987.5 +v -2987.5 -2995.5 2987.5 +v -2987.5 -2995.5 2987.5 +v 987.5 -3004.5 2987.5 +v 987.5 -2995.5 2987.5 +v 987.5 -3004.5 12.5 +v -2987.5 -3004.5 12.5 +v 987.5 -2995.5 12.5 +v 987.5 -2995.5 12.5 +v -2987.5 -3004.5 12.5 +v -2987.5 -2995.5 12.5 +v 987.5 -3004.5 2987.5 +v 987.5 -3004.5 12.5 +v 987.5 -2995.5 2987.5 +v 987.5 -2995.5 2987.5 +v 987.5 -3004.5 12.5 +v 987.5 -2995.5 12.5 +v -2987.5 -3004.5 12.5 +v -2987.5 -3004.5 2987.5 +v -2987.5 -2995.5 12.5 +v -2987.5 -2995.5 12.5 +v -2987.5 -3004.5 2987.5 +v -2987.5 -2995.5 2987.5 +v -2987.5 -2995.5 12.5 +v -2987.5 -2995.5 2987.5 +v 987.5 -2995.5 12.5 +v 987.5 -2995.5 12.5 +v -2987.5 -2995.5 2987.5 +v 987.5 -2995.5 2987.5 +v -2987.5 -3004.5 12.5 +v 987.5 -3004.5 12.5 +v -2987.5 -3004.5 2987.5 +v -2987.5 -3004.5 2987.5 +v 987.5 -3004.5 12.5 +v 987.5 -3004.5 2987.5 +v -2987.5 -2987.5 -5.5 +v 2987.5 -2987.5 -5.5 +v -2987.5 2987.5 -5.5 +v -2987.5 2987.5 -5.5 +v 2987.5 -2987.5 -5.5 +v 2987.5 2987.5 -5.5 +v 2987.5 -2987.5 -14.5 +v -2987.5 -2987.5 -14.5 +v 2987.5 2987.5 -14.5 +v 2987.5 2987.5 -14.5 +v -2987.5 -2987.5 -14.5 +v -2987.5 2987.5 -14.5 +v 2987.5 -2987.5 -5.5 +v 2987.5 -2987.5 -14.5 +v 2987.5 2987.5 -5.5 +v 2987.5 2987.5 -5.5 +v 2987.5 -2987.5 -14.5 +v 2987.5 2987.5 -14.5 +v -2987.5 -2987.5 -14.5 +v -2987.5 -2987.5 -5.5 +v -2987.5 2987.5 -14.5 +v -2987.5 2987.5 -14.5 +v -2987.5 -2987.5 -5.5 +v -2987.5 2987.5 -5.5 +v -2987.5 2987.5 -14.5 +v -2987.5 2987.5 -5.5 +v 2987.5 2987.5 -14.5 +v 2987.5 2987.5 -14.5 +v -2987.5 2987.5 -5.5 +v 2987.5 2987.5 -5.5 +v -2987.5 -2987.5 -14.5 +v 2987.5 -2987.5 -14.5 +v -2987.5 -2987.5 -5.5 +v -2987.5 -2987.5 -5.5 +v 2987.5 -2987.5 -14.5 +v 2987.5 -2987.5 -5.5 +v 995.5 -2987.5 987.5 +v 1004.5 -2987.5 987.5 +v 995.5 2987.5 987.5 +v 995.5 2987.5 987.5 +v 1004.5 -2987.5 987.5 +v 1004.5 2987.5 987.5 +v 1004.5 -2987.5 12.5 +v 995.5 -2987.5 12.5 +v 1004.5 2987.5 12.5 +v 1004.5 2987.5 12.5 +v 995.5 -2987.5 12.5 +v 995.5 2987.5 12.5 +v 1004.5 -2987.5 987.5 +v 1004.5 -2987.5 12.5 +v 1004.5 2987.5 987.5 +v 1004.5 2987.5 987.5 +v 1004.5 -2987.5 12.5 +v 1004.5 2987.5 12.5 +v 995.5 -2987.5 12.5 +v 995.5 -2987.5 987.5 +v 995.5 2987.5 12.5 +v 995.5 2987.5 12.5 +v 995.5 -2987.5 987.5 +v 995.5 2987.5 987.5 +v 995.5 2987.5 12.5 +v 995.5 2987.5 987.5 +v 1004.5 2987.5 12.5 +v 1004.5 2987.5 12.5 +v 995.5 2987.5 987.5 +v 1004.5 2987.5 987.5 +v 995.5 -2987.5 12.5 +v 1004.5 -2987.5 12.5 +v 995.5 -2987.5 987.5 +v 995.5 -2987.5 987.5 +v 1004.5 -2987.5 12.5 +v 1004.5 -2987.5 987.5 +v 995.5 -2987.5 2987.5 +v 1004.5 -2987.5 2987.5 +v 995.5 2987.5 2987.5 +v 995.5 2987.5 2987.5 +v 1004.5 -2987.5 2987.5 +v 1004.5 2987.5 2987.5 +v 1004.5 -2987.5 2012.5 +v 995.5 -2987.5 2012.5 +v 1004.5 2987.5 2012.5 +v 1004.5 2987.5 2012.5 +v 995.5 -2987.5 2012.5 +v 995.5 2987.5 2012.5 +v 1004.5 -2987.5 2987.5 +v 1004.5 -2987.5 2012.5 +v 1004.5 2987.5 2987.5 +v 1004.5 2987.5 2987.5 +v 1004.5 -2987.5 2012.5 +v 1004.5 2987.5 2012.5 +v 995.5 -2987.5 2012.5 +v 995.5 -2987.5 2987.5 +v 995.5 2987.5 2012.5 +v 995.5 2987.5 2012.5 +v 995.5 -2987.5 2987.5 +v 995.5 2987.5 2987.5 +v 995.5 2987.5 2012.5 +v 995.5 2987.5 2987.5 +v 1004.5 2987.5 2012.5 +v 1004.5 2987.5 2012.5 +v 995.5 2987.5 2987.5 +v 1004.5 2987.5 2987.5 +v 995.5 -2987.5 2012.5 +v 1004.5 -2987.5 2012.5 +v 995.5 -2987.5 2987.5 +v 995.5 -2987.5 2987.5 +v 1004.5 -2987.5 2012.5 +v 1004.5 -2987.5 2987.5 +v 995.5 -2987.5 1987.5 +v 1004.5 -2987.5 1987.5 +v 995.5 -1012.5 1987.5 +v 995.5 -1012.5 1987.5 +v 1004.5 -2987.5 1987.5 +v 1004.5 -1012.5 1987.5 +v 1004.5 -2987.5 1012.5 +v 995.5 -2987.5 1012.5 +v 1004.5 -1012.5 1012.5 +v 1004.5 -1012.5 1012.5 +v 995.5 -2987.5 1012.5 +v 995.5 -1012.5 1012.5 +v 1004.5 -2987.5 1987.5 +v 1004.5 -2987.5 1012.5 +v 1004.5 -1012.5 1987.5 +v 1004.5 -1012.5 1987.5 +v 1004.5 -2987.5 1012.5 +v 1004.5 -1012.5 1012.5 +v 995.5 -2987.5 1012.5 +v 995.5 -2987.5 1987.5 +v 995.5 -1012.5 1012.5 +v 995.5 -1012.5 1012.5 +v 995.5 -2987.5 1987.5 +v 995.5 -1012.5 1987.5 +v 995.5 -1012.5 1012.5 +v 995.5 -1012.5 1987.5 +v 1004.5 -1012.5 1012.5 +v 1004.5 -1012.5 1012.5 +v 995.5 -1012.5 1987.5 +v 1004.5 -1012.5 1987.5 +v 995.5 -2987.5 1012.5 +v 1004.5 -2987.5 1012.5 +v 995.5 -2987.5 1987.5 +v 995.5 -2987.5 1987.5 +v 1004.5 -2987.5 1012.5 +v 1004.5 -2987.5 1987.5 +v 995.5 1012.5 1987.5 +v 1004.5 1012.5 1987.5 +v 995.5 2987.5 1987.5 +v 995.5 2987.5 1987.5 +v 1004.5 1012.5 1987.5 +v 1004.5 2987.5 1987.5 +v 1004.5 1012.5 1012.5 +v 995.5 1012.5 1012.5 +v 1004.5 2987.5 1012.5 +v 1004.5 2987.5 1012.5 +v 995.5 1012.5 1012.5 +v 995.5 2987.5 1012.5 +v 1004.5 1012.5 1987.5 +v 1004.5 1012.5 1012.5 +v 1004.5 2987.5 1987.5 +v 1004.5 2987.5 1987.5 +v 1004.5 1012.5 1012.5 +v 1004.5 2987.5 1012.5 +v 995.5 1012.5 1012.5 +v 995.5 1012.5 1987.5 +v 995.5 2987.5 1012.5 +v 995.5 2987.5 1012.5 +v 995.5 1012.5 1987.5 +v 995.5 2987.5 1987.5 +v 995.5 2987.5 1012.5 +v 995.5 2987.5 1987.5 +v 1004.5 2987.5 1012.5 +v 1004.5 2987.5 1012.5 +v 995.5 2987.5 1987.5 +v 1004.5 2987.5 1987.5 +v 995.5 1012.5 1012.5 +v 1004.5 1012.5 1012.5 +v 995.5 1012.5 1987.5 +v 995.5 1012.5 1987.5 +v 1004.5 1012.5 1012.5 +v 1004.5 1012.5 1987.5 +v -2987.5 2995.5 2987.5 +v 987.5 2995.5 2987.5 +v -2987.5 3004.5 2987.5 +v -2987.5 3004.5 2987.5 +v 987.5 2995.5 2987.5 +v 987.5 3004.5 2987.5 +v 987.5 2995.5 12.5 +v -2987.5 2995.5 12.5 +v 987.5 3004.5 12.5 +v 987.5 3004.5 12.5 +v -2987.5 2995.5 12.5 +v -2987.5 3004.5 12.5 +v 987.5 2995.5 2987.5 +v 987.5 2995.5 12.5 +v 987.5 3004.5 2987.5 +v 987.5 3004.5 2987.5 +v 987.5 2995.5 12.5 +v 987.5 3004.5 12.5 +v -2987.5 2995.5 12.5 +v -2987.5 2995.5 2987.5 +v -2987.5 3004.5 12.5 +v -2987.5 3004.5 12.5 +v -2987.5 2995.5 2987.5 +v -2987.5 3004.5 2987.5 +v -2987.5 3004.5 12.5 +v -2987.5 3004.5 2987.5 +v 987.5 3004.5 12.5 +v 987.5 3004.5 12.5 +v -2987.5 3004.5 2987.5 +v 987.5 3004.5 2987.5 +v -2987.5 2995.5 12.5 +v 987.5 2995.5 12.5 +v -2987.5 2995.5 2987.5 +v -2987.5 2995.5 2987.5 +v 987.5 2995.5 12.5 +v 987.5 2995.5 2987.5 +v -3004.5 -2987.5 2987.5 +v -2995.5 -2987.5 2987.5 +v -3004.5 2987.5 2987.5 +v -3004.5 2987.5 2987.5 +v -2995.5 -2987.5 2987.5 +v -2995.5 2987.5 2987.5 +v -2995.5 -2987.5 12.5 +v -3004.5 -2987.5 12.5 +v -2995.5 2987.5 12.5 +v -2995.5 2987.5 12.5 +v -3004.5 -2987.5 12.5 +v -3004.5 2987.5 12.5 +v -2995.5 -2987.5 2987.5 +v -2995.5 -2987.5 12.5 +v -2995.5 2987.5 2987.5 +v -2995.5 2987.5 2987.5 +v -2995.5 -2987.5 12.5 +v -2995.5 2987.5 12.5 +v -3004.5 -2987.5 12.5 +v -3004.5 -2987.5 2987.5 +v -3004.5 2987.5 12.5 +v -3004.5 2987.5 12.5 +v -3004.5 -2987.5 2987.5 +v -3004.5 2987.5 2987.5 +v -3004.5 2987.5 12.5 +v -3004.5 2987.5 2987.5 +v -2995.5 2987.5 12.5 +v -2995.5 2987.5 12.5 +v -3004.5 2987.5 2987.5 +v -2995.5 2987.5 2987.5 +v -3004.5 -2987.5 12.5 +v -2995.5 -2987.5 12.5 +v -3004.5 -2987.5 2987.5 +v -3004.5 -2987.5 2987.5 +v -2995.5 -2987.5 12.5 +v -2995.5 -2987.5 2987.5 +v -1660 -2650 495 +v -1659.24 -2653.83 495 +v -1660 -2650 5 +v -1660 -2650 5 +v -1659.24 -2653.83 495 +v -1659.24 -2653.83 5 +v -1659.24 -2653.83 495 +v -1657.07 -2657.07 495 +v -1659.24 -2653.83 5 +v -1659.24 -2653.83 5 +v -1657.07 -2657.07 495 +v -1657.07 -2657.07 5 +v -1657.07 -2657.07 495 +v -1653.83 -2659.24 495 +v -1657.07 -2657.07 5 +v -1657.07 -2657.07 5 +v -1653.83 -2659.24 495 +v -1653.83 -2659.24 5 +v -1653.83 -2659.24 495 +v -1650 -2660 495 +v -1653.83 -2659.24 5 +v -1653.83 -2659.24 5 +v -1650 -2660 495 +v -1650 -2660 5 +v -1650 -2660 495 +v -1646.17 -2659.24 495 +v -1650 -2660 5 +v -1650 -2660 5 +v -1646.17 -2659.24 495 +v -1646.17 -2659.24 5 +v -1646.17 -2659.24 495 +v -1642.93 -2657.07 495 +v -1646.17 -2659.24 5 +v -1646.17 -2659.24 5 +v -1642.93 -2657.07 495 +v -1642.93 -2657.07 5 +v -1642.93 -2657.07 495 +v -1640.76 -2653.83 495 +v -1642.93 -2657.07 5 +v -1642.93 -2657.07 5 +v -1640.76 -2653.83 495 +v -1640.76 -2653.83 5 +v -1640.76 -2653.83 495 +v -1640 -2650 495 +v -1640.76 -2653.83 5 +v -1640.76 -2653.83 5 +v -1640 -2650 495 +v -1640 -2650 5 +v -1640 -2650 495 +v -1640.76 -2646.17 495 +v -1640 -2650 5 +v -1640 -2650 5 +v -1640.76 -2646.17 495 +v -1640.76 -2646.17 5 +v -1640.76 -2646.17 495 +v -1642.93 -2642.93 495 +v -1640.76 -2646.17 5 +v -1640.76 -2646.17 5 +v -1642.93 -2642.93 495 +v -1642.93 -2642.93 5 +v -1642.93 -2642.93 495 +v -1646.17 -2640.76 495 +v -1642.93 -2642.93 5 +v -1642.93 -2642.93 5 +v -1646.17 -2640.76 495 +v -1646.17 -2640.76 5 +v -1646.17 -2640.76 495 +v -1650 -2640 495 +v -1646.17 -2640.76 5 +v -1646.17 -2640.76 5 +v -1650 -2640 495 +v -1650 -2640 5 +v -1650 -2640 495 +v -1653.83 -2640.76 495 +v -1650 -2640 5 +v -1650 -2640 5 +v -1653.83 -2640.76 495 +v -1653.83 -2640.76 5 +v -1653.83 -2640.76 495 +v -1657.07 -2642.93 495 +v -1653.83 -2640.76 5 +v -1653.83 -2640.76 5 +v -1657.07 -2642.93 495 +v -1657.07 -2642.93 5 +v -1657.07 -2642.93 495 +v -1659.24 -2646.17 495 +v -1657.07 -2642.93 5 +v -1657.07 -2642.93 5 +v -1659.24 -2646.17 495 +v -1659.24 -2646.17 5 +v -1659.24 -2646.17 495 +v -1660 -2650 495 +v -1659.24 -2646.17 5 +v -1659.24 -2646.17 5 +v -1660 -2650 495 +v -1660 -2650 5 +v -1360 -2650 495 +v -1359.24 -2653.83 495 +v -1360 -2650 5 +v -1360 -2650 5 +v -1359.24 -2653.83 495 +v -1359.24 -2653.83 5 +v -1359.24 -2653.83 495 +v -1357.07 -2657.07 495 +v -1359.24 -2653.83 5 +v -1359.24 -2653.83 5 +v -1357.07 -2657.07 495 +v -1357.07 -2657.07 5 +v -1357.07 -2657.07 495 +v -1353.83 -2659.24 495 +v -1357.07 -2657.07 5 +v -1357.07 -2657.07 5 +v -1353.83 -2659.24 495 +v -1353.83 -2659.24 5 +v -1353.83 -2659.24 495 +v -1350 -2660 495 +v -1353.83 -2659.24 5 +v -1353.83 -2659.24 5 +v -1350 -2660 495 +v -1350 -2660 5 +v -1350 -2660 495 +v -1346.17 -2659.24 495 +v -1350 -2660 5 +v -1350 -2660 5 +v -1346.17 -2659.24 495 +v -1346.17 -2659.24 5 +v -1346.17 -2659.24 495 +v -1342.93 -2657.07 495 +v -1346.17 -2659.24 5 +v -1346.17 -2659.24 5 +v -1342.93 -2657.07 495 +v -1342.93 -2657.07 5 +v -1342.93 -2657.07 495 +v -1340.76 -2653.83 495 +v -1342.93 -2657.07 5 +v -1342.93 -2657.07 5 +v -1340.76 -2653.83 495 +v -1340.76 -2653.83 5 +v -1340.76 -2653.83 495 +v -1340 -2650 495 +v -1340.76 -2653.83 5 +v -1340.76 -2653.83 5 +v -1340 -2650 495 +v -1340 -2650 5 +v -1340 -2650 495 +v -1340.76 -2646.17 495 +v -1340 -2650 5 +v -1340 -2650 5 +v -1340.76 -2646.17 495 +v -1340.76 -2646.17 5 +v -1340.76 -2646.17 495 +v -1342.93 -2642.93 495 +v -1340.76 -2646.17 5 +v -1340.76 -2646.17 5 +v -1342.93 -2642.93 495 +v -1342.93 -2642.93 5 +v -1342.93 -2642.93 495 +v -1346.17 -2640.76 495 +v -1342.93 -2642.93 5 +v -1342.93 -2642.93 5 +v -1346.17 -2640.76 495 +v -1346.17 -2640.76 5 +v -1346.17 -2640.76 495 +v -1350 -2640 495 +v -1346.17 -2640.76 5 +v -1346.17 -2640.76 5 +v -1350 -2640 495 +v -1350 -2640 5 +v -1350 -2640 495 +v -1353.83 -2640.76 495 +v -1350 -2640 5 +v -1350 -2640 5 +v -1353.83 -2640.76 495 +v -1353.83 -2640.76 5 +v -1353.83 -2640.76 495 +v -1357.07 -2642.93 495 +v -1353.83 -2640.76 5 +v -1353.83 -2640.76 5 +v -1357.07 -2642.93 495 +v -1357.07 -2642.93 5 +v -1357.07 -2642.93 495 +v -1359.24 -2646.17 495 +v -1357.07 -2642.93 5 +v -1357.07 -2642.93 5 +v -1359.24 -2646.17 495 +v -1359.24 -2646.17 5 +v -1359.24 -2646.17 495 +v -1360 -2650 495 +v -1359.24 -2646.17 5 +v -1359.24 -2646.17 5 +v -1360 -2650 495 +v -1360 -2650 5 +v -1360 -2350 495 +v -1359.24 -2353.83 495 +v -1360 -2350 5 +v -1360 -2350 5 +v -1359.24 -2353.83 495 +v -1359.24 -2353.83 5 +v -1359.24 -2353.83 495 +v -1357.07 -2357.07 495 +v -1359.24 -2353.83 5 +v -1359.24 -2353.83 5 +v -1357.07 -2357.07 495 +v -1357.07 -2357.07 5 +v -1357.07 -2357.07 495 +v -1353.83 -2359.24 495 +v -1357.07 -2357.07 5 +v -1357.07 -2357.07 5 +v -1353.83 -2359.24 495 +v -1353.83 -2359.24 5 +v -1353.83 -2359.24 495 +v -1350 -2360 495 +v -1353.83 -2359.24 5 +v -1353.83 -2359.24 5 +v -1350 -2360 495 +v -1350 -2360 5 +v -1350 -2360 495 +v -1346.17 -2359.24 495 +v -1350 -2360 5 +v -1350 -2360 5 +v -1346.17 -2359.24 495 +v -1346.17 -2359.24 5 +v -1346.17 -2359.24 495 +v -1342.93 -2357.07 495 +v -1346.17 -2359.24 5 +v -1346.17 -2359.24 5 +v -1342.93 -2357.07 495 +v -1342.93 -2357.07 5 +v -1342.93 -2357.07 495 +v -1340.76 -2353.83 495 +v -1342.93 -2357.07 5 +v -1342.93 -2357.07 5 +v -1340.76 -2353.83 495 +v -1340.76 -2353.83 5 +v -1340.76 -2353.83 495 +v -1340 -2350 495 +v -1340.76 -2353.83 5 +v -1340.76 -2353.83 5 +v -1340 -2350 495 +v -1340 -2350 5 +v -1340 -2350 495 +v -1340.76 -2346.17 495 +v -1340 -2350 5 +v -1340 -2350 5 +v -1340.76 -2346.17 495 +v -1340.76 -2346.17 5 +v -1340.76 -2346.17 495 +v -1342.93 -2342.93 495 +v -1340.76 -2346.17 5 +v -1340.76 -2346.17 5 +v -1342.93 -2342.93 495 +v -1342.93 -2342.93 5 +v -1342.93 -2342.93 495 +v -1346.17 -2340.76 495 +v -1342.93 -2342.93 5 +v -1342.93 -2342.93 5 +v -1346.17 -2340.76 495 +v -1346.17 -2340.76 5 +v -1346.17 -2340.76 495 +v -1350 -2340 495 +v -1346.17 -2340.76 5 +v -1346.17 -2340.76 5 +v -1350 -2340 495 +v -1350 -2340 5 +v -1350 -2340 495 +v -1353.83 -2340.76 495 +v -1350 -2340 5 +v -1350 -2340 5 +v -1353.83 -2340.76 495 +v -1353.83 -2340.76 5 +v -1353.83 -2340.76 495 +v -1357.07 -2342.93 495 +v -1353.83 -2340.76 5 +v -1353.83 -2340.76 5 +v -1357.07 -2342.93 495 +v -1357.07 -2342.93 5 +v -1357.07 -2342.93 495 +v -1359.24 -2346.17 495 +v -1357.07 -2342.93 5 +v -1357.07 -2342.93 5 +v -1359.24 -2346.17 495 +v -1359.24 -2346.17 5 +v -1359.24 -2346.17 495 +v -1360 -2350 495 +v -1359.24 -2346.17 5 +v -1359.24 -2346.17 5 +v -1360 -2350 495 +v -1360 -2350 5 +v -1660 -2350 495 +v -1659.24 -2353.83 495 +v -1660 -2350 5 +v -1660 -2350 5 +v -1659.24 -2353.83 495 +v -1659.24 -2353.83 5 +v -1659.24 -2353.83 495 +v -1657.07 -2357.07 495 +v -1659.24 -2353.83 5 +v -1659.24 -2353.83 5 +v -1657.07 -2357.07 495 +v -1657.07 -2357.07 5 +v -1657.07 -2357.07 495 +v -1653.83 -2359.24 495 +v -1657.07 -2357.07 5 +v -1657.07 -2357.07 5 +v -1653.83 -2359.24 495 +v -1653.83 -2359.24 5 +v -1653.83 -2359.24 495 +v -1650 -2360 495 +v -1653.83 -2359.24 5 +v -1653.83 -2359.24 5 +v -1650 -2360 495 +v -1650 -2360 5 +v -1650 -2360 495 +v -1646.17 -2359.24 495 +v -1650 -2360 5 +v -1650 -2360 5 +v -1646.17 -2359.24 495 +v -1646.17 -2359.24 5 +v -1646.17 -2359.24 495 +v -1642.93 -2357.07 495 +v -1646.17 -2359.24 5 +v -1646.17 -2359.24 5 +v -1642.93 -2357.07 495 +v -1642.93 -2357.07 5 +v -1642.93 -2357.07 495 +v -1640.76 -2353.83 495 +v -1642.93 -2357.07 5 +v -1642.93 -2357.07 5 +v -1640.76 -2353.83 495 +v -1640.76 -2353.83 5 +v -1640.76 -2353.83 495 +v -1640 -2350 495 +v -1640.76 -2353.83 5 +v -1640.76 -2353.83 5 +v -1640 -2350 495 +v -1640 -2350 5 +v -1640 -2350 495 +v -1640.76 -2346.17 495 +v -1640 -2350 5 +v -1640 -2350 5 +v -1640.76 -2346.17 495 +v -1640.76 -2346.17 5 +v -1640.76 -2346.17 495 +v -1642.93 -2342.93 495 +v -1640.76 -2346.17 5 +v -1640.76 -2346.17 5 +v -1642.93 -2342.93 495 +v -1642.93 -2342.93 5 +v -1642.93 -2342.93 495 +v -1646.17 -2340.76 495 +v -1642.93 -2342.93 5 +v -1642.93 -2342.93 5 +v -1646.17 -2340.76 495 +v -1646.17 -2340.76 5 +v -1646.17 -2340.76 495 +v -1650 -2340 495 +v -1646.17 -2340.76 5 +v -1646.17 -2340.76 5 +v -1650 -2340 495 +v -1650 -2340 5 +v -1650 -2340 495 +v -1653.83 -2340.76 495 +v -1650 -2340 5 +v -1650 -2340 5 +v -1653.83 -2340.76 495 +v -1653.83 -2340.76 5 +v -1653.83 -2340.76 495 +v -1657.07 -2342.93 495 +v -1653.83 -2340.76 5 +v -1653.83 -2340.76 5 +v -1657.07 -2342.93 495 +v -1657.07 -2342.93 5 +v -1657.07 -2342.93 495 +v -1659.24 -2346.17 495 +v -1657.07 -2342.93 5 +v -1657.07 -2342.93 5 +v -1659.24 -2346.17 495 +v -1659.24 -2346.17 5 +v -1659.24 -2346.17 495 +v -1660 -2350 495 +v -1659.24 -2346.17 5 +v -1659.24 -2346.17 5 +v -1660 -2350 495 +v -1660 -2350 5 +v -1300 -2300 510 +v -1700 -2300 510 +v -1300 -2700 510 +v -1300 -2700 510 +v -1700 -2300 510 +v -1700 -2700 510 +v -1700 -2300 500 +v -1300 -2300 500 +v -1700 -2700 500 +v -1700 -2700 500 +v -1300 -2300 500 +v -1300 -2700 500 +v -1700 -2300 510 +v -1700 -2300 500 +v -1700 -2700 510 +v -1700 -2700 510 +v -1700 -2300 500 +v -1700 -2700 500 +v -1300 -2300 500 +v -1300 -2300 510 +v -1300 -2700 500 +v -1300 -2700 500 +v -1300 -2300 510 +v -1300 -2700 510 +v -1300 -2700 500 +v -1300 -2700 510 +v -1700 -2700 500 +v -1700 -2700 500 +v -1300 -2700 510 +v -1700 -2700 510 +v -1300 -2300 500 +v -1700 -2300 500 +v -1300 -2300 510 +v -1300 -2300 510 +v -1700 -2300 500 +v -1700 -2300 510 +v -1560 -2705 810 +v -1559.24 -2708.83 810 +v -1560 -2705 510 +v -1560 -2705 510 +v -1559.24 -2708.83 810 +v -1559.24 -2708.83 510 +v -1559.24 -2708.83 810 +v -1557.07 -2712.07 810 +v -1559.24 -2708.83 510 +v -1559.24 -2708.83 510 +v -1557.07 -2712.07 810 +v -1557.07 -2712.07 510 +v -1557.07 -2712.07 810 +v -1553.83 -2714.24 810 +v -1557.07 -2712.07 510 +v -1557.07 -2712.07 510 +v -1553.83 -2714.24 810 +v -1553.83 -2714.24 510 +v -1553.83 -2714.24 810 +v -1550 -2715 810 +v -1553.83 -2714.24 510 +v -1553.83 -2714.24 510 +v -1550 -2715 810 +v -1550 -2715 510 +v -1550 -2715 810 +v -1546.17 -2714.24 810 +v -1550 -2715 510 +v -1550 -2715 510 +v -1546.17 -2714.24 810 +v -1546.17 -2714.24 510 +v -1546.17 -2714.24 810 +v -1542.93 -2712.07 810 +v -1546.17 -2714.24 510 +v -1546.17 -2714.24 510 +v -1542.93 -2712.07 810 +v -1542.93 -2712.07 510 +v -1542.93 -2712.07 810 +v -1540.76 -2708.83 810 +v -1542.93 -2712.07 510 +v -1542.93 -2712.07 510 +v -1540.76 -2708.83 810 +v -1540.76 -2708.83 510 +v -1540.76 -2708.83 810 +v -1540 -2705 810 +v -1540.76 -2708.83 510 +v -1540.76 -2708.83 510 +v -1540 -2705 810 +v -1540 -2705 510 +v -1540 -2705 810 +v -1540.76 -2701.17 810 +v -1540 -2705 510 +v -1540 -2705 510 +v -1540.76 -2701.17 810 +v -1540.76 -2701.17 510 +v -1540.76 -2701.17 810 +v -1542.93 -2697.93 810 +v -1540.76 -2701.17 510 +v -1540.76 -2701.17 510 +v -1542.93 -2697.93 810 +v -1542.93 -2697.93 510 +v -1542.93 -2697.93 810 +v -1546.17 -2695.76 810 +v -1542.93 -2697.93 510 +v -1542.93 -2697.93 510 +v -1546.17 -2695.76 810 +v -1546.17 -2695.76 510 +v -1546.17 -2695.76 810 +v -1550 -2695 810 +v -1546.17 -2695.76 510 +v -1546.17 -2695.76 510 +v -1550 -2695 810 +v -1550 -2695 510 +v -1550 -2695 810 +v -1553.83 -2695.76 810 +v -1550 -2695 510 +v -1550 -2695 510 +v -1553.83 -2695.76 810 +v -1553.83 -2695.76 510 +v -1553.83 -2695.76 810 +v -1557.07 -2697.93 810 +v -1553.83 -2695.76 510 +v -1553.83 -2695.76 510 +v -1557.07 -2697.93 810 +v -1557.07 -2697.93 510 +v -1557.07 -2697.93 810 +v -1559.24 -2701.17 810 +v -1557.07 -2697.93 510 +v -1557.07 -2697.93 510 +v -1559.24 -2701.17 810 +v -1559.24 -2701.17 510 +v -1559.24 -2701.17 810 +v -1560 -2705 810 +v -1559.24 -2701.17 510 +v -1559.24 -2701.17 510 +v -1560 -2705 810 +v -1560 -2705 510 +v -1460 -2705 810 +v -1459.24 -2708.83 810 +v -1460 -2705 510 +v -1460 -2705 510 +v -1459.24 -2708.83 810 +v -1459.24 -2708.83 510 +v -1459.24 -2708.83 810 +v -1457.07 -2712.07 810 +v -1459.24 -2708.83 510 +v -1459.24 -2708.83 510 +v -1457.07 -2712.07 810 +v -1457.07 -2712.07 510 +v -1457.07 -2712.07 810 +v -1453.83 -2714.24 810 +v -1457.07 -2712.07 510 +v -1457.07 -2712.07 510 +v -1453.83 -2714.24 810 +v -1453.83 -2714.24 510 +v -1453.83 -2714.24 810 +v -1450 -2715 810 +v -1453.83 -2714.24 510 +v -1453.83 -2714.24 510 +v -1450 -2715 810 +v -1450 -2715 510 +v -1450 -2715 810 +v -1446.17 -2714.24 810 +v -1450 -2715 510 +v -1450 -2715 510 +v -1446.17 -2714.24 810 +v -1446.17 -2714.24 510 +v -1446.17 -2714.24 810 +v -1442.93 -2712.07 810 +v -1446.17 -2714.24 510 +v -1446.17 -2714.24 510 +v -1442.93 -2712.07 810 +v -1442.93 -2712.07 510 +v -1442.93 -2712.07 810 +v -1440.76 -2708.83 810 +v -1442.93 -2712.07 510 +v -1442.93 -2712.07 510 +v -1440.76 -2708.83 810 +v -1440.76 -2708.83 510 +v -1440.76 -2708.83 810 +v -1440 -2705 810 +v -1440.76 -2708.83 510 +v -1440.76 -2708.83 510 +v -1440 -2705 810 +v -1440 -2705 510 +v -1440 -2705 810 +v -1440.76 -2701.17 810 +v -1440 -2705 510 +v -1440 -2705 510 +v -1440.76 -2701.17 810 +v -1440.76 -2701.17 510 +v -1440.76 -2701.17 810 +v -1442.93 -2697.93 810 +v -1440.76 -2701.17 510 +v -1440.76 -2701.17 510 +v -1442.93 -2697.93 810 +v -1442.93 -2697.93 510 +v -1442.93 -2697.93 810 +v -1446.17 -2695.76 810 +v -1442.93 -2697.93 510 +v -1442.93 -2697.93 510 +v -1446.17 -2695.76 810 +v -1446.17 -2695.76 510 +v -1446.17 -2695.76 810 +v -1450 -2695 810 +v -1446.17 -2695.76 510 +v -1446.17 -2695.76 510 +v -1450 -2695 810 +v -1450 -2695 510 +v -1450 -2695 810 +v -1453.83 -2695.76 810 +v -1450 -2695 510 +v -1450 -2695 510 +v -1453.83 -2695.76 810 +v -1453.83 -2695.76 510 +v -1453.83 -2695.76 810 +v -1457.07 -2697.93 810 +v -1453.83 -2695.76 510 +v -1453.83 -2695.76 510 +v -1457.07 -2697.93 810 +v -1457.07 -2697.93 510 +v -1457.07 -2697.93 810 +v -1459.24 -2701.17 810 +v -1457.07 -2697.93 510 +v -1457.07 -2697.93 510 +v -1459.24 -2701.17 810 +v -1459.24 -2701.17 510 +v -1459.24 -2701.17 810 +v -1460 -2705 810 +v -1459.24 -2701.17 510 +v -1459.24 -2701.17 510 +v -1460 -2705 810 +v -1460 -2705 510 +v -1300 -2690 910 +v -1700 -2690 910 +v -1300 -2700 910 +v -1300 -2700 910 +v -1700 -2690 910 +v -1700 -2700 910 +v -1700 -2690 710 +v -1300 -2690 710 +v -1700 -2700 710 +v -1700 -2700 710 +v -1300 -2690 710 +v -1300 -2700 710 +v -1700 -2690 910 +v -1700 -2690 710 +v -1700 -2700 910 +v -1700 -2700 910 +v -1700 -2690 710 +v -1700 -2700 710 +v -1300 -2690 710 +v -1300 -2690 910 +v -1300 -2700 710 +v -1300 -2700 710 +v -1300 -2690 910 +v -1300 -2700 910 +v -1300 -2700 710 +v -1300 -2700 910 +v -1700 -2700 710 +v -1700 -2700 710 +v -1300 -2700 910 +v -1700 -2700 910 +v -1300 -2690 710 +v -1700 -2690 710 +v -1300 -2690 910 +v -1300 -2690 910 +v -1700 -2690 710 +v -1700 -2690 910 +v -798.346 -313.769 495 +v -797.753 -309.913 495 +v -798.346 -313.769 5 +v -798.346 -313.769 5 +v -797.753 -309.913 495 +v -797.753 -309.913 5 +v -797.753 -309.913 495 +v -798.68 -306.123 495 +v -797.753 -309.913 5 +v -797.753 -309.913 5 +v -798.68 -306.123 495 +v -798.68 -306.123 5 +v -798.68 -306.123 495 +v -800.987 -302.976 495 +v -798.68 -306.123 5 +v -798.68 -306.123 5 +v -800.987 -302.976 495 +v -800.987 -302.976 5 +v -800.987 -302.976 495 +v -804.323 -300.952 495 +v -800.987 -302.976 5 +v -800.987 -302.976 5 +v -804.323 -300.952 495 +v -804.323 -300.952 5 +v -804.323 -300.952 495 +v -808.179 -300.359 495 +v -804.323 -300.952 5 +v -804.323 -300.952 5 +v -808.179 -300.359 495 +v -808.179 -300.359 5 +v -808.179 -300.359 495 +v -811.969 -301.286 495 +v -808.179 -300.359 5 +v -808.179 -300.359 5 +v -811.969 -301.286 495 +v -811.969 -301.286 5 +v -811.969 -301.286 495 +v -815.116 -303.593 495 +v -811.969 -301.286 5 +v -811.969 -301.286 5 +v -815.116 -303.593 495 +v -815.116 -303.593 5 +v -815.116 -303.593 495 +v -817.14 -306.929 495 +v -815.116 -303.593 5 +v -815.116 -303.593 5 +v -817.14 -306.929 495 +v -817.14 -306.929 5 +v -817.14 -306.929 495 +v -817.734 -310.785 495 +v -817.14 -306.929 5 +v -817.14 -306.929 5 +v -817.734 -310.785 495 +v -817.734 -310.785 5 +v -817.734 -310.785 495 +v -816.806 -314.575 495 +v -817.734 -310.785 5 +v -817.734 -310.785 5 +v -816.806 -314.575 495 +v -816.806 -314.575 5 +v -816.806 -314.575 495 +v -814.499 -317.722 495 +v -816.806 -314.575 5 +v -816.806 -314.575 5 +v -814.499 -317.722 495 +v -814.499 -317.722 5 +v -814.499 -317.722 495 +v -811.163 -319.746 495 +v -814.499 -317.722 5 +v -814.499 -317.722 5 +v -811.163 -319.746 495 +v -811.163 -319.746 5 +v -811.163 -319.746 495 +v -807.307 -320.34 495 +v -811.163 -319.746 5 +v -811.163 -319.746 5 +v -807.307 -320.34 495 +v -807.307 -320.34 5 +v -807.307 -320.34 495 +v -803.517 -319.412 495 +v -807.307 -320.34 5 +v -807.307 -320.34 5 +v -803.517 -319.412 495 +v -803.517 -319.412 5 +v -803.517 -319.412 495 +v -800.37 -317.105 495 +v -803.517 -319.412 5 +v -803.517 -319.412 5 +v -800.37 -317.105 495 +v -800.37 -317.105 5 +v -800.37 -317.105 495 +v -798.346 -313.769 495 +v -800.37 -317.105 5 +v -800.37 -317.105 5 +v -798.346 -313.769 495 +v -798.346 -313.769 5 +v -1080.25 -211.163 495 +v -1079.66 -207.307 495 +v -1080.25 -211.163 5 +v -1080.25 -211.163 5 +v -1079.66 -207.307 495 +v -1079.66 -207.307 5 +v -1079.66 -207.307 495 +v -1080.59 -203.517 495 +v -1079.66 -207.307 5 +v -1079.66 -207.307 5 +v -1080.59 -203.517 495 +v -1080.59 -203.517 5 +v -1080.59 -203.517 495 +v -1082.9 -200.37 495 +v -1080.59 -203.517 5 +v -1080.59 -203.517 5 +v -1082.9 -200.37 495 +v -1082.9 -200.37 5 +v -1082.9 -200.37 495 +v -1086.23 -198.346 495 +v -1082.9 -200.37 5 +v -1082.9 -200.37 5 +v -1086.23 -198.346 495 +v -1086.23 -198.346 5 +v -1086.23 -198.346 495 +v -1090.09 -197.753 495 +v -1086.23 -198.346 5 +v -1086.23 -198.346 5 +v -1090.09 -197.753 495 +v -1090.09 -197.753 5 +v -1090.09 -197.753 495 +v -1093.88 -198.68 495 +v -1090.09 -197.753 5 +v -1090.09 -197.753 5 +v -1093.88 -198.68 495 +v -1093.88 -198.68 5 +v -1093.88 -198.68 495 +v -1097.02 -200.987 495 +v -1093.88 -198.68 5 +v -1093.88 -198.68 5 +v -1097.02 -200.987 495 +v -1097.02 -200.987 5 +v -1097.02 -200.987 495 +v -1099.05 -204.323 495 +v -1097.02 -200.987 5 +v -1097.02 -200.987 5 +v -1099.05 -204.323 495 +v -1099.05 -204.323 5 +v -1099.05 -204.323 495 +v -1099.64 -208.179 495 +v -1099.05 -204.323 5 +v -1099.05 -204.323 5 +v -1099.64 -208.179 495 +v -1099.64 -208.179 5 +v -1099.64 -208.179 495 +v -1098.71 -211.969 495 +v -1099.64 -208.179 5 +v -1099.64 -208.179 5 +v -1098.71 -211.969 495 +v -1098.71 -211.969 5 +v -1098.71 -211.969 495 +v -1096.41 -215.116 495 +v -1098.71 -211.969 5 +v -1098.71 -211.969 5 +v -1096.41 -215.116 495 +v -1096.41 -215.116 5 +v -1096.41 -215.116 495 +v -1093.07 -217.14 495 +v -1096.41 -215.116 5 +v -1096.41 -215.116 5 +v -1093.07 -217.14 495 +v -1093.07 -217.14 5 +v -1093.07 -217.14 495 +v -1089.21 -217.734 495 +v -1093.07 -217.14 5 +v -1093.07 -217.14 5 +v -1089.21 -217.734 495 +v -1089.21 -217.734 5 +v -1089.21 -217.734 495 +v -1085.42 -216.806 495 +v -1089.21 -217.734 5 +v -1089.21 -217.734 5 +v -1085.42 -216.806 495 +v -1085.42 -216.806 5 +v -1085.42 -216.806 495 +v -1082.28 -214.499 495 +v -1085.42 -216.806 5 +v -1085.42 -216.806 5 +v -1082.28 -214.499 495 +v -1082.28 -214.499 5 +v -1082.28 -214.499 495 +v -1080.25 -211.163 495 +v -1082.28 -214.499 5 +v -1082.28 -214.499 5 +v -1080.25 -211.163 495 +v -1080.25 -211.163 5 +v -1182.86 -493.071 495 +v -1182.27 -489.215 495 +v -1182.86 -493.071 5 +v -1182.86 -493.071 5 +v -1182.27 -489.215 495 +v -1182.27 -489.215 5 +v -1182.27 -489.215 495 +v -1183.19 -485.425 495 +v -1182.27 -489.215 5 +v -1182.27 -489.215 5 +v -1183.19 -485.425 495 +v -1183.19 -485.425 5 +v -1183.19 -485.425 495 +v -1185.5 -482.278 495 +v -1183.19 -485.425 5 +v -1183.19 -485.425 5 +v -1185.5 -482.278 495 +v -1185.5 -482.278 5 +v -1185.5 -482.278 495 +v -1188.84 -480.254 495 +v -1185.5 -482.278 5 +v -1185.5 -482.278 5 +v -1188.84 -480.254 495 +v -1188.84 -480.254 5 +v -1188.84 -480.254 495 +v -1192.69 -479.66 495 +v -1188.84 -480.254 5 +v -1188.84 -480.254 5 +v -1192.69 -479.66 495 +v -1192.69 -479.66 5 +v -1192.69 -479.66 495 +v -1196.48 -480.588 495 +v -1192.69 -479.66 5 +v -1192.69 -479.66 5 +v -1196.48 -480.588 495 +v -1196.48 -480.588 5 +v -1196.48 -480.588 495 +v -1199.63 -482.895 495 +v -1196.48 -480.588 5 +v -1196.48 -480.588 5 +v -1199.63 -482.895 495 +v -1199.63 -482.895 5 +v -1199.63 -482.895 495 +v -1201.65 -486.231 495 +v -1199.63 -482.895 5 +v -1199.63 -482.895 5 +v -1201.65 -486.231 495 +v -1201.65 -486.231 5 +v -1201.65 -486.231 495 +v -1202.25 -490.087 495 +v -1201.65 -486.231 5 +v -1201.65 -486.231 5 +v -1202.25 -490.087 495 +v -1202.25 -490.087 5 +v -1202.25 -490.087 495 +v -1201.32 -493.877 495 +v -1202.25 -490.087 5 +v -1202.25 -490.087 5 +v -1201.32 -493.877 495 +v -1201.32 -493.877 5 +v -1201.32 -493.877 495 +v -1199.01 -497.024 495 +v -1201.32 -493.877 5 +v -1201.32 -493.877 5 +v -1199.01 -497.024 495 +v -1199.01 -497.024 5 +v -1199.01 -497.024 495 +v -1195.68 -499.048 495 +v -1199.01 -497.024 5 +v -1199.01 -497.024 5 +v -1195.68 -499.048 495 +v -1195.68 -499.048 5 +v -1195.68 -499.048 495 +v -1191.82 -499.641 495 +v -1195.68 -499.048 5 +v -1195.68 -499.048 5 +v -1191.82 -499.641 495 +v -1191.82 -499.641 5 +v -1191.82 -499.641 495 +v -1188.03 -498.714 495 +v -1191.82 -499.641 5 +v -1191.82 -499.641 5 +v -1188.03 -498.714 495 +v -1188.03 -498.714 5 +v -1188.03 -498.714 495 +v -1184.88 -496.407 495 +v -1188.03 -498.714 5 +v -1188.03 -498.714 5 +v -1184.88 -496.407 495 +v -1184.88 -496.407 5 +v -1184.88 -496.407 495 +v -1182.86 -493.071 495 +v -1184.88 -496.407 5 +v -1184.88 -496.407 5 +v -1182.86 -493.071 495 +v -1182.86 -493.071 5 +v -900.952 -595.677 495 +v -900.359 -591.821 495 +v -900.952 -595.677 5 +v -900.952 -595.677 5 +v -900.359 -591.821 495 +v -900.359 -591.821 5 +v -900.359 -591.821 495 +v -901.286 -588.031 495 +v -900.359 -591.821 5 +v -900.359 -591.821 5 +v -901.286 -588.031 495 +v -901.286 -588.031 5 +v -901.286 -588.031 495 +v -903.593 -584.884 495 +v -901.286 -588.031 5 +v -901.286 -588.031 5 +v -903.593 -584.884 495 +v -903.593 -584.884 5 +v -903.593 -584.884 495 +v -906.929 -582.86 495 +v -903.593 -584.884 5 +v -903.593 -584.884 5 +v -906.929 -582.86 495 +v -906.929 -582.86 5 +v -906.929 -582.86 495 +v -910.785 -582.266 495 +v -906.929 -582.86 5 +v -906.929 -582.86 5 +v -910.785 -582.266 495 +v -910.785 -582.266 5 +v -910.785 -582.266 495 +v -914.575 -583.194 495 +v -910.785 -582.266 5 +v -910.785 -582.266 5 +v -914.575 -583.194 495 +v -914.575 -583.194 5 +v -914.575 -583.194 495 +v -917.722 -585.501 495 +v -914.575 -583.194 5 +v -914.575 -583.194 5 +v -917.722 -585.501 495 +v -917.722 -585.501 5 +v -917.722 -585.501 495 +v -919.746 -588.837 495 +v -917.722 -585.501 5 +v -917.722 -585.501 5 +v -919.746 -588.837 495 +v -919.746 -588.837 5 +v -919.746 -588.837 495 +v -920.34 -592.693 495 +v -919.746 -588.837 5 +v -919.746 -588.837 5 +v -920.34 -592.693 495 +v -920.34 -592.693 5 +v -920.34 -592.693 495 +v -919.412 -596.483 495 +v -920.34 -592.693 5 +v -920.34 -592.693 5 +v -919.412 -596.483 495 +v -919.412 -596.483 5 +v -919.412 -596.483 495 +v -917.105 -599.63 495 +v -919.412 -596.483 5 +v -919.412 -596.483 5 +v -917.105 -599.63 495 +v -917.105 -599.63 5 +v -917.105 -599.63 495 +v -913.769 -601.654 495 +v -917.105 -599.63 5 +v -917.105 -599.63 5 +v -913.769 -601.654 495 +v -913.769 -601.654 5 +v -913.769 -601.654 495 +v -909.913 -602.247 495 +v -913.769 -601.654 5 +v -913.769 -601.654 5 +v -909.913 -602.247 495 +v -909.913 -602.247 5 +v -909.913 -602.247 495 +v -906.123 -601.32 495 +v -909.913 -602.247 5 +v -909.913 -602.247 5 +v -906.123 -601.32 495 +v -906.123 -601.32 5 +v -906.123 -601.32 495 +v -902.976 -599.013 495 +v -906.123 -601.32 5 +v -906.123 -601.32 5 +v -902.976 -599.013 495 +v -902.976 -599.013 5 +v -902.976 -599.013 495 +v -900.952 -595.677 495 +v -902.976 -599.013 5 +v -902.976 -599.013 5 +v -900.952 -595.677 495 +v -900.952 -595.677 5 +v -1256.34 -519.534 510 +v -880.466 -656.343 510 +v -1119.53 -143.657 510 +v -1119.53 -143.657 510 +v -880.466 -656.343 510 +v -743.657 -280.466 510 +v -880.466 -656.343 500 +v -1256.34 -519.534 500 +v -743.657 -280.466 500 +v -743.657 -280.466 500 +v -1256.34 -519.534 500 +v -1119.53 -143.657 500 +v -880.466 -656.343 510 +v -880.466 -656.343 500 +v -743.657 -280.466 510 +v -743.657 -280.466 510 +v -880.466 -656.343 500 +v -743.657 -280.466 500 +v -1256.34 -519.534 500 +v -1256.34 -519.534 510 +v -1119.53 -143.657 500 +v -1119.53 -143.657 500 +v -1256.34 -519.534 510 +v -1119.53 -143.657 510 +v -1119.53 -143.657 500 +v -1119.53 -143.657 510 +v -743.657 -280.466 500 +v -743.657 -280.466 500 +v -1119.53 -143.657 510 +v -743.657 -280.466 510 +v -1256.34 -519.534 500 +v -880.466 -656.343 500 +v -1256.34 -519.534 510 +v -1256.34 -519.534 510 +v -880.466 -656.343 500 +v -880.466 -656.343 510 +v -873.504 -227.884 810 +v -872.911 -224.028 810 +v -873.504 -227.884 510 +v -873.504 -227.884 510 +v -872.911 -224.028 810 +v -872.911 -224.028 510 +v -872.911 -224.028 810 +v -873.838 -220.238 810 +v -872.911 -224.028 510 +v -872.911 -224.028 510 +v -873.838 -220.238 810 +v -873.838 -220.238 510 +v -873.838 -220.238 810 +v -876.145 -217.091 810 +v -873.838 -220.238 510 +v -873.838 -220.238 510 +v -876.145 -217.091 810 +v -876.145 -217.091 510 +v -876.145 -217.091 810 +v -879.481 -215.067 810 +v -876.145 -217.091 510 +v -876.145 -217.091 510 +v -879.481 -215.067 810 +v -879.481 -215.067 510 +v -879.481 -215.067 810 +v -883.337 -214.474 810 +v -879.481 -215.067 510 +v -879.481 -215.067 510 +v -883.337 -214.474 810 +v -883.337 -214.474 510 +v -883.337 -214.474 810 +v -887.127 -215.401 810 +v -883.337 -214.474 510 +v -883.337 -214.474 510 +v -887.127 -215.401 810 +v -887.127 -215.401 510 +v -887.127 -215.401 810 +v -890.274 -217.708 810 +v -887.127 -215.401 510 +v -887.127 -215.401 510 +v -890.274 -217.708 810 +v -890.274 -217.708 510 +v -890.274 -217.708 810 +v -892.298 -221.044 810 +v -890.274 -217.708 510 +v -890.274 -217.708 510 +v -892.298 -221.044 810 +v -892.298 -221.044 510 +v -892.298 -221.044 810 +v -892.892 -224.9 810 +v -892.298 -221.044 510 +v -892.298 -221.044 510 +v -892.892 -224.9 810 +v -892.892 -224.9 510 +v -892.892 -224.9 810 +v -891.964 -228.69 810 +v -892.892 -224.9 510 +v -892.892 -224.9 510 +v -891.964 -228.69 810 +v -891.964 -228.69 510 +v -891.964 -228.69 810 +v -889.657 -231.837 810 +v -891.964 -228.69 510 +v -891.964 -228.69 510 +v -889.657 -231.837 810 +v -889.657 -231.837 510 +v -889.657 -231.837 810 +v -886.321 -233.861 810 +v -889.657 -231.837 510 +v -889.657 -231.837 510 +v -886.321 -233.861 810 +v -886.321 -233.861 510 +v -886.321 -233.861 810 +v -882.465 -234.454 810 +v -886.321 -233.861 510 +v -886.321 -233.861 510 +v -882.465 -234.454 810 +v -882.465 -234.454 510 +v -882.465 -234.454 810 +v -878.675 -233.527 810 +v -882.465 -234.454 510 +v -882.465 -234.454 510 +v -878.675 -233.527 810 +v -878.675 -233.527 510 +v -878.675 -233.527 810 +v -875.528 -231.22 810 +v -878.675 -233.527 510 +v -878.675 -233.527 510 +v -875.528 -231.22 810 +v -875.528 -231.22 510 +v -875.528 -231.22 810 +v -873.504 -227.884 810 +v -875.528 -231.22 510 +v -875.528 -231.22 510 +v -873.504 -227.884 810 +v -873.504 -227.884 510 +v -967.474 -193.682 810 +v -966.88 -189.826 810 +v -967.474 -193.682 510 +v -967.474 -193.682 510 +v -966.88 -189.826 810 +v -966.88 -189.826 510 +v -966.88 -189.826 810 +v -967.807 -186.036 810 +v -966.88 -189.826 510 +v -966.88 -189.826 510 +v -967.807 -186.036 810 +v -967.807 -186.036 510 +v -967.807 -186.036 810 +v -970.115 -182.889 810 +v -967.807 -186.036 510 +v -967.807 -186.036 510 +v -970.115 -182.889 810 +v -970.115 -182.889 510 +v -970.115 -182.889 810 +v -973.45 -180.865 810 +v -970.115 -182.889 510 +v -970.115 -182.889 510 +v -973.45 -180.865 810 +v -973.45 -180.865 510 +v -973.45 -180.865 810 +v -977.307 -180.272 810 +v -973.45 -180.865 510 +v -973.45 -180.865 510 +v -977.307 -180.272 810 +v -977.307 -180.272 510 +v -977.307 -180.272 810 +v -981.097 -181.199 810 +v -977.307 -180.272 510 +v -977.307 -180.272 510 +v -981.097 -181.199 810 +v -981.097 -181.199 510 +v -981.097 -181.199 810 +v -984.243 -183.506 810 +v -981.097 -181.199 510 +v -981.097 -181.199 510 +v -984.243 -183.506 810 +v -984.243 -183.506 510 +v -984.243 -183.506 810 +v -986.267 -186.842 810 +v -984.243 -183.506 510 +v -984.243 -183.506 510 +v -986.267 -186.842 810 +v -986.267 -186.842 510 +v -986.267 -186.842 810 +v -986.861 -190.698 810 +v -986.267 -186.842 510 +v -986.267 -186.842 510 +v -986.861 -190.698 810 +v -986.861 -190.698 510 +v -986.861 -190.698 810 +v -985.934 -194.488 810 +v -986.861 -190.698 510 +v -986.861 -190.698 510 +v -985.934 -194.488 810 +v -985.934 -194.488 510 +v -985.934 -194.488 810 +v -983.626 -197.635 810 +v -985.934 -194.488 510 +v -985.934 -194.488 510 +v -983.626 -197.635 810 +v -983.626 -197.635 510 +v -983.626 -197.635 810 +v -980.291 -199.659 810 +v -983.626 -197.635 510 +v -983.626 -197.635 510 +v -980.291 -199.659 810 +v -980.291 -199.659 510 +v -980.291 -199.659 810 +v -976.434 -200.252 810 +v -980.291 -199.659 510 +v -980.291 -199.659 510 +v -976.434 -200.252 810 +v -976.434 -200.252 510 +v -976.434 -200.252 810 +v -972.644 -199.325 810 +v -976.434 -200.252 510 +v -976.434 -200.252 510 +v -972.644 -199.325 810 +v -972.644 -199.325 510 +v -972.644 -199.325 810 +v -969.498 -197.018 810 +v -972.644 -199.325 510 +v -972.644 -199.325 510 +v -969.498 -197.018 810 +v -969.498 -197.018 510 +v -969.498 -197.018 810 +v -967.474 -193.682 810 +v -969.498 -197.018 510 +v -969.498 -197.018 510 +v -967.474 -193.682 810 +v -967.474 -193.682 510 +v -1122.95 -153.054 910 +v -747.078 -289.862 910 +v -1119.53 -143.657 910 +v -1119.53 -143.657 910 +v -747.078 -289.862 910 +v -743.657 -280.465 910 +v -747.078 -289.862 710 +v -1122.95 -153.054 710 +v -743.657 -280.465 710 +v -743.657 -280.465 710 +v -1122.95 -153.054 710 +v -1119.53 -143.657 710 +v -747.078 -289.862 910 +v -747.078 -289.862 710 +v -743.657 -280.465 910 +v -743.657 -280.465 910 +v -747.078 -289.862 710 +v -743.657 -280.465 710 +v -1122.95 -153.054 710 +v -1122.95 -153.054 910 +v -1119.53 -143.657 710 +v -1119.53 -143.657 710 +v -1122.95 -153.054 910 +v -1119.53 -143.657 910 +v -1119.53 -143.657 710 +v -1119.53 -143.657 910 +v -743.657 -280.465 710 +v -743.657 -280.465 710 +v -1119.53 -143.657 910 +v -743.657 -280.465 910 +v -1122.95 -153.054 710 +v -747.078 -289.862 710 +v -1122.95 -153.054 910 +v -1122.95 -153.054 910 +v -747.078 -289.862 710 +v -747.078 -289.862 910 +v -1900.95 -1604.32 495 +v -1902.98 -1600.99 495 +v -1900.95 -1604.32 5 +v -1900.95 -1604.32 5 +v -1902.98 -1600.99 495 +v -1902.98 -1600.99 5 +v -1902.98 -1600.99 495 +v -1906.12 -1598.68 495 +v -1902.98 -1600.99 5 +v -1902.98 -1600.99 5 +v -1906.12 -1598.68 495 +v -1906.12 -1598.68 5 +v -1906.12 -1598.68 495 +v -1909.91 -1597.75 495 +v -1906.12 -1598.68 5 +v -1906.12 -1598.68 5 +v -1909.91 -1597.75 495 +v -1909.91 -1597.75 5 +v -1909.91 -1597.75 495 +v -1913.77 -1598.35 495 +v -1909.91 -1597.75 5 +v -1909.91 -1597.75 5 +v -1913.77 -1598.35 495 +v -1913.77 -1598.35 5 +v -1913.77 -1598.35 495 +v -1917.1 -1600.37 495 +v -1913.77 -1598.35 5 +v -1913.77 -1598.35 5 +v -1917.1 -1600.37 495 +v -1917.1 -1600.37 5 +v -1917.1 -1600.37 495 +v -1919.41 -1603.52 495 +v -1917.1 -1600.37 5 +v -1917.1 -1600.37 5 +v -1919.41 -1603.52 495 +v -1919.41 -1603.52 5 +v -1919.41 -1603.52 495 +v -1920.34 -1607.31 495 +v -1919.41 -1603.52 5 +v -1919.41 -1603.52 5 +v -1920.34 -1607.31 495 +v -1920.34 -1607.31 5 +v -1920.34 -1607.31 495 +v -1919.75 -1611.16 495 +v -1920.34 -1607.31 5 +v -1920.34 -1607.31 5 +v -1919.75 -1611.16 495 +v -1919.75 -1611.16 5 +v -1919.75 -1611.16 495 +v -1917.72 -1614.5 495 +v -1919.75 -1611.16 5 +v -1919.75 -1611.16 5 +v -1917.72 -1614.5 495 +v -1917.72 -1614.5 5 +v -1917.72 -1614.5 495 +v -1914.58 -1616.81 495 +v -1917.72 -1614.5 5 +v -1917.72 -1614.5 5 +v -1914.58 -1616.81 495 +v -1914.58 -1616.81 5 +v -1914.58 -1616.81 495 +v -1910.79 -1617.73 495 +v -1914.58 -1616.81 5 +v -1914.58 -1616.81 5 +v -1910.79 -1617.73 495 +v -1910.79 -1617.73 5 +v -1910.79 -1617.73 495 +v -1906.93 -1617.14 495 +v -1910.79 -1617.73 5 +v -1910.79 -1617.73 5 +v -1906.93 -1617.14 495 +v -1906.93 -1617.14 5 +v -1906.93 -1617.14 495 +v -1903.59 -1615.12 495 +v -1906.93 -1617.14 5 +v -1906.93 -1617.14 5 +v -1903.59 -1615.12 495 +v -1903.59 -1615.12 5 +v -1903.59 -1615.12 495 +v -1901.29 -1611.97 495 +v -1903.59 -1615.12 5 +v -1903.59 -1615.12 5 +v -1901.29 -1611.97 495 +v -1901.29 -1611.97 5 +v -1901.29 -1611.97 495 +v -1900.36 -1608.18 495 +v -1901.29 -1611.97 5 +v -1901.29 -1611.97 5 +v -1900.36 -1608.18 495 +v -1900.36 -1608.18 5 +v -1900.36 -1608.18 495 +v -1900.95 -1604.32 495 +v -1900.36 -1608.18 5 +v -1900.36 -1608.18 5 +v -1900.95 -1604.32 495 +v -1900.95 -1604.32 5 +v -2182.86 -1706.93 495 +v -2184.88 -1703.59 495 +v -2182.86 -1706.93 5 +v -2182.86 -1706.93 5 +v -2184.88 -1703.59 495 +v -2184.88 -1703.59 5 +v -2184.88 -1703.59 495 +v -2188.03 -1701.29 495 +v -2184.88 -1703.59 5 +v -2184.88 -1703.59 5 +v -2188.03 -1701.29 495 +v -2188.03 -1701.29 5 +v -2188.03 -1701.29 495 +v -2191.82 -1700.36 495 +v -2188.03 -1701.29 5 +v -2188.03 -1701.29 5 +v -2191.82 -1700.36 495 +v -2191.82 -1700.36 5 +v -2191.82 -1700.36 495 +v -2195.68 -1700.95 495 +v -2191.82 -1700.36 5 +v -2191.82 -1700.36 5 +v -2195.68 -1700.95 495 +v -2195.68 -1700.95 5 +v -2195.68 -1700.95 495 +v -2199.01 -1702.98 495 +v -2195.68 -1700.95 5 +v -2195.68 -1700.95 5 +v -2199.01 -1702.98 495 +v -2199.01 -1702.98 5 +v -2199.01 -1702.98 495 +v -2201.32 -1706.12 495 +v -2199.01 -1702.98 5 +v -2199.01 -1702.98 5 +v -2201.32 -1706.12 495 +v -2201.32 -1706.12 5 +v -2201.32 -1706.12 495 +v -2202.25 -1709.91 495 +v -2201.32 -1706.12 5 +v -2201.32 -1706.12 5 +v -2202.25 -1709.91 495 +v -2202.25 -1709.91 5 +v -2202.25 -1709.91 495 +v -2201.65 -1713.77 495 +v -2202.25 -1709.91 5 +v -2202.25 -1709.91 5 +v -2201.65 -1713.77 495 +v -2201.65 -1713.77 5 +v -2201.65 -1713.77 495 +v -2199.63 -1717.1 495 +v -2201.65 -1713.77 5 +v -2201.65 -1713.77 5 +v -2199.63 -1717.1 495 +v -2199.63 -1717.1 5 +v -2199.63 -1717.1 495 +v -2196.48 -1719.41 495 +v -2199.63 -1717.1 5 +v -2199.63 -1717.1 5 +v -2196.48 -1719.41 495 +v -2196.48 -1719.41 5 +v -2196.48 -1719.41 495 +v -2192.69 -1720.34 495 +v -2196.48 -1719.41 5 +v -2196.48 -1719.41 5 +v -2192.69 -1720.34 495 +v -2192.69 -1720.34 5 +v -2192.69 -1720.34 495 +v -2188.84 -1719.75 495 +v -2192.69 -1720.34 5 +v -2192.69 -1720.34 5 +v -2188.84 -1719.75 495 +v -2188.84 -1719.75 5 +v -2188.84 -1719.75 495 +v -2185.5 -1717.72 495 +v -2188.84 -1719.75 5 +v -2188.84 -1719.75 5 +v -2185.5 -1717.72 495 +v -2185.5 -1717.72 5 +v -2185.5 -1717.72 495 +v -2183.19 -1714.58 495 +v -2185.5 -1717.72 5 +v -2185.5 -1717.72 5 +v -2183.19 -1714.58 495 +v -2183.19 -1714.58 5 +v -2183.19 -1714.58 495 +v -2182.27 -1710.79 495 +v -2183.19 -1714.58 5 +v -2183.19 -1714.58 5 +v -2182.27 -1710.79 495 +v -2182.27 -1710.79 5 +v -2182.27 -1710.79 495 +v -2182.86 -1706.93 495 +v -2182.27 -1710.79 5 +v -2182.27 -1710.79 5 +v -2182.86 -1706.93 495 +v -2182.86 -1706.93 5 +v -2080.25 -1988.84 495 +v -2082.28 -1985.5 495 +v -2080.25 -1988.84 5 +v -2080.25 -1988.84 5 +v -2082.28 -1985.5 495 +v -2082.28 -1985.5 5 +v -2082.28 -1985.5 495 +v -2085.42 -1983.19 495 +v -2082.28 -1985.5 5 +v -2082.28 -1985.5 5 +v -2085.42 -1983.19 495 +v -2085.42 -1983.19 5 +v -2085.42 -1983.19 495 +v -2089.21 -1982.27 495 +v -2085.42 -1983.19 5 +v -2085.42 -1983.19 5 +v -2089.21 -1982.27 495 +v -2089.21 -1982.27 5 +v -2089.21 -1982.27 495 +v -2093.07 -1982.86 495 +v -2089.21 -1982.27 5 +v -2089.21 -1982.27 5 +v -2093.07 -1982.86 495 +v -2093.07 -1982.86 5 +v -2093.07 -1982.86 495 +v -2096.41 -1984.88 495 +v -2093.07 -1982.86 5 +v -2093.07 -1982.86 5 +v -2096.41 -1984.88 495 +v -2096.41 -1984.88 5 +v -2096.41 -1984.88 495 +v -2098.71 -1988.03 495 +v -2096.41 -1984.88 5 +v -2096.41 -1984.88 5 +v -2098.71 -1988.03 495 +v -2098.71 -1988.03 5 +v -2098.71 -1988.03 495 +v -2099.64 -1991.82 495 +v -2098.71 -1988.03 5 +v -2098.71 -1988.03 5 +v -2099.64 -1991.82 495 +v -2099.64 -1991.82 5 +v -2099.64 -1991.82 495 +v -2099.05 -1995.68 495 +v -2099.64 -1991.82 5 +v -2099.64 -1991.82 5 +v -2099.05 -1995.68 495 +v -2099.05 -1995.68 5 +v -2099.05 -1995.68 495 +v -2097.02 -1999.01 495 +v -2099.05 -1995.68 5 +v -2099.05 -1995.68 5 +v -2097.02 -1999.01 495 +v -2097.02 -1999.01 5 +v -2097.02 -1999.01 495 +v -2093.88 -2001.32 495 +v -2097.02 -1999.01 5 +v -2097.02 -1999.01 5 +v -2093.88 -2001.32 495 +v -2093.88 -2001.32 5 +v -2093.88 -2001.32 495 +v -2090.09 -2002.25 495 +v -2093.88 -2001.32 5 +v -2093.88 -2001.32 5 +v -2090.09 -2002.25 495 +v -2090.09 -2002.25 5 +v -2090.09 -2002.25 495 +v -2086.23 -2001.65 495 +v -2090.09 -2002.25 5 +v -2090.09 -2002.25 5 +v -2086.23 -2001.65 495 +v -2086.23 -2001.65 5 +v -2086.23 -2001.65 495 +v -2082.9 -1999.63 495 +v -2086.23 -2001.65 5 +v -2086.23 -2001.65 5 +v -2082.9 -1999.63 495 +v -2082.9 -1999.63 5 +v -2082.9 -1999.63 495 +v -2080.59 -1996.48 495 +v -2082.9 -1999.63 5 +v -2082.9 -1999.63 5 +v -2080.59 -1996.48 495 +v -2080.59 -1996.48 5 +v -2080.59 -1996.48 495 +v -2079.66 -1992.69 495 +v -2080.59 -1996.48 5 +v -2080.59 -1996.48 5 +v -2079.66 -1992.69 495 +v -2079.66 -1992.69 5 +v -2079.66 -1992.69 495 +v -2080.25 -1988.84 495 +v -2079.66 -1992.69 5 +v -2079.66 -1992.69 5 +v -2080.25 -1988.84 495 +v -2080.25 -1988.84 5 +v -1798.35 -1886.23 495 +v -1800.37 -1882.9 495 +v -1798.35 -1886.23 5 +v -1798.35 -1886.23 5 +v -1800.37 -1882.9 495 +v -1800.37 -1882.9 5 +v -1800.37 -1882.9 495 +v -1803.52 -1880.59 495 +v -1800.37 -1882.9 5 +v -1800.37 -1882.9 5 +v -1803.52 -1880.59 495 +v -1803.52 -1880.59 5 +v -1803.52 -1880.59 495 +v -1807.31 -1879.66 495 +v -1803.52 -1880.59 5 +v -1803.52 -1880.59 5 +v -1807.31 -1879.66 495 +v -1807.31 -1879.66 5 +v -1807.31 -1879.66 495 +v -1811.16 -1880.25 495 +v -1807.31 -1879.66 5 +v -1807.31 -1879.66 5 +v -1811.16 -1880.25 495 +v -1811.16 -1880.25 5 +v -1811.16 -1880.25 495 +v -1814.5 -1882.28 495 +v -1811.16 -1880.25 5 +v -1811.16 -1880.25 5 +v -1814.5 -1882.28 495 +v -1814.5 -1882.28 5 +v -1814.5 -1882.28 495 +v -1816.81 -1885.42 495 +v -1814.5 -1882.28 5 +v -1814.5 -1882.28 5 +v -1816.81 -1885.42 495 +v -1816.81 -1885.42 5 +v -1816.81 -1885.42 495 +v -1817.73 -1889.21 495 +v -1816.81 -1885.42 5 +v -1816.81 -1885.42 5 +v -1817.73 -1889.21 495 +v -1817.73 -1889.21 5 +v -1817.73 -1889.21 495 +v -1817.14 -1893.07 495 +v -1817.73 -1889.21 5 +v -1817.73 -1889.21 5 +v -1817.14 -1893.07 495 +v -1817.14 -1893.07 5 +v -1817.14 -1893.07 495 +v -1815.12 -1896.41 495 +v -1817.14 -1893.07 5 +v -1817.14 -1893.07 5 +v -1815.12 -1896.41 495 +v -1815.12 -1896.41 5 +v -1815.12 -1896.41 495 +v -1811.97 -1898.71 495 +v -1815.12 -1896.41 5 +v -1815.12 -1896.41 5 +v -1811.97 -1898.71 495 +v -1811.97 -1898.71 5 +v -1811.97 -1898.71 495 +v -1808.18 -1899.64 495 +v -1811.97 -1898.71 5 +v -1811.97 -1898.71 5 +v -1808.18 -1899.64 495 +v -1808.18 -1899.64 5 +v -1808.18 -1899.64 495 +v -1804.32 -1899.05 495 +v -1808.18 -1899.64 5 +v -1808.18 -1899.64 5 +v -1804.32 -1899.05 495 +v -1804.32 -1899.05 5 +v -1804.32 -1899.05 495 +v -1800.99 -1897.02 495 +v -1804.32 -1899.05 5 +v -1804.32 -1899.05 5 +v -1800.99 -1897.02 495 +v -1800.99 -1897.02 5 +v -1800.99 -1897.02 495 +v -1798.68 -1893.88 495 +v -1800.99 -1897.02 5 +v -1800.99 -1897.02 5 +v -1798.68 -1893.88 495 +v -1798.68 -1893.88 5 +v -1798.68 -1893.88 495 +v -1797.75 -1890.09 495 +v -1798.68 -1893.88 5 +v -1798.68 -1893.88 5 +v -1797.75 -1890.09 495 +v -1797.75 -1890.09 5 +v -1797.75 -1890.09 495 +v -1798.35 -1886.23 495 +v -1797.75 -1890.09 5 +v -1797.75 -1890.09 5 +v -1798.35 -1886.23 495 +v -1798.35 -1886.23 5 +v -2119.53 -2056.34 510 +v -1743.66 -1919.53 510 +v -2256.34 -1680.47 510 +v -2256.34 -1680.47 510 +v -1743.66 -1919.53 510 +v -1880.47 -1543.66 510 +v -1743.66 -1919.53 500 +v -2119.53 -2056.34 500 +v -1880.47 -1543.66 500 +v -1880.47 -1543.66 500 +v -2119.53 -2056.34 500 +v -2256.34 -1680.47 500 +v -1743.66 -1919.53 510 +v -1743.66 -1919.53 500 +v -1880.47 -1543.66 510 +v -1880.47 -1543.66 510 +v -1743.66 -1919.53 500 +v -1880.47 -1543.66 500 +v -2119.53 -2056.34 500 +v -2119.53 -2056.34 510 +v -2256.34 -1680.47 500 +v -2256.34 -1680.47 500 +v -2119.53 -2056.34 510 +v -2256.34 -1680.47 510 +v -2256.34 -1680.47 500 +v -2256.34 -1680.47 510 +v -1880.47 -1543.66 500 +v -1880.47 -1543.66 500 +v -2256.34 -1680.47 510 +v -1880.47 -1543.66 510 +v -2119.53 -2056.34 500 +v -1743.66 -1919.53 500 +v -2119.53 -2056.34 510 +v -2119.53 -2056.34 510 +v -1743.66 -1919.53 500 +v -1743.66 -1919.53 510 +v -2013.73 -1586.84 810 +v -2015.76 -1583.51 810 +v -2013.73 -1586.84 510 +v -2013.73 -1586.84 510 +v -2015.76 -1583.51 810 +v -2015.76 -1583.51 510 +v -2015.76 -1583.51 810 +v -2018.9 -1581.2 810 +v -2015.76 -1583.51 510 +v -2015.76 -1583.51 510 +v -2018.9 -1581.2 810 +v -2018.9 -1581.2 510 +v -2018.9 -1581.2 810 +v -2022.69 -1580.27 810 +v -2018.9 -1581.2 510 +v -2018.9 -1581.2 510 +v -2022.69 -1580.27 810 +v -2022.69 -1580.27 510 +v -2022.69 -1580.27 810 +v -2026.55 -1580.86 810 +v -2022.69 -1580.27 510 +v -2022.69 -1580.27 510 +v -2026.55 -1580.86 810 +v -2026.55 -1580.86 510 +v -2026.55 -1580.86 810 +v -2029.89 -1582.89 810 +v -2026.55 -1580.86 510 +v -2026.55 -1580.86 510 +v -2029.89 -1582.89 810 +v -2029.89 -1582.89 510 +v -2029.89 -1582.89 810 +v -2032.19 -1586.04 810 +v -2029.89 -1582.89 510 +v -2029.89 -1582.89 510 +v -2032.19 -1586.04 810 +v -2032.19 -1586.04 510 +v -2032.19 -1586.04 810 +v -2033.12 -1589.83 810 +v -2032.19 -1586.04 510 +v -2032.19 -1586.04 510 +v -2033.12 -1589.83 810 +v -2033.12 -1589.83 510 +v -2033.12 -1589.83 810 +v -2032.53 -1593.68 810 +v -2033.12 -1589.83 510 +v -2033.12 -1589.83 510 +v -2032.53 -1593.68 810 +v -2032.53 -1593.68 510 +v -2032.53 -1593.68 810 +v -2030.5 -1597.02 810 +v -2032.53 -1593.68 510 +v -2032.53 -1593.68 510 +v -2030.5 -1597.02 810 +v -2030.5 -1597.02 510 +v -2030.5 -1597.02 810 +v -2027.36 -1599.33 810 +v -2030.5 -1597.02 510 +v -2030.5 -1597.02 510 +v -2027.36 -1599.33 810 +v -2027.36 -1599.33 510 +v -2027.36 -1599.33 810 +v -2023.57 -1600.25 810 +v -2027.36 -1599.33 510 +v -2027.36 -1599.33 510 +v -2023.57 -1600.25 810 +v -2023.57 -1600.25 510 +v -2023.57 -1600.25 810 +v -2019.71 -1599.66 810 +v -2023.57 -1600.25 510 +v -2023.57 -1600.25 510 +v -2019.71 -1599.66 810 +v -2019.71 -1599.66 510 +v -2019.71 -1599.66 810 +v -2016.37 -1597.63 810 +v -2019.71 -1599.66 510 +v -2019.71 -1599.66 510 +v -2016.37 -1597.63 810 +v -2016.37 -1597.63 510 +v -2016.37 -1597.63 810 +v -2014.07 -1594.49 810 +v -2016.37 -1597.63 510 +v -2016.37 -1597.63 510 +v -2014.07 -1594.49 810 +v -2014.07 -1594.49 510 +v -2014.07 -1594.49 810 +v -2013.14 -1590.7 810 +v -2014.07 -1594.49 510 +v -2014.07 -1594.49 510 +v -2013.14 -1590.7 810 +v -2013.14 -1590.7 510 +v -2013.14 -1590.7 810 +v -2013.73 -1586.84 810 +v -2013.14 -1590.7 510 +v -2013.14 -1590.7 510 +v -2013.73 -1586.84 810 +v -2013.73 -1586.84 510 +v -2107.7 -1621.04 810 +v -2109.73 -1617.71 810 +v -2107.7 -1621.04 510 +v -2107.7 -1621.04 510 +v -2109.73 -1617.71 810 +v -2109.73 -1617.71 510 +v -2109.73 -1617.71 810 +v -2112.87 -1615.4 810 +v -2109.73 -1617.71 510 +v -2109.73 -1617.71 510 +v -2112.87 -1615.4 810 +v -2112.87 -1615.4 510 +v -2112.87 -1615.4 810 +v -2116.66 -1614.47 810 +v -2112.87 -1615.4 510 +v -2112.87 -1615.4 510 +v -2116.66 -1614.47 810 +v -2116.66 -1614.47 510 +v -2116.66 -1614.47 810 +v -2120.52 -1615.07 810 +v -2116.66 -1614.47 510 +v -2116.66 -1614.47 510 +v -2120.52 -1615.07 810 +v -2120.52 -1615.07 510 +v -2120.52 -1615.07 810 +v -2123.85 -1617.09 810 +v -2120.52 -1615.07 510 +v -2120.52 -1615.07 510 +v -2123.85 -1617.09 810 +v -2123.85 -1617.09 510 +v -2123.85 -1617.09 810 +v -2126.16 -1620.24 810 +v -2123.85 -1617.09 510 +v -2123.85 -1617.09 510 +v -2126.16 -1620.24 810 +v -2126.16 -1620.24 510 +v -2126.16 -1620.24 810 +v -2127.09 -1624.03 810 +v -2126.16 -1620.24 510 +v -2126.16 -1620.24 510 +v -2127.09 -1624.03 810 +v -2127.09 -1624.03 510 +v -2127.09 -1624.03 810 +v -2126.5 -1627.88 810 +v -2127.09 -1624.03 510 +v -2127.09 -1624.03 510 +v -2126.5 -1627.88 810 +v -2126.5 -1627.88 510 +v -2126.5 -1627.88 810 +v -2124.47 -1631.22 810 +v -2126.5 -1627.88 510 +v -2126.5 -1627.88 510 +v -2124.47 -1631.22 810 +v -2124.47 -1631.22 510 +v -2124.47 -1631.22 810 +v -2121.32 -1633.53 810 +v -2124.47 -1631.22 510 +v -2124.47 -1631.22 510 +v -2121.32 -1633.53 810 +v -2121.32 -1633.53 510 +v -2121.32 -1633.53 810 +v -2117.53 -1634.45 810 +v -2121.32 -1633.53 510 +v -2121.32 -1633.53 510 +v -2117.53 -1634.45 810 +v -2117.53 -1634.45 510 +v -2117.53 -1634.45 810 +v -2113.68 -1633.86 810 +v -2117.53 -1634.45 510 +v -2117.53 -1634.45 510 +v -2113.68 -1633.86 810 +v -2113.68 -1633.86 510 +v -2113.68 -1633.86 810 +v -2110.34 -1631.84 810 +v -2113.68 -1633.86 510 +v -2113.68 -1633.86 510 +v -2110.34 -1631.84 810 +v -2110.34 -1631.84 510 +v -2110.34 -1631.84 810 +v -2108.04 -1628.69 810 +v -2110.34 -1631.84 510 +v -2110.34 -1631.84 510 +v -2108.04 -1628.69 810 +v -2108.04 -1628.69 510 +v -2108.04 -1628.69 810 +v -2107.11 -1624.9 810 +v -2108.04 -1628.69 510 +v -2108.04 -1628.69 510 +v -2107.11 -1624.9 810 +v -2107.11 -1624.9 510 +v -2107.11 -1624.9 810 +v -2107.7 -1621.04 810 +v -2107.11 -1624.9 510 +v -2107.11 -1624.9 510 +v -2107.7 -1621.04 810 +v -2107.7 -1621.04 510 +v -2252.92 -1689.86 910 +v -1877.05 -1553.05 910 +v -2256.34 -1680.47 910 +v -2256.34 -1680.47 910 +v -1877.05 -1553.05 910 +v -1880.47 -1543.66 910 +v -1877.05 -1553.05 710 +v -2252.92 -1689.86 710 +v -1880.47 -1543.66 710 +v -1880.47 -1543.66 710 +v -2252.92 -1689.86 710 +v -2256.34 -1680.47 710 +v -1877.05 -1553.05 910 +v -1877.05 -1553.05 710 +v -1880.47 -1543.66 910 +v -1880.47 -1543.66 910 +v -1877.05 -1553.05 710 +v -1880.47 -1543.66 710 +v -2252.92 -1689.86 710 +v -2252.92 -1689.86 910 +v -2256.34 -1680.47 710 +v -2256.34 -1680.47 710 +v -2252.92 -1689.86 910 +v -2256.34 -1680.47 910 +v -2256.34 -1680.47 710 +v -2256.34 -1680.47 910 +v -1880.47 -1543.66 710 +v -1880.47 -1543.66 710 +v -2256.34 -1680.47 910 +v -1880.47 -1543.66 910 +v -2252.92 -1689.86 710 +v -1877.05 -1553.05 710 +v -2252.92 -1689.86 910 +v -2252.92 -1689.86 910 +v -1877.05 -1553.05 710 +v -1877.05 -1553.05 910 +v -2880 1350 695 +v -2881.52 1357.65 695 +v -2880 1350 5 +v -2880 1350 5 +v -2881.52 1357.65 695 +v -2881.52 1357.65 5 +v -2881.52 1357.65 695 +v -2885.86 1364.14 695 +v -2881.52 1357.65 5 +v -2881.52 1357.65 5 +v -2885.86 1364.14 695 +v -2885.86 1364.14 5 +v -2885.86 1364.14 695 +v -2892.35 1368.48 695 +v -2885.86 1364.14 5 +v -2885.86 1364.14 5 +v -2892.35 1368.48 695 +v -2892.35 1368.48 5 +v -2892.35 1368.48 695 +v -2900 1370 695 +v -2892.35 1368.48 5 +v -2892.35 1368.48 5 +v -2900 1370 695 +v -2900 1370 5 +v -2900 1370 695 +v -2907.65 1368.48 695 +v -2900 1370 5 +v -2900 1370 5 +v -2907.65 1368.48 695 +v -2907.65 1368.48 5 +v -2907.65 1368.48 695 +v -2914.14 1364.14 695 +v -2907.65 1368.48 5 +v -2907.65 1368.48 5 +v -2914.14 1364.14 695 +v -2914.14 1364.14 5 +v -2914.14 1364.14 695 +v -2918.48 1357.65 695 +v -2914.14 1364.14 5 +v -2914.14 1364.14 5 +v -2918.48 1357.65 695 +v -2918.48 1357.65 5 +v -2918.48 1357.65 695 +v -2920 1350 695 +v -2918.48 1357.65 5 +v -2918.48 1357.65 5 +v -2920 1350 695 +v -2920 1350 5 +v -2920 1350 695 +v -2918.48 1342.35 695 +v -2920 1350 5 +v -2920 1350 5 +v -2918.48 1342.35 695 +v -2918.48 1342.35 5 +v -2918.48 1342.35 695 +v -2914.14 1335.86 695 +v -2918.48 1342.35 5 +v -2918.48 1342.35 5 +v -2914.14 1335.86 695 +v -2914.14 1335.86 5 +v -2914.14 1335.86 695 +v -2907.65 1331.52 695 +v -2914.14 1335.86 5 +v -2914.14 1335.86 5 +v -2907.65 1331.52 695 +v -2907.65 1331.52 5 +v -2907.65 1331.52 695 +v -2900 1330 695 +v -2907.65 1331.52 5 +v -2907.65 1331.52 5 +v -2900 1330 695 +v -2900 1330 5 +v -2900 1330 695 +v -2892.35 1331.52 695 +v -2900 1330 5 +v -2900 1330 5 +v -2892.35 1331.52 695 +v -2892.35 1331.52 5 +v -2892.35 1331.52 695 +v -2885.86 1335.86 695 +v -2892.35 1331.52 5 +v -2892.35 1331.52 5 +v -2885.86 1335.86 695 +v -2885.86 1335.86 5 +v -2885.86 1335.86 695 +v -2881.52 1342.35 695 +v -2885.86 1335.86 5 +v -2885.86 1335.86 5 +v -2881.52 1342.35 695 +v -2881.52 1342.35 5 +v -2881.52 1342.35 695 +v -2880 1350 695 +v -2881.52 1342.35 5 +v -2881.52 1342.35 5 +v -2880 1350 695 +v -2880 1350 5 +v 20 1350 695 +v 18.4776 1357.65 695 +v 20 1350 5 +v 20 1350 5 +v 18.4776 1357.65 695 +v 18.4776 1357.65 5 +v 18.4776 1357.65 695 +v 14.1421 1364.14 695 +v 18.4776 1357.65 5 +v 18.4776 1357.65 5 +v 14.1421 1364.14 695 +v 14.1421 1364.14 5 +v 14.1421 1364.14 695 +v 7.65367 1368.48 695 +v 14.1421 1364.14 5 +v 14.1421 1364.14 5 +v 7.65367 1368.48 695 +v 7.65367 1368.48 5 +v 7.65367 1368.48 695 +v -1e-006 1370 695 +v 7.65367 1368.48 5 +v 7.65367 1368.48 5 +v -1e-006 1370 695 +v -1e-006 1370 5 +v -1e-006 1370 695 +v -7.65367 1368.48 695 +v -1e-006 1370 5 +v -1e-006 1370 5 +v -7.65367 1368.48 695 +v -7.65367 1368.48 5 +v -7.65367 1368.48 695 +v -14.1421 1364.14 695 +v -7.65367 1368.48 5 +v -7.65367 1368.48 5 +v -14.1421 1364.14 695 +v -14.1421 1364.14 5 +v -14.1421 1364.14 695 +v -18.4776 1357.65 695 +v -14.1421 1364.14 5 +v -14.1421 1364.14 5 +v -18.4776 1357.65 695 +v -18.4776 1357.65 5 +v -18.4776 1357.65 695 +v -20 1350 695 +v -18.4776 1357.65 5 +v -18.4776 1357.65 5 +v -20 1350 695 +v -20 1350 5 +v -20 1350 695 +v -18.4776 1342.35 695 +v -20 1350 5 +v -20 1350 5 +v -18.4776 1342.35 695 +v -18.4776 1342.35 5 +v -18.4776 1342.35 695 +v -14.1421 1335.86 695 +v -18.4776 1342.35 5 +v -18.4776 1342.35 5 +v -14.1421 1335.86 695 +v -14.1421 1335.86 5 +v -14.1421 1335.86 695 +v -7.65367 1331.52 695 +v -14.1421 1335.86 5 +v -14.1421 1335.86 5 +v -7.65367 1331.52 695 +v -7.65367 1331.52 5 +v -7.65367 1331.52 695 +v 0 1330 695 +v -7.65367 1331.52 5 +v -7.65367 1331.52 5 +v 0 1330 695 +v 0 1330 5 +v 0 1330 695 +v 7.65367 1331.52 695 +v 0 1330 5 +v 0 1330 5 +v 7.65367 1331.52 695 +v 7.65367 1331.52 5 +v 7.65367 1331.52 695 +v 14.1421 1335.86 695 +v 7.65367 1331.52 5 +v 7.65367 1331.52 5 +v 14.1421 1335.86 695 +v 14.1421 1335.86 5 +v 14.1421 1335.86 695 +v 18.4776 1342.35 695 +v 14.1421 1335.86 5 +v 14.1421 1335.86 5 +v 18.4776 1342.35 695 +v 18.4776 1342.35 5 +v 18.4776 1342.35 695 +v 20 1350 695 +v 18.4776 1342.35 5 +v 18.4776 1342.35 5 +v 20 1350 695 +v 20 1350 5 +v 20 2650 695 +v 18.4776 2657.65 695 +v 20 2650 5 +v 20 2650 5 +v 18.4776 2657.65 695 +v 18.4776 2657.65 5 +v 18.4776 2657.65 695 +v 14.1421 2664.14 695 +v 18.4776 2657.65 5 +v 18.4776 2657.65 5 +v 14.1421 2664.14 695 +v 14.1421 2664.14 5 +v 14.1421 2664.14 695 +v 7.65367 2668.48 695 +v 14.1421 2664.14 5 +v 14.1421 2664.14 5 +v 7.65367 2668.48 695 +v 7.65367 2668.48 5 +v 7.65367 2668.48 695 +v -1e-006 2670 695 +v 7.65367 2668.48 5 +v 7.65367 2668.48 5 +v -1e-006 2670 695 +v -1e-006 2670 5 +v -1e-006 2670 695 +v -7.65367 2668.48 695 +v -1e-006 2670 5 +v -1e-006 2670 5 +v -7.65367 2668.48 695 +v -7.65367 2668.48 5 +v -7.65367 2668.48 695 +v -14.1421 2664.14 695 +v -7.65367 2668.48 5 +v -7.65367 2668.48 5 +v -14.1421 2664.14 695 +v -14.1421 2664.14 5 +v -14.1421 2664.14 695 +v -18.4776 2657.65 695 +v -14.1421 2664.14 5 +v -14.1421 2664.14 5 +v -18.4776 2657.65 695 +v -18.4776 2657.65 5 +v -18.4776 2657.65 695 +v -20 2650 695 +v -18.4776 2657.65 5 +v -18.4776 2657.65 5 +v -20 2650 695 +v -20 2650 5 +v -20 2650 695 +v -18.4776 2642.35 695 +v -20 2650 5 +v -20 2650 5 +v -18.4776 2642.35 695 +v -18.4776 2642.35 5 +v -18.4776 2642.35 695 +v -14.1421 2635.86 695 +v -18.4776 2642.35 5 +v -18.4776 2642.35 5 +v -14.1421 2635.86 695 +v -14.1421 2635.86 5 +v -14.1421 2635.86 695 +v -7.65367 2631.52 695 +v -14.1421 2635.86 5 +v -14.1421 2635.86 5 +v -7.65367 2631.52 695 +v -7.65367 2631.52 5 +v -7.65367 2631.52 695 +v 0 2630 695 +v -7.65367 2631.52 5 +v -7.65367 2631.52 5 +v 0 2630 695 +v 0 2630 5 +v 0 2630 695 +v 7.65367 2631.52 695 +v 0 2630 5 +v 0 2630 5 +v 7.65367 2631.52 695 +v 7.65367 2631.52 5 +v 7.65367 2631.52 695 +v 14.1421 2635.86 695 +v 7.65367 2631.52 5 +v 7.65367 2631.52 5 +v 14.1421 2635.86 695 +v 14.1421 2635.86 5 +v 14.1421 2635.86 695 +v 18.4776 2642.35 695 +v 14.1421 2635.86 5 +v 14.1421 2635.86 5 +v 18.4776 2642.35 695 +v 18.4776 2642.35 5 +v 18.4776 2642.35 695 +v 20 2650 695 +v 18.4776 2642.35 5 +v 18.4776 2642.35 5 +v 20 2650 695 +v 20 2650 5 +v -2880 2650 695 +v -2881.52 2657.65 695 +v -2880 2650 5 +v -2880 2650 5 +v -2881.52 2657.65 695 +v -2881.52 2657.65 5 +v -2881.52 2657.65 695 +v -2885.86 2664.14 695 +v -2881.52 2657.65 5 +v -2881.52 2657.65 5 +v -2885.86 2664.14 695 +v -2885.86 2664.14 5 +v -2885.86 2664.14 695 +v -2892.35 2668.48 695 +v -2885.86 2664.14 5 +v -2885.86 2664.14 5 +v -2892.35 2668.48 695 +v -2892.35 2668.48 5 +v -2892.35 2668.48 695 +v -2900 2670 695 +v -2892.35 2668.48 5 +v -2892.35 2668.48 5 +v -2900 2670 695 +v -2900 2670 5 +v -2900 2670 695 +v -2907.65 2668.48 695 +v -2900 2670 5 +v -2900 2670 5 +v -2907.65 2668.48 695 +v -2907.65 2668.48 5 +v -2907.65 2668.48 695 +v -2914.14 2664.14 695 +v -2907.65 2668.48 5 +v -2907.65 2668.48 5 +v -2914.14 2664.14 695 +v -2914.14 2664.14 5 +v -2914.14 2664.14 695 +v -2918.48 2657.65 695 +v -2914.14 2664.14 5 +v -2914.14 2664.14 5 +v -2918.48 2657.65 695 +v -2918.48 2657.65 5 +v -2918.48 2657.65 695 +v -2920 2650 695 +v -2918.48 2657.65 5 +v -2918.48 2657.65 5 +v -2920 2650 695 +v -2920 2650 5 +v -2920 2650 695 +v -2918.48 2642.35 695 +v -2920 2650 5 +v -2920 2650 5 +v -2918.48 2642.35 695 +v -2918.48 2642.35 5 +v -2918.48 2642.35 695 +v -2914.14 2635.86 695 +v -2918.48 2642.35 5 +v -2918.48 2642.35 5 +v -2914.14 2635.86 695 +v -2914.14 2635.86 5 +v -2914.14 2635.86 695 +v -2907.65 2631.52 695 +v -2914.14 2635.86 5 +v -2914.14 2635.86 5 +v -2907.65 2631.52 695 +v -2907.65 2631.52 5 +v -2907.65 2631.52 695 +v -2900 2630 695 +v -2907.65 2631.52 5 +v -2907.65 2631.52 5 +v -2900 2630 695 +v -2900 2630 5 +v -2900 2630 695 +v -2892.35 2631.52 695 +v -2900 2630 5 +v -2900 2630 5 +v -2892.35 2631.52 695 +v -2892.35 2631.52 5 +v -2892.35 2631.52 695 +v -2885.86 2635.86 695 +v -2892.35 2631.52 5 +v -2892.35 2631.52 5 +v -2885.86 2635.86 695 +v -2885.86 2635.86 5 +v -2885.86 2635.86 695 +v -2881.52 2642.35 695 +v -2885.86 2635.86 5 +v -2885.86 2635.86 5 +v -2881.52 2642.35 695 +v -2881.52 2642.35 5 +v -2881.52 2642.35 695 +v -2880 2650 695 +v -2881.52 2642.35 5 +v -2881.52 2642.35 5 +v -2880 2650 695 +v -2880 2650 5 +v -2900 1250 730 +v -100 1250 730 +v -2900 2750 730 +v -2900 2750 730 +v -100 1250 730 +v -100 2750 730 +v -100 1250 680 +v -2900 1250 680 +v -100 2750 680 +v -100 2750 680 +v -2900 1250 680 +v -2900 2750 680 +v -100 1250 730 +v -100 1250 680 +v -100 2750 730 +v -100 2750 730 +v -100 1250 680 +v -100 2750 680 +v -2900 1250 680 +v -2900 1250 730 +v -2900 2750 680 +v -2900 2750 680 +v -2900 1250 730 +v -2900 2750 730 +v -2900 2750 680 +v -2900 2750 730 +v -100 2750 680 +v -100 2750 680 +v -2900 2750 730 +v -100 2750 730 +v -2900 1250 680 +v -100 1250 680 +v -2900 1250 730 +v -2900 1250 730 +v -100 1250 680 +v -100 1250 730 +v -281.015 2712.06 495 +v -279.138 2715.48 495 +v -281.015 2712.06 5 +v -281.015 2712.06 5 +v -279.138 2715.48 495 +v -279.138 2715.48 5 +v -279.138 2715.48 495 +v -278.713 2719.36 495 +v -279.138 2715.48 5 +v -279.138 2715.48 5 +v -278.713 2719.36 495 +v -278.713 2719.36 5 +v -278.713 2719.36 495 +v -279.805 2723.11 495 +v -278.713 2719.36 5 +v -278.713 2719.36 5 +v -279.805 2723.11 495 +v -279.805 2723.11 5 +v -279.805 2723.11 495 +v -282.247 2726.15 495 +v -279.805 2723.11 5 +v -279.805 2723.11 5 +v -282.247 2726.15 495 +v -282.247 2726.15 5 +v -282.247 2726.15 495 +v -285.668 2728.03 495 +v -282.247 2726.15 5 +v -282.247 2726.15 5 +v -285.668 2728.03 495 +v -285.668 2728.03 5 +v -285.668 2728.03 495 +v -289.547 2728.45 495 +v -285.668 2728.03 5 +v -285.668 2728.03 5 +v -289.547 2728.45 495 +v -289.547 2728.45 5 +v -289.547 2728.45 495 +v -293.293 2727.36 495 +v -289.547 2728.45 5 +v -289.547 2728.45 5 +v -293.293 2727.36 495 +v -293.293 2727.36 5 +v -293.293 2727.36 495 +v -296.336 2724.92 495 +v -293.293 2727.36 5 +v -293.293 2727.36 5 +v -296.336 2724.92 495 +v -296.336 2724.92 5 +v -296.336 2724.92 495 +v -298.212 2721.5 495 +v -296.336 2724.92 5 +v -296.336 2724.92 5 +v -298.212 2721.5 495 +v -298.212 2721.5 5 +v -298.212 2721.5 495 +v -298.637 2717.62 495 +v -298.212 2721.5 5 +v -298.212 2721.5 5 +v -298.637 2717.62 495 +v -298.637 2717.62 5 +v -298.637 2717.62 495 +v -297.545 2713.87 495 +v -298.637 2717.62 5 +v -298.637 2717.62 5 +v -297.545 2713.87 495 +v -297.545 2713.87 5 +v -297.545 2713.87 495 +v -295.103 2710.83 495 +v -297.545 2713.87 5 +v -297.545 2713.87 5 +v -295.103 2710.83 495 +v -295.103 2710.83 5 +v -295.103 2710.83 495 +v -291.682 2708.95 495 +v -295.103 2710.83 5 +v -295.103 2710.83 5 +v -291.682 2708.95 495 +v -291.682 2708.95 5 +v -291.682 2708.95 495 +v -287.804 2708.53 495 +v -291.682 2708.95 5 +v -291.682 2708.95 5 +v -287.804 2708.53 495 +v -287.804 2708.53 5 +v -287.804 2708.53 495 +v -284.058 2709.62 495 +v -287.804 2708.53 5 +v -287.804 2708.53 5 +v -284.058 2709.62 495 +v -284.058 2709.62 5 +v -284.058 2709.62 495 +v -281.015 2712.06 495 +v -284.058 2709.62 5 +v -284.058 2709.62 5 +v -281.015 2712.06 495 +v -281.015 2712.06 5 +v -510.828 2904.9 495 +v -508.951 2908.32 495 +v -510.828 2904.9 5 +v -510.828 2904.9 5 +v -508.951 2908.32 495 +v -508.951 2908.32 5 +v -508.951 2908.32 495 +v -508.527 2912.2 495 +v -508.951 2908.32 5 +v -508.951 2908.32 5 +v -508.527 2912.2 495 +v -508.527 2912.2 5 +v -508.527 2912.2 495 +v -509.618 2915.94 495 +v -508.527 2912.2 5 +v -508.527 2912.2 5 +v -509.618 2915.94 495 +v -509.618 2915.94 5 +v -509.618 2915.94 495 +v -512.061 2918.99 495 +v -509.618 2915.94 5 +v -509.618 2915.94 5 +v -512.061 2918.99 495 +v -512.061 2918.99 5 +v -512.061 2918.99 495 +v -515.481 2920.86 495 +v -512.061 2918.99 5 +v -512.061 2918.99 5 +v -515.481 2920.86 495 +v -515.481 2920.86 5 +v -515.481 2920.86 495 +v -519.36 2921.29 495 +v -515.481 2920.86 5 +v -515.481 2920.86 5 +v -519.36 2921.29 495 +v -519.36 2921.29 5 +v -519.36 2921.29 495 +v -523.106 2920.19 495 +v -519.36 2921.29 5 +v -519.36 2921.29 5 +v -523.106 2920.19 495 +v -523.106 2920.19 5 +v -523.106 2920.19 495 +v -526.149 2917.75 495 +v -523.106 2920.19 5 +v -523.106 2920.19 5 +v -526.149 2917.75 495 +v -526.149 2917.75 5 +v -526.149 2917.75 495 +v -528.026 2914.33 495 +v -526.149 2917.75 5 +v -526.149 2917.75 5 +v -528.026 2914.33 495 +v -528.026 2914.33 5 +v -528.026 2914.33 495 +v -528.451 2910.45 495 +v -528.026 2914.33 5 +v -528.026 2914.33 5 +v -528.451 2910.45 495 +v -528.451 2910.45 5 +v -528.451 2910.45 495 +v -527.359 2906.71 495 +v -528.451 2910.45 5 +v -528.451 2910.45 5 +v -527.359 2906.71 495 +v -527.359 2906.71 5 +v -527.359 2906.71 495 +v -524.916 2903.66 495 +v -527.359 2906.71 5 +v -527.359 2906.71 5 +v -524.916 2903.66 495 +v -524.916 2903.66 5 +v -524.916 2903.66 495 +v -521.496 2901.79 495 +v -524.916 2903.66 5 +v -524.916 2903.66 5 +v -521.496 2901.79 495 +v -521.496 2901.79 5 +v -521.496 2901.79 495 +v -517.617 2901.36 495 +v -521.496 2901.79 5 +v -521.496 2901.79 5 +v -517.617 2901.36 495 +v -517.617 2901.36 5 +v -517.617 2901.36 495 +v -513.871 2902.45 495 +v -517.617 2901.36 5 +v -517.617 2901.36 5 +v -513.871 2902.45 495 +v -513.871 2902.45 5 +v -513.871 2902.45 495 +v -510.828 2904.9 495 +v -513.871 2902.45 5 +v -513.871 2902.45 5 +v -510.828 2904.9 495 +v -510.828 2904.9 5 +v -703.664 2675.08 495 +v -701.788 2678.5 495 +v -703.664 2675.08 5 +v -703.664 2675.08 5 +v -701.788 2678.5 495 +v -701.788 2678.5 5 +v -701.788 2678.5 495 +v -701.363 2682.38 495 +v -701.788 2678.5 5 +v -701.788 2678.5 5 +v -701.363 2682.38 495 +v -701.363 2682.38 5 +v -701.363 2682.38 495 +v -702.455 2686.13 495 +v -701.363 2682.38 5 +v -701.363 2682.38 5 +v -702.455 2686.13 495 +v -702.455 2686.13 5 +v -702.455 2686.13 495 +v -704.897 2689.17 495 +v -702.455 2686.13 5 +v -702.455 2686.13 5 +v -704.897 2689.17 495 +v -704.897 2689.17 5 +v -704.897 2689.17 495 +v -708.318 2691.05 495 +v -704.897 2689.17 5 +v -704.897 2689.17 5 +v -708.318 2691.05 495 +v -708.318 2691.05 5 +v -708.318 2691.05 495 +v -712.196 2691.47 495 +v -708.318 2691.05 5 +v -708.318 2691.05 5 +v -712.196 2691.47 495 +v -712.196 2691.47 5 +v -712.196 2691.47 495 +v -715.942 2690.38 495 +v -712.196 2691.47 5 +v -712.196 2691.47 5 +v -715.942 2690.38 495 +v -715.942 2690.38 5 +v -715.942 2690.38 495 +v -718.985 2687.94 495 +v -715.942 2690.38 5 +v -715.942 2690.38 5 +v -718.985 2687.94 495 +v -718.985 2687.94 5 +v -718.985 2687.94 495 +v -720.862 2684.52 495 +v -718.985 2687.94 5 +v -718.985 2687.94 5 +v -720.862 2684.52 495 +v -720.862 2684.52 5 +v -720.862 2684.52 495 +v -721.287 2680.64 495 +v -720.862 2684.52 5 +v -720.862 2684.52 5 +v -721.287 2680.64 495 +v -721.287 2680.64 5 +v -721.287 2680.64 495 +v -720.195 2676.89 495 +v -721.287 2680.64 5 +v -721.287 2680.64 5 +v -720.195 2676.89 495 +v -720.195 2676.89 5 +v -720.195 2676.89 495 +v -717.753 2673.85 495 +v -720.195 2676.89 5 +v -720.195 2676.89 5 +v -717.753 2673.85 495 +v -717.753 2673.85 5 +v -717.753 2673.85 495 +v -714.332 2671.97 495 +v -717.753 2673.85 5 +v -717.753 2673.85 5 +v -714.332 2671.97 495 +v -714.332 2671.97 5 +v -714.332 2671.97 495 +v -710.453 2671.55 495 +v -714.332 2671.97 5 +v -714.332 2671.97 5 +v -710.453 2671.55 495 +v -710.453 2671.55 5 +v -710.453 2671.55 495 +v -706.707 2672.64 495 +v -710.453 2671.55 5 +v -710.453 2671.55 5 +v -706.707 2672.64 495 +v -706.707 2672.64 5 +v -706.707 2672.64 495 +v -703.664 2675.08 495 +v -706.707 2672.64 5 +v -706.707 2672.64 5 +v -703.664 2675.08 495 +v -703.664 2675.08 5 +v -473.851 2482.25 495 +v -471.974 2485.67 495 +v -473.851 2482.25 5 +v -473.851 2482.25 5 +v -471.974 2485.67 495 +v -471.974 2485.67 5 +v -471.974 2485.67 495 +v -471.55 2489.55 495 +v -471.974 2485.67 5 +v -471.974 2485.67 5 +v -471.55 2489.55 495 +v -471.55 2489.55 5 +v -471.55 2489.55 495 +v -472.641 2493.29 495 +v -471.55 2489.55 5 +v -471.55 2489.55 5 +v -472.641 2493.29 495 +v -472.641 2493.29 5 +v -472.641 2493.29 495 +v -475.084 2496.34 495 +v -472.641 2493.29 5 +v -472.641 2493.29 5 +v -475.084 2496.34 495 +v -475.084 2496.34 5 +v -475.084 2496.34 495 +v -478.504 2498.21 495 +v -475.084 2496.34 5 +v -475.084 2496.34 5 +v -478.504 2498.21 495 +v -478.504 2498.21 5 +v -478.504 2498.21 495 +v -482.383 2498.64 495 +v -478.504 2498.21 5 +v -478.504 2498.21 5 +v -482.383 2498.64 495 +v -482.383 2498.64 5 +v -482.383 2498.64 495 +v -486.129 2497.55 495 +v -482.383 2498.64 5 +v -482.383 2498.64 5 +v -486.129 2497.55 495 +v -486.129 2497.55 5 +v -486.129 2497.55 495 +v -489.172 2495.1 495 +v -486.129 2497.55 5 +v -486.129 2497.55 5 +v -489.172 2495.1 495 +v -489.172 2495.1 5 +v -489.172 2495.1 495 +v -491.049 2491.68 495 +v -489.172 2495.1 5 +v -489.172 2495.1 5 +v -491.049 2491.68 495 +v -491.049 2491.68 5 +v -491.049 2491.68 495 +v -491.473 2487.8 495 +v -491.049 2491.68 5 +v -491.049 2491.68 5 +v -491.473 2487.8 495 +v -491.473 2487.8 5 +v -491.473 2487.8 495 +v -490.382 2484.06 495 +v -491.473 2487.8 5 +v -491.473 2487.8 5 +v -490.382 2484.06 495 +v -490.382 2484.06 5 +v -490.382 2484.06 495 +v -487.939 2481.01 495 +v -490.382 2484.06 5 +v -490.382 2484.06 5 +v -487.939 2481.01 495 +v -487.939 2481.01 5 +v -487.939 2481.01 495 +v -484.519 2479.14 495 +v -487.939 2481.01 5 +v -487.939 2481.01 5 +v -484.519 2479.14 495 +v -484.519 2479.14 5 +v -484.519 2479.14 495 +v -480.64 2478.71 495 +v -484.519 2479.14 5 +v -484.519 2479.14 5 +v -480.64 2478.71 495 +v -480.64 2478.71 5 +v -480.64 2478.71 495 +v -476.894 2479.81 495 +v -480.64 2478.71 5 +v -480.64 2478.71 5 +v -476.894 2479.81 495 +v -476.894 2479.81 5 +v -476.894 2479.81 495 +v -473.851 2482.25 495 +v -476.894 2479.81 5 +v -476.894 2479.81 5 +v -473.851 2482.25 495 +v -473.851 2482.25 5 +v -781.766 2675.35 510 +v -475.349 2418.23 510 +v -524.651 2981.77 510 +v -524.651 2981.77 510 +v -475.349 2418.23 510 +v -218.234 2724.65 510 +v -475.349 2418.23 500 +v -781.766 2675.35 500 +v -218.234 2724.65 500 +v -218.234 2724.65 500 +v -781.766 2675.35 500 +v -524.651 2981.77 500 +v -475.349 2418.23 510 +v -475.349 2418.23 500 +v -218.234 2724.65 510 +v -218.234 2724.65 510 +v -475.349 2418.23 500 +v -218.234 2724.65 500 +v -781.766 2675.35 500 +v -781.766 2675.35 510 +v -524.651 2981.77 500 +v -524.651 2981.77 500 +v -781.766 2675.35 510 +v -524.651 2981.77 510 +v -524.651 2981.77 500 +v -524.651 2981.77 510 +v -218.234 2724.65 500 +v -218.234 2724.65 500 +v -524.651 2981.77 510 +v -218.234 2724.65 510 +v -781.766 2675.35 500 +v -475.349 2418.23 500 +v -781.766 2675.35 510 +v -781.766 2675.35 510 +v -475.349 2418.23 500 +v -475.349 2418.23 510 +v -322.266 2818.47 810 +v -320.389 2821.89 810 +v -322.266 2818.47 510 +v -322.266 2818.47 510 +v -320.389 2821.89 810 +v -320.389 2821.89 510 +v -320.389 2821.89 810 +v -319.964 2825.77 810 +v -320.389 2821.89 510 +v -320.389 2821.89 510 +v -319.964 2825.77 810 +v -319.964 2825.77 510 +v -319.964 2825.77 810 +v -321.056 2829.52 810 +v -319.964 2825.77 510 +v -319.964 2825.77 510 +v -321.056 2829.52 810 +v -321.056 2829.52 510 +v -321.056 2829.52 810 +v -323.498 2832.56 810 +v -321.056 2829.52 510 +v -321.056 2829.52 510 +v -323.498 2832.56 810 +v -323.498 2832.56 510 +v -323.498 2832.56 810 +v -326.919 2834.44 810 +v -323.498 2832.56 510 +v -323.498 2832.56 510 +v -326.919 2834.44 810 +v -326.919 2834.44 510 +v -326.919 2834.44 810 +v -330.798 2834.86 810 +v -326.919 2834.44 510 +v -326.919 2834.44 510 +v -330.798 2834.86 810 +v -330.798 2834.86 510 +v -330.798 2834.86 810 +v -334.544 2833.77 810 +v -330.798 2834.86 510 +v -330.798 2834.86 510 +v -334.544 2833.77 810 +v -334.544 2833.77 510 +v -334.544 2833.77 810 +v -337.587 2831.33 810 +v -334.544 2833.77 510 +v -334.544 2833.77 510 +v -337.587 2831.33 810 +v -337.587 2831.33 510 +v -337.587 2831.33 810 +v -339.464 2827.91 810 +v -337.587 2831.33 510 +v -337.587 2831.33 510 +v -339.464 2827.91 810 +v -339.464 2827.91 510 +v -339.464 2827.91 810 +v -339.888 2824.03 810 +v -339.464 2827.91 510 +v -339.464 2827.91 510 +v -339.888 2824.03 810 +v -339.888 2824.03 510 +v -339.888 2824.03 810 +v -338.796 2820.28 810 +v -339.888 2824.03 510 +v -339.888 2824.03 510 +v -338.796 2820.28 810 +v -338.796 2820.28 510 +v -338.796 2820.28 810 +v -336.354 2817.24 810 +v -338.796 2820.28 510 +v -338.796 2820.28 510 +v -336.354 2817.24 810 +v -336.354 2817.24 510 +v -336.354 2817.24 810 +v -332.933 2815.36 810 +v -336.354 2817.24 510 +v -336.354 2817.24 510 +v -332.933 2815.36 810 +v -332.933 2815.36 510 +v -332.933 2815.36 810 +v -329.055 2814.94 810 +v -332.933 2815.36 510 +v -332.933 2815.36 510 +v -329.055 2814.94 810 +v -329.055 2814.94 510 +v -329.055 2814.94 810 +v -325.309 2816.03 810 +v -329.055 2814.94 510 +v -329.055 2814.94 510 +v -325.309 2816.03 810 +v -325.309 2816.03 510 +v -325.309 2816.03 810 +v -322.266 2818.47 810 +v -325.309 2816.03 510 +v -325.309 2816.03 510 +v -322.266 2818.47 810 +v -322.266 2818.47 510 +v -398.87 2882.75 810 +v -396.994 2886.17 810 +v -398.87 2882.75 510 +v -398.87 2882.75 510 +v -396.994 2886.17 810 +v -396.994 2886.17 510 +v -396.994 2886.17 810 +v -396.569 2890.05 810 +v -396.994 2886.17 510 +v -396.994 2886.17 510 +v -396.569 2890.05 810 +v -396.569 2890.05 510 +v -396.569 2890.05 810 +v -397.661 2893.8 810 +v -396.569 2890.05 510 +v -396.569 2890.05 510 +v -397.661 2893.8 810 +v -397.661 2893.8 510 +v -397.661 2893.8 810 +v -400.103 2896.84 810 +v -397.661 2893.8 510 +v -397.661 2893.8 510 +v -400.103 2896.84 810 +v -400.103 2896.84 510 +v -400.103 2896.84 810 +v -403.524 2898.72 810 +v -400.103 2896.84 510 +v -400.103 2896.84 510 +v -403.524 2898.72 810 +v -403.524 2898.72 510 +v -403.524 2898.72 810 +v -407.402 2899.14 810 +v -403.524 2898.72 510 +v -403.524 2898.72 510 +v -407.402 2899.14 810 +v -407.402 2899.14 510 +v -407.402 2899.14 810 +v -411.148 2898.05 810 +v -407.402 2899.14 510 +v -407.402 2899.14 510 +v -411.148 2898.05 810 +v -411.148 2898.05 510 +v -411.148 2898.05 810 +v -414.191 2895.61 810 +v -411.148 2898.05 510 +v -411.148 2898.05 510 +v -414.191 2895.61 810 +v -414.191 2895.61 510 +v -414.191 2895.61 810 +v -416.068 2892.19 810 +v -414.191 2895.61 510 +v -414.191 2895.61 510 +v -416.068 2892.19 810 +v -416.068 2892.19 510 +v -416.068 2892.19 810 +v -416.493 2888.31 810 +v -416.068 2892.19 510 +v -416.068 2892.19 510 +v -416.493 2888.31 810 +v -416.493 2888.31 510 +v -416.493 2888.31 810 +v -415.401 2884.56 810 +v -416.493 2888.31 510 +v -416.493 2888.31 510 +v -415.401 2884.56 810 +v -415.401 2884.56 510 +v -415.401 2884.56 810 +v -412.959 2881.52 810 +v -415.401 2884.56 510 +v -415.401 2884.56 510 +v -412.959 2881.52 810 +v -412.959 2881.52 510 +v -412.959 2881.52 810 +v -409.538 2879.64 810 +v -412.959 2881.52 510 +v -412.959 2881.52 510 +v -409.538 2879.64 810 +v -409.538 2879.64 510 +v -409.538 2879.64 810 +v -405.659 2879.22 810 +v -409.538 2879.64 510 +v -409.538 2879.64 510 +v -405.659 2879.22 810 +v -405.659 2879.22 510 +v -405.659 2879.22 810 +v -401.913 2880.31 810 +v -405.659 2879.22 510 +v -405.659 2879.22 510 +v -401.913 2880.31 810 +v -401.913 2880.31 510 +v -401.913 2880.31 810 +v -398.87 2882.75 810 +v -401.913 2880.31 510 +v -401.913 2880.31 510 +v -398.87 2882.75 810 +v -398.87 2882.75 510 +v -531.079 2974.11 910 +v -224.661 2716.99 910 +v -524.651 2981.77 910 +v -524.651 2981.77 910 +v -224.661 2716.99 910 +v -218.234 2724.65 910 +v -224.661 2716.99 710 +v -531.079 2974.11 710 +v -218.234 2724.65 710 +v -218.234 2724.65 710 +v -531.079 2974.11 710 +v -524.651 2981.77 710 +v -224.661 2716.99 910 +v -224.661 2716.99 710 +v -218.234 2724.65 910 +v -218.234 2724.65 910 +v -224.661 2716.99 710 +v -218.234 2724.65 710 +v -531.079 2974.11 710 +v -531.079 2974.11 910 +v -524.651 2981.77 710 +v -524.651 2981.77 710 +v -531.079 2974.11 910 +v -524.651 2981.77 910 +v -524.651 2981.77 710 +v -524.651 2981.77 910 +v -218.234 2724.65 710 +v -218.234 2724.65 710 +v -524.651 2981.77 910 +v -218.234 2724.65 910 +v -531.079 2974.11 710 +v -224.661 2716.99 710 +v -531.079 2974.11 910 +v -531.079 2974.11 910 +v -224.661 2716.99 710 +v -224.661 2716.99 910 +v -1281.01 2712.06 495 +v -1279.14 2715.48 495 +v -1281.01 2712.06 5 +v -1281.01 2712.06 5 +v -1279.14 2715.48 495 +v -1279.14 2715.48 5 +v -1279.14 2715.48 495 +v -1278.71 2719.36 495 +v -1279.14 2715.48 5 +v -1279.14 2715.48 5 +v -1278.71 2719.36 495 +v -1278.71 2719.36 5 +v -1278.71 2719.36 495 +v -1279.81 2723.11 495 +v -1278.71 2719.36 5 +v -1278.71 2719.36 5 +v -1279.81 2723.11 495 +v -1279.81 2723.11 5 +v -1279.81 2723.11 495 +v -1282.25 2726.15 495 +v -1279.81 2723.11 5 +v -1279.81 2723.11 5 +v -1282.25 2726.15 495 +v -1282.25 2726.15 5 +v -1282.25 2726.15 495 +v -1285.67 2728.03 495 +v -1282.25 2726.15 5 +v -1282.25 2726.15 5 +v -1285.67 2728.03 495 +v -1285.67 2728.03 5 +v -1285.67 2728.03 495 +v -1289.55 2728.45 495 +v -1285.67 2728.03 5 +v -1285.67 2728.03 5 +v -1289.55 2728.45 495 +v -1289.55 2728.45 5 +v -1289.55 2728.45 495 +v -1293.29 2727.36 495 +v -1289.55 2728.45 5 +v -1289.55 2728.45 5 +v -1293.29 2727.36 495 +v -1293.29 2727.36 5 +v -1293.29 2727.36 495 +v -1296.34 2724.92 495 +v -1293.29 2727.36 5 +v -1293.29 2727.36 5 +v -1296.34 2724.92 495 +v -1296.34 2724.92 5 +v -1296.34 2724.92 495 +v -1298.21 2721.5 495 +v -1296.34 2724.92 5 +v -1296.34 2724.92 5 +v -1298.21 2721.5 495 +v -1298.21 2721.5 5 +v -1298.21 2721.5 495 +v -1298.64 2717.62 495 +v -1298.21 2721.5 5 +v -1298.21 2721.5 5 +v -1298.64 2717.62 495 +v -1298.64 2717.62 5 +v -1298.64 2717.62 495 +v -1297.55 2713.87 495 +v -1298.64 2717.62 5 +v -1298.64 2717.62 5 +v -1297.55 2713.87 495 +v -1297.55 2713.87 5 +v -1297.55 2713.87 495 +v -1295.1 2710.83 495 +v -1297.55 2713.87 5 +v -1297.55 2713.87 5 +v -1295.1 2710.83 495 +v -1295.1 2710.83 5 +v -1295.1 2710.83 495 +v -1291.68 2708.95 495 +v -1295.1 2710.83 5 +v -1295.1 2710.83 5 +v -1291.68 2708.95 495 +v -1291.68 2708.95 5 +v -1291.68 2708.95 495 +v -1287.8 2708.53 495 +v -1291.68 2708.95 5 +v -1291.68 2708.95 5 +v -1287.8 2708.53 495 +v -1287.8 2708.53 5 +v -1287.8 2708.53 495 +v -1284.06 2709.62 495 +v -1287.8 2708.53 5 +v -1287.8 2708.53 5 +v -1284.06 2709.62 495 +v -1284.06 2709.62 5 +v -1284.06 2709.62 495 +v -1281.01 2712.06 495 +v -1284.06 2709.62 5 +v -1284.06 2709.62 5 +v -1281.01 2712.06 495 +v -1281.01 2712.06 5 +v -1510.83 2904.9 495 +v -1508.95 2908.32 495 +v -1510.83 2904.9 5 +v -1510.83 2904.9 5 +v -1508.95 2908.32 495 +v -1508.95 2908.32 5 +v -1508.95 2908.32 495 +v -1508.53 2912.2 495 +v -1508.95 2908.32 5 +v -1508.95 2908.32 5 +v -1508.53 2912.2 495 +v -1508.53 2912.2 5 +v -1508.53 2912.2 495 +v -1509.62 2915.94 495 +v -1508.53 2912.2 5 +v -1508.53 2912.2 5 +v -1509.62 2915.94 495 +v -1509.62 2915.94 5 +v -1509.62 2915.94 495 +v -1512.06 2918.99 495 +v -1509.62 2915.94 5 +v -1509.62 2915.94 5 +v -1512.06 2918.99 495 +v -1512.06 2918.99 5 +v -1512.06 2918.99 495 +v -1515.48 2920.86 495 +v -1512.06 2918.99 5 +v -1512.06 2918.99 5 +v -1515.48 2920.86 495 +v -1515.48 2920.86 5 +v -1515.48 2920.86 495 +v -1519.36 2921.29 495 +v -1515.48 2920.86 5 +v -1515.48 2920.86 5 +v -1519.36 2921.29 495 +v -1519.36 2921.29 5 +v -1519.36 2921.29 495 +v -1523.11 2920.19 495 +v -1519.36 2921.29 5 +v -1519.36 2921.29 5 +v -1523.11 2920.19 495 +v -1523.11 2920.19 5 +v -1523.11 2920.19 495 +v -1526.15 2917.75 495 +v -1523.11 2920.19 5 +v -1523.11 2920.19 5 +v -1526.15 2917.75 495 +v -1526.15 2917.75 5 +v -1526.15 2917.75 495 +v -1528.03 2914.33 495 +v -1526.15 2917.75 5 +v -1526.15 2917.75 5 +v -1528.03 2914.33 495 +v -1528.03 2914.33 5 +v -1528.03 2914.33 495 +v -1528.45 2910.45 495 +v -1528.03 2914.33 5 +v -1528.03 2914.33 5 +v -1528.45 2910.45 495 +v -1528.45 2910.45 5 +v -1528.45 2910.45 495 +v -1527.36 2906.71 495 +v -1528.45 2910.45 5 +v -1528.45 2910.45 5 +v -1527.36 2906.71 495 +v -1527.36 2906.71 5 +v -1527.36 2906.71 495 +v -1524.92 2903.66 495 +v -1527.36 2906.71 5 +v -1527.36 2906.71 5 +v -1524.92 2903.66 495 +v -1524.92 2903.66 5 +v -1524.92 2903.66 495 +v -1521.5 2901.79 495 +v -1524.92 2903.66 5 +v -1524.92 2903.66 5 +v -1521.5 2901.79 495 +v -1521.5 2901.79 5 +v -1521.5 2901.79 495 +v -1517.62 2901.36 495 +v -1521.5 2901.79 5 +v -1521.5 2901.79 5 +v -1517.62 2901.36 495 +v -1517.62 2901.36 5 +v -1517.62 2901.36 495 +v -1513.87 2902.45 495 +v -1517.62 2901.36 5 +v -1517.62 2901.36 5 +v -1513.87 2902.45 495 +v -1513.87 2902.45 5 +v -1513.87 2902.45 495 +v -1510.83 2904.9 495 +v -1513.87 2902.45 5 +v -1513.87 2902.45 5 +v -1510.83 2904.9 495 +v -1510.83 2904.9 5 +v -1703.66 2675.08 495 +v -1701.79 2678.5 495 +v -1703.66 2675.08 5 +v -1703.66 2675.08 5 +v -1701.79 2678.5 495 +v -1701.79 2678.5 5 +v -1701.79 2678.5 495 +v -1701.36 2682.38 495 +v -1701.79 2678.5 5 +v -1701.79 2678.5 5 +v -1701.36 2682.38 495 +v -1701.36 2682.38 5 +v -1701.36 2682.38 495 +v -1702.45 2686.13 495 +v -1701.36 2682.38 5 +v -1701.36 2682.38 5 +v -1702.45 2686.13 495 +v -1702.45 2686.13 5 +v -1702.45 2686.13 495 +v -1704.9 2689.17 495 +v -1702.45 2686.13 5 +v -1702.45 2686.13 5 +v -1704.9 2689.17 495 +v -1704.9 2689.17 5 +v -1704.9 2689.17 495 +v -1708.32 2691.05 495 +v -1704.9 2689.17 5 +v -1704.9 2689.17 5 +v -1708.32 2691.05 495 +v -1708.32 2691.05 5 +v -1708.32 2691.05 495 +v -1712.2 2691.47 495 +v -1708.32 2691.05 5 +v -1708.32 2691.05 5 +v -1712.2 2691.47 495 +v -1712.2 2691.47 5 +v -1712.2 2691.47 495 +v -1715.94 2690.38 495 +v -1712.2 2691.47 5 +v -1712.2 2691.47 5 +v -1715.94 2690.38 495 +v -1715.94 2690.38 5 +v -1715.94 2690.38 495 +v -1718.99 2687.94 495 +v -1715.94 2690.38 5 +v -1715.94 2690.38 5 +v -1718.99 2687.94 495 +v -1718.99 2687.94 5 +v -1718.99 2687.94 495 +v -1720.86 2684.52 495 +v -1718.99 2687.94 5 +v -1718.99 2687.94 5 +v -1720.86 2684.52 495 +v -1720.86 2684.52 5 +v -1720.86 2684.52 495 +v -1721.29 2680.64 495 +v -1720.86 2684.52 5 +v -1720.86 2684.52 5 +v -1721.29 2680.64 495 +v -1721.29 2680.64 5 +v -1721.29 2680.64 495 +v -1720.19 2676.89 495 +v -1721.29 2680.64 5 +v -1721.29 2680.64 5 +v -1720.19 2676.89 495 +v -1720.19 2676.89 5 +v -1720.19 2676.89 495 +v -1717.75 2673.85 495 +v -1720.19 2676.89 5 +v -1720.19 2676.89 5 +v -1717.75 2673.85 495 +v -1717.75 2673.85 5 +v -1717.75 2673.85 495 +v -1714.33 2671.97 495 +v -1717.75 2673.85 5 +v -1717.75 2673.85 5 +v -1714.33 2671.97 495 +v -1714.33 2671.97 5 +v -1714.33 2671.97 495 +v -1710.45 2671.55 495 +v -1714.33 2671.97 5 +v -1714.33 2671.97 5 +v -1710.45 2671.55 495 +v -1710.45 2671.55 5 +v -1710.45 2671.55 495 +v -1706.71 2672.64 495 +v -1710.45 2671.55 5 +v -1710.45 2671.55 5 +v -1706.71 2672.64 495 +v -1706.71 2672.64 5 +v -1706.71 2672.64 495 +v -1703.66 2675.08 495 +v -1706.71 2672.64 5 +v -1706.71 2672.64 5 +v -1703.66 2675.08 495 +v -1703.66 2675.08 5 +v -1473.85 2482.25 495 +v -1471.97 2485.67 495 +v -1473.85 2482.25 5 +v -1473.85 2482.25 5 +v -1471.97 2485.67 495 +v -1471.97 2485.67 5 +v -1471.97 2485.67 495 +v -1471.55 2489.55 495 +v -1471.97 2485.67 5 +v -1471.97 2485.67 5 +v -1471.55 2489.55 495 +v -1471.55 2489.55 5 +v -1471.55 2489.55 495 +v -1472.64 2493.29 495 +v -1471.55 2489.55 5 +v -1471.55 2489.55 5 +v -1472.64 2493.29 495 +v -1472.64 2493.29 5 +v -1472.64 2493.29 495 +v -1475.08 2496.34 495 +v -1472.64 2493.29 5 +v -1472.64 2493.29 5 +v -1475.08 2496.34 495 +v -1475.08 2496.34 5 +v -1475.08 2496.34 495 +v -1478.5 2498.21 495 +v -1475.08 2496.34 5 +v -1475.08 2496.34 5 +v -1478.5 2498.21 495 +v -1478.5 2498.21 5 +v -1478.5 2498.21 495 +v -1482.38 2498.64 495 +v -1478.5 2498.21 5 +v -1478.5 2498.21 5 +v -1482.38 2498.64 495 +v -1482.38 2498.64 5 +v -1482.38 2498.64 495 +v -1486.13 2497.55 495 +v -1482.38 2498.64 5 +v -1482.38 2498.64 5 +v -1486.13 2497.55 495 +v -1486.13 2497.55 5 +v -1486.13 2497.55 495 +v -1489.17 2495.1 495 +v -1486.13 2497.55 5 +v -1486.13 2497.55 5 +v -1489.17 2495.1 495 +v -1489.17 2495.1 5 +v -1489.17 2495.1 495 +v -1491.05 2491.68 495 +v -1489.17 2495.1 5 +v -1489.17 2495.1 5 +v -1491.05 2491.68 495 +v -1491.05 2491.68 5 +v -1491.05 2491.68 495 +v -1491.47 2487.8 495 +v -1491.05 2491.68 5 +v -1491.05 2491.68 5 +v -1491.47 2487.8 495 +v -1491.47 2487.8 5 +v -1491.47 2487.8 495 +v -1490.38 2484.06 495 +v -1491.47 2487.8 5 +v -1491.47 2487.8 5 +v -1490.38 2484.06 495 +v -1490.38 2484.06 5 +v -1490.38 2484.06 495 +v -1487.94 2481.01 495 +v -1490.38 2484.06 5 +v -1490.38 2484.06 5 +v -1487.94 2481.01 495 +v -1487.94 2481.01 5 +v -1487.94 2481.01 495 +v -1484.52 2479.14 495 +v -1487.94 2481.01 5 +v -1487.94 2481.01 5 +v -1484.52 2479.14 495 +v -1484.52 2479.14 5 +v -1484.52 2479.14 495 +v -1480.64 2478.71 495 +v -1484.52 2479.14 5 +v -1484.52 2479.14 5 +v -1480.64 2478.71 495 +v -1480.64 2478.71 5 +v -1480.64 2478.71 495 +v -1476.89 2479.81 495 +v -1480.64 2478.71 5 +v -1480.64 2478.71 5 +v -1476.89 2479.81 495 +v -1476.89 2479.81 5 +v -1476.89 2479.81 495 +v -1473.85 2482.25 495 +v -1476.89 2479.81 5 +v -1476.89 2479.81 5 +v -1473.85 2482.25 495 +v -1473.85 2482.25 5 +v -1781.77 2675.35 510 +v -1475.35 2418.23 510 +v -1524.65 2981.77 510 +v -1524.65 2981.77 510 +v -1475.35 2418.23 510 +v -1218.23 2724.65 510 +v -1475.35 2418.23 500 +v -1781.77 2675.35 500 +v -1218.23 2724.65 500 +v -1218.23 2724.65 500 +v -1781.77 2675.35 500 +v -1524.65 2981.77 500 +v -1475.35 2418.23 510 +v -1475.35 2418.23 500 +v -1218.23 2724.65 510 +v -1218.23 2724.65 510 +v -1475.35 2418.23 500 +v -1218.23 2724.65 500 +v -1781.77 2675.35 500 +v -1781.77 2675.35 510 +v -1524.65 2981.77 500 +v -1524.65 2981.77 500 +v -1781.77 2675.35 510 +v -1524.65 2981.77 510 +v -1524.65 2981.77 500 +v -1524.65 2981.77 510 +v -1218.23 2724.65 500 +v -1218.23 2724.65 500 +v -1524.65 2981.77 510 +v -1218.23 2724.65 510 +v -1781.77 2675.35 500 +v -1475.35 2418.23 500 +v -1781.77 2675.35 510 +v -1781.77 2675.35 510 +v -1475.35 2418.23 500 +v -1475.35 2418.23 510 +v -1322.27 2818.47 810 +v -1320.39 2821.89 810 +v -1322.27 2818.47 510 +v -1322.27 2818.47 510 +v -1320.39 2821.89 810 +v -1320.39 2821.89 510 +v -1320.39 2821.89 810 +v -1319.96 2825.77 810 +v -1320.39 2821.89 510 +v -1320.39 2821.89 510 +v -1319.96 2825.77 810 +v -1319.96 2825.77 510 +v -1319.96 2825.77 810 +v -1321.06 2829.52 810 +v -1319.96 2825.77 510 +v -1319.96 2825.77 510 +v -1321.06 2829.52 810 +v -1321.06 2829.52 510 +v -1321.06 2829.52 810 +v -1323.5 2832.56 810 +v -1321.06 2829.52 510 +v -1321.06 2829.52 510 +v -1323.5 2832.56 810 +v -1323.5 2832.56 510 +v -1323.5 2832.56 810 +v -1326.92 2834.44 810 +v -1323.5 2832.56 510 +v -1323.5 2832.56 510 +v -1326.92 2834.44 810 +v -1326.92 2834.44 510 +v -1326.92 2834.44 810 +v -1330.8 2834.86 810 +v -1326.92 2834.44 510 +v -1326.92 2834.44 510 +v -1330.8 2834.86 810 +v -1330.8 2834.86 510 +v -1330.8 2834.86 810 +v -1334.54 2833.77 810 +v -1330.8 2834.86 510 +v -1330.8 2834.86 510 +v -1334.54 2833.77 810 +v -1334.54 2833.77 510 +v -1334.54 2833.77 810 +v -1337.59 2831.33 810 +v -1334.54 2833.77 510 +v -1334.54 2833.77 510 +v -1337.59 2831.33 810 +v -1337.59 2831.33 510 +v -1337.59 2831.33 810 +v -1339.46 2827.91 810 +v -1337.59 2831.33 510 +v -1337.59 2831.33 510 +v -1339.46 2827.91 810 +v -1339.46 2827.91 510 +v -1339.46 2827.91 810 +v -1339.89 2824.03 810 +v -1339.46 2827.91 510 +v -1339.46 2827.91 510 +v -1339.89 2824.03 810 +v -1339.89 2824.03 510 +v -1339.89 2824.03 810 +v -1338.8 2820.28 810 +v -1339.89 2824.03 510 +v -1339.89 2824.03 510 +v -1338.8 2820.28 810 +v -1338.8 2820.28 510 +v -1338.8 2820.28 810 +v -1336.35 2817.24 810 +v -1338.8 2820.28 510 +v -1338.8 2820.28 510 +v -1336.35 2817.24 810 +v -1336.35 2817.24 510 +v -1336.35 2817.24 810 +v -1332.93 2815.36 810 +v -1336.35 2817.24 510 +v -1336.35 2817.24 510 +v -1332.93 2815.36 810 +v -1332.93 2815.36 510 +v -1332.93 2815.36 810 +v -1329.05 2814.94 810 +v -1332.93 2815.36 510 +v -1332.93 2815.36 510 +v -1329.05 2814.94 810 +v -1329.05 2814.94 510 +v -1329.05 2814.94 810 +v -1325.31 2816.03 810 +v -1329.05 2814.94 510 +v -1329.05 2814.94 510 +v -1325.31 2816.03 810 +v -1325.31 2816.03 510 +v -1325.31 2816.03 810 +v -1322.27 2818.47 810 +v -1325.31 2816.03 510 +v -1325.31 2816.03 510 +v -1322.27 2818.47 810 +v -1322.27 2818.47 510 +v -1398.87 2882.75 810 +v -1396.99 2886.17 810 +v -1398.87 2882.75 510 +v -1398.87 2882.75 510 +v -1396.99 2886.17 810 +v -1396.99 2886.17 510 +v -1396.99 2886.17 810 +v -1396.57 2890.05 810 +v -1396.99 2886.17 510 +v -1396.99 2886.17 510 +v -1396.57 2890.05 810 +v -1396.57 2890.05 510 +v -1396.57 2890.05 810 +v -1397.66 2893.8 810 +v -1396.57 2890.05 510 +v -1396.57 2890.05 510 +v -1397.66 2893.8 810 +v -1397.66 2893.8 510 +v -1397.66 2893.8 810 +v -1400.1 2896.84 810 +v -1397.66 2893.8 510 +v -1397.66 2893.8 510 +v -1400.1 2896.84 810 +v -1400.1 2896.84 510 +v -1400.1 2896.84 810 +v -1403.52 2898.72 810 +v -1400.1 2896.84 510 +v -1400.1 2896.84 510 +v -1403.52 2898.72 810 +v -1403.52 2898.72 510 +v -1403.52 2898.72 810 +v -1407.4 2899.14 810 +v -1403.52 2898.72 510 +v -1403.52 2898.72 510 +v -1407.4 2899.14 810 +v -1407.4 2899.14 510 +v -1407.4 2899.14 810 +v -1411.15 2898.05 810 +v -1407.4 2899.14 510 +v -1407.4 2899.14 510 +v -1411.15 2898.05 810 +v -1411.15 2898.05 510 +v -1411.15 2898.05 810 +v -1414.19 2895.61 810 +v -1411.15 2898.05 510 +v -1411.15 2898.05 510 +v -1414.19 2895.61 810 +v -1414.19 2895.61 510 +v -1414.19 2895.61 810 +v -1416.07 2892.19 810 +v -1414.19 2895.61 510 +v -1414.19 2895.61 510 +v -1416.07 2892.19 810 +v -1416.07 2892.19 510 +v -1416.07 2892.19 810 +v -1416.49 2888.31 810 +v -1416.07 2892.19 510 +v -1416.07 2892.19 510 +v -1416.49 2888.31 810 +v -1416.49 2888.31 510 +v -1416.49 2888.31 810 +v -1415.4 2884.56 810 +v -1416.49 2888.31 510 +v -1416.49 2888.31 510 +v -1415.4 2884.56 810 +v -1415.4 2884.56 510 +v -1415.4 2884.56 810 +v -1412.96 2881.52 810 +v -1415.4 2884.56 510 +v -1415.4 2884.56 510 +v -1412.96 2881.52 810 +v -1412.96 2881.52 510 +v -1412.96 2881.52 810 +v -1409.54 2879.64 810 +v -1412.96 2881.52 510 +v -1412.96 2881.52 510 +v -1409.54 2879.64 810 +v -1409.54 2879.64 510 +v -1409.54 2879.64 810 +v -1405.66 2879.22 810 +v -1409.54 2879.64 510 +v -1409.54 2879.64 510 +v -1405.66 2879.22 810 +v -1405.66 2879.22 510 +v -1405.66 2879.22 810 +v -1401.91 2880.31 810 +v -1405.66 2879.22 510 +v -1405.66 2879.22 510 +v -1401.91 2880.31 810 +v -1401.91 2880.31 510 +v -1401.91 2880.31 810 +v -1398.87 2882.75 810 +v -1401.91 2880.31 510 +v -1401.91 2880.31 510 +v -1398.87 2882.75 810 +v -1398.87 2882.75 510 +v -1531.08 2974.11 910 +v -1224.66 2716.99 910 +v -1524.65 2981.77 910 +v -1524.65 2981.77 910 +v -1224.66 2716.99 910 +v -1218.23 2724.65 910 +v -1224.66 2716.99 710 +v -1531.08 2974.11 710 +v -1218.23 2724.65 710 +v -1218.23 2724.65 710 +v -1531.08 2974.11 710 +v -1524.65 2981.77 710 +v -1224.66 2716.99 910 +v -1224.66 2716.99 710 +v -1218.23 2724.65 910 +v -1218.23 2724.65 910 +v -1224.66 2716.99 710 +v -1218.23 2724.65 710 +v -1531.08 2974.11 710 +v -1531.08 2974.11 910 +v -1524.65 2981.77 710 +v -1524.65 2981.77 710 +v -1531.08 2974.11 910 +v -1524.65 2981.77 910 +v -1524.65 2981.77 710 +v -1524.65 2981.77 910 +v -1218.23 2724.65 710 +v -1218.23 2724.65 710 +v -1524.65 2981.77 910 +v -1218.23 2724.65 910 +v -1531.08 2974.11 710 +v -1224.66 2716.99 710 +v -1531.08 2974.11 910 +v -1531.08 2974.11 910 +v -1224.66 2716.99 710 +v -1224.66 2716.99 910 +v -2281.01 2712.06 495 +v -2279.14 2715.48 495 +v -2281.01 2712.06 5 +v -2281.01 2712.06 5 +v -2279.14 2715.48 495 +v -2279.14 2715.48 5 +v -2279.14 2715.48 495 +v -2278.71 2719.36 495 +v -2279.14 2715.48 5 +v -2279.14 2715.48 5 +v -2278.71 2719.36 495 +v -2278.71 2719.36 5 +v -2278.71 2719.36 495 +v -2279.81 2723.11 495 +v -2278.71 2719.36 5 +v -2278.71 2719.36 5 +v -2279.81 2723.11 495 +v -2279.81 2723.11 5 +v -2279.81 2723.11 495 +v -2282.25 2726.15 495 +v -2279.81 2723.11 5 +v -2279.81 2723.11 5 +v -2282.25 2726.15 495 +v -2282.25 2726.15 5 +v -2282.25 2726.15 495 +v -2285.67 2728.03 495 +v -2282.25 2726.15 5 +v -2282.25 2726.15 5 +v -2285.67 2728.03 495 +v -2285.67 2728.03 5 +v -2285.67 2728.03 495 +v -2289.55 2728.45 495 +v -2285.67 2728.03 5 +v -2285.67 2728.03 5 +v -2289.55 2728.45 495 +v -2289.55 2728.45 5 +v -2289.55 2728.45 495 +v -2293.29 2727.36 495 +v -2289.55 2728.45 5 +v -2289.55 2728.45 5 +v -2293.29 2727.36 495 +v -2293.29 2727.36 5 +v -2293.29 2727.36 495 +v -2296.34 2724.92 495 +v -2293.29 2727.36 5 +v -2293.29 2727.36 5 +v -2296.34 2724.92 495 +v -2296.34 2724.92 5 +v -2296.34 2724.92 495 +v -2298.21 2721.5 495 +v -2296.34 2724.92 5 +v -2296.34 2724.92 5 +v -2298.21 2721.5 495 +v -2298.21 2721.5 5 +v -2298.21 2721.5 495 +v -2298.64 2717.62 495 +v -2298.21 2721.5 5 +v -2298.21 2721.5 5 +v -2298.64 2717.62 495 +v -2298.64 2717.62 5 +v -2298.64 2717.62 495 +v -2297.55 2713.87 495 +v -2298.64 2717.62 5 +v -2298.64 2717.62 5 +v -2297.55 2713.87 495 +v -2297.55 2713.87 5 +v -2297.55 2713.87 495 +v -2295.1 2710.83 495 +v -2297.55 2713.87 5 +v -2297.55 2713.87 5 +v -2295.1 2710.83 495 +v -2295.1 2710.83 5 +v -2295.1 2710.83 495 +v -2291.68 2708.95 495 +v -2295.1 2710.83 5 +v -2295.1 2710.83 5 +v -2291.68 2708.95 495 +v -2291.68 2708.95 5 +v -2291.68 2708.95 495 +v -2287.8 2708.53 495 +v -2291.68 2708.95 5 +v -2291.68 2708.95 5 +v -2287.8 2708.53 495 +v -2287.8 2708.53 5 +v -2287.8 2708.53 495 +v -2284.06 2709.62 495 +v -2287.8 2708.53 5 +v -2287.8 2708.53 5 +v -2284.06 2709.62 495 +v -2284.06 2709.62 5 +v -2284.06 2709.62 495 +v -2281.01 2712.06 495 +v -2284.06 2709.62 5 +v -2284.06 2709.62 5 +v -2281.01 2712.06 495 +v -2281.01 2712.06 5 +v -2510.83 2904.9 495 +v -2508.95 2908.32 495 +v -2510.83 2904.9 5 +v -2510.83 2904.9 5 +v -2508.95 2908.32 495 +v -2508.95 2908.32 5 +v -2508.95 2908.32 495 +v -2508.53 2912.2 495 +v -2508.95 2908.32 5 +v -2508.95 2908.32 5 +v -2508.53 2912.2 495 +v -2508.53 2912.2 5 +v -2508.53 2912.2 495 +v -2509.62 2915.94 495 +v -2508.53 2912.2 5 +v -2508.53 2912.2 5 +v -2509.62 2915.94 495 +v -2509.62 2915.94 5 +v -2509.62 2915.94 495 +v -2512.06 2918.99 495 +v -2509.62 2915.94 5 +v -2509.62 2915.94 5 +v -2512.06 2918.99 495 +v -2512.06 2918.99 5 +v -2512.06 2918.99 495 +v -2515.48 2920.86 495 +v -2512.06 2918.99 5 +v -2512.06 2918.99 5 +v -2515.48 2920.86 495 +v -2515.48 2920.86 5 +v -2515.48 2920.86 495 +v -2519.36 2921.29 495 +v -2515.48 2920.86 5 +v -2515.48 2920.86 5 +v -2519.36 2921.29 495 +v -2519.36 2921.29 5 +v -2519.36 2921.29 495 +v -2523.11 2920.19 495 +v -2519.36 2921.29 5 +v -2519.36 2921.29 5 +v -2523.11 2920.19 495 +v -2523.11 2920.19 5 +v -2523.11 2920.19 495 +v -2526.15 2917.75 495 +v -2523.11 2920.19 5 +v -2523.11 2920.19 5 +v -2526.15 2917.75 495 +v -2526.15 2917.75 5 +v -2526.15 2917.75 495 +v -2528.03 2914.33 495 +v -2526.15 2917.75 5 +v -2526.15 2917.75 5 +v -2528.03 2914.33 495 +v -2528.03 2914.33 5 +v -2528.03 2914.33 495 +v -2528.45 2910.45 495 +v -2528.03 2914.33 5 +v -2528.03 2914.33 5 +v -2528.45 2910.45 495 +v -2528.45 2910.45 5 +v -2528.45 2910.45 495 +v -2527.36 2906.71 495 +v -2528.45 2910.45 5 +v -2528.45 2910.45 5 +v -2527.36 2906.71 495 +v -2527.36 2906.71 5 +v -2527.36 2906.71 495 +v -2524.92 2903.66 495 +v -2527.36 2906.71 5 +v -2527.36 2906.71 5 +v -2524.92 2903.66 495 +v -2524.92 2903.66 5 +v -2524.92 2903.66 495 +v -2521.5 2901.79 495 +v -2524.92 2903.66 5 +v -2524.92 2903.66 5 +v -2521.5 2901.79 495 +v -2521.5 2901.79 5 +v -2521.5 2901.79 495 +v -2517.62 2901.36 495 +v -2521.5 2901.79 5 +v -2521.5 2901.79 5 +v -2517.62 2901.36 495 +v -2517.62 2901.36 5 +v -2517.62 2901.36 495 +v -2513.87 2902.45 495 +v -2517.62 2901.36 5 +v -2517.62 2901.36 5 +v -2513.87 2902.45 495 +v -2513.87 2902.45 5 +v -2513.87 2902.45 495 +v -2510.83 2904.9 495 +v -2513.87 2902.45 5 +v -2513.87 2902.45 5 +v -2510.83 2904.9 495 +v -2510.83 2904.9 5 +v -2703.66 2675.08 495 +v -2701.79 2678.5 495 +v -2703.66 2675.08 5 +v -2703.66 2675.08 5 +v -2701.79 2678.5 495 +v -2701.79 2678.5 5 +v -2701.79 2678.5 495 +v -2701.36 2682.38 495 +v -2701.79 2678.5 5 +v -2701.79 2678.5 5 +v -2701.36 2682.38 495 +v -2701.36 2682.38 5 +v -2701.36 2682.38 495 +v -2702.45 2686.13 495 +v -2701.36 2682.38 5 +v -2701.36 2682.38 5 +v -2702.45 2686.13 495 +v -2702.45 2686.13 5 +v -2702.45 2686.13 495 +v -2704.9 2689.17 495 +v -2702.45 2686.13 5 +v -2702.45 2686.13 5 +v -2704.9 2689.17 495 +v -2704.9 2689.17 5 +v -2704.9 2689.17 495 +v -2708.32 2691.05 495 +v -2704.9 2689.17 5 +v -2704.9 2689.17 5 +v -2708.32 2691.05 495 +v -2708.32 2691.05 5 +v -2708.32 2691.05 495 +v -2712.2 2691.47 495 +v -2708.32 2691.05 5 +v -2708.32 2691.05 5 +v -2712.2 2691.47 495 +v -2712.2 2691.47 5 +v -2712.2 2691.47 495 +v -2715.94 2690.38 495 +v -2712.2 2691.47 5 +v -2712.2 2691.47 5 +v -2715.94 2690.38 495 +v -2715.94 2690.38 5 +v -2715.94 2690.38 495 +v -2718.99 2687.94 495 +v -2715.94 2690.38 5 +v -2715.94 2690.38 5 +v -2718.99 2687.94 495 +v -2718.99 2687.94 5 +v -2718.99 2687.94 495 +v -2720.86 2684.52 495 +v -2718.99 2687.94 5 +v -2718.99 2687.94 5 +v -2720.86 2684.52 495 +v -2720.86 2684.52 5 +v -2720.86 2684.52 495 +v -2721.29 2680.64 495 +v -2720.86 2684.52 5 +v -2720.86 2684.52 5 +v -2721.29 2680.64 495 +v -2721.29 2680.64 5 +v -2721.29 2680.64 495 +v -2720.19 2676.89 495 +v -2721.29 2680.64 5 +v -2721.29 2680.64 5 +v -2720.19 2676.89 495 +v -2720.19 2676.89 5 +v -2720.19 2676.89 495 +v -2717.75 2673.85 495 +v -2720.19 2676.89 5 +v -2720.19 2676.89 5 +v -2717.75 2673.85 495 +v -2717.75 2673.85 5 +v -2717.75 2673.85 495 +v -2714.33 2671.97 495 +v -2717.75 2673.85 5 +v -2717.75 2673.85 5 +v -2714.33 2671.97 495 +v -2714.33 2671.97 5 +v -2714.33 2671.97 495 +v -2710.45 2671.55 495 +v -2714.33 2671.97 5 +v -2714.33 2671.97 5 +v -2710.45 2671.55 495 +v -2710.45 2671.55 5 +v -2710.45 2671.55 495 +v -2706.71 2672.64 495 +v -2710.45 2671.55 5 +v -2710.45 2671.55 5 +v -2706.71 2672.64 495 +v -2706.71 2672.64 5 +v -2706.71 2672.64 495 +v -2703.66 2675.08 495 +v -2706.71 2672.64 5 +v -2706.71 2672.64 5 +v -2703.66 2675.08 495 +v -2703.66 2675.08 5 +v -2473.85 2482.25 495 +v -2471.97 2485.67 495 +v -2473.85 2482.25 5 +v -2473.85 2482.25 5 +v -2471.97 2485.67 495 +v -2471.97 2485.67 5 +v -2471.97 2485.67 495 +v -2471.55 2489.55 495 +v -2471.97 2485.67 5 +v -2471.97 2485.67 5 +v -2471.55 2489.55 495 +v -2471.55 2489.55 5 +v -2471.55 2489.55 495 +v -2472.64 2493.29 495 +v -2471.55 2489.55 5 +v -2471.55 2489.55 5 +v -2472.64 2493.29 495 +v -2472.64 2493.29 5 +v -2472.64 2493.29 495 +v -2475.08 2496.34 495 +v -2472.64 2493.29 5 +v -2472.64 2493.29 5 +v -2475.08 2496.34 495 +v -2475.08 2496.34 5 +v -2475.08 2496.34 495 +v -2478.5 2498.21 495 +v -2475.08 2496.34 5 +v -2475.08 2496.34 5 +v -2478.5 2498.21 495 +v -2478.5 2498.21 5 +v -2478.5 2498.21 495 +v -2482.38 2498.64 495 +v -2478.5 2498.21 5 +v -2478.5 2498.21 5 +v -2482.38 2498.64 495 +v -2482.38 2498.64 5 +v -2482.38 2498.64 495 +v -2486.13 2497.55 495 +v -2482.38 2498.64 5 +v -2482.38 2498.64 5 +v -2486.13 2497.55 495 +v -2486.13 2497.55 5 +v -2486.13 2497.55 495 +v -2489.17 2495.1 495 +v -2486.13 2497.55 5 +v -2486.13 2497.55 5 +v -2489.17 2495.1 495 +v -2489.17 2495.1 5 +v -2489.17 2495.1 495 +v -2491.05 2491.68 495 +v -2489.17 2495.1 5 +v -2489.17 2495.1 5 +v -2491.05 2491.68 495 +v -2491.05 2491.68 5 +v -2491.05 2491.68 495 +v -2491.47 2487.8 495 +v -2491.05 2491.68 5 +v -2491.05 2491.68 5 +v -2491.47 2487.8 495 +v -2491.47 2487.8 5 +v -2491.47 2487.8 495 +v -2490.38 2484.06 495 +v -2491.47 2487.8 5 +v -2491.47 2487.8 5 +v -2490.38 2484.06 495 +v -2490.38 2484.06 5 +v -2490.38 2484.06 495 +v -2487.94 2481.01 495 +v -2490.38 2484.06 5 +v -2490.38 2484.06 5 +v -2487.94 2481.01 495 +v -2487.94 2481.01 5 +v -2487.94 2481.01 495 +v -2484.52 2479.14 495 +v -2487.94 2481.01 5 +v -2487.94 2481.01 5 +v -2484.52 2479.14 495 +v -2484.52 2479.14 5 +v -2484.52 2479.14 495 +v -2480.64 2478.71 495 +v -2484.52 2479.14 5 +v -2484.52 2479.14 5 +v -2480.64 2478.71 495 +v -2480.64 2478.71 5 +v -2480.64 2478.71 495 +v -2476.89 2479.81 495 +v -2480.64 2478.71 5 +v -2480.64 2478.71 5 +v -2476.89 2479.81 495 +v -2476.89 2479.81 5 +v -2476.89 2479.81 495 +v -2473.85 2482.25 495 +v -2476.89 2479.81 5 +v -2476.89 2479.81 5 +v -2473.85 2482.25 495 +v -2473.85 2482.25 5 +v -2781.77 2675.35 510 +v -2475.35 2418.23 510 +v -2524.65 2981.77 510 +v -2524.65 2981.77 510 +v -2475.35 2418.23 510 +v -2218.23 2724.65 510 +v -2475.35 2418.23 500 +v -2781.77 2675.35 500 +v -2218.23 2724.65 500 +v -2218.23 2724.65 500 +v -2781.77 2675.35 500 +v -2524.65 2981.77 500 +v -2475.35 2418.23 510 +v -2475.35 2418.23 500 +v -2218.23 2724.65 510 +v -2218.23 2724.65 510 +v -2475.35 2418.23 500 +v -2218.23 2724.65 500 +v -2781.77 2675.35 500 +v -2781.77 2675.35 510 +v -2524.65 2981.77 500 +v -2524.65 2981.77 500 +v -2781.77 2675.35 510 +v -2524.65 2981.77 510 +v -2524.65 2981.77 500 +v -2524.65 2981.77 510 +v -2218.23 2724.65 500 +v -2218.23 2724.65 500 +v -2524.65 2981.77 510 +v -2218.23 2724.65 510 +v -2781.77 2675.35 500 +v -2475.35 2418.23 500 +v -2781.77 2675.35 510 +v -2781.77 2675.35 510 +v -2475.35 2418.23 500 +v -2475.35 2418.23 510 +v -2322.27 2818.47 810 +v -2320.39 2821.89 810 +v -2322.27 2818.47 510 +v -2322.27 2818.47 510 +v -2320.39 2821.89 810 +v -2320.39 2821.89 510 +v -2320.39 2821.89 810 +v -2319.96 2825.77 810 +v -2320.39 2821.89 510 +v -2320.39 2821.89 510 +v -2319.96 2825.77 810 +v -2319.96 2825.77 510 +v -2319.96 2825.77 810 +v -2321.06 2829.52 810 +v -2319.96 2825.77 510 +v -2319.96 2825.77 510 +v -2321.06 2829.52 810 +v -2321.06 2829.52 510 +v -2321.06 2829.52 810 +v -2323.5 2832.56 810 +v -2321.06 2829.52 510 +v -2321.06 2829.52 510 +v -2323.5 2832.56 810 +v -2323.5 2832.56 510 +v -2323.5 2832.56 810 +v -2326.92 2834.44 810 +v -2323.5 2832.56 510 +v -2323.5 2832.56 510 +v -2326.92 2834.44 810 +v -2326.92 2834.44 510 +v -2326.92 2834.44 810 +v -2330.8 2834.86 810 +v -2326.92 2834.44 510 +v -2326.92 2834.44 510 +v -2330.8 2834.86 810 +v -2330.8 2834.86 510 +v -2330.8 2834.86 810 +v -2334.54 2833.77 810 +v -2330.8 2834.86 510 +v -2330.8 2834.86 510 +v -2334.54 2833.77 810 +v -2334.54 2833.77 510 +v -2334.54 2833.77 810 +v -2337.59 2831.33 810 +v -2334.54 2833.77 510 +v -2334.54 2833.77 510 +v -2337.59 2831.33 810 +v -2337.59 2831.33 510 +v -2337.59 2831.33 810 +v -2339.46 2827.91 810 +v -2337.59 2831.33 510 +v -2337.59 2831.33 510 +v -2339.46 2827.91 810 +v -2339.46 2827.91 510 +v -2339.46 2827.91 810 +v -2339.89 2824.03 810 +v -2339.46 2827.91 510 +v -2339.46 2827.91 510 +v -2339.89 2824.03 810 +v -2339.89 2824.03 510 +v -2339.89 2824.03 810 +v -2338.8 2820.28 810 +v -2339.89 2824.03 510 +v -2339.89 2824.03 510 +v -2338.8 2820.28 810 +v -2338.8 2820.28 510 +v -2338.8 2820.28 810 +v -2336.35 2817.24 810 +v -2338.8 2820.28 510 +v -2338.8 2820.28 510 +v -2336.35 2817.24 810 +v -2336.35 2817.24 510 +v -2336.35 2817.24 810 +v -2332.93 2815.36 810 +v -2336.35 2817.24 510 +v -2336.35 2817.24 510 +v -2332.93 2815.36 810 +v -2332.93 2815.36 510 +v -2332.93 2815.36 810 +v -2329.05 2814.94 810 +v -2332.93 2815.36 510 +v -2332.93 2815.36 510 +v -2329.05 2814.94 810 +v -2329.05 2814.94 510 +v -2329.05 2814.94 810 +v -2325.31 2816.03 810 +v -2329.05 2814.94 510 +v -2329.05 2814.94 510 +v -2325.31 2816.03 810 +v -2325.31 2816.03 510 +v -2325.31 2816.03 810 +v -2322.27 2818.47 810 +v -2325.31 2816.03 510 +v -2325.31 2816.03 510 +v -2322.27 2818.47 810 +v -2322.27 2818.47 510 +v -2398.87 2882.75 810 +v -2396.99 2886.17 810 +v -2398.87 2882.75 510 +v -2398.87 2882.75 510 +v -2396.99 2886.17 810 +v -2396.99 2886.17 510 +v -2396.99 2886.17 810 +v -2396.57 2890.05 810 +v -2396.99 2886.17 510 +v -2396.99 2886.17 510 +v -2396.57 2890.05 810 +v -2396.57 2890.05 510 +v -2396.57 2890.05 810 +v -2397.66 2893.8 810 +v -2396.57 2890.05 510 +v -2396.57 2890.05 510 +v -2397.66 2893.8 810 +v -2397.66 2893.8 510 +v -2397.66 2893.8 810 +v -2400.1 2896.84 810 +v -2397.66 2893.8 510 +v -2397.66 2893.8 510 +v -2400.1 2896.84 810 +v -2400.1 2896.84 510 +v -2400.1 2896.84 810 +v -2403.52 2898.72 810 +v -2400.1 2896.84 510 +v -2400.1 2896.84 510 +v -2403.52 2898.72 810 +v -2403.52 2898.72 510 +v -2403.52 2898.72 810 +v -2407.4 2899.14 810 +v -2403.52 2898.72 510 +v -2403.52 2898.72 510 +v -2407.4 2899.14 810 +v -2407.4 2899.14 510 +v -2407.4 2899.14 810 +v -2411.15 2898.05 810 +v -2407.4 2899.14 510 +v -2407.4 2899.14 510 +v -2411.15 2898.05 810 +v -2411.15 2898.05 510 +v -2411.15 2898.05 810 +v -2414.19 2895.61 810 +v -2411.15 2898.05 510 +v -2411.15 2898.05 510 +v -2414.19 2895.61 810 +v -2414.19 2895.61 510 +v -2414.19 2895.61 810 +v -2416.07 2892.19 810 +v -2414.19 2895.61 510 +v -2414.19 2895.61 510 +v -2416.07 2892.19 810 +v -2416.07 2892.19 510 +v -2416.07 2892.19 810 +v -2416.49 2888.31 810 +v -2416.07 2892.19 510 +v -2416.07 2892.19 510 +v -2416.49 2888.31 810 +v -2416.49 2888.31 510 +v -2416.49 2888.31 810 +v -2415.4 2884.56 810 +v -2416.49 2888.31 510 +v -2416.49 2888.31 510 +v -2415.4 2884.56 810 +v -2415.4 2884.56 510 +v -2415.4 2884.56 810 +v -2412.96 2881.52 810 +v -2415.4 2884.56 510 +v -2415.4 2884.56 510 +v -2412.96 2881.52 810 +v -2412.96 2881.52 510 +v -2412.96 2881.52 810 +v -2409.54 2879.64 810 +v -2412.96 2881.52 510 +v -2412.96 2881.52 510 +v -2409.54 2879.64 810 +v -2409.54 2879.64 510 +v -2409.54 2879.64 810 +v -2405.66 2879.22 810 +v -2409.54 2879.64 510 +v -2409.54 2879.64 510 +v -2405.66 2879.22 810 +v -2405.66 2879.22 510 +v -2405.66 2879.22 810 +v -2401.91 2880.31 810 +v -2405.66 2879.22 510 +v -2405.66 2879.22 510 +v -2401.91 2880.31 810 +v -2401.91 2880.31 510 +v -2401.91 2880.31 810 +v -2398.87 2882.75 810 +v -2401.91 2880.31 510 +v -2401.91 2880.31 510 +v -2398.87 2882.75 810 +v -2398.87 2882.75 510 +v -2531.08 2974.11 910 +v -2224.66 2716.99 910 +v -2524.65 2981.77 910 +v -2524.65 2981.77 910 +v -2224.66 2716.99 910 +v -2218.23 2724.65 910 +v -2224.66 2716.99 710 +v -2531.08 2974.11 710 +v -2218.23 2724.65 710 +v -2218.23 2724.65 710 +v -2531.08 2974.11 710 +v -2524.65 2981.77 710 +v -2224.66 2716.99 910 +v -2224.66 2716.99 710 +v -2218.23 2724.65 910 +v -2218.23 2724.65 910 +v -2224.66 2716.99 710 +v -2218.23 2724.65 710 +v -2531.08 2974.11 710 +v -2531.08 2974.11 910 +v -2524.65 2981.77 710 +v -2524.65 2981.77 710 +v -2531.08 2974.11 910 +v -2524.65 2981.77 910 +v -2524.65 2981.77 710 +v -2524.65 2981.77 910 +v -2218.23 2724.65 710 +v -2218.23 2724.65 710 +v -2524.65 2981.77 910 +v -2218.23 2724.65 910 +v -2531.08 2974.11 710 +v -2224.66 2716.99 710 +v -2531.08 2974.11 910 +v -2531.08 2974.11 910 +v -2224.66 2716.99 710 +v -2224.66 2716.99 910 +v -660 1150 495 +v -659.239 1146.17 495 +v -660 1150 5 +v -660 1150 5 +v -659.239 1146.17 495 +v -659.239 1146.17 5 +v -659.239 1146.17 495 +v -657.071 1142.93 495 +v -659.239 1146.17 5 +v -659.239 1146.17 5 +v -657.071 1142.93 495 +v -657.071 1142.93 5 +v -657.071 1142.93 495 +v -653.827 1140.76 495 +v -657.071 1142.93 5 +v -657.071 1142.93 5 +v -653.827 1140.76 495 +v -653.827 1140.76 5 +v -653.827 1140.76 495 +v -650 1140 495 +v -653.827 1140.76 5 +v -653.827 1140.76 5 +v -650 1140 495 +v -650 1140 5 +v -650 1140 495 +v -646.173 1140.76 495 +v -650 1140 5 +v -650 1140 5 +v -646.173 1140.76 495 +v -646.173 1140.76 5 +v -646.173 1140.76 495 +v -642.929 1142.93 495 +v -646.173 1140.76 5 +v -646.173 1140.76 5 +v -642.929 1142.93 495 +v -642.929 1142.93 5 +v -642.929 1142.93 495 +v -640.761 1146.17 495 +v -642.929 1142.93 5 +v -642.929 1142.93 5 +v -640.761 1146.17 495 +v -640.761 1146.17 5 +v -640.761 1146.17 495 +v -640 1150 495 +v -640.761 1146.17 5 +v -640.761 1146.17 5 +v -640 1150 495 +v -640 1150 5 +v -640 1150 495 +v -640.761 1153.83 495 +v -640 1150 5 +v -640 1150 5 +v -640.761 1153.83 495 +v -640.761 1153.83 5 +v -640.761 1153.83 495 +v -642.929 1157.07 495 +v -640.761 1153.83 5 +v -640.761 1153.83 5 +v -642.929 1157.07 495 +v -642.929 1157.07 5 +v -642.929 1157.07 495 +v -646.173 1159.24 495 +v -642.929 1157.07 5 +v -642.929 1157.07 5 +v -646.173 1159.24 495 +v -646.173 1159.24 5 +v -646.173 1159.24 495 +v -650 1160 495 +v -646.173 1159.24 5 +v -646.173 1159.24 5 +v -650 1160 495 +v -650 1160 5 +v -650 1160 495 +v -653.827 1159.24 495 +v -650 1160 5 +v -650 1160 5 +v -653.827 1159.24 495 +v -653.827 1159.24 5 +v -653.827 1159.24 495 +v -657.071 1157.07 495 +v -653.827 1159.24 5 +v -653.827 1159.24 5 +v -657.071 1157.07 495 +v -657.071 1157.07 5 +v -657.071 1157.07 495 +v -659.239 1153.83 495 +v -657.071 1157.07 5 +v -657.071 1157.07 5 +v -659.239 1153.83 495 +v -659.239 1153.83 5 +v -659.239 1153.83 495 +v -660 1150 495 +v -659.239 1153.83 5 +v -659.239 1153.83 5 +v -660 1150 495 +v -660 1150 5 +v -360 1150 495 +v -359.239 1146.17 495 +v -360 1150 5 +v -360 1150 5 +v -359.239 1146.17 495 +v -359.239 1146.17 5 +v -359.239 1146.17 495 +v -357.071 1142.93 495 +v -359.239 1146.17 5 +v -359.239 1146.17 5 +v -357.071 1142.93 495 +v -357.071 1142.93 5 +v -357.071 1142.93 495 +v -353.827 1140.76 495 +v -357.071 1142.93 5 +v -357.071 1142.93 5 +v -353.827 1140.76 495 +v -353.827 1140.76 5 +v -353.827 1140.76 495 +v -350 1140 495 +v -353.827 1140.76 5 +v -353.827 1140.76 5 +v -350 1140 495 +v -350 1140 5 +v -350 1140 495 +v -346.173 1140.76 495 +v -350 1140 5 +v -350 1140 5 +v -346.173 1140.76 495 +v -346.173 1140.76 5 +v -346.173 1140.76 495 +v -342.929 1142.93 495 +v -346.173 1140.76 5 +v -346.173 1140.76 5 +v -342.929 1142.93 495 +v -342.929 1142.93 5 +v -342.929 1142.93 495 +v -340.761 1146.17 495 +v -342.929 1142.93 5 +v -342.929 1142.93 5 +v -340.761 1146.17 495 +v -340.761 1146.17 5 +v -340.761 1146.17 495 +v -340 1150 495 +v -340.761 1146.17 5 +v -340.761 1146.17 5 +v -340 1150 495 +v -340 1150 5 +v -340 1150 495 +v -340.761 1153.83 495 +v -340 1150 5 +v -340 1150 5 +v -340.761 1153.83 495 +v -340.761 1153.83 5 +v -340.761 1153.83 495 +v -342.929 1157.07 495 +v -340.761 1153.83 5 +v -340.761 1153.83 5 +v -342.929 1157.07 495 +v -342.929 1157.07 5 +v -342.929 1157.07 495 +v -346.173 1159.24 495 +v -342.929 1157.07 5 +v -342.929 1157.07 5 +v -346.173 1159.24 495 +v -346.173 1159.24 5 +v -346.173 1159.24 495 +v -350 1160 495 +v -346.173 1159.24 5 +v -346.173 1159.24 5 +v -350 1160 495 +v -350 1160 5 +v -350 1160 495 +v -353.827 1159.24 495 +v -350 1160 5 +v -350 1160 5 +v -353.827 1159.24 495 +v -353.827 1159.24 5 +v -353.827 1159.24 495 +v -357.071 1157.07 495 +v -353.827 1159.24 5 +v -353.827 1159.24 5 +v -357.071 1157.07 495 +v -357.071 1157.07 5 +v -357.071 1157.07 495 +v -359.239 1153.83 495 +v -357.071 1157.07 5 +v -357.071 1157.07 5 +v -359.239 1153.83 495 +v -359.239 1153.83 5 +v -359.239 1153.83 495 +v -360 1150 495 +v -359.239 1153.83 5 +v -359.239 1153.83 5 +v -360 1150 495 +v -360 1150 5 +v -360 1450 495 +v -359.239 1446.17 495 +v -360 1450 5 +v -360 1450 5 +v -359.239 1446.17 495 +v -359.239 1446.17 5 +v -359.239 1446.17 495 +v -357.071 1442.93 495 +v -359.239 1446.17 5 +v -359.239 1446.17 5 +v -357.071 1442.93 495 +v -357.071 1442.93 5 +v -357.071 1442.93 495 +v -353.827 1440.76 495 +v -357.071 1442.93 5 +v -357.071 1442.93 5 +v -353.827 1440.76 495 +v -353.827 1440.76 5 +v -353.827 1440.76 495 +v -350 1440 495 +v -353.827 1440.76 5 +v -353.827 1440.76 5 +v -350 1440 495 +v -350 1440 5 +v -350 1440 495 +v -346.173 1440.76 495 +v -350 1440 5 +v -350 1440 5 +v -346.173 1440.76 495 +v -346.173 1440.76 5 +v -346.173 1440.76 495 +v -342.929 1442.93 495 +v -346.173 1440.76 5 +v -346.173 1440.76 5 +v -342.929 1442.93 495 +v -342.929 1442.93 5 +v -342.929 1442.93 495 +v -340.761 1446.17 495 +v -342.929 1442.93 5 +v -342.929 1442.93 5 +v -340.761 1446.17 495 +v -340.761 1446.17 5 +v -340.761 1446.17 495 +v -340 1450 495 +v -340.761 1446.17 5 +v -340.761 1446.17 5 +v -340 1450 495 +v -340 1450 5 +v -340 1450 495 +v -340.761 1453.83 495 +v -340 1450 5 +v -340 1450 5 +v -340.761 1453.83 495 +v -340.761 1453.83 5 +v -340.761 1453.83 495 +v -342.929 1457.07 495 +v -340.761 1453.83 5 +v -340.761 1453.83 5 +v -342.929 1457.07 495 +v -342.929 1457.07 5 +v -342.929 1457.07 495 +v -346.173 1459.24 495 +v -342.929 1457.07 5 +v -342.929 1457.07 5 +v -346.173 1459.24 495 +v -346.173 1459.24 5 +v -346.173 1459.24 495 +v -350 1460 495 +v -346.173 1459.24 5 +v -346.173 1459.24 5 +v -350 1460 495 +v -350 1460 5 +v -350 1460 495 +v -353.827 1459.24 495 +v -350 1460 5 +v -350 1460 5 +v -353.827 1459.24 495 +v -353.827 1459.24 5 +v -353.827 1459.24 495 +v -357.071 1457.07 495 +v -353.827 1459.24 5 +v -353.827 1459.24 5 +v -357.071 1457.07 495 +v -357.071 1457.07 5 +v -357.071 1457.07 495 +v -359.239 1453.83 495 +v -357.071 1457.07 5 +v -357.071 1457.07 5 +v -359.239 1453.83 495 +v -359.239 1453.83 5 +v -359.239 1453.83 495 +v -360 1450 495 +v -359.239 1453.83 5 +v -359.239 1453.83 5 +v -360 1450 495 +v -360 1450 5 +v -660 1450 495 +v -659.239 1446.17 495 +v -660 1450 5 +v -660 1450 5 +v -659.239 1446.17 495 +v -659.239 1446.17 5 +v -659.239 1446.17 495 +v -657.071 1442.93 495 +v -659.239 1446.17 5 +v -659.239 1446.17 5 +v -657.071 1442.93 495 +v -657.071 1442.93 5 +v -657.071 1442.93 495 +v -653.827 1440.76 495 +v -657.071 1442.93 5 +v -657.071 1442.93 5 +v -653.827 1440.76 495 +v -653.827 1440.76 5 +v -653.827 1440.76 495 +v -650 1440 495 +v -653.827 1440.76 5 +v -653.827 1440.76 5 +v -650 1440 495 +v -650 1440 5 +v -650 1440 495 +v -646.173 1440.76 495 +v -650 1440 5 +v -650 1440 5 +v -646.173 1440.76 495 +v -646.173 1440.76 5 +v -646.173 1440.76 495 +v -642.929 1442.93 495 +v -646.173 1440.76 5 +v -646.173 1440.76 5 +v -642.929 1442.93 495 +v -642.929 1442.93 5 +v -642.929 1442.93 495 +v -640.761 1446.17 495 +v -642.929 1442.93 5 +v -642.929 1442.93 5 +v -640.761 1446.17 495 +v -640.761 1446.17 5 +v -640.761 1446.17 495 +v -640 1450 495 +v -640.761 1446.17 5 +v -640.761 1446.17 5 +v -640 1450 495 +v -640 1450 5 +v -640 1450 495 +v -640.761 1453.83 495 +v -640 1450 5 +v -640 1450 5 +v -640.761 1453.83 495 +v -640.761 1453.83 5 +v -640.761 1453.83 495 +v -642.929 1457.07 495 +v -640.761 1453.83 5 +v -640.761 1453.83 5 +v -642.929 1457.07 495 +v -642.929 1457.07 5 +v -642.929 1457.07 495 +v -646.173 1459.24 495 +v -642.929 1457.07 5 +v -642.929 1457.07 5 +v -646.173 1459.24 495 +v -646.173 1459.24 5 +v -646.173 1459.24 495 +v -650 1460 495 +v -646.173 1459.24 5 +v -646.173 1459.24 5 +v -650 1460 495 +v -650 1460 5 +v -650 1460 495 +v -653.827 1459.24 495 +v -650 1460 5 +v -650 1460 5 +v -653.827 1459.24 495 +v -653.827 1459.24 5 +v -653.827 1459.24 495 +v -657.071 1457.07 495 +v -653.827 1459.24 5 +v -653.827 1459.24 5 +v -657.071 1457.07 495 +v -657.071 1457.07 5 +v -657.071 1457.07 495 +v -659.239 1453.83 495 +v -657.071 1457.07 5 +v -657.071 1457.07 5 +v -659.239 1453.83 495 +v -659.239 1453.83 5 +v -659.239 1453.83 495 +v -660 1450 495 +v -659.239 1453.83 5 +v -659.239 1453.83 5 +v -660 1450 495 +v -660 1450 5 +v -300 1500 510 +v -700 1500 510 +v -300 1100 510 +v -300 1100 510 +v -700 1500 510 +v -700 1100 510 +v -700 1500 500 +v -300 1500 500 +v -700 1100 500 +v -700 1100 500 +v -300 1500 500 +v -300 1100 500 +v -700 1500 510 +v -700 1500 500 +v -700 1100 510 +v -700 1100 510 +v -700 1500 500 +v -700 1100 500 +v -300 1500 500 +v -300 1500 510 +v -300 1100 500 +v -300 1100 500 +v -300 1500 510 +v -300 1100 510 +v -300 1100 500 +v -300 1100 510 +v -700 1100 500 +v -700 1100 500 +v -300 1100 510 +v -700 1100 510 +v -300 1500 500 +v -700 1500 500 +v -300 1500 510 +v -300 1500 510 +v -700 1500 500 +v -700 1500 510 +v -560 1095 810 +v -559.239 1091.17 810 +v -560 1095 510 +v -560 1095 510 +v -559.239 1091.17 810 +v -559.239 1091.17 510 +v -559.239 1091.17 810 +v -557.071 1087.93 810 +v -559.239 1091.17 510 +v -559.239 1091.17 510 +v -557.071 1087.93 810 +v -557.071 1087.93 510 +v -557.071 1087.93 810 +v -553.827 1085.76 810 +v -557.071 1087.93 510 +v -557.071 1087.93 510 +v -553.827 1085.76 810 +v -553.827 1085.76 510 +v -553.827 1085.76 810 +v -550 1085 810 +v -553.827 1085.76 510 +v -553.827 1085.76 510 +v -550 1085 810 +v -550 1085 510 +v -550 1085 810 +v -546.173 1085.76 810 +v -550 1085 510 +v -550 1085 510 +v -546.173 1085.76 810 +v -546.173 1085.76 510 +v -546.173 1085.76 810 +v -542.929 1087.93 810 +v -546.173 1085.76 510 +v -546.173 1085.76 510 +v -542.929 1087.93 810 +v -542.929 1087.93 510 +v -542.929 1087.93 810 +v -540.761 1091.17 810 +v -542.929 1087.93 510 +v -542.929 1087.93 510 +v -540.761 1091.17 810 +v -540.761 1091.17 510 +v -540.761 1091.17 810 +v -540 1095 810 +v -540.761 1091.17 510 +v -540.761 1091.17 510 +v -540 1095 810 +v -540 1095 510 +v -540 1095 810 +v -540.761 1098.83 810 +v -540 1095 510 +v -540 1095 510 +v -540.761 1098.83 810 +v -540.761 1098.83 510 +v -540.761 1098.83 810 +v -542.929 1102.07 810 +v -540.761 1098.83 510 +v -540.761 1098.83 510 +v -542.929 1102.07 810 +v -542.929 1102.07 510 +v -542.929 1102.07 810 +v -546.173 1104.24 810 +v -542.929 1102.07 510 +v -542.929 1102.07 510 +v -546.173 1104.24 810 +v -546.173 1104.24 510 +v -546.173 1104.24 810 +v -550 1105 810 +v -546.173 1104.24 510 +v -546.173 1104.24 510 +v -550 1105 810 +v -550 1105 510 +v -550 1105 810 +v -553.827 1104.24 810 +v -550 1105 510 +v -550 1105 510 +v -553.827 1104.24 810 +v -553.827 1104.24 510 +v -553.827 1104.24 810 +v -557.071 1102.07 810 +v -553.827 1104.24 510 +v -553.827 1104.24 510 +v -557.071 1102.07 810 +v -557.071 1102.07 510 +v -557.071 1102.07 810 +v -559.239 1098.83 810 +v -557.071 1102.07 510 +v -557.071 1102.07 510 +v -559.239 1098.83 810 +v -559.239 1098.83 510 +v -559.239 1098.83 810 +v -560 1095 810 +v -559.239 1098.83 510 +v -559.239 1098.83 510 +v -560 1095 810 +v -560 1095 510 +v -460 1095 810 +v -459.239 1091.17 810 +v -460 1095 510 +v -460 1095 510 +v -459.239 1091.17 810 +v -459.239 1091.17 510 +v -459.239 1091.17 810 +v -457.071 1087.93 810 +v -459.239 1091.17 510 +v -459.239 1091.17 510 +v -457.071 1087.93 810 +v -457.071 1087.93 510 +v -457.071 1087.93 810 +v -453.827 1085.76 810 +v -457.071 1087.93 510 +v -457.071 1087.93 510 +v -453.827 1085.76 810 +v -453.827 1085.76 510 +v -453.827 1085.76 810 +v -450 1085 810 +v -453.827 1085.76 510 +v -453.827 1085.76 510 +v -450 1085 810 +v -450 1085 510 +v -450 1085 810 +v -446.173 1085.76 810 +v -450 1085 510 +v -450 1085 510 +v -446.173 1085.76 810 +v -446.173 1085.76 510 +v -446.173 1085.76 810 +v -442.929 1087.93 810 +v -446.173 1085.76 510 +v -446.173 1085.76 510 +v -442.929 1087.93 810 +v -442.929 1087.93 510 +v -442.929 1087.93 810 +v -440.761 1091.17 810 +v -442.929 1087.93 510 +v -442.929 1087.93 510 +v -440.761 1091.17 810 +v -440.761 1091.17 510 +v -440.761 1091.17 810 +v -440 1095 810 +v -440.761 1091.17 510 +v -440.761 1091.17 510 +v -440 1095 810 +v -440 1095 510 +v -440 1095 810 +v -440.761 1098.83 810 +v -440 1095 510 +v -440 1095 510 +v -440.761 1098.83 810 +v -440.761 1098.83 510 +v -440.761 1098.83 810 +v -442.929 1102.07 810 +v -440.761 1098.83 510 +v -440.761 1098.83 510 +v -442.929 1102.07 810 +v -442.929 1102.07 510 +v -442.929 1102.07 810 +v -446.173 1104.24 810 +v -442.929 1102.07 510 +v -442.929 1102.07 510 +v -446.173 1104.24 810 +v -446.173 1104.24 510 +v -446.173 1104.24 810 +v -450 1105 810 +v -446.173 1104.24 510 +v -446.173 1104.24 510 +v -450 1105 810 +v -450 1105 510 +v -450 1105 810 +v -453.827 1104.24 810 +v -450 1105 510 +v -450 1105 510 +v -453.827 1104.24 810 +v -453.827 1104.24 510 +v -453.827 1104.24 810 +v -457.071 1102.07 810 +v -453.827 1104.24 510 +v -453.827 1104.24 510 +v -457.071 1102.07 810 +v -457.071 1102.07 510 +v -457.071 1102.07 810 +v -459.239 1098.83 810 +v -457.071 1102.07 510 +v -457.071 1102.07 510 +v -459.239 1098.83 810 +v -459.239 1098.83 510 +v -459.239 1098.83 810 +v -460 1095 810 +v -459.239 1098.83 510 +v -459.239 1098.83 510 +v -460 1095 810 +v -460 1095 510 +v -300 1110 910 +v -700 1110 910 +v -300 1100 910 +v -300 1100 910 +v -700 1110 910 +v -700 1100 910 +v -700 1110 710 +v -300 1110 710 +v -700 1100 710 +v -700 1100 710 +v -300 1110 710 +v -300 1100 710 +v -700 1110 910 +v -700 1110 710 +v -700 1100 910 +v -700 1100 910 +v -700 1110 710 +v -700 1100 710 +v -300 1110 710 +v -300 1110 910 +v -300 1100 710 +v -300 1100 710 +v -300 1110 910 +v -300 1100 910 +v -300 1100 710 +v -300 1100 910 +v -700 1100 710 +v -700 1100 710 +v -300 1100 910 +v -700 1100 910 +v -300 1110 710 +v -700 1110 710 +v -300 1110 910 +v -300 1110 910 +v -700 1110 710 +v -700 1110 910 +v -1660 1150 495 +v -1659.24 1146.17 495 +v -1660 1150 5 +v -1660 1150 5 +v -1659.24 1146.17 495 +v -1659.24 1146.17 5 +v -1659.24 1146.17 495 +v -1657.07 1142.93 495 +v -1659.24 1146.17 5 +v -1659.24 1146.17 5 +v -1657.07 1142.93 495 +v -1657.07 1142.93 5 +v -1657.07 1142.93 495 +v -1653.83 1140.76 495 +v -1657.07 1142.93 5 +v -1657.07 1142.93 5 +v -1653.83 1140.76 495 +v -1653.83 1140.76 5 +v -1653.83 1140.76 495 +v -1650 1140 495 +v -1653.83 1140.76 5 +v -1653.83 1140.76 5 +v -1650 1140 495 +v -1650 1140 5 +v -1650 1140 495 +v -1646.17 1140.76 495 +v -1650 1140 5 +v -1650 1140 5 +v -1646.17 1140.76 495 +v -1646.17 1140.76 5 +v -1646.17 1140.76 495 +v -1642.93 1142.93 495 +v -1646.17 1140.76 5 +v -1646.17 1140.76 5 +v -1642.93 1142.93 495 +v -1642.93 1142.93 5 +v -1642.93 1142.93 495 +v -1640.76 1146.17 495 +v -1642.93 1142.93 5 +v -1642.93 1142.93 5 +v -1640.76 1146.17 495 +v -1640.76 1146.17 5 +v -1640.76 1146.17 495 +v -1640 1150 495 +v -1640.76 1146.17 5 +v -1640.76 1146.17 5 +v -1640 1150 495 +v -1640 1150 5 +v -1640 1150 495 +v -1640.76 1153.83 495 +v -1640 1150 5 +v -1640 1150 5 +v -1640.76 1153.83 495 +v -1640.76 1153.83 5 +v -1640.76 1153.83 495 +v -1642.93 1157.07 495 +v -1640.76 1153.83 5 +v -1640.76 1153.83 5 +v -1642.93 1157.07 495 +v -1642.93 1157.07 5 +v -1642.93 1157.07 495 +v -1646.17 1159.24 495 +v -1642.93 1157.07 5 +v -1642.93 1157.07 5 +v -1646.17 1159.24 495 +v -1646.17 1159.24 5 +v -1646.17 1159.24 495 +v -1650 1160 495 +v -1646.17 1159.24 5 +v -1646.17 1159.24 5 +v -1650 1160 495 +v -1650 1160 5 +v -1650 1160 495 +v -1653.83 1159.24 495 +v -1650 1160 5 +v -1650 1160 5 +v -1653.83 1159.24 495 +v -1653.83 1159.24 5 +v -1653.83 1159.24 495 +v -1657.07 1157.07 495 +v -1653.83 1159.24 5 +v -1653.83 1159.24 5 +v -1657.07 1157.07 495 +v -1657.07 1157.07 5 +v -1657.07 1157.07 495 +v -1659.24 1153.83 495 +v -1657.07 1157.07 5 +v -1657.07 1157.07 5 +v -1659.24 1153.83 495 +v -1659.24 1153.83 5 +v -1659.24 1153.83 495 +v -1660 1150 495 +v -1659.24 1153.83 5 +v -1659.24 1153.83 5 +v -1660 1150 495 +v -1660 1150 5 +v -1360 1150 495 +v -1359.24 1146.17 495 +v -1360 1150 5 +v -1360 1150 5 +v -1359.24 1146.17 495 +v -1359.24 1146.17 5 +v -1359.24 1146.17 495 +v -1357.07 1142.93 495 +v -1359.24 1146.17 5 +v -1359.24 1146.17 5 +v -1357.07 1142.93 495 +v -1357.07 1142.93 5 +v -1357.07 1142.93 495 +v -1353.83 1140.76 495 +v -1357.07 1142.93 5 +v -1357.07 1142.93 5 +v -1353.83 1140.76 495 +v -1353.83 1140.76 5 +v -1353.83 1140.76 495 +v -1350 1140 495 +v -1353.83 1140.76 5 +v -1353.83 1140.76 5 +v -1350 1140 495 +v -1350 1140 5 +v -1350 1140 495 +v -1346.17 1140.76 495 +v -1350 1140 5 +v -1350 1140 5 +v -1346.17 1140.76 495 +v -1346.17 1140.76 5 +v -1346.17 1140.76 495 +v -1342.93 1142.93 495 +v -1346.17 1140.76 5 +v -1346.17 1140.76 5 +v -1342.93 1142.93 495 +v -1342.93 1142.93 5 +v -1342.93 1142.93 495 +v -1340.76 1146.17 495 +v -1342.93 1142.93 5 +v -1342.93 1142.93 5 +v -1340.76 1146.17 495 +v -1340.76 1146.17 5 +v -1340.76 1146.17 495 +v -1340 1150 495 +v -1340.76 1146.17 5 +v -1340.76 1146.17 5 +v -1340 1150 495 +v -1340 1150 5 +v -1340 1150 495 +v -1340.76 1153.83 495 +v -1340 1150 5 +v -1340 1150 5 +v -1340.76 1153.83 495 +v -1340.76 1153.83 5 +v -1340.76 1153.83 495 +v -1342.93 1157.07 495 +v -1340.76 1153.83 5 +v -1340.76 1153.83 5 +v -1342.93 1157.07 495 +v -1342.93 1157.07 5 +v -1342.93 1157.07 495 +v -1346.17 1159.24 495 +v -1342.93 1157.07 5 +v -1342.93 1157.07 5 +v -1346.17 1159.24 495 +v -1346.17 1159.24 5 +v -1346.17 1159.24 495 +v -1350 1160 495 +v -1346.17 1159.24 5 +v -1346.17 1159.24 5 +v -1350 1160 495 +v -1350 1160 5 +v -1350 1160 495 +v -1353.83 1159.24 495 +v -1350 1160 5 +v -1350 1160 5 +v -1353.83 1159.24 495 +v -1353.83 1159.24 5 +v -1353.83 1159.24 495 +v -1357.07 1157.07 495 +v -1353.83 1159.24 5 +v -1353.83 1159.24 5 +v -1357.07 1157.07 495 +v -1357.07 1157.07 5 +v -1357.07 1157.07 495 +v -1359.24 1153.83 495 +v -1357.07 1157.07 5 +v -1357.07 1157.07 5 +v -1359.24 1153.83 495 +v -1359.24 1153.83 5 +v -1359.24 1153.83 495 +v -1360 1150 495 +v -1359.24 1153.83 5 +v -1359.24 1153.83 5 +v -1360 1150 495 +v -1360 1150 5 +v -1360 1450 495 +v -1359.24 1446.17 495 +v -1360 1450 5 +v -1360 1450 5 +v -1359.24 1446.17 495 +v -1359.24 1446.17 5 +v -1359.24 1446.17 495 +v -1357.07 1442.93 495 +v -1359.24 1446.17 5 +v -1359.24 1446.17 5 +v -1357.07 1442.93 495 +v -1357.07 1442.93 5 +v -1357.07 1442.93 495 +v -1353.83 1440.76 495 +v -1357.07 1442.93 5 +v -1357.07 1442.93 5 +v -1353.83 1440.76 495 +v -1353.83 1440.76 5 +v -1353.83 1440.76 495 +v -1350 1440 495 +v -1353.83 1440.76 5 +v -1353.83 1440.76 5 +v -1350 1440 495 +v -1350 1440 5 +v -1350 1440 495 +v -1346.17 1440.76 495 +v -1350 1440 5 +v -1350 1440 5 +v -1346.17 1440.76 495 +v -1346.17 1440.76 5 +v -1346.17 1440.76 495 +v -1342.93 1442.93 495 +v -1346.17 1440.76 5 +v -1346.17 1440.76 5 +v -1342.93 1442.93 495 +v -1342.93 1442.93 5 +v -1342.93 1442.93 495 +v -1340.76 1446.17 495 +v -1342.93 1442.93 5 +v -1342.93 1442.93 5 +v -1340.76 1446.17 495 +v -1340.76 1446.17 5 +v -1340.76 1446.17 495 +v -1340 1450 495 +v -1340.76 1446.17 5 +v -1340.76 1446.17 5 +v -1340 1450 495 +v -1340 1450 5 +v -1340 1450 495 +v -1340.76 1453.83 495 +v -1340 1450 5 +v -1340 1450 5 +v -1340.76 1453.83 495 +v -1340.76 1453.83 5 +v -1340.76 1453.83 495 +v -1342.93 1457.07 495 +v -1340.76 1453.83 5 +v -1340.76 1453.83 5 +v -1342.93 1457.07 495 +v -1342.93 1457.07 5 +v -1342.93 1457.07 495 +v -1346.17 1459.24 495 +v -1342.93 1457.07 5 +v -1342.93 1457.07 5 +v -1346.17 1459.24 495 +v -1346.17 1459.24 5 +v -1346.17 1459.24 495 +v -1350 1460 495 +v -1346.17 1459.24 5 +v -1346.17 1459.24 5 +v -1350 1460 495 +v -1350 1460 5 +v -1350 1460 495 +v -1353.83 1459.24 495 +v -1350 1460 5 +v -1350 1460 5 +v -1353.83 1459.24 495 +v -1353.83 1459.24 5 +v -1353.83 1459.24 495 +v -1357.07 1457.07 495 +v -1353.83 1459.24 5 +v -1353.83 1459.24 5 +v -1357.07 1457.07 495 +v -1357.07 1457.07 5 +v -1357.07 1457.07 495 +v -1359.24 1453.83 495 +v -1357.07 1457.07 5 +v -1357.07 1457.07 5 +v -1359.24 1453.83 495 +v -1359.24 1453.83 5 +v -1359.24 1453.83 495 +v -1360 1450 495 +v -1359.24 1453.83 5 +v -1359.24 1453.83 5 +v -1360 1450 495 +v -1360 1450 5 +v -1660 1450 495 +v -1659.24 1446.17 495 +v -1660 1450 5 +v -1660 1450 5 +v -1659.24 1446.17 495 +v -1659.24 1446.17 5 +v -1659.24 1446.17 495 +v -1657.07 1442.93 495 +v -1659.24 1446.17 5 +v -1659.24 1446.17 5 +v -1657.07 1442.93 495 +v -1657.07 1442.93 5 +v -1657.07 1442.93 495 +v -1653.83 1440.76 495 +v -1657.07 1442.93 5 +v -1657.07 1442.93 5 +v -1653.83 1440.76 495 +v -1653.83 1440.76 5 +v -1653.83 1440.76 495 +v -1650 1440 495 +v -1653.83 1440.76 5 +v -1653.83 1440.76 5 +v -1650 1440 495 +v -1650 1440 5 +v -1650 1440 495 +v -1646.17 1440.76 495 +v -1650 1440 5 +v -1650 1440 5 +v -1646.17 1440.76 495 +v -1646.17 1440.76 5 +v -1646.17 1440.76 495 +v -1642.93 1442.93 495 +v -1646.17 1440.76 5 +v -1646.17 1440.76 5 +v -1642.93 1442.93 495 +v -1642.93 1442.93 5 +v -1642.93 1442.93 495 +v -1640.76 1446.17 495 +v -1642.93 1442.93 5 +v -1642.93 1442.93 5 +v -1640.76 1446.17 495 +v -1640.76 1446.17 5 +v -1640.76 1446.17 495 +v -1640 1450 495 +v -1640.76 1446.17 5 +v -1640.76 1446.17 5 +v -1640 1450 495 +v -1640 1450 5 +v -1640 1450 495 +v -1640.76 1453.83 495 +v -1640 1450 5 +v -1640 1450 5 +v -1640.76 1453.83 495 +v -1640.76 1453.83 5 +v -1640.76 1453.83 495 +v -1642.93 1457.07 495 +v -1640.76 1453.83 5 +v -1640.76 1453.83 5 +v -1642.93 1457.07 495 +v -1642.93 1457.07 5 +v -1642.93 1457.07 495 +v -1646.17 1459.24 495 +v -1642.93 1457.07 5 +v -1642.93 1457.07 5 +v -1646.17 1459.24 495 +v -1646.17 1459.24 5 +v -1646.17 1459.24 495 +v -1650 1460 495 +v -1646.17 1459.24 5 +v -1646.17 1459.24 5 +v -1650 1460 495 +v -1650 1460 5 +v -1650 1460 495 +v -1653.83 1459.24 495 +v -1650 1460 5 +v -1650 1460 5 +v -1653.83 1459.24 495 +v -1653.83 1459.24 5 +v -1653.83 1459.24 495 +v -1657.07 1457.07 495 +v -1653.83 1459.24 5 +v -1653.83 1459.24 5 +v -1657.07 1457.07 495 +v -1657.07 1457.07 5 +v -1657.07 1457.07 495 +v -1659.24 1453.83 495 +v -1657.07 1457.07 5 +v -1657.07 1457.07 5 +v -1659.24 1453.83 495 +v -1659.24 1453.83 5 +v -1659.24 1453.83 495 +v -1660 1450 495 +v -1659.24 1453.83 5 +v -1659.24 1453.83 5 +v -1660 1450 495 +v -1660 1450 5 +v -1300 1500 510 +v -1700 1500 510 +v -1300 1100 510 +v -1300 1100 510 +v -1700 1500 510 +v -1700 1100 510 +v -1700 1500 500 +v -1300 1500 500 +v -1700 1100 500 +v -1700 1100 500 +v -1300 1500 500 +v -1300 1100 500 +v -1700 1500 510 +v -1700 1500 500 +v -1700 1100 510 +v -1700 1100 510 +v -1700 1500 500 +v -1700 1100 500 +v -1300 1500 500 +v -1300 1500 510 +v -1300 1100 500 +v -1300 1100 500 +v -1300 1500 510 +v -1300 1100 510 +v -1300 1100 500 +v -1300 1100 510 +v -1700 1100 500 +v -1700 1100 500 +v -1300 1100 510 +v -1700 1100 510 +v -1300 1500 500 +v -1700 1500 500 +v -1300 1500 510 +v -1300 1500 510 +v -1700 1500 500 +v -1700 1500 510 +v -1560 1095 810 +v -1559.24 1091.17 810 +v -1560 1095 510 +v -1560 1095 510 +v -1559.24 1091.17 810 +v -1559.24 1091.17 510 +v -1559.24 1091.17 810 +v -1557.07 1087.93 810 +v -1559.24 1091.17 510 +v -1559.24 1091.17 510 +v -1557.07 1087.93 810 +v -1557.07 1087.93 510 +v -1557.07 1087.93 810 +v -1553.83 1085.76 810 +v -1557.07 1087.93 510 +v -1557.07 1087.93 510 +v -1553.83 1085.76 810 +v -1553.83 1085.76 510 +v -1553.83 1085.76 810 +v -1550 1085 810 +v -1553.83 1085.76 510 +v -1553.83 1085.76 510 +v -1550 1085 810 +v -1550 1085 510 +v -1550 1085 810 +v -1546.17 1085.76 810 +v -1550 1085 510 +v -1550 1085 510 +v -1546.17 1085.76 810 +v -1546.17 1085.76 510 +v -1546.17 1085.76 810 +v -1542.93 1087.93 810 +v -1546.17 1085.76 510 +v -1546.17 1085.76 510 +v -1542.93 1087.93 810 +v -1542.93 1087.93 510 +v -1542.93 1087.93 810 +v -1540.76 1091.17 810 +v -1542.93 1087.93 510 +v -1542.93 1087.93 510 +v -1540.76 1091.17 810 +v -1540.76 1091.17 510 +v -1540.76 1091.17 810 +v -1540 1095 810 +v -1540.76 1091.17 510 +v -1540.76 1091.17 510 +v -1540 1095 810 +v -1540 1095 510 +v -1540 1095 810 +v -1540.76 1098.83 810 +v -1540 1095 510 +v -1540 1095 510 +v -1540.76 1098.83 810 +v -1540.76 1098.83 510 +v -1540.76 1098.83 810 +v -1542.93 1102.07 810 +v -1540.76 1098.83 510 +v -1540.76 1098.83 510 +v -1542.93 1102.07 810 +v -1542.93 1102.07 510 +v -1542.93 1102.07 810 +v -1546.17 1104.24 810 +v -1542.93 1102.07 510 +v -1542.93 1102.07 510 +v -1546.17 1104.24 810 +v -1546.17 1104.24 510 +v -1546.17 1104.24 810 +v -1550 1105 810 +v -1546.17 1104.24 510 +v -1546.17 1104.24 510 +v -1550 1105 810 +v -1550 1105 510 +v -1550 1105 810 +v -1553.83 1104.24 810 +v -1550 1105 510 +v -1550 1105 510 +v -1553.83 1104.24 810 +v -1553.83 1104.24 510 +v -1553.83 1104.24 810 +v -1557.07 1102.07 810 +v -1553.83 1104.24 510 +v -1553.83 1104.24 510 +v -1557.07 1102.07 810 +v -1557.07 1102.07 510 +v -1557.07 1102.07 810 +v -1559.24 1098.83 810 +v -1557.07 1102.07 510 +v -1557.07 1102.07 510 +v -1559.24 1098.83 810 +v -1559.24 1098.83 510 +v -1559.24 1098.83 810 +v -1560 1095 810 +v -1559.24 1098.83 510 +v -1559.24 1098.83 510 +v -1560 1095 810 +v -1560 1095 510 +v -1460 1095 810 +v -1459.24 1091.17 810 +v -1460 1095 510 +v -1460 1095 510 +v -1459.24 1091.17 810 +v -1459.24 1091.17 510 +v -1459.24 1091.17 810 +v -1457.07 1087.93 810 +v -1459.24 1091.17 510 +v -1459.24 1091.17 510 +v -1457.07 1087.93 810 +v -1457.07 1087.93 510 +v -1457.07 1087.93 810 +v -1453.83 1085.76 810 +v -1457.07 1087.93 510 +v -1457.07 1087.93 510 +v -1453.83 1085.76 810 +v -1453.83 1085.76 510 +v -1453.83 1085.76 810 +v -1450 1085 810 +v -1453.83 1085.76 510 +v -1453.83 1085.76 510 +v -1450 1085 810 +v -1450 1085 510 +v -1450 1085 810 +v -1446.17 1085.76 810 +v -1450 1085 510 +v -1450 1085 510 +v -1446.17 1085.76 810 +v -1446.17 1085.76 510 +v -1446.17 1085.76 810 +v -1442.93 1087.93 810 +v -1446.17 1085.76 510 +v -1446.17 1085.76 510 +v -1442.93 1087.93 810 +v -1442.93 1087.93 510 +v -1442.93 1087.93 810 +v -1440.76 1091.17 810 +v -1442.93 1087.93 510 +v -1442.93 1087.93 510 +v -1440.76 1091.17 810 +v -1440.76 1091.17 510 +v -1440.76 1091.17 810 +v -1440 1095 810 +v -1440.76 1091.17 510 +v -1440.76 1091.17 510 +v -1440 1095 810 +v -1440 1095 510 +v -1440 1095 810 +v -1440.76 1098.83 810 +v -1440 1095 510 +v -1440 1095 510 +v -1440.76 1098.83 810 +v -1440.76 1098.83 510 +v -1440.76 1098.83 810 +v -1442.93 1102.07 810 +v -1440.76 1098.83 510 +v -1440.76 1098.83 510 +v -1442.93 1102.07 810 +v -1442.93 1102.07 510 +v -1442.93 1102.07 810 +v -1446.17 1104.24 810 +v -1442.93 1102.07 510 +v -1442.93 1102.07 510 +v -1446.17 1104.24 810 +v -1446.17 1104.24 510 +v -1446.17 1104.24 810 +v -1450 1105 810 +v -1446.17 1104.24 510 +v -1446.17 1104.24 510 +v -1450 1105 810 +v -1450 1105 510 +v -1450 1105 810 +v -1453.83 1104.24 810 +v -1450 1105 510 +v -1450 1105 510 +v -1453.83 1104.24 810 +v -1453.83 1104.24 510 +v -1453.83 1104.24 810 +v -1457.07 1102.07 810 +v -1453.83 1104.24 510 +v -1453.83 1104.24 510 +v -1457.07 1102.07 810 +v -1457.07 1102.07 510 +v -1457.07 1102.07 810 +v -1459.24 1098.83 810 +v -1457.07 1102.07 510 +v -1457.07 1102.07 510 +v -1459.24 1098.83 810 +v -1459.24 1098.83 510 +v -1459.24 1098.83 810 +v -1460 1095 810 +v -1459.24 1098.83 510 +v -1459.24 1098.83 510 +v -1460 1095 810 +v -1460 1095 510 +v -1300 1110 910 +v -1700 1110 910 +v -1300 1100 910 +v -1300 1100 910 +v -1700 1110 910 +v -1700 1100 910 +v -1700 1110 710 +v -1300 1110 710 +v -1700 1100 710 +v -1700 1100 710 +v -1300 1110 710 +v -1300 1100 710 +v -1700 1110 910 +v -1700 1110 710 +v -1700 1100 910 +v -1700 1100 910 +v -1700 1110 710 +v -1700 1100 710 +v -1300 1110 710 +v -1300 1110 910 +v -1300 1100 710 +v -1300 1100 710 +v -1300 1110 910 +v -1300 1100 910 +v -1300 1100 710 +v -1300 1100 910 +v -1700 1100 710 +v -1700 1100 710 +v -1300 1100 910 +v -1700 1100 910 +v -1300 1110 710 +v -1700 1110 710 +v -1300 1110 910 +v -1300 1110 910 +v -1700 1110 710 +v -1700 1110 910 +v -2660 1150 495 +v -2659.24 1146.17 495 +v -2660 1150 5 +v -2660 1150 5 +v -2659.24 1146.17 495 +v -2659.24 1146.17 5 +v -2659.24 1146.17 495 +v -2657.07 1142.93 495 +v -2659.24 1146.17 5 +v -2659.24 1146.17 5 +v -2657.07 1142.93 495 +v -2657.07 1142.93 5 +v -2657.07 1142.93 495 +v -2653.83 1140.76 495 +v -2657.07 1142.93 5 +v -2657.07 1142.93 5 +v -2653.83 1140.76 495 +v -2653.83 1140.76 5 +v -2653.83 1140.76 495 +v -2650 1140 495 +v -2653.83 1140.76 5 +v -2653.83 1140.76 5 +v -2650 1140 495 +v -2650 1140 5 +v -2650 1140 495 +v -2646.17 1140.76 495 +v -2650 1140 5 +v -2650 1140 5 +v -2646.17 1140.76 495 +v -2646.17 1140.76 5 +v -2646.17 1140.76 495 +v -2642.93 1142.93 495 +v -2646.17 1140.76 5 +v -2646.17 1140.76 5 +v -2642.93 1142.93 495 +v -2642.93 1142.93 5 +v -2642.93 1142.93 495 +v -2640.76 1146.17 495 +v -2642.93 1142.93 5 +v -2642.93 1142.93 5 +v -2640.76 1146.17 495 +v -2640.76 1146.17 5 +v -2640.76 1146.17 495 +v -2640 1150 495 +v -2640.76 1146.17 5 +v -2640.76 1146.17 5 +v -2640 1150 495 +v -2640 1150 5 +v -2640 1150 495 +v -2640.76 1153.83 495 +v -2640 1150 5 +v -2640 1150 5 +v -2640.76 1153.83 495 +v -2640.76 1153.83 5 +v -2640.76 1153.83 495 +v -2642.93 1157.07 495 +v -2640.76 1153.83 5 +v -2640.76 1153.83 5 +v -2642.93 1157.07 495 +v -2642.93 1157.07 5 +v -2642.93 1157.07 495 +v -2646.17 1159.24 495 +v -2642.93 1157.07 5 +v -2642.93 1157.07 5 +v -2646.17 1159.24 495 +v -2646.17 1159.24 5 +v -2646.17 1159.24 495 +v -2650 1160 495 +v -2646.17 1159.24 5 +v -2646.17 1159.24 5 +v -2650 1160 495 +v -2650 1160 5 +v -2650 1160 495 +v -2653.83 1159.24 495 +v -2650 1160 5 +v -2650 1160 5 +v -2653.83 1159.24 495 +v -2653.83 1159.24 5 +v -2653.83 1159.24 495 +v -2657.07 1157.07 495 +v -2653.83 1159.24 5 +v -2653.83 1159.24 5 +v -2657.07 1157.07 495 +v -2657.07 1157.07 5 +v -2657.07 1157.07 495 +v -2659.24 1153.83 495 +v -2657.07 1157.07 5 +v -2657.07 1157.07 5 +v -2659.24 1153.83 495 +v -2659.24 1153.83 5 +v -2659.24 1153.83 495 +v -2660 1150 495 +v -2659.24 1153.83 5 +v -2659.24 1153.83 5 +v -2660 1150 495 +v -2660 1150 5 +v -2360 1150 495 +v -2359.24 1146.17 495 +v -2360 1150 5 +v -2360 1150 5 +v -2359.24 1146.17 495 +v -2359.24 1146.17 5 +v -2359.24 1146.17 495 +v -2357.07 1142.93 495 +v -2359.24 1146.17 5 +v -2359.24 1146.17 5 +v -2357.07 1142.93 495 +v -2357.07 1142.93 5 +v -2357.07 1142.93 495 +v -2353.83 1140.76 495 +v -2357.07 1142.93 5 +v -2357.07 1142.93 5 +v -2353.83 1140.76 495 +v -2353.83 1140.76 5 +v -2353.83 1140.76 495 +v -2350 1140 495 +v -2353.83 1140.76 5 +v -2353.83 1140.76 5 +v -2350 1140 495 +v -2350 1140 5 +v -2350 1140 495 +v -2346.17 1140.76 495 +v -2350 1140 5 +v -2350 1140 5 +v -2346.17 1140.76 495 +v -2346.17 1140.76 5 +v -2346.17 1140.76 495 +v -2342.93 1142.93 495 +v -2346.17 1140.76 5 +v -2346.17 1140.76 5 +v -2342.93 1142.93 495 +v -2342.93 1142.93 5 +v -2342.93 1142.93 495 +v -2340.76 1146.17 495 +v -2342.93 1142.93 5 +v -2342.93 1142.93 5 +v -2340.76 1146.17 495 +v -2340.76 1146.17 5 +v -2340.76 1146.17 495 +v -2340 1150 495 +v -2340.76 1146.17 5 +v -2340.76 1146.17 5 +v -2340 1150 495 +v -2340 1150 5 +v -2340 1150 495 +v -2340.76 1153.83 495 +v -2340 1150 5 +v -2340 1150 5 +v -2340.76 1153.83 495 +v -2340.76 1153.83 5 +v -2340.76 1153.83 495 +v -2342.93 1157.07 495 +v -2340.76 1153.83 5 +v -2340.76 1153.83 5 +v -2342.93 1157.07 495 +v -2342.93 1157.07 5 +v -2342.93 1157.07 495 +v -2346.17 1159.24 495 +v -2342.93 1157.07 5 +v -2342.93 1157.07 5 +v -2346.17 1159.24 495 +v -2346.17 1159.24 5 +v -2346.17 1159.24 495 +v -2350 1160 495 +v -2346.17 1159.24 5 +v -2346.17 1159.24 5 +v -2350 1160 495 +v -2350 1160 5 +v -2350 1160 495 +v -2353.83 1159.24 495 +v -2350 1160 5 +v -2350 1160 5 +v -2353.83 1159.24 495 +v -2353.83 1159.24 5 +v -2353.83 1159.24 495 +v -2357.07 1157.07 495 +v -2353.83 1159.24 5 +v -2353.83 1159.24 5 +v -2357.07 1157.07 495 +v -2357.07 1157.07 5 +v -2357.07 1157.07 495 +v -2359.24 1153.83 495 +v -2357.07 1157.07 5 +v -2357.07 1157.07 5 +v -2359.24 1153.83 495 +v -2359.24 1153.83 5 +v -2359.24 1153.83 495 +v -2360 1150 495 +v -2359.24 1153.83 5 +v -2359.24 1153.83 5 +v -2360 1150 495 +v -2360 1150 5 +v -2360 1450 495 +v -2359.24 1446.17 495 +v -2360 1450 5 +v -2360 1450 5 +v -2359.24 1446.17 495 +v -2359.24 1446.17 5 +v -2359.24 1446.17 495 +v -2357.07 1442.93 495 +v -2359.24 1446.17 5 +v -2359.24 1446.17 5 +v -2357.07 1442.93 495 +v -2357.07 1442.93 5 +v -2357.07 1442.93 495 +v -2353.83 1440.76 495 +v -2357.07 1442.93 5 +v -2357.07 1442.93 5 +v -2353.83 1440.76 495 +v -2353.83 1440.76 5 +v -2353.83 1440.76 495 +v -2350 1440 495 +v -2353.83 1440.76 5 +v -2353.83 1440.76 5 +v -2350 1440 495 +v -2350 1440 5 +v -2350 1440 495 +v -2346.17 1440.76 495 +v -2350 1440 5 +v -2350 1440 5 +v -2346.17 1440.76 495 +v -2346.17 1440.76 5 +v -2346.17 1440.76 495 +v -2342.93 1442.93 495 +v -2346.17 1440.76 5 +v -2346.17 1440.76 5 +v -2342.93 1442.93 495 +v -2342.93 1442.93 5 +v -2342.93 1442.93 495 +v -2340.76 1446.17 495 +v -2342.93 1442.93 5 +v -2342.93 1442.93 5 +v -2340.76 1446.17 495 +v -2340.76 1446.17 5 +v -2340.76 1446.17 495 +v -2340 1450 495 +v -2340.76 1446.17 5 +v -2340.76 1446.17 5 +v -2340 1450 495 +v -2340 1450 5 +v -2340 1450 495 +v -2340.76 1453.83 495 +v -2340 1450 5 +v -2340 1450 5 +v -2340.76 1453.83 495 +v -2340.76 1453.83 5 +v -2340.76 1453.83 495 +v -2342.93 1457.07 495 +v -2340.76 1453.83 5 +v -2340.76 1453.83 5 +v -2342.93 1457.07 495 +v -2342.93 1457.07 5 +v -2342.93 1457.07 495 +v -2346.17 1459.24 495 +v -2342.93 1457.07 5 +v -2342.93 1457.07 5 +v -2346.17 1459.24 495 +v -2346.17 1459.24 5 +v -2346.17 1459.24 495 +v -2350 1460 495 +v -2346.17 1459.24 5 +v -2346.17 1459.24 5 +v -2350 1460 495 +v -2350 1460 5 +v -2350 1460 495 +v -2353.83 1459.24 495 +v -2350 1460 5 +v -2350 1460 5 +v -2353.83 1459.24 495 +v -2353.83 1459.24 5 +v -2353.83 1459.24 495 +v -2357.07 1457.07 495 +v -2353.83 1459.24 5 +v -2353.83 1459.24 5 +v -2357.07 1457.07 495 +v -2357.07 1457.07 5 +v -2357.07 1457.07 495 +v -2359.24 1453.83 495 +v -2357.07 1457.07 5 +v -2357.07 1457.07 5 +v -2359.24 1453.83 495 +v -2359.24 1453.83 5 +v -2359.24 1453.83 495 +v -2360 1450 495 +v -2359.24 1453.83 5 +v -2359.24 1453.83 5 +v -2360 1450 495 +v -2360 1450 5 +v -2660 1450 495 +v -2659.24 1446.17 495 +v -2660 1450 5 +v -2660 1450 5 +v -2659.24 1446.17 495 +v -2659.24 1446.17 5 +v -2659.24 1446.17 495 +v -2657.07 1442.93 495 +v -2659.24 1446.17 5 +v -2659.24 1446.17 5 +v -2657.07 1442.93 495 +v -2657.07 1442.93 5 +v -2657.07 1442.93 495 +v -2653.83 1440.76 495 +v -2657.07 1442.93 5 +v -2657.07 1442.93 5 +v -2653.83 1440.76 495 +v -2653.83 1440.76 5 +v -2653.83 1440.76 495 +v -2650 1440 495 +v -2653.83 1440.76 5 +v -2653.83 1440.76 5 +v -2650 1440 495 +v -2650 1440 5 +v -2650 1440 495 +v -2646.17 1440.76 495 +v -2650 1440 5 +v -2650 1440 5 +v -2646.17 1440.76 495 +v -2646.17 1440.76 5 +v -2646.17 1440.76 495 +v -2642.93 1442.93 495 +v -2646.17 1440.76 5 +v -2646.17 1440.76 5 +v -2642.93 1442.93 495 +v -2642.93 1442.93 5 +v -2642.93 1442.93 495 +v -2640.76 1446.17 495 +v -2642.93 1442.93 5 +v -2642.93 1442.93 5 +v -2640.76 1446.17 495 +v -2640.76 1446.17 5 +v -2640.76 1446.17 495 +v -2640 1450 495 +v -2640.76 1446.17 5 +v -2640.76 1446.17 5 +v -2640 1450 495 +v -2640 1450 5 +v -2640 1450 495 +v -2640.76 1453.83 495 +v -2640 1450 5 +v -2640 1450 5 +v -2640.76 1453.83 495 +v -2640.76 1453.83 5 +v -2640.76 1453.83 495 +v -2642.93 1457.07 495 +v -2640.76 1453.83 5 +v -2640.76 1453.83 5 +v -2642.93 1457.07 495 +v -2642.93 1457.07 5 +v -2642.93 1457.07 495 +v -2646.17 1459.24 495 +v -2642.93 1457.07 5 +v -2642.93 1457.07 5 +v -2646.17 1459.24 495 +v -2646.17 1459.24 5 +v -2646.17 1459.24 495 +v -2650 1460 495 +v -2646.17 1459.24 5 +v -2646.17 1459.24 5 +v -2650 1460 495 +v -2650 1460 5 +v -2650 1460 495 +v -2653.83 1459.24 495 +v -2650 1460 5 +v -2650 1460 5 +v -2653.83 1459.24 495 +v -2653.83 1459.24 5 +v -2653.83 1459.24 495 +v -2657.07 1457.07 495 +v -2653.83 1459.24 5 +v -2653.83 1459.24 5 +v -2657.07 1457.07 495 +v -2657.07 1457.07 5 +v -2657.07 1457.07 495 +v -2659.24 1453.83 495 +v -2657.07 1457.07 5 +v -2657.07 1457.07 5 +v -2659.24 1453.83 495 +v -2659.24 1453.83 5 +v -2659.24 1453.83 495 +v -2660 1450 495 +v -2659.24 1453.83 5 +v -2659.24 1453.83 5 +v -2660 1450 495 +v -2660 1450 5 +v -2300 1500 510 +v -2700 1500 510 +v -2300 1100 510 +v -2300 1100 510 +v -2700 1500 510 +v -2700 1100 510 +v -2700 1500 500 +v -2300 1500 500 +v -2700 1100 500 +v -2700 1100 500 +v -2300 1500 500 +v -2300 1100 500 +v -2700 1500 510 +v -2700 1500 500 +v -2700 1100 510 +v -2700 1100 510 +v -2700 1500 500 +v -2700 1100 500 +v -2300 1500 500 +v -2300 1500 510 +v -2300 1100 500 +v -2300 1100 500 +v -2300 1500 510 +v -2300 1100 510 +v -2300 1100 500 +v -2300 1100 510 +v -2700 1100 500 +v -2700 1100 500 +v -2300 1100 510 +v -2700 1100 510 +v -2300 1500 500 +v -2700 1500 500 +v -2300 1500 510 +v -2300 1500 510 +v -2700 1500 500 +v -2700 1500 510 +v -2560 1095 810 +v -2559.24 1091.17 810 +v -2560 1095 510 +v -2560 1095 510 +v -2559.24 1091.17 810 +v -2559.24 1091.17 510 +v -2559.24 1091.17 810 +v -2557.07 1087.93 810 +v -2559.24 1091.17 510 +v -2559.24 1091.17 510 +v -2557.07 1087.93 810 +v -2557.07 1087.93 510 +v -2557.07 1087.93 810 +v -2553.83 1085.76 810 +v -2557.07 1087.93 510 +v -2557.07 1087.93 510 +v -2553.83 1085.76 810 +v -2553.83 1085.76 510 +v -2553.83 1085.76 810 +v -2550 1085 810 +v -2553.83 1085.76 510 +v -2553.83 1085.76 510 +v -2550 1085 810 +v -2550 1085 510 +v -2550 1085 810 +v -2546.17 1085.76 810 +v -2550 1085 510 +v -2550 1085 510 +v -2546.17 1085.76 810 +v -2546.17 1085.76 510 +v -2546.17 1085.76 810 +v -2542.93 1087.93 810 +v -2546.17 1085.76 510 +v -2546.17 1085.76 510 +v -2542.93 1087.93 810 +v -2542.93 1087.93 510 +v -2542.93 1087.93 810 +v -2540.76 1091.17 810 +v -2542.93 1087.93 510 +v -2542.93 1087.93 510 +v -2540.76 1091.17 810 +v -2540.76 1091.17 510 +v -2540.76 1091.17 810 +v -2540 1095 810 +v -2540.76 1091.17 510 +v -2540.76 1091.17 510 +v -2540 1095 810 +v -2540 1095 510 +v -2540 1095 810 +v -2540.76 1098.83 810 +v -2540 1095 510 +v -2540 1095 510 +v -2540.76 1098.83 810 +v -2540.76 1098.83 510 +v -2540.76 1098.83 810 +v -2542.93 1102.07 810 +v -2540.76 1098.83 510 +v -2540.76 1098.83 510 +v -2542.93 1102.07 810 +v -2542.93 1102.07 510 +v -2542.93 1102.07 810 +v -2546.17 1104.24 810 +v -2542.93 1102.07 510 +v -2542.93 1102.07 510 +v -2546.17 1104.24 810 +v -2546.17 1104.24 510 +v -2546.17 1104.24 810 +v -2550 1105 810 +v -2546.17 1104.24 510 +v -2546.17 1104.24 510 +v -2550 1105 810 +v -2550 1105 510 +v -2550 1105 810 +v -2553.83 1104.24 810 +v -2550 1105 510 +v -2550 1105 510 +v -2553.83 1104.24 810 +v -2553.83 1104.24 510 +v -2553.83 1104.24 810 +v -2557.07 1102.07 810 +v -2553.83 1104.24 510 +v -2553.83 1104.24 510 +v -2557.07 1102.07 810 +v -2557.07 1102.07 510 +v -2557.07 1102.07 810 +v -2559.24 1098.83 810 +v -2557.07 1102.07 510 +v -2557.07 1102.07 510 +v -2559.24 1098.83 810 +v -2559.24 1098.83 510 +v -2559.24 1098.83 810 +v -2560 1095 810 +v -2559.24 1098.83 510 +v -2559.24 1098.83 510 +v -2560 1095 810 +v -2560 1095 510 +v -2460 1095 810 +v -2459.24 1091.17 810 +v -2460 1095 510 +v -2460 1095 510 +v -2459.24 1091.17 810 +v -2459.24 1091.17 510 +v -2459.24 1091.17 810 +v -2457.07 1087.93 810 +v -2459.24 1091.17 510 +v -2459.24 1091.17 510 +v -2457.07 1087.93 810 +v -2457.07 1087.93 510 +v -2457.07 1087.93 810 +v -2453.83 1085.76 810 +v -2457.07 1087.93 510 +v -2457.07 1087.93 510 +v -2453.83 1085.76 810 +v -2453.83 1085.76 510 +v -2453.83 1085.76 810 +v -2450 1085 810 +v -2453.83 1085.76 510 +v -2453.83 1085.76 510 +v -2450 1085 810 +v -2450 1085 510 +v -2450 1085 810 +v -2446.17 1085.76 810 +v -2450 1085 510 +v -2450 1085 510 +v -2446.17 1085.76 810 +v -2446.17 1085.76 510 +v -2446.17 1085.76 810 +v -2442.93 1087.93 810 +v -2446.17 1085.76 510 +v -2446.17 1085.76 510 +v -2442.93 1087.93 810 +v -2442.93 1087.93 510 +v -2442.93 1087.93 810 +v -2440.76 1091.17 810 +v -2442.93 1087.93 510 +v -2442.93 1087.93 510 +v -2440.76 1091.17 810 +v -2440.76 1091.17 510 +v -2440.76 1091.17 810 +v -2440 1095 810 +v -2440.76 1091.17 510 +v -2440.76 1091.17 510 +v -2440 1095 810 +v -2440 1095 510 +v -2440 1095 810 +v -2440.76 1098.83 810 +v -2440 1095 510 +v -2440 1095 510 +v -2440.76 1098.83 810 +v -2440.76 1098.83 510 +v -2440.76 1098.83 810 +v -2442.93 1102.07 810 +v -2440.76 1098.83 510 +v -2440.76 1098.83 510 +v -2442.93 1102.07 810 +v -2442.93 1102.07 510 +v -2442.93 1102.07 810 +v -2446.17 1104.24 810 +v -2442.93 1102.07 510 +v -2442.93 1102.07 510 +v -2446.17 1104.24 810 +v -2446.17 1104.24 510 +v -2446.17 1104.24 810 +v -2450 1105 810 +v -2446.17 1104.24 510 +v -2446.17 1104.24 510 +v -2450 1105 810 +v -2450 1105 510 +v -2450 1105 810 +v -2453.83 1104.24 810 +v -2450 1105 510 +v -2450 1105 510 +v -2453.83 1104.24 810 +v -2453.83 1104.24 510 +v -2453.83 1104.24 810 +v -2457.07 1102.07 810 +v -2453.83 1104.24 510 +v -2453.83 1104.24 510 +v -2457.07 1102.07 810 +v -2457.07 1102.07 510 +v -2457.07 1102.07 810 +v -2459.24 1098.83 810 +v -2457.07 1102.07 510 +v -2457.07 1102.07 510 +v -2459.24 1098.83 810 +v -2459.24 1098.83 510 +v -2459.24 1098.83 810 +v -2460 1095 810 +v -2459.24 1098.83 510 +v -2459.24 1098.83 510 +v -2460 1095 810 +v -2460 1095 510 +v -2300 1110 910 +v -2700 1110 910 +v -2300 1100 910 +v -2300 1100 910 +v -2700 1110 910 +v -2700 1100 910 +v -2700 1110 710 +v -2300 1110 710 +v -2700 1100 710 +v -2700 1100 710 +v -2300 1110 710 +v -2300 1100 710 +v -2700 1110 910 +v -2700 1110 710 +v -2700 1100 910 +v -2700 1100 910 +v -2700 1110 710 +v -2700 1100 710 +v -2300 1110 710 +v -2300 1110 910 +v -2300 1100 710 +v -2300 1100 710 +v -2300 1110 910 +v -2300 1100 910 +v -2300 1100 710 +v -2300 1100 910 +v -2700 1100 710 +v -2700 1100 710 +v -2300 1100 910 +v -2700 1100 910 +v -2300 1110 710 +v -2700 1110 710 +v -2300 1110 910 +v -2300 1110 910 +v -2700 1110 710 +v -2700 1110 910 +f 1 2 3 +f 4 5 6 +f 7 8 9 +f 10 11 12 +f 13 14 15 +f 16 17 18 +f 19 20 21 +f 22 23 24 +f 25 26 27 +f 28 29 30 +f 31 32 33 +f 34 35 36 +f 37 38 39 +f 40 41 42 +f 43 44 45 +f 46 47 48 +f 49 50 51 +f 52 53 54 +f 55 56 57 +f 58 59 60 +f 61 62 63 +f 64 65 66 +f 67 68 69 +f 70 71 72 +f 73 74 75 +f 76 77 78 +f 79 80 81 +f 82 83 84 +f 85 86 87 +f 88 89 90 +f 91 92 93 +f 94 95 96 +f 97 98 99 +f 100 101 102 +f 103 104 105 +f 106 107 108 +f 109 110 111 +f 112 113 114 +f 115 116 117 +f 118 119 120 +f 121 122 123 +f 124 125 126 +f 127 128 129 +f 130 131 132 +f 133 134 135 +f 136 137 138 +f 139 140 141 +f 142 143 144 +f 145 146 147 +f 148 149 150 +f 151 152 153 +f 154 155 156 +f 157 158 159 +f 160 161 162 +f 163 164 165 +f 166 167 168 +f 169 170 171 +f 172 173 174 +f 175 176 177 +f 178 179 180 +f 181 182 183 +f 184 185 186 +f 187 188 189 +f 190 191 192 +f 193 194 195 +f 196 197 198 +f 199 200 201 +f 202 203 204 +f 205 206 207 +f 208 209 210 +f 211 212 213 +f 214 215 216 +f 217 218 219 +f 220 221 222 +f 223 224 225 +f 226 227 228 +f 229 230 231 +f 232 233 234 +f 235 236 237 +f 238 239 240 +f 241 242 243 +f 244 245 246 +f 247 248 249 +f 250 251 252 +f 253 254 255 +f 256 257 258 +f 259 260 261 +f 262 263 264 +f 265 266 267 +f 268 269 270 +f 271 272 273 +f 274 275 276 +f 277 278 279 +f 280 281 282 +f 283 284 285 +f 286 287 288 +f 289 290 291 +f 292 293 294 +f 295 296 297 +f 298 299 300 +f 301 302 303 +f 304 305 306 +f 307 308 309 +f 310 311 312 +f 313 314 315 +f 316 317 318 +f 319 320 321 +f 322 323 324 +f 325 326 327 +f 328 329 330 +f 331 332 333 +f 334 335 336 +f 337 338 339 +f 340 341 342 +f 343 344 345 +f 346 347 348 +f 349 350 351 +f 352 353 354 +f 355 356 357 +f 358 359 360 +f 361 362 363 +f 364 365 366 +f 367 368 369 +f 370 371 372 +f 373 374 375 +f 376 377 378 +f 379 380 381 +f 382 383 384 +f 385 386 387 +f 388 389 390 +f 391 392 393 +f 394 395 396 +f 397 398 399 +f 400 401 402 +f 403 404 405 +f 406 407 408 +f 409 410 411 +f 412 413 414 +f 415 416 417 +f 418 419 420 +f 421 422 423 +f 424 425 426 +f 427 428 429 +f 430 431 432 +f 433 434 435 +f 436 437 438 +f 439 440 441 +f 442 443 444 +f 445 446 447 +f 448 449 450 +f 451 452 453 +f 454 455 456 +f 457 458 459 +f 460 461 462 +f 463 464 465 +f 466 467 468 +f 469 470 471 +f 472 473 474 +f 475 476 477 +f 478 479 480 +f 481 482 483 +f 484 485 486 +f 487 488 489 +f 490 491 492 +f 493 494 495 +f 496 497 498 +f 499 500 501 +f 502 503 504 +f 505 506 507 +f 508 509 510 +f 511 512 513 +f 514 515 516 +f 517 518 519 +f 520 521 522 +f 523 524 525 +f 526 527 528 +f 529 530 531 +f 532 533 534 +f 535 536 537 +f 538 539 540 +f 541 542 543 +f 544 545 546 +f 547 548 549 +f 550 551 552 +f 553 554 555 +f 556 557 558 +f 559 560 561 +f 562 563 564 +f 565 566 567 +f 568 569 570 +f 571 572 573 +f 574 575 576 +f 577 578 579 +f 580 581 582 +f 583 584 585 +f 586 587 588 +f 589 590 591 +f 592 593 594 +f 595 596 597 +f 598 599 600 +f 601 602 603 +f 604 605 606 +f 607 608 609 +f 610 611 612 +f 613 614 615 +f 616 617 618 +f 619 620 621 +f 622 623 624 +f 625 626 627 +f 628 629 630 +f 631 632 633 +f 634 635 636 +f 637 638 639 +f 640 641 642 +f 643 644 645 +f 646 647 648 +f 649 650 651 +f 652 653 654 +f 655 656 657 +f 658 659 660 +f 661 662 663 +f 664 665 666 +f 667 668 669 +f 670 671 672 +f 673 674 675 +f 676 677 678 +f 679 680 681 +f 682 683 684 +f 685 686 687 +f 688 689 690 +f 691 692 693 +f 694 695 696 +f 697 698 699 +f 700 701 702 +f 703 704 705 +f 706 707 708 +f 709 710 711 +f 712 713 714 +f 715 716 717 +f 718 719 720 +f 721 722 723 +f 724 725 726 +f 727 728 729 +f 730 731 732 +f 733 734 735 +f 736 737 738 +f 739 740 741 +f 742 743 744 +f 745 746 747 +f 748 749 750 +f 751 752 753 +f 754 755 756 +f 757 758 759 +f 760 761 762 +f 763 764 765 +f 766 767 768 +f 769 770 771 +f 772 773 774 +f 775 776 777 +f 778 779 780 +f 781 782 783 +f 784 785 786 +f 787 788 789 +f 790 791 792 +f 793 794 795 +f 796 797 798 +f 799 800 801 +f 802 803 804 +f 805 806 807 +f 808 809 810 +f 811 812 813 +f 814 815 816 +f 817 818 819 +f 820 821 822 +f 823 824 825 +f 826 827 828 +f 829 830 831 +f 832 833 834 +f 835 836 837 +f 838 839 840 +f 841 842 843 +f 844 845 846 +f 847 848 849 +f 850 851 852 +f 853 854 855 +f 856 857 858 +f 859 860 861 +f 862 863 864 +f 865 866 867 +f 868 869 870 +f 871 872 873 +f 874 875 876 +f 877 878 879 +f 880 881 882 +f 883 884 885 +f 886 887 888 +f 889 890 891 +f 892 893 894 +f 895 896 897 +f 898 899 900 +f 901 902 903 +f 904 905 906 +f 907 908 909 +f 910 911 912 +f 913 914 915 +f 916 917 918 +f 919 920 921 +f 922 923 924 +f 925 926 927 +f 928 929 930 +f 931 932 933 +f 934 935 936 +f 937 938 939 +f 940 941 942 +f 943 944 945 +f 946 947 948 +f 949 950 951 +f 952 953 954 +f 955 956 957 +f 958 959 960 +f 961 962 963 +f 964 965 966 +f 967 968 969 +f 970 971 972 +f 973 974 975 +f 976 977 978 +f 979 980 981 +f 982 983 984 +f 985 986 987 +f 988 989 990 +f 991 992 993 +f 994 995 996 +f 997 998 999 +f 1000 1001 1002 +f 1003 1004 1005 +f 1006 1007 1008 +f 1009 1010 1011 +f 1012 1013 1014 +f 1015 1016 1017 +f 1018 1019 1020 +f 1021 1022 1023 +f 1024 1025 1026 +f 1027 1028 1029 +f 1030 1031 1032 +f 1033 1034 1035 +f 1036 1037 1038 +f 1039 1040 1041 +f 1042 1043 1044 +f 1045 1046 1047 +f 1048 1049 1050 +f 1051 1052 1053 +f 1054 1055 1056 +f 1057 1058 1059 +f 1060 1061 1062 +f 1063 1064 1065 +f 1066 1067 1068 +f 1069 1070 1071 +f 1072 1073 1074 +f 1075 1076 1077 +f 1078 1079 1080 +f 1081 1082 1083 +f 1084 1085 1086 +f 1087 1088 1089 +f 1090 1091 1092 +f 1093 1094 1095 +f 1096 1097 1098 +f 1099 1100 1101 +f 1102 1103 1104 +f 1105 1106 1107 +f 1108 1109 1110 +f 1111 1112 1113 +f 1114 1115 1116 +f 1117 1118 1119 +f 1120 1121 1122 +f 1123 1124 1125 +f 1126 1127 1128 +f 1129 1130 1131 +f 1132 1133 1134 +f 1135 1136 1137 +f 1138 1139 1140 +f 1141 1142 1143 +f 1144 1145 1146 +f 1147 1148 1149 +f 1150 1151 1152 +f 1153 1154 1155 +f 1156 1157 1158 +f 1159 1160 1161 +f 1162 1163 1164 +f 1165 1166 1167 +f 1168 1169 1170 +f 1171 1172 1173 +f 1174 1175 1176 +f 1177 1178 1179 +f 1180 1181 1182 +f 1183 1184 1185 +f 1186 1187 1188 +f 1189 1190 1191 +f 1192 1193 1194 +f 1195 1196 1197 +f 1198 1199 1200 +f 1201 1202 1203 +f 1204 1205 1206 +f 1207 1208 1209 +f 1210 1211 1212 +f 1213 1214 1215 +f 1216 1217 1218 +f 1219 1220 1221 +f 1222 1223 1224 +f 1225 1226 1227 +f 1228 1229 1230 +f 1231 1232 1233 +f 1234 1235 1236 +f 1237 1238 1239 +f 1240 1241 1242 +f 1243 1244 1245 +f 1246 1247 1248 +f 1249 1250 1251 +f 1252 1253 1254 +f 1255 1256 1257 +f 1258 1259 1260 +f 1261 1262 1263 +f 1264 1265 1266 +f 1267 1268 1269 +f 1270 1271 1272 +f 1273 1274 1275 +f 1276 1277 1278 +f 1279 1280 1281 +f 1282 1283 1284 +f 1285 1286 1287 +f 1288 1289 1290 +f 1291 1292 1293 +f 1294 1295 1296 +f 1297 1298 1299 +f 1300 1301 1302 +f 1303 1304 1305 +f 1306 1307 1308 +f 1309 1310 1311 +f 1312 1313 1314 +f 1315 1316 1317 +f 1318 1319 1320 +f 1321 1322 1323 +f 1324 1325 1326 +f 1327 1328 1329 +f 1330 1331 1332 +f 1333 1334 1335 +f 1336 1337 1338 +f 1339 1340 1341 +f 1342 1343 1344 +f 1345 1346 1347 +f 1348 1349 1350 +f 1351 1352 1353 +f 1354 1355 1356 +f 1357 1358 1359 +f 1360 1361 1362 +f 1363 1364 1365 +f 1366 1367 1368 +f 1369 1370 1371 +f 1372 1373 1374 +f 1375 1376 1377 +f 1378 1379 1380 +f 1381 1382 1383 +f 1384 1385 1386 +f 1387 1388 1389 +f 1390 1391 1392 +f 1393 1394 1395 +f 1396 1397 1398 +f 1399 1400 1401 +f 1402 1403 1404 +f 1405 1406 1407 +f 1408 1409 1410 +f 1411 1412 1413 +f 1414 1415 1416 +f 1417 1418 1419 +f 1420 1421 1422 +f 1423 1424 1425 +f 1426 1427 1428 +f 1429 1430 1431 +f 1432 1433 1434 +f 1435 1436 1437 +f 1438 1439 1440 +f 1441 1442 1443 +f 1444 1445 1446 +f 1447 1448 1449 +f 1450 1451 1452 +f 1453 1454 1455 +f 1456 1457 1458 +f 1459 1460 1461 +f 1462 1463 1464 +f 1465 1466 1467 +f 1468 1469 1470 +f 1471 1472 1473 +f 1474 1475 1476 +f 1477 1478 1479 +f 1480 1481 1482 +f 1483 1484 1485 +f 1486 1487 1488 +f 1489 1490 1491 +f 1492 1493 1494 +f 1495 1496 1497 +f 1498 1499 1500 +f 1501 1502 1503 +f 1504 1505 1506 +f 1507 1508 1509 +f 1510 1511 1512 +f 1513 1514 1515 +f 1516 1517 1518 +f 1519 1520 1521 +f 1522 1523 1524 +f 1525 1526 1527 +f 1528 1529 1530 +f 1531 1532 1533 +f 1534 1535 1536 +f 1537 1538 1539 +f 1540 1541 1542 +f 1543 1544 1545 +f 1546 1547 1548 +f 1549 1550 1551 +f 1552 1553 1554 +f 1555 1556 1557 +f 1558 1559 1560 +f 1561 1562 1563 +f 1564 1565 1566 +f 1567 1568 1569 +f 1570 1571 1572 +f 1573 1574 1575 +f 1576 1577 1578 +f 1579 1580 1581 +f 1582 1583 1584 +f 1585 1586 1587 +f 1588 1589 1590 +f 1591 1592 1593 +f 1594 1595 1596 +f 1597 1598 1599 +f 1600 1601 1602 +f 1603 1604 1605 +f 1606 1607 1608 +f 1609 1610 1611 +f 1612 1613 1614 +f 1615 1616 1617 +f 1618 1619 1620 +f 1621 1622 1623 +f 1624 1625 1626 +f 1627 1628 1629 +f 1630 1631 1632 +f 1633 1634 1635 +f 1636 1637 1638 +f 1639 1640 1641 +f 1642 1643 1644 +f 1645 1646 1647 +f 1648 1649 1650 +f 1651 1652 1653 +f 1654 1655 1656 +f 1657 1658 1659 +f 1660 1661 1662 +f 1663 1664 1665 +f 1666 1667 1668 +f 1669 1670 1671 +f 1672 1673 1674 +f 1675 1676 1677 +f 1678 1679 1680 +f 1681 1682 1683 +f 1684 1685 1686 +f 1687 1688 1689 +f 1690 1691 1692 +f 1693 1694 1695 +f 1696 1697 1698 +f 1699 1700 1701 +f 1702 1703 1704 +f 1705 1706 1707 +f 1708 1709 1710 +f 1711 1712 1713 +f 1714 1715 1716 +f 1717 1718 1719 +f 1720 1721 1722 +f 1723 1724 1725 +f 1726 1727 1728 +f 1729 1730 1731 +f 1732 1733 1734 +f 1735 1736 1737 +f 1738 1739 1740 +f 1741 1742 1743 +f 1744 1745 1746 +f 1747 1748 1749 +f 1750 1751 1752 +f 1753 1754 1755 +f 1756 1757 1758 +f 1759 1760 1761 +f 1762 1763 1764 +f 1765 1766 1767 +f 1768 1769 1770 +f 1771 1772 1773 +f 1774 1775 1776 +f 1777 1778 1779 +f 1780 1781 1782 +f 1783 1784 1785 +f 1786 1787 1788 +f 1789 1790 1791 +f 1792 1793 1794 +f 1795 1796 1797 +f 1798 1799 1800 +f 1801 1802 1803 +f 1804 1805 1806 +f 1807 1808 1809 +f 1810 1811 1812 +f 1813 1814 1815 +f 1816 1817 1818 +f 1819 1820 1821 +f 1822 1823 1824 +f 1825 1826 1827 +f 1828 1829 1830 +f 1831 1832 1833 +f 1834 1835 1836 +f 1837 1838 1839 +f 1840 1841 1842 +f 1843 1844 1845 +f 1846 1847 1848 +f 1849 1850 1851 +f 1852 1853 1854 +f 1855 1856 1857 +f 1858 1859 1860 +f 1861 1862 1863 +f 1864 1865 1866 +f 1867 1868 1869 +f 1870 1871 1872 +f 1873 1874 1875 +f 1876 1877 1878 +f 1879 1880 1881 +f 1882 1883 1884 +f 1885 1886 1887 +f 1888 1889 1890 +f 1891 1892 1893 +f 1894 1895 1896 +f 1897 1898 1899 +f 1900 1901 1902 +f 1903 1904 1905 +f 1906 1907 1908 +f 1909 1910 1911 +f 1912 1913 1914 +f 1915 1916 1917 +f 1918 1919 1920 +f 1921 1922 1923 +f 1924 1925 1926 +f 1927 1928 1929 +f 1930 1931 1932 +f 1933 1934 1935 +f 1936 1937 1938 +f 1939 1940 1941 +f 1942 1943 1944 +f 1945 1946 1947 +f 1948 1949 1950 +f 1951 1952 1953 +f 1954 1955 1956 +f 1957 1958 1959 +f 1960 1961 1962 +f 1963 1964 1965 +f 1966 1967 1968 +f 1969 1970 1971 +f 1972 1973 1974 +f 1975 1976 1977 +f 1978 1979 1980 +f 1981 1982 1983 +f 1984 1985 1986 +f 1987 1988 1989 +f 1990 1991 1992 +f 1993 1994 1995 +f 1996 1997 1998 +f 1999 2000 2001 +f 2002 2003 2004 +f 2005 2006 2007 +f 2008 2009 2010 +f 2011 2012 2013 +f 2014 2015 2016 +f 2017 2018 2019 +f 2020 2021 2022 +f 2023 2024 2025 +f 2026 2027 2028 +f 2029 2030 2031 +f 2032 2033 2034 +f 2035 2036 2037 +f 2038 2039 2040 +f 2041 2042 2043 +f 2044 2045 2046 +f 2047 2048 2049 +f 2050 2051 2052 +f 2053 2054 2055 +f 2056 2057 2058 +f 2059 2060 2061 +f 2062 2063 2064 +f 2065 2066 2067 +f 2068 2069 2070 +f 2071 2072 2073 +f 2074 2075 2076 +f 2077 2078 2079 +f 2080 2081 2082 +f 2083 2084 2085 +f 2086 2087 2088 +f 2089 2090 2091 +f 2092 2093 2094 +f 2095 2096 2097 +f 2098 2099 2100 +f 2101 2102 2103 +f 2104 2105 2106 +f 2107 2108 2109 +f 2110 2111 2112 +f 2113 2114 2115 +f 2116 2117 2118 +f 2119 2120 2121 +f 2122 2123 2124 +f 2125 2126 2127 +f 2128 2129 2130 +f 2131 2132 2133 +f 2134 2135 2136 +f 2137 2138 2139 +f 2140 2141 2142 +f 2143 2144 2145 +f 2146 2147 2148 +f 2149 2150 2151 +f 2152 2153 2154 +f 2155 2156 2157 +f 2158 2159 2160 +f 2161 2162 2163 +f 2164 2165 2166 +f 2167 2168 2169 +f 2170 2171 2172 +f 2173 2174 2175 +f 2176 2177 2178 +f 2179 2180 2181 +f 2182 2183 2184 +f 2185 2186 2187 +f 2188 2189 2190 +f 2191 2192 2193 +f 2194 2195 2196 +f 2197 2198 2199 +f 2200 2201 2202 +f 2203 2204 2205 +f 2206 2207 2208 +f 2209 2210 2211 +f 2212 2213 2214 +f 2215 2216 2217 +f 2218 2219 2220 +f 2221 2222 2223 +f 2224 2225 2226 +f 2227 2228 2229 +f 2230 2231 2232 +f 2233 2234 2235 +f 2236 2237 2238 +f 2239 2240 2241 +f 2242 2243 2244 +f 2245 2246 2247 +f 2248 2249 2250 +f 2251 2252 2253 +f 2254 2255 2256 +f 2257 2258 2259 +f 2260 2261 2262 +f 2263 2264 2265 +f 2266 2267 2268 +f 2269 2270 2271 +f 2272 2273 2274 +f 2275 2276 2277 +f 2278 2279 2280 +f 2281 2282 2283 +f 2284 2285 2286 +f 2287 2288 2289 +f 2290 2291 2292 +f 2293 2294 2295 +f 2296 2297 2298 +f 2299 2300 2301 +f 2302 2303 2304 +f 2305 2306 2307 +f 2308 2309 2310 +f 2311 2312 2313 +f 2314 2315 2316 +f 2317 2318 2319 +f 2320 2321 2322 +f 2323 2324 2325 +f 2326 2327 2328 +f 2329 2330 2331 +f 2332 2333 2334 +f 2335 2336 2337 +f 2338 2339 2340 +f 2341 2342 2343 +f 2344 2345 2346 +f 2347 2348 2349 +f 2350 2351 2352 +f 2353 2354 2355 +f 2356 2357 2358 +f 2359 2360 2361 +f 2362 2363 2364 +f 2365 2366 2367 +f 2368 2369 2370 +f 2371 2372 2373 +f 2374 2375 2376 +f 2377 2378 2379 +f 2380 2381 2382 +f 2383 2384 2385 +f 2386 2387 2388 +f 2389 2390 2391 +f 2392 2393 2394 +f 2395 2396 2397 +f 2398 2399 2400 +f 2401 2402 2403 +f 2404 2405 2406 +f 2407 2408 2409 +f 2410 2411 2412 +f 2413 2414 2415 +f 2416 2417 2418 +f 2419 2420 2421 +f 2422 2423 2424 +f 2425 2426 2427 +f 2428 2429 2430 +f 2431 2432 2433 +f 2434 2435 2436 +f 2437 2438 2439 +f 2440 2441 2442 +f 2443 2444 2445 +f 2446 2447 2448 +f 2449 2450 2451 +f 2452 2453 2454 +f 2455 2456 2457 +f 2458 2459 2460 +f 2461 2462 2463 +f 2464 2465 2466 +f 2467 2468 2469 +f 2470 2471 2472 +f 2473 2474 2475 +f 2476 2477 2478 +f 2479 2480 2481 +f 2482 2483 2484 +f 2485 2486 2487 +f 2488 2489 2490 +f 2491 2492 2493 +f 2494 2495 2496 +f 2497 2498 2499 +f 2500 2501 2502 +f 2503 2504 2505 +f 2506 2507 2508 +f 2509 2510 2511 +f 2512 2513 2514 +f 2515 2516 2517 +f 2518 2519 2520 +f 2521 2522 2523 +f 2524 2525 2526 +f 2527 2528 2529 +f 2530 2531 2532 +f 2533 2534 2535 +f 2536 2537 2538 +f 2539 2540 2541 +f 2542 2543 2544 +f 2545 2546 2547 +f 2548 2549 2550 +f 2551 2552 2553 +f 2554 2555 2556 +f 2557 2558 2559 +f 2560 2561 2562 +f 2563 2564 2565 +f 2566 2567 2568 +f 2569 2570 2571 +f 2572 2573 2574 +f 2575 2576 2577 +f 2578 2579 2580 +f 2581 2582 2583 +f 2584 2585 2586 +f 2587 2588 2589 +f 2590 2591 2592 +f 2593 2594 2595 +f 2596 2597 2598 +f 2599 2600 2601 +f 2602 2603 2604 +f 2605 2606 2607 +f 2608 2609 2610 +f 2611 2612 2613 +f 2614 2615 2616 +f 2617 2618 2619 +f 2620 2621 2622 +f 2623 2624 2625 +f 2626 2627 2628 +f 2629 2630 2631 +f 2632 2633 2634 +f 2635 2636 2637 +f 2638 2639 2640 +f 2641 2642 2643 +f 2644 2645 2646 +f 2647 2648 2649 +f 2650 2651 2652 +f 2653 2654 2655 +f 2656 2657 2658 +f 2659 2660 2661 +f 2662 2663 2664 +f 2665 2666 2667 +f 2668 2669 2670 +f 2671 2672 2673 +f 2674 2675 2676 +f 2677 2678 2679 +f 2680 2681 2682 +f 2683 2684 2685 +f 2686 2687 2688 +f 2689 2690 2691 +f 2692 2693 2694 +f 2695 2696 2697 +f 2698 2699 2700 +f 2701 2702 2703 +f 2704 2705 2706 +f 2707 2708 2709 +f 2710 2711 2712 +f 2713 2714 2715 +f 2716 2717 2718 +f 2719 2720 2721 +f 2722 2723 2724 +f 2725 2726 2727 +f 2728 2729 2730 +f 2731 2732 2733 +f 2734 2735 2736 +f 2737 2738 2739 +f 2740 2741 2742 +f 2743 2744 2745 +f 2746 2747 2748 +f 2749 2750 2751 +f 2752 2753 2754 +f 2755 2756 2757 +f 2758 2759 2760 +f 2761 2762 2763 +f 2764 2765 2766 +f 2767 2768 2769 +f 2770 2771 2772 +f 2773 2774 2775 +f 2776 2777 2778 +f 2779 2780 2781 +f 2782 2783 2784 +f 2785 2786 2787 +f 2788 2789 2790 +f 2791 2792 2793 +f 2794 2795 2796 +f 2797 2798 2799 +f 2800 2801 2802 +f 2803 2804 2805 +f 2806 2807 2808 +f 2809 2810 2811 +f 2812 2813 2814 +f 2815 2816 2817 +f 2818 2819 2820 +f 2821 2822 2823 +f 2824 2825 2826 +f 2827 2828 2829 +f 2830 2831 2832 +f 2833 2834 2835 +f 2836 2837 2838 +f 2839 2840 2841 +f 2842 2843 2844 +f 2845 2846 2847 +f 2848 2849 2850 +f 2851 2852 2853 +f 2854 2855 2856 +f 2857 2858 2859 +f 2860 2861 2862 +f 2863 2864 2865 +f 2866 2867 2868 +f 2869 2870 2871 +f 2872 2873 2874 +f 2875 2876 2877 +f 2878 2879 2880 +f 2881 2882 2883 +f 2884 2885 2886 +f 2887 2888 2889 +f 2890 2891 2892 +f 2893 2894 2895 +f 2896 2897 2898 +f 2899 2900 2901 +f 2902 2903 2904 +f 2905 2906 2907 +f 2908 2909 2910 +f 2911 2912 2913 +f 2914 2915 2916 +f 2917 2918 2919 +f 2920 2921 2922 +f 2923 2924 2925 +f 2926 2927 2928 +f 2929 2930 2931 +f 2932 2933 2934 +f 2935 2936 2937 +f 2938 2939 2940 +f 2941 2942 2943 +f 2944 2945 2946 +f 2947 2948 2949 +f 2950 2951 2952 +f 2953 2954 2955 +f 2956 2957 2958 +f 2959 2960 2961 +f 2962 2963 2964 +f 2965 2966 2967 +f 2968 2969 2970 +f 2971 2972 2973 +f 2974 2975 2976 +f 2977 2978 2979 +f 2980 2981 2982 +f 2983 2984 2985 +f 2986 2987 2988 +f 2989 2990 2991 +f 2992 2993 2994 +f 2995 2996 2997 +f 2998 2999 3000 +f 3001 3002 3003 +f 3004 3005 3006 +f 3007 3008 3009 +f 3010 3011 3012 +f 3013 3014 3015 +f 3016 3017 3018 +f 3019 3020 3021 +f 3022 3023 3024 +f 3025 3026 3027 +f 3028 3029 3030 +f 3031 3032 3033 +f 3034 3035 3036 +f 3037 3038 3039 +f 3040 3041 3042 +f 3043 3044 3045 +f 3046 3047 3048 +f 3049 3050 3051 +f 3052 3053 3054 +f 3055 3056 3057 +f 3058 3059 3060 +f 3061 3062 3063 +f 3064 3065 3066 +f 3067 3068 3069 +f 3070 3071 3072 +f 3073 3074 3075 +f 3076 3077 3078 +f 3079 3080 3081 +f 3082 3083 3084 +f 3085 3086 3087 +f 3088 3089 3090 +f 3091 3092 3093 +f 3094 3095 3096 +f 3097 3098 3099 +f 3100 3101 3102 +f 3103 3104 3105 +f 3106 3107 3108 +f 3109 3110 3111 +f 3112 3113 3114 +f 3115 3116 3117 +f 3118 3119 3120 +f 3121 3122 3123 +f 3124 3125 3126 +f 3127 3128 3129 +f 3130 3131 3132 +f 3133 3134 3135 +f 3136 3137 3138 +f 3139 3140 3141 +f 3142 3143 3144 +f 3145 3146 3147 +f 3148 3149 3150 +f 3151 3152 3153 +f 3154 3155 3156 +f 3157 3158 3159 +f 3160 3161 3162 +f 3163 3164 3165 +f 3166 3167 3168 +f 3169 3170 3171 +f 3172 3173 3174 +f 3175 3176 3177 +f 3178 3179 3180 +f 3181 3182 3183 +f 3184 3185 3186 +f 3187 3188 3189 +f 3190 3191 3192 +f 3193 3194 3195 +f 3196 3197 3198 +f 3199 3200 3201 +f 3202 3203 3204 +f 3205 3206 3207 +f 3208 3209 3210 +f 3211 3212 3213 +f 3214 3215 3216 +f 3217 3218 3219 +f 3220 3221 3222 +f 3223 3224 3225 +f 3226 3227 3228 +f 3229 3230 3231 +f 3232 3233 3234 +f 3235 3236 3237 +f 3238 3239 3240 +f 3241 3242 3243 +f 3244 3245 3246 +f 3247 3248 3249 +f 3250 3251 3252 +f 3253 3254 3255 +f 3256 3257 3258 +f 3259 3260 3261 +f 3262 3263 3264 +f 3265 3266 3267 +f 3268 3269 3270 +f 3271 3272 3273 +f 3274 3275 3276 +f 3277 3278 3279 +f 3280 3281 3282 +f 3283 3284 3285 +f 3286 3287 3288 +f 3289 3290 3291 +f 3292 3293 3294 +f 3295 3296 3297 +f 3298 3299 3300 +f 3301 3302 3303 +f 3304 3305 3306 +f 3307 3308 3309 +f 3310 3311 3312 +f 3313 3314 3315 +f 3316 3317 3318 +f 3319 3320 3321 +f 3322 3323 3324 +f 3325 3326 3327 +f 3328 3329 3330 +f 3331 3332 3333 +f 3334 3335 3336 +f 3337 3338 3339 +f 3340 3341 3342 +f 3343 3344 3345 +f 3346 3347 3348 +f 3349 3350 3351 +f 3352 3353 3354 +f 3355 3356 3357 +f 3358 3359 3360 +f 3361 3362 3363 +f 3364 3365 3366 +f 3367 3368 3369 +f 3370 3371 3372 +f 3373 3374 3375 +f 3376 3377 3378 +f 3379 3380 3381 +f 3382 3383 3384 +f 3385 3386 3387 +f 3388 3389 3390 +f 3391 3392 3393 +f 3394 3395 3396 +f 3397 3398 3399 +f 3400 3401 3402 +f 3403 3404 3405 +f 3406 3407 3408 +f 3409 3410 3411 +f 3412 3413 3414 +f 3415 3416 3417 +f 3418 3419 3420 +f 3421 3422 3423 +f 3424 3425 3426 +f 3427 3428 3429 +f 3430 3431 3432 +f 3433 3434 3435 +f 3436 3437 3438 +f 3439 3440 3441 +f 3442 3443 3444 +f 3445 3446 3447 +f 3448 3449 3450 +f 3451 3452 3453 +f 3454 3455 3456 +f 3457 3458 3459 +f 3460 3461 3462 +f 3463 3464 3465 +f 3466 3467 3468 +f 3469 3470 3471 +f 3472 3473 3474 +f 3475 3476 3477 +f 3478 3479 3480 +f 3481 3482 3483 +f 3484 3485 3486 +f 3487 3488 3489 +f 3490 3491 3492 +f 3493 3494 3495 +f 3496 3497 3498 +f 3499 3500 3501 +f 3502 3503 3504 +f 3505 3506 3507 +f 3508 3509 3510 +f 3511 3512 3513 +f 3514 3515 3516 +f 3517 3518 3519 +f 3520 3521 3522 +f 3523 3524 3525 +f 3526 3527 3528 +f 3529 3530 3531 +f 3532 3533 3534 +f 3535 3536 3537 +f 3538 3539 3540 +f 3541 3542 3543 +f 3544 3545 3546 +f 3547 3548 3549 +f 3550 3551 3552 +f 3553 3554 3555 +f 3556 3557 3558 +f 3559 3560 3561 +f 3562 3563 3564 +f 3565 3566 3567 +f 3568 3569 3570 +f 3571 3572 3573 +f 3574 3575 3576 +f 3577 3578 3579 +f 3580 3581 3582 +f 3583 3584 3585 +f 3586 3587 3588 +f 3589 3590 3591 +f 3592 3593 3594 +f 3595 3596 3597 +f 3598 3599 3600 +f 3601 3602 3603 +f 3604 3605 3606 +f 3607 3608 3609 +f 3610 3611 3612 +f 3613 3614 3615 +f 3616 3617 3618 +f 3619 3620 3621 +f 3622 3623 3624 +f 3625 3626 3627 +f 3628 3629 3630 +f 3631 3632 3633 +f 3634 3635 3636 +f 3637 3638 3639 +f 3640 3641 3642 +f 3643 3644 3645 +f 3646 3647 3648 +f 3649 3650 3651 +f 3652 3653 3654 +f 3655 3656 3657 +f 3658 3659 3660 +f 3661 3662 3663 +f 3664 3665 3666 +f 3667 3668 3669 +f 3670 3671 3672 +f 3673 3674 3675 +f 3676 3677 3678 +f 3679 3680 3681 +f 3682 3683 3684 +f 3685 3686 3687 +f 3688 3689 3690 +f 3691 3692 3693 +f 3694 3695 3696 +f 3697 3698 3699 +f 3700 3701 3702 +f 3703 3704 3705 +f 3706 3707 3708 +f 3709 3710 3711 +f 3712 3713 3714 +f 3715 3716 3717 +f 3718 3719 3720 +f 3721 3722 3723 +f 3724 3725 3726 +f 3727 3728 3729 +f 3730 3731 3732 +f 3733 3734 3735 +f 3736 3737 3738 +f 3739 3740 3741 +f 3742 3743 3744 +f 3745 3746 3747 +f 3748 3749 3750 +f 3751 3752 3753 +f 3754 3755 3756 +f 3757 3758 3759 +f 3760 3761 3762 +f 3763 3764 3765 +f 3766 3767 3768 +f 3769 3770 3771 +f 3772 3773 3774 +f 3775 3776 3777 +f 3778 3779 3780 +f 3781 3782 3783 +f 3784 3785 3786 +f 3787 3788 3789 +f 3790 3791 3792 +f 3793 3794 3795 +f 3796 3797 3798 +f 3799 3800 3801 +f 3802 3803 3804 +f 3805 3806 3807 +f 3808 3809 3810 +f 3811 3812 3813 +f 3814 3815 3816 +f 3817 3818 3819 +f 3820 3821 3822 +f 3823 3824 3825 +f 3826 3827 3828 +f 3829 3830 3831 +f 3832 3833 3834 +f 3835 3836 3837 +f 3838 3839 3840 +f 3841 3842 3843 +f 3844 3845 3846 +f 3847 3848 3849 +f 3850 3851 3852 +f 3853 3854 3855 +f 3856 3857 3858 +f 3859 3860 3861 +f 3862 3863 3864 +f 3865 3866 3867 +f 3868 3869 3870 +f 3871 3872 3873 +f 3874 3875 3876 +f 3877 3878 3879 +f 3880 3881 3882 +f 3883 3884 3885 +f 3886 3887 3888 +f 3889 3890 3891 +f 3892 3893 3894 +f 3895 3896 3897 +f 3898 3899 3900 +f 3901 3902 3903 +f 3904 3905 3906 +f 3907 3908 3909 +f 3910 3911 3912 +f 3913 3914 3915 +f 3916 3917 3918 +f 3919 3920 3921 +f 3922 3923 3924 +f 3925 3926 3927 +f 3928 3929 3930 +f 3931 3932 3933 +f 3934 3935 3936 +f 3937 3938 3939 +f 3940 3941 3942 +f 3943 3944 3945 +f 3946 3947 3948 +f 3949 3950 3951 +f 3952 3953 3954 +f 3955 3956 3957 +f 3958 3959 3960 +f 3961 3962 3963 +f 3964 3965 3966 +f 3967 3968 3969 +f 3970 3971 3972 +f 3973 3974 3975 +f 3976 3977 3978 +f 3979 3980 3981 +f 3982 3983 3984 +f 3985 3986 3987 +f 3988 3989 3990 +f 3991 3992 3993 +f 3994 3995 3996 +f 3997 3998 3999 +f 4000 4001 4002 +f 4003 4004 4005 +f 4006 4007 4008 +f 4009 4010 4011 +f 4012 4013 4014 +f 4015 4016 4017 +f 4018 4019 4020 +f 4021 4022 4023 +f 4024 4025 4026 +f 4027 4028 4029 +f 4030 4031 4032 +f 4033 4034 4035 +f 4036 4037 4038 +f 4039 4040 4041 +f 4042 4043 4044 +f 4045 4046 4047 +f 4048 4049 4050 +f 4051 4052 4053 +f 4054 4055 4056 +f 4057 4058 4059 +f 4060 4061 4062 +f 4063 4064 4065 +f 4066 4067 4068 +f 4069 4070 4071 +f 4072 4073 4074 +f 4075 4076 4077 +f 4078 4079 4080 +f 4081 4082 4083 +f 4084 4085 4086 +f 4087 4088 4089 +f 4090 4091 4092 +f 4093 4094 4095 +f 4096 4097 4098 +f 4099 4100 4101 +f 4102 4103 4104 +f 4105 4106 4107 +f 4108 4109 4110 +f 4111 4112 4113 +f 4114 4115 4116 +f 4117 4118 4119 +f 4120 4121 4122 +f 4123 4124 4125 +f 4126 4127 4128 +f 4129 4130 4131 +f 4132 4133 4134 +f 4135 4136 4137 +f 4138 4139 4140 +f 4141 4142 4143 +f 4144 4145 4146 +f 4147 4148 4149 +f 4150 4151 4152 +f 4153 4154 4155 +f 4156 4157 4158 +f 4159 4160 4161 +f 4162 4163 4164 +f 4165 4166 4167 +f 4168 4169 4170 +f 4171 4172 4173 +f 4174 4175 4176 +f 4177 4178 4179 +f 4180 4181 4182 +f 4183 4184 4185 +f 4186 4187 4188 +f 4189 4190 4191 +f 4192 4193 4194 +f 4195 4196 4197 +f 4198 4199 4200 +f 4201 4202 4203 +f 4204 4205 4206 +f 4207 4208 4209 +f 4210 4211 4212 +f 4213 4214 4215 +f 4216 4217 4218 +f 4219 4220 4221 +f 4222 4223 4224 +f 4225 4226 4227 +f 4228 4229 4230 +f 4231 4232 4233 +f 4234 4235 4236 +f 4237 4238 4239 +f 4240 4241 4242 +f 4243 4244 4245 +f 4246 4247 4248 +f 4249 4250 4251 +f 4252 4253 4254 +f 4255 4256 4257 +f 4258 4259 4260 +f 4261 4262 4263 +f 4264 4265 4266 +f 4267 4268 4269 +f 4270 4271 4272 +f 4273 4274 4275 +f 4276 4277 4278 +f 4279 4280 4281 +f 4282 4283 4284 +f 4285 4286 4287 +f 4288 4289 4290 +f 4291 4292 4293 +f 4294 4295 4296 +f 4297 4298 4299 +f 4300 4301 4302 +f 4303 4304 4305 +f 4306 4307 4308 +f 4309 4310 4311 +f 4312 4313 4314 +f 4315 4316 4317 +f 4318 4319 4320 +f 4321 4322 4323 +f 4324 4325 4326 +f 4327 4328 4329 +f 4330 4331 4332 +f 4333 4334 4335 +f 4336 4337 4338 +f 4339 4340 4341 +f 4342 4343 4344 +f 4345 4346 4347 +f 4348 4349 4350 +f 4351 4352 4353 +f 4354 4355 4356 +f 4357 4358 4359 +f 4360 4361 4362 +f 4363 4364 4365 +f 4366 4367 4368 +f 4369 4370 4371 +f 4372 4373 4374 +f 4375 4376 4377 +f 4378 4379 4380 +f 4381 4382 4383 +f 4384 4385 4386 +f 4387 4388 4389 +f 4390 4391 4392 +f 4393 4394 4395 +f 4396 4397 4398 +f 4399 4400 4401 +f 4402 4403 4404 +f 4405 4406 4407 +f 4408 4409 4410 +f 4411 4412 4413 +f 4414 4415 4416 +f 4417 4418 4419 +f 4420 4421 4422 +f 4423 4424 4425 +f 4426 4427 4428 +f 4429 4430 4431 +f 4432 4433 4434 +f 4435 4436 4437 +f 4438 4439 4440 +f 4441 4442 4443 +f 4444 4445 4446 +f 4447 4448 4449 +f 4450 4451 4452 +f 4453 4454 4455 +f 4456 4457 4458 +f 4459 4460 4461 +f 4462 4463 4464 +f 4465 4466 4467 +f 4468 4469 4470 +f 4471 4472 4473 +f 4474 4475 4476 +f 4477 4478 4479 +f 4480 4481 4482 +f 4483 4484 4485 +f 4486 4487 4488 +f 4489 4490 4491 +f 4492 4493 4494 +f 4495 4496 4497 +f 4498 4499 4500 +f 4501 4502 4503 +f 4504 4505 4506 +f 4507 4508 4509 +f 4510 4511 4512 +f 4513 4514 4515 +f 4516 4517 4518 +f 4519 4520 4521 +f 4522 4523 4524 +f 4525 4526 4527 +f 4528 4529 4530 +f 4531 4532 4533 +f 4534 4535 4536 +f 4537 4538 4539 +f 4540 4541 4542 +f 4543 4544 4545 +f 4546 4547 4548 +f 4549 4550 4551 +f 4552 4553 4554 +f 4555 4556 4557 +f 4558 4559 4560 +f 4561 4562 4563 +f 4564 4565 4566 +f 4567 4568 4569 +f 4570 4571 4572 +f 4573 4574 4575 +f 4576 4577 4578 +f 4579 4580 4581 +f 4582 4583 4584 +f 4585 4586 4587 +f 4588 4589 4590 +f 4591 4592 4593 +f 4594 4595 4596 +f 4597 4598 4599 +f 4600 4601 4602 +f 4603 4604 4605 +f 4606 4607 4608 +f 4609 4610 4611 +f 4612 4613 4614 +f 4615 4616 4617 +f 4618 4619 4620 +f 4621 4622 4623 +f 4624 4625 4626 +f 4627 4628 4629 +f 4630 4631 4632 +f 4633 4634 4635 +f 4636 4637 4638 +f 4639 4640 4641 +f 4642 4643 4644 +f 4645 4646 4647 +f 4648 4649 4650 +f 4651 4652 4653 +f 4654 4655 4656 +f 4657 4658 4659 +f 4660 4661 4662 +f 4663 4664 4665 +f 4666 4667 4668 +f 4669 4670 4671 +f 4672 4673 4674 +f 4675 4676 4677 +f 4678 4679 4680 +f 4681 4682 4683 +f 4684 4685 4686 +f 4687 4688 4689 +f 4690 4691 4692 +f 4693 4694 4695 +f 4696 4697 4698 +f 4699 4700 4701 +f 4702 4703 4704 +f 4705 4706 4707 +f 4708 4709 4710 +f 4711 4712 4713 +f 4714 4715 4716 +f 4717 4718 4719 +f 4720 4721 4722 +f 4723 4724 4725 +f 4726 4727 4728 +f 4729 4730 4731 +f 4732 4733 4734 +f 4735 4736 4737 +f 4738 4739 4740 +f 4741 4742 4743 +f 4744 4745 4746 +f 4747 4748 4749 +f 4750 4751 4752 +f 4753 4754 4755 +f 4756 4757 4758 +f 4759 4760 4761 +f 4762 4763 4764 +f 4765 4766 4767 +f 4768 4769 4770 +f 4771 4772 4773 +f 4774 4775 4776 +f 4777 4778 4779 +f 4780 4781 4782 +f 4783 4784 4785 +f 4786 4787 4788 +f 4789 4790 4791 +f 4792 4793 4794 +f 4795 4796 4797 +f 4798 4799 4800 +f 4801 4802 4803 +f 4804 4805 4806 +f 4807 4808 4809 +f 4810 4811 4812 +f 4813 4814 4815 +f 4816 4817 4818 +f 4819 4820 4821 +f 4822 4823 4824 +f 4825 4826 4827 +f 4828 4829 4830 +f 4831 4832 4833 +f 4834 4835 4836 +f 4837 4838 4839 +f 4840 4841 4842 +f 4843 4844 4845 +f 4846 4847 4848 +f 4849 4850 4851 +f 4852 4853 4854 +f 4855 4856 4857 +f 4858 4859 4860 +f 4861 4862 4863 +f 4864 4865 4866 +f 4867 4868 4869 +f 4870 4871 4872 +f 4873 4874 4875 +f 4876 4877 4878 +f 4879 4880 4881 +f 4882 4883 4884 +f 4885 4886 4887 +f 4888 4889 4890 +f 4891 4892 4893 +f 4894 4895 4896 +f 4897 4898 4899 +f 4900 4901 4902 +f 4903 4904 4905 +f 4906 4907 4908 +f 4909 4910 4911 +f 4912 4913 4914 +f 4915 4916 4917 +f 4918 4919 4920 +f 4921 4922 4923 +f 4924 4925 4926 +f 4927 4928 4929 +f 4930 4931 4932 +f 4933 4934 4935 +f 4936 4937 4938 +f 4939 4940 4941 +f 4942 4943 4944 +f 4945 4946 4947 +f 4948 4949 4950 +f 4951 4952 4953 +f 4954 4955 4956 +f 4957 4958 4959 +f 4960 4961 4962 +f 4963 4964 4965 +f 4966 4967 4968 +f 4969 4970 4971 +f 4972 4973 4974 +f 4975 4976 4977 +f 4978 4979 4980 +f 4981 4982 4983 +f 4984 4985 4986 +f 4987 4988 4989 +f 4990 4991 4992 +f 4993 4994 4995 +f 4996 4997 4998 +f 4999 5000 5001 +f 5002 5003 5004 +f 5005 5006 5007 +f 5008 5009 5010 +f 5011 5012 5013 +f 5014 5015 5016 +f 5017 5018 5019 +f 5020 5021 5022 +f 5023 5024 5025 +f 5026 5027 5028 +f 5029 5030 5031 +f 5032 5033 5034 +f 5035 5036 5037 +f 5038 5039 5040 +f 5041 5042 5043 +f 5044 5045 5046 +f 5047 5048 5049 +f 5050 5051 5052 +f 5053 5054 5055 +f 5056 5057 5058 +f 5059 5060 5061 +f 5062 5063 5064 +f 5065 5066 5067 +f 5068 5069 5070 +f 5071 5072 5073 +f 5074 5075 5076 +f 5077 5078 5079 +f 5080 5081 5082 +f 5083 5084 5085 +f 5086 5087 5088 +f 5089 5090 5091 +f 5092 5093 5094 +f 5095 5096 5097 +f 5098 5099 5100 +f 5101 5102 5103 +f 5104 5105 5106 +f 5107 5108 5109 +f 5110 5111 5112 +f 5113 5114 5115 +f 5116 5117 5118 +f 5119 5120 5121 +f 5122 5123 5124 +f 5125 5126 5127 +f 5128 5129 5130 +f 5131 5132 5133 +f 5134 5135 5136 +f 5137 5138 5139 +f 5140 5141 5142 +f 5143 5144 5145 +f 5146 5147 5148 +f 5149 5150 5151 +f 5152 5153 5154 +f 5155 5156 5157 +f 5158 5159 5160 +f 5161 5162 5163 +f 5164 5165 5166 +f 5167 5168 5169 +f 5170 5171 5172 +f 5173 5174 5175 +f 5176 5177 5178 +f 5179 5180 5181 +f 5182 5183 5184 +f 5185 5186 5187 +f 5188 5189 5190 +f 5191 5192 5193 +f 5194 5195 5196 +f 5197 5198 5199 +f 5200 5201 5202 +f 5203 5204 5205 +f 5206 5207 5208 +f 5209 5210 5211 +f 5212 5213 5214 +f 5215 5216 5217 +f 5218 5219 5220 +f 5221 5222 5223 +f 5224 5225 5226 +f 5227 5228 5229 +f 5230 5231 5232 +f 5233 5234 5235 +f 5236 5237 5238 +f 5239 5240 5241 +f 5242 5243 5244 +f 5245 5246 5247 +f 5248 5249 5250 +f 5251 5252 5253 +f 5254 5255 5256 +f 5257 5258 5259 +f 5260 5261 5262 +f 5263 5264 5265 +f 5266 5267 5268 +f 5269 5270 5271 +f 5272 5273 5274 +f 5275 5276 5277 +f 5278 5279 5280 +f 5281 5282 5283 +f 5284 5285 5286 +f 5287 5288 5289 +f 5290 5291 5292 +f 5293 5294 5295 +f 5296 5297 5298 +f 5299 5300 5301 +f 5302 5303 5304 +f 5305 5306 5307 +f 5308 5309 5310 +f 5311 5312 5313 +f 5314 5315 5316 +f 5317 5318 5319 +f 5320 5321 5322 +f 5323 5324 5325 +f 5326 5327 5328 +f 5329 5330 5331 +f 5332 5333 5334 +f 5335 5336 5337 +f 5338 5339 5340 +f 5341 5342 5343 +f 5344 5345 5346 +f 5347 5348 5349 +f 5350 5351 5352 +f 5353 5354 5355 +f 5356 5357 5358 +f 5359 5360 5361 +f 5362 5363 5364 +f 5365 5366 5367 +f 5368 5369 5370 +f 5371 5372 5373 +f 5374 5375 5376 +f 5377 5378 5379 +f 5380 5381 5382 +f 5383 5384 5385 +f 5386 5387 5388 +f 5389 5390 5391 +f 5392 5393 5394 +f 5395 5396 5397 +f 5398 5399 5400 +f 5401 5402 5403 +f 5404 5405 5406 +f 5407 5408 5409 +f 5410 5411 5412 +f 5413 5414 5415 +f 5416 5417 5418 +f 5419 5420 5421 +f 5422 5423 5424 +f 5425 5426 5427 +f 5428 5429 5430 +f 5431 5432 5433 +f 5434 5435 5436 +f 5437 5438 5439 +f 5440 5441 5442 +f 5443 5444 5445 +f 5446 5447 5448 +f 5449 5450 5451 +f 5452 5453 5454 +f 5455 5456 5457 +f 5458 5459 5460 +f 5461 5462 5463 +f 5464 5465 5466 +f 5467 5468 5469 +f 5470 5471 5472 +f 5473 5474 5475 +f 5476 5477 5478 +f 5479 5480 5481 +f 5482 5483 5484 +f 5485 5486 5487 +f 5488 5489 5490 +f 5491 5492 5493 +f 5494 5495 5496 +f 5497 5498 5499 +f 5500 5501 5502 +f 5503 5504 5505 +f 5506 5507 5508 +f 5509 5510 5511 +f 5512 5513 5514 +f 5515 5516 5517 +f 5518 5519 5520 +f 5521 5522 5523 +f 5524 5525 5526 +f 5527 5528 5529 +f 5530 5531 5532 +f 5533 5534 5535 +f 5536 5537 5538 +f 5539 5540 5541 +f 5542 5543 5544 +f 5545 5546 5547 +f 5548 5549 5550 +f 5551 5552 5553 +f 5554 5555 5556 +f 5557 5558 5559 +f 5560 5561 5562 +f 5563 5564 5565 +f 5566 5567 5568 +f 5569 5570 5571 +f 5572 5573 5574 +f 5575 5576 5577 +f 5578 5579 5580 +f 5581 5582 5583 +f 5584 5585 5586 +f 5587 5588 5589 +f 5590 5591 5592 +f 5593 5594 5595 +f 5596 5597 5598 +f 5599 5600 5601 +f 5602 5603 5604 +f 5605 5606 5607 +f 5608 5609 5610 +f 5611 5612 5613 +f 5614 5615 5616 +f 5617 5618 5619 +f 5620 5621 5622 +f 5623 5624 5625 +f 5626 5627 5628 +f 5629 5630 5631 +f 5632 5633 5634 +f 5635 5636 5637 +f 5638 5639 5640 +f 5641 5642 5643 +f 5644 5645 5646 +f 5647 5648 5649 +f 5650 5651 5652 +f 5653 5654 5655 +f 5656 5657 5658 +f 5659 5660 5661 +f 5662 5663 5664 +f 5665 5666 5667 +f 5668 5669 5670 +f 5671 5672 5673 +f 5674 5675 5676 +f 5677 5678 5679 +f 5680 5681 5682 +f 5683 5684 5685 +f 5686 5687 5688 +f 5689 5690 5691 +f 5692 5693 5694 +f 5695 5696 5697 +f 5698 5699 5700 +f 5701 5702 5703 +f 5704 5705 5706 +f 5707 5708 5709 +f 5710 5711 5712 +f 5713 5714 5715 +f 5716 5717 5718 +f 5719 5720 5721 +f 5722 5723 5724 +f 5725 5726 5727 +f 5728 5729 5730 +f 5731 5732 5733 +f 5734 5735 5736 +f 5737 5738 5739 +f 5740 5741 5742 +f 5743 5744 5745 +f 5746 5747 5748 +f 5749 5750 5751 +f 5752 5753 5754 +f 5755 5756 5757 +f 5758 5759 5760 +f 5761 5762 5763 +f 5764 5765 5766 +f 5767 5768 5769 +f 5770 5771 5772 +f 5773 5774 5775 +f 5776 5777 5778 +f 5779 5780 5781 +f 5782 5783 5784 +f 5785 5786 5787 +f 5788 5789 5790 +f 5791 5792 5793 +f 5794 5795 5796 +f 5797 5798 5799 +f 5800 5801 5802 +f 5803 5804 5805 +f 5806 5807 5808 +f 5809 5810 5811 +f 5812 5813 5814 +f 5815 5816 5817 +f 5818 5819 5820 +f 5821 5822 5823 +f 5824 5825 5826 +f 5827 5828 5829 +f 5830 5831 5832 +f 5833 5834 5835 +f 5836 5837 5838 +f 5839 5840 5841 +f 5842 5843 5844 +f 5845 5846 5847 +f 5848 5849 5850 +f 5851 5852 5853 +f 5854 5855 5856 +f 5857 5858 5859 +f 5860 5861 5862 +f 5863 5864 5865 +f 5866 5867 5868 +f 5869 5870 5871 +f 5872 5873 5874 +f 5875 5876 5877 +f 5878 5879 5880 +f 5881 5882 5883 +f 5884 5885 5886 +f 5887 5888 5889 +f 5890 5891 5892 +f 5893 5894 5895 +f 5896 5897 5898 +f 5899 5900 5901 +f 5902 5903 5904 +f 5905 5906 5907 +f 5908 5909 5910 +f 5911 5912 5913 +f 5914 5915 5916 +f 5917 5918 5919 +f 5920 5921 5922 +f 5923 5924 5925 +f 5926 5927 5928 +f 5929 5930 5931 +f 5932 5933 5934 +f 5935 5936 5937 +f 5938 5939 5940 +f 5941 5942 5943 +f 5944 5945 5946 +f 5947 5948 5949 +f 5950 5951 5952 +f 5953 5954 5955 +f 5956 5957 5958 +f 5959 5960 5961 +f 5962 5963 5964 +f 5965 5966 5967 +f 5968 5969 5970 +f 5971 5972 5973 +f 5974 5975 5976 +f 5977 5978 5979 +f 5980 5981 5982 +f 5983 5984 5985 +f 5986 5987 5988 +f 5989 5990 5991 +f 5992 5993 5994 +f 5995 5996 5997 +f 5998 5999 6000 +f 6001 6002 6003 +f 6004 6005 6006 +f 6007 6008 6009 +f 6010 6011 6012 +f 6013 6014 6015 +f 6016 6017 6018 +f 6019 6020 6021 +f 6022 6023 6024 +f 6025 6026 6027 +f 6028 6029 6030 +f 6031 6032 6033 +f 6034 6035 6036 +f 6037 6038 6039 +f 6040 6041 6042 +f 6043 6044 6045 +f 6046 6047 6048 +f 6049 6050 6051 +f 6052 6053 6054 +f 6055 6056 6057 +f 6058 6059 6060 +f 6061 6062 6063 +f 6064 6065 6066 +f 6067 6068 6069 +f 6070 6071 6072 +f 6073 6074 6075 +f 6076 6077 6078 +f 6079 6080 6081 +f 6082 6083 6084 +f 6085 6086 6087 +f 6088 6089 6090 +f 6091 6092 6093 +f 6094 6095 6096 +f 6097 6098 6099 +f 6100 6101 6102 +f 6103 6104 6105 +f 6106 6107 6108 +f 6109 6110 6111 +f 6112 6113 6114 +f 6115 6116 6117 +f 6118 6119 6120 +f 6121 6122 6123 +f 6124 6125 6126 +f 6127 6128 6129 +f 6130 6131 6132 +f 6133 6134 6135 +f 6136 6137 6138 +f 6139 6140 6141 +f 6142 6143 6144 +f 6145 6146 6147 +f 6148 6149 6150 +f 6151 6152 6153 +f 6154 6155 6156 +f 6157 6158 6159 +f 6160 6161 6162 +f 6163 6164 6165 +f 6166 6167 6168 +f 6169 6170 6171 +f 6172 6173 6174 +f 6175 6176 6177 +f 6178 6179 6180 +f 6181 6182 6183 +f 6184 6185 6186 +f 6187 6188 6189 +f 6190 6191 6192 +f 6193 6194 6195 +f 6196 6197 6198 +f 6199 6200 6201 +f 6202 6203 6204 +f 6205 6206 6207 +f 6208 6209 6210 +f 6211 6212 6213 +f 6214 6215 6216 +f 6217 6218 6219 +f 6220 6221 6222 +f 6223 6224 6225 +f 6226 6227 6228 +f 6229 6230 6231 +f 6232 6233 6234 +f 6235 6236 6237 +f 6238 6239 6240 +f 6241 6242 6243 +f 6244 6245 6246 +f 6247 6248 6249 +f 6250 6251 6252 +f 6253 6254 6255 +f 6256 6257 6258 +f 6259 6260 6261 +f 6262 6263 6264 +f 6265 6266 6267 +f 6268 6269 6270 +f 6271 6272 6273 +f 6274 6275 6276 +f 6277 6278 6279 +f 6280 6281 6282 +f 6283 6284 6285 +f 6286 6287 6288 +f 6289 6290 6291 +f 6292 6293 6294 +f 6295 6296 6297 +f 6298 6299 6300 +f 6301 6302 6303 +f 6304 6305 6306 +f 6307 6308 6309 +f 6310 6311 6312 +f 6313 6314 6315 +f 6316 6317 6318 +f 6319 6320 6321 +f 6322 6323 6324 +f 6325 6326 6327 +f 6328 6329 6330 +f 6331 6332 6333 +f 6334 6335 6336 +f 6337 6338 6339 +f 6340 6341 6342 +f 6343 6344 6345 +f 6346 6347 6348 +f 6349 6350 6351 +f 6352 6353 6354 +f 6355 6356 6357 +f 6358 6359 6360 +f 6361 6362 6363 +f 6364 6365 6366 +f 6367 6368 6369 +f 6370 6371 6372 +f 6373 6374 6375 +f 6376 6377 6378 +f 6379 6380 6381 +f 6382 6383 6384 +f 6385 6386 6387 +f 6388 6389 6390 +f 6391 6392 6393 +f 6394 6395 6396 +f 6397 6398 6399 +f 6400 6401 6402 +f 6403 6404 6405 +f 6406 6407 6408 +f 6409 6410 6411 +f 6412 6413 6414 +f 6415 6416 6417 +f 6418 6419 6420 +f 6421 6422 6423 +f 6424 6425 6426 +f 6427 6428 6429 +f 6430 6431 6432 +f 6433 6434 6435 +f 6436 6437 6438 +f 6439 6440 6441 +f 6442 6443 6444 +f 6445 6446 6447 +f 6448 6449 6450 +f 6451 6452 6453 +f 6454 6455 6456 +f 6457 6458 6459 +f 6460 6461 6462 +f 6463 6464 6465 +f 6466 6467 6468 +f 6469 6470 6471 +f 6472 6473 6474 +f 6475 6476 6477 +f 6478 6479 6480 +f 6481 6482 6483 +f 6484 6485 6486 +f 6487 6488 6489 +f 6490 6491 6492 +f 6493 6494 6495 +f 6496 6497 6498 +f 6499 6500 6501 +f 6502 6503 6504 +f 6505 6506 6507 +f 6508 6509 6510 +f 6511 6512 6513 +f 6514 6515 6516 +f 6517 6518 6519 +f 6520 6521 6522 +f 6523 6524 6525 +f 6526 6527 6528 +f 6529 6530 6531 +f 6532 6533 6534 +f 6535 6536 6537 +f 6538 6539 6540 diff --git a/trunk/fcl_test/test/rob.obj b/trunk/fcl_test/test/rob.obj new file mode 100644 index 00000000..fbc5c75f --- /dev/null +++ b/trunk/fcl_test/test/rob.obj @@ -0,0 +1,865 @@ +648 216 +v -500 -395 375 +v 500 -395 375 +v 462 -203.6 375 +v -500 -395 375 +v 462 -203.6 375 +v 353.5 -41.5 375 +v -500 -395 375 +v 353.5 -41.5 375 +v 191.4 66.4 375 +v -500 -395 375 +v 191.4 66.4 375 +v -500 66.4 375 +v -500 66.4 75 +v 191.4 66.4 75 +v 353.5 -41.5 75 +v -500 66.4 75 +v 353.5 -41.5 75 +v 462 -203.6 75 +v -500 66.4 75 +v 462 -203.6 75 +v 500 -395 75 +v -500 66.4 75 +v 500 -395 75 +v -500 -395 75 +v -500 -395 375 +v -500 -395 75 +v 500 -395 75 +v -500 -395 375 +v 500 -395 75 +v 500 -395 375 +v 500 -395 375 +v 500 -395 75 +v 462 -203.6 75 +v 500 -395 375 +v 462 -203.6 75 +v 462 -203.6 375 +v 462 -203.6 375 +v 462 -203.6 75 +v 353.5 -41.5 75 +v 462 -203.6 375 +v 353.5 -41.5 75 +v 353.5 -41.5 375 +v 353.5 -41.5 375 +v 353.5 -41.5 75 +v 191.4 66.4 75 +v 353.5 -41.5 375 +v 191.4 66.4 75 +v 191.4 66.4 375 +v 191.4 66.4 375 +v 191.4 66.4 75 +v -500 66.4 75 +v 191.4 66.4 375 +v -500 66.4 75 +v -500 66.4 375 +v -500 66.4 375 +v -500 66.4 75 +v -500 -395 75 +v -500 66.4 375 +v -500 -395 75 +v -500 -395 375 +v -500 66.4 375 +v 191.4 66.4 375 +v -38 296.4 375 +v -500 66.4 375 +v -38 296.4 375 +v -500 296.4 375 +v -500 296.4 75 +v -38 296.4 75 +v 191.4 66.4 75 +v -500 296.4 75 +v 191.4 66.4 75 +v -500 66.4 75 +v -500 66.4 375 +v -500 66.4 75 +v 191.4 66.4 75 +v -500 66.4 375 +v 191.4 66.4 75 +v 191.4 66.4 375 +v 191.4 66.4 375 +v 191.4 66.4 75 +v -38 296.4 75 +v 191.4 66.4 375 +v -38 296.4 75 +v -38 296.4 375 +v -38 296.4 375 +v -38 296.4 75 +v -500 296.4 75 +v -38 296.4 375 +v -500 296.4 75 +v -500 296.4 375 +v -500 296.4 375 +v -500 296.4 75 +v -500 66.4 75 +v -500 296.4 375 +v -500 66.4 75 +v -500 66.4 375 +v -500 296.4 375 +v -38 296.4 375 +v -146.5 458.6 375 +v -500 296.4 375 +v -146.5 458.6 375 +v -308.7 566.4 375 +v -500 296.4 375 +v -308.7 566.4 375 +v -500 605 375 +v -500 605 75 +v -308.7 566.4 75 +v -146.5 458.6 75 +v -500 605 75 +v -146.5 458.6 75 +v -38 296.4 75 +v -500 605 75 +v -38 296.4 75 +v -500 296.4 75 +v -500 296.4 375 +v -500 296.4 75 +v -38 296.4 75 +v -500 296.4 375 +v -38 296.4 75 +v -38 296.4 375 +v -38 296.4 375 +v -38 296.4 75 +v -146.5 458.6 75 +v -38 296.4 375 +v -146.5 458.6 75 +v -146.5 458.6 375 +v -146.5 458.6 375 +v -146.5 458.6 75 +v -308.7 566.4 75 +v -146.5 458.6 375 +v -308.7 566.4 75 +v -308.7 566.4 375 +v -308.7 566.4 375 +v -308.7 566.4 75 +v -500 605 75 +v -308.7 566.4 375 +v -500 605 75 +v -500 605 375 +v -500 605 375 +v -500 605 75 +v -500 296.4 75 +v -500 605 375 +v -500 296.4 75 +v -500 296.4 375 +v -500 -595 175 +v 500 -595 175 +v -500 -395 175 +v -500 -395 175 +v 500 -595 175 +v 500 -395 175 +v 500 -595 75 +v -500 -595 75 +v 500 -395 75 +v 500 -395 75 +v -500 -595 75 +v -500 -395 75 +v 500 -595 175 +v 500 -595 75 +v 500 -395 175 +v 500 -395 175 +v 500 -595 75 +v 500 -395 75 +v -500 -595 75 +v -500 -595 175 +v -500 -395 75 +v -500 -395 75 +v -500 -595 175 +v -500 -395 175 +v -500 -395 75 +v -500 -395 175 +v 500 -395 75 +v 500 -395 75 +v -500 -395 175 +v 500 -395 175 +v -500 -595 75 +v 500 -595 75 +v -500 -595 175 +v -500 -595 175 +v 500 -595 75 +v 500 -595 175 +v -500 -605 195 +v 500 -605 195 +v -500 -395 195 +v -500 -395 195 +v 500 -605 195 +v 500 -395 195 +v 500 -605 175 +v -500 -605 175 +v 500 -395 175 +v 500 -395 175 +v -500 -605 175 +v -500 -395 175 +v 500 -605 195 +v 500 -605 175 +v 500 -395 195 +v 500 -395 195 +v 500 -605 175 +v 500 -395 175 +v -500 -605 175 +v -500 -605 195 +v -500 -395 175 +v -500 -395 175 +v -500 -605 195 +v -500 -395 195 +v -500 -395 175 +v -500 -395 195 +v 500 -395 175 +v 500 -395 175 +v -500 -395 195 +v 500 -395 195 +v -500 -605 175 +v 500 -605 175 +v -500 -605 195 +v -500 -605 195 +v 500 -605 175 +v 500 -605 195 +v -430 -495 75 +v -431.522 -487.346 75 +v -430 -495 -425 +v -430 -495 -425 +v -431.522 -487.346 75 +v -431.522 -487.346 -425 +v -431.522 -487.346 75 +v -435.858 -480.858 75 +v -431.522 -487.346 -425 +v -431.522 -487.346 -425 +v -435.858 -480.858 75 +v -435.858 -480.858 -425 +v -435.858 -480.858 75 +v -442.346 -476.522 75 +v -435.858 -480.858 -425 +v -435.858 -480.858 -425 +v -442.346 -476.522 75 +v -442.346 -476.522 -425 +v -442.346 -476.522 75 +v -450 -475 75 +v -442.346 -476.522 -425 +v -442.346 -476.522 -425 +v -450 -475 75 +v -450 -475 -425 +v -450 -475 75 +v -457.654 -476.522 75 +v -450 -475 -425 +v -450 -475 -425 +v -457.654 -476.522 75 +v -457.654 -476.522 -425 +v -457.654 -476.522 75 +v -464.142 -480.858 75 +v -457.654 -476.522 -425 +v -457.654 -476.522 -425 +v -464.142 -480.858 75 +v -464.142 -480.858 -425 +v -464.142 -480.858 75 +v -468.478 -487.346 75 +v -464.142 -480.858 -425 +v -464.142 -480.858 -425 +v -468.478 -487.346 75 +v -468.478 -487.346 -425 +v -468.478 -487.346 75 +v -470 -495 75 +v -468.478 -487.346 -425 +v -468.478 -487.346 -425 +v -470 -495 75 +v -470 -495 -425 +v -470 -495 75 +v -468.478 -502.654 75 +v -470 -495 -425 +v -470 -495 -425 +v -468.478 -502.654 75 +v -468.478 -502.654 -425 +v -468.478 -502.654 75 +v -464.142 -509.142 75 +v -468.478 -502.654 -425 +v -468.478 -502.654 -425 +v -464.142 -509.142 75 +v -464.142 -509.142 -425 +v -464.142 -509.142 75 +v -457.654 -513.478 75 +v -464.142 -509.142 -425 +v -464.142 -509.142 -425 +v -457.654 -513.478 75 +v -457.654 -513.478 -425 +v -457.654 -513.478 75 +v -450 -515 75 +v -457.654 -513.478 -425 +v -457.654 -513.478 -425 +v -450 -515 75 +v -450 -515 -425 +v -450 -515 75 +v -442.346 -513.478 75 +v -450 -515 -425 +v -450 -515 -425 +v -442.346 -513.478 75 +v -442.346 -513.478 -425 +v -442.346 -513.478 75 +v -435.858 -509.142 75 +v -442.346 -513.478 -425 +v -442.346 -513.478 -425 +v -435.858 -509.142 75 +v -435.858 -509.142 -425 +v -435.858 -509.142 75 +v -431.522 -502.654 75 +v -435.858 -509.142 -425 +v -435.858 -509.142 -425 +v -431.522 -502.654 75 +v -431.522 -502.654 -425 +v -431.522 -502.654 75 +v -430 -495 75 +v -431.522 -502.654 -425 +v -431.522 -502.654 -425 +v -430 -495 75 +v -430 -495 -425 +v 470 -495 75 +v 468.478 -487.346 75 +v 470 -495 -425 +v 470 -495 -425 +v 468.478 -487.346 75 +v 468.478 -487.346 -425 +v 468.478 -487.346 75 +v 464.142 -480.858 75 +v 468.478 -487.346 -425 +v 468.478 -487.346 -425 +v 464.142 -480.858 75 +v 464.142 -480.858 -425 +v 464.142 -480.858 75 +v 457.654 -476.522 75 +v 464.142 -480.858 -425 +v 464.142 -480.858 -425 +v 457.654 -476.522 75 +v 457.654 -476.522 -425 +v 457.654 -476.522 75 +v 450 -475 75 +v 457.654 -476.522 -425 +v 457.654 -476.522 -425 +v 450 -475 75 +v 450 -475 -425 +v 450 -475 75 +v 442.346 -476.522 75 +v 450 -475 -425 +v 450 -475 -425 +v 442.346 -476.522 75 +v 442.346 -476.522 -425 +v 442.346 -476.522 75 +v 435.858 -480.858 75 +v 442.346 -476.522 -425 +v 442.346 -476.522 -425 +v 435.858 -480.858 75 +v 435.858 -480.858 -425 +v 435.858 -480.858 75 +v 431.522 -487.346 75 +v 435.858 -480.858 -425 +v 435.858 -480.858 -425 +v 431.522 -487.346 75 +v 431.522 -487.346 -425 +v 431.522 -487.346 75 +v 430 -495 75 +v 431.522 -487.346 -425 +v 431.522 -487.346 -425 +v 430 -495 75 +v 430 -495 -425 +v 430 -495 75 +v 431.522 -502.654 75 +v 430 -495 -425 +v 430 -495 -425 +v 431.522 -502.654 75 +v 431.522 -502.654 -425 +v 431.522 -502.654 75 +v 435.858 -509.142 75 +v 431.522 -502.654 -425 +v 431.522 -502.654 -425 +v 435.858 -509.142 75 +v 435.858 -509.142 -425 +v 435.858 -509.142 75 +v 442.346 -513.478 75 +v 435.858 -509.142 -425 +v 435.858 -509.142 -425 +v 442.346 -513.478 75 +v 442.346 -513.478 -425 +v 442.346 -513.478 75 +v 450 -515 75 +v 442.346 -513.478 -425 +v 442.346 -513.478 -425 +v 450 -515 75 +v 450 -515 -425 +v 450 -515 75 +v 457.654 -513.478 75 +v 450 -515 -425 +v 450 -515 -425 +v 457.654 -513.478 75 +v 457.654 -513.478 -425 +v 457.654 -513.478 75 +v 464.142 -509.142 75 +v 457.654 -513.478 -425 +v 457.654 -513.478 -425 +v 464.142 -509.142 75 +v 464.142 -509.142 -425 +v 464.142 -509.142 75 +v 468.478 -502.654 75 +v 464.142 -509.142 -425 +v 464.142 -509.142 -425 +v 468.478 -502.654 75 +v 468.478 -502.654 -425 +v 468.478 -502.654 75 +v 470 -495 75 +v 468.478 -502.654 -425 +v 468.478 -502.654 -425 +v 470 -495 75 +v 470 -495 -425 +v -380 505 75 +v -381.522 512.654 75 +v -380 505 -425 +v -380 505 -425 +v -381.522 512.654 75 +v -381.522 512.654 -425 +v -381.522 512.654 75 +v -385.858 519.142 75 +v -381.522 512.654 -425 +v -381.522 512.654 -425 +v -385.858 519.142 75 +v -385.858 519.142 -425 +v -385.858 519.142 75 +v -392.346 523.478 75 +v -385.858 519.142 -425 +v -385.858 519.142 -425 +v -392.346 523.478 75 +v -392.346 523.478 -425 +v -392.346 523.478 75 +v -400 525 75 +v -392.346 523.478 -425 +v -392.346 523.478 -425 +v -400 525 75 +v -400 525 -425 +v -400 525 75 +v -407.654 523.478 75 +v -400 525 -425 +v -400 525 -425 +v -407.654 523.478 75 +v -407.654 523.478 -425 +v -407.654 523.478 75 +v -414.142 519.142 75 +v -407.654 523.478 -425 +v -407.654 523.478 -425 +v -414.142 519.142 75 +v -414.142 519.142 -425 +v -414.142 519.142 75 +v -418.478 512.654 75 +v -414.142 519.142 -425 +v -414.142 519.142 -425 +v -418.478 512.654 75 +v -418.478 512.654 -425 +v -418.478 512.654 75 +v -420 505 75 +v -418.478 512.654 -425 +v -418.478 512.654 -425 +v -420 505 75 +v -420 505 -425 +v -420 505 75 +v -418.478 497.346 75 +v -420 505 -425 +v -420 505 -425 +v -418.478 497.346 75 +v -418.478 497.346 -425 +v -418.478 497.346 75 +v -414.142 490.858 75 +v -418.478 497.346 -425 +v -418.478 497.346 -425 +v -414.142 490.858 75 +v -414.142 490.858 -425 +v -414.142 490.858 75 +v -407.654 486.522 75 +v -414.142 490.858 -425 +v -414.142 490.858 -425 +v -407.654 486.522 75 +v -407.654 486.522 -425 +v -407.654 486.522 75 +v -400 485 75 +v -407.654 486.522 -425 +v -407.654 486.522 -425 +v -400 485 75 +v -400 485 -425 +v -400 485 75 +v -392.346 486.522 75 +v -400 485 -425 +v -400 485 -425 +v -392.346 486.522 75 +v -392.346 486.522 -425 +v -392.346 486.522 75 +v -385.858 490.858 75 +v -392.346 486.522 -425 +v -392.346 486.522 -425 +v -385.858 490.858 75 +v -385.858 490.858 -425 +v -385.858 490.858 75 +v -381.522 497.346 75 +v -385.858 490.858 -425 +v -385.858 490.858 -425 +v -381.522 497.346 75 +v -381.522 497.346 -425 +v -381.522 497.346 75 +v -380 505 75 +v -381.522 497.346 -425 +v -381.522 497.346 -425 +v -380 505 75 +v -380 505 -425 +v -500 -395 425 +v 500 -395 425 +v 462 -203.6 425 +v -500 -395 425 +v 462 -203.6 425 +v 353.5 -41.5 425 +v -500 -395 425 +v 353.5 -41.5 425 +v 191.4 66.4 425 +v -500 -395 425 +v 191.4 66.4 425 +v -500 66.4 425 +v -500 66.4 375 +v 191.4 66.4 375 +v 353.5 -41.5 375 +v -500 66.4 375 +v 353.5 -41.5 375 +v 462 -203.6 375 +v -500 66.4 375 +v 462 -203.6 375 +v 500 -395 375 +v -500 66.4 375 +v 500 -395 375 +v -500 -395 375 +v -500 -395 425 +v -500 -395 375 +v 500 -395 375 +v -500 -395 425 +v 500 -395 375 +v 500 -395 425 +v 500 -395 425 +v 500 -395 375 +v 462 -203.6 375 +v 500 -395 425 +v 462 -203.6 375 +v 462 -203.6 425 +v 462 -203.6 425 +v 462 -203.6 375 +v 353.5 -41.5 375 +v 462 -203.6 425 +v 353.5 -41.5 375 +v 353.5 -41.5 425 +v 353.5 -41.5 425 +v 353.5 -41.5 375 +v 191.4 66.4 375 +v 353.5 -41.5 425 +v 191.4 66.4 375 +v 191.4 66.4 425 +v 191.4 66.4 425 +v 191.4 66.4 375 +v -500 66.4 375 +v 191.4 66.4 425 +v -500 66.4 375 +v -500 66.4 425 +v -500 66.4 425 +v -500 66.4 375 +v -500 -395 375 +v -500 66.4 425 +v -500 -395 375 +v -500 -395 425 +v -500 66.4 425 +v 191.4 66.4 425 +v -38 296.4 425 +v -500 66.4 425 +v -38 296.4 425 +v -500 296.4 425 +v -500 296.4 375 +v -38 296.4 375 +v 191.4 66.4 375 +v -500 296.4 375 +v 191.4 66.4 375 +v -500 66.4 375 +v -500 66.4 425 +v -500 66.4 375 +v 191.4 66.4 375 +v -500 66.4 425 +v 191.4 66.4 375 +v 191.4 66.4 425 +v 191.4 66.4 425 +v 191.4 66.4 375 +v -38 296.4 375 +v 191.4 66.4 425 +v -38 296.4 375 +v -38 296.4 425 +v -38 296.4 425 +v -38 296.4 375 +v -500 296.4 375 +v -38 296.4 425 +v -500 296.4 375 +v -500 296.4 425 +v -500 296.4 425 +v -500 296.4 375 +v -500 66.4 375 +v -500 296.4 425 +v -500 66.4 375 +v -500 66.4 425 +v -500 296.4 425 +v -38 296.4 425 +v -146.5 458.6 425 +v -500 296.4 425 +v -146.5 458.6 425 +v -308.7 566.4 425 +v -500 296.4 425 +v -308.7 566.4 425 +v -500 605 425 +v -500 605 375 +v -308.7 566.4 375 +v -146.5 458.6 375 +v -500 605 375 +v -146.5 458.6 375 +v -38 296.4 375 +v -500 605 375 +v -38 296.4 375 +v -500 296.4 375 +v -500 296.4 425 +v -500 296.4 375 +v -38 296.4 375 +v -500 296.4 425 +v -38 296.4 375 +v -38 296.4 425 +v -38 296.4 425 +v -38 296.4 375 +v -146.5 458.6 375 +v -38 296.4 425 +v -146.5 458.6 375 +v -146.5 458.6 425 +v -146.5 458.6 425 +v -146.5 458.6 375 +v -308.7 566.4 375 +v -146.5 458.6 425 +v -308.7 566.4 375 +v -308.7 566.4 425 +v -308.7 566.4 425 +v -308.7 566.4 375 +v -500 605 375 +v -308.7 566.4 425 +v -500 605 375 +v -500 605 425 +v -500 605 425 +v -500 605 375 +v -500 296.4 375 +v -500 605 425 +v -500 296.4 375 +v -500 296.4 425 +f 1 2 3 +f 4 5 6 +f 7 8 9 +f 10 11 12 +f 13 14 15 +f 16 17 18 +f 19 20 21 +f 22 23 24 +f 25 26 27 +f 28 29 30 +f 31 32 33 +f 34 35 36 +f 37 38 39 +f 40 41 42 +f 43 44 45 +f 46 47 48 +f 49 50 51 +f 52 53 54 +f 55 56 57 +f 58 59 60 +f 61 62 63 +f 64 65 66 +f 67 68 69 +f 70 71 72 +f 73 74 75 +f 76 77 78 +f 79 80 81 +f 82 83 84 +f 85 86 87 +f 88 89 90 +f 91 92 93 +f 94 95 96 +f 97 98 99 +f 100 101 102 +f 103 104 105 +f 106 107 108 +f 109 110 111 +f 112 113 114 +f 115 116 117 +f 118 119 120 +f 121 122 123 +f 124 125 126 +f 127 128 129 +f 130 131 132 +f 133 134 135 +f 136 137 138 +f 139 140 141 +f 142 143 144 +f 145 146 147 +f 148 149 150 +f 151 152 153 +f 154 155 156 +f 157 158 159 +f 160 161 162 +f 163 164 165 +f 166 167 168 +f 169 170 171 +f 172 173 174 +f 175 176 177 +f 178 179 180 +f 181 182 183 +f 184 185 186 +f 187 188 189 +f 190 191 192 +f 193 194 195 +f 196 197 198 +f 199 200 201 +f 202 203 204 +f 205 206 207 +f 208 209 210 +f 211 212 213 +f 214 215 216 +f 217 218 219 +f 220 221 222 +f 223 224 225 +f 226 227 228 +f 229 230 231 +f 232 233 234 +f 235 236 237 +f 238 239 240 +f 241 242 243 +f 244 245 246 +f 247 248 249 +f 250 251 252 +f 253 254 255 +f 256 257 258 +f 259 260 261 +f 262 263 264 +f 265 266 267 +f 268 269 270 +f 271 272 273 +f 274 275 276 +f 277 278 279 +f 280 281 282 +f 283 284 285 +f 286 287 288 +f 289 290 291 +f 292 293 294 +f 295 296 297 +f 298 299 300 +f 301 302 303 +f 304 305 306 +f 307 308 309 +f 310 311 312 +f 313 314 315 +f 316 317 318 +f 319 320 321 +f 322 323 324 +f 325 326 327 +f 328 329 330 +f 331 332 333 +f 334 335 336 +f 337 338 339 +f 340 341 342 +f 343 344 345 +f 346 347 348 +f 349 350 351 +f 352 353 354 +f 355 356 357 +f 358 359 360 +f 361 362 363 +f 364 365 366 +f 367 368 369 +f 370 371 372 +f 373 374 375 +f 376 377 378 +f 379 380 381 +f 382 383 384 +f 385 386 387 +f 388 389 390 +f 391 392 393 +f 394 395 396 +f 397 398 399 +f 400 401 402 +f 403 404 405 +f 406 407 408 +f 409 410 411 +f 412 413 414 +f 415 416 417 +f 418 419 420 +f 421 422 423 +f 424 425 426 +f 427 428 429 +f 430 431 432 +f 433 434 435 +f 436 437 438 +f 439 440 441 +f 442 443 444 +f 445 446 447 +f 448 449 450 +f 451 452 453 +f 454 455 456 +f 457 458 459 +f 460 461 462 +f 463 464 465 +f 466 467 468 +f 469 470 471 +f 472 473 474 +f 475 476 477 +f 478 479 480 +f 481 482 483 +f 484 485 486 +f 487 488 489 +f 490 491 492 +f 493 494 495 +f 496 497 498 +f 499 500 501 +f 502 503 504 +f 505 506 507 +f 508 509 510 +f 511 512 513 +f 514 515 516 +f 517 518 519 +f 520 521 522 +f 523 524 525 +f 526 527 528 +f 529 530 531 +f 532 533 534 +f 535 536 537 +f 538 539 540 +f 541 542 543 +f 544 545 546 +f 547 548 549 +f 550 551 552 +f 553 554 555 +f 556 557 558 +f 559 560 561 +f 562 563 564 +f 565 566 567 +f 568 569 570 +f 571 572 573 +f 574 575 576 +f 577 578 579 +f 580 581 582 +f 583 584 585 +f 586 587 588 +f 589 590 591 +f 592 593 594 +f 595 596 597 +f 598 599 600 +f 601 602 603 +f 604 605 606 +f 607 608 609 +f 610 611 612 +f 613 614 615 +f 616 617 618 +f 619 620 621 +f 622 623 624 +f 625 626 627 +f 628 629 630 +f 631 632 633 +f 634 635 636 +f 637 638 639 +f 640 641 642 +f 643 644 645 +f 646 647 648 diff --git a/trunk/fcl_test/test/test_core_broad_phase.cpp b/trunk/fcl_test/test/test_core_broad_phase.cpp new file mode 100644 index 00000000..ae196f99 --- /dev/null +++ b/trunk/fcl_test/test/test_core_broad_phase.cpp @@ -0,0 +1,247 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#include "fcl/broad_phase_collision.h" +#include "fcl/geometric_shape_to_BVH_model.h" +#include "fcl/transform.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> + +using namespace fcl; + + +void generateEnvironments(std::vector<CollisionObject*>& env, int n); + + +TEST(test_core, broad_phase_collision) +{ + bool exhaustive = false; + + std::vector<CollisionObject*> env; + generateEnvironments(env, 100); + + std::vector<CollisionObject*> query; + generateEnvironments(query, 10); + + BroadPhaseCollisionManager* manager1 = new NaiveCollisionManager(); + BroadPhaseCollisionManager* manager2 = new SSaPCollisionManager(); + BroadPhaseCollisionManager* manager3 = new SaPCollisionManager(); + BroadPhaseCollisionManager* manager4 = new IntervalTreeCollisionManager(); + + + for(unsigned int i = 0; i < env.size(); ++i) + { + manager1->registerObject(env[i]); + manager2->registerObject(env[i]); + manager3->registerObject(env[i]); + manager4->registerObject(env[i]); + } + + manager1->setup(); + manager2->setup(); + manager3->setup(); + manager4->setup(); + + CollisionData self_data1; + self_data1.exhaustive = exhaustive; + CollisionData self_data2; + self_data2.exhaustive = exhaustive; + CollisionData self_data3; + self_data3.exhaustive = exhaustive; + CollisionData self_data4; + self_data4.exhaustive = exhaustive; + + manager1->collide(&self_data1, defaultCollisionFunction); + manager2->collide(&self_data2, defaultCollisionFunction); + manager3->collide(&self_data3, defaultCollisionFunction); + manager3->collide(&self_data4, defaultCollisionFunction); + + bool self_res1 = (self_data1.contacts.size() > 0); + bool self_res2 = (self_data2.contacts.size() > 0); + bool self_res3 = (self_data3.contacts.size() > 0); + bool self_res4 = (self_data4.contacts.size() > 0); + + ASSERT_TRUE(self_res1 == self_res2); + ASSERT_TRUE(self_res1 == self_res3); + ASSERT_TRUE(self_res1 == self_res4); + + + for(unsigned int i = 0; i < query.size(); ++i) + { + CollisionData query_data1; + query_data1.exhaustive = exhaustive; + CollisionData query_data2; + query_data2.exhaustive = exhaustive; + CollisionData query_data3; + query_data3.exhaustive = exhaustive; + CollisionData query_data4; + query_data4.exhaustive = exhaustive; + + manager1->collide(query[i], &query_data1, defaultCollisionFunction); + manager2->collide(query[i], &query_data2, defaultCollisionFunction); + manager3->collide(query[i], &query_data3, defaultCollisionFunction); + manager4->collide(query[i], &query_data4, defaultCollisionFunction); + + bool query_res1 = (query_data1.contacts.size() > 0); + bool query_res2 = (query_data2.contacts.size() > 0); + bool query_res3 = (query_data3.contacts.size() > 0); + bool query_res4 = (query_data4.contacts.size() > 0); + + ASSERT_TRUE(query_res1 == query_res2); + ASSERT_TRUE(query_res1 == query_res3); + ASSERT_TRUE(query_res1 == query_res4); + } + + + for(unsigned int i = 0; i < env.size(); ++i) + delete env[i]; + for(unsigned int i = 0; i < query.size(); ++i) + delete query[i]; + + delete manager1; + delete manager2; + delete manager3; + delete manager4; +} + + + +TEST(test_core, broad_phase_self_collision_exhaustive) +{ + bool exhaustive = true; + + std::vector<CollisionObject*> env; + generateEnvironments(env, 100); + + BroadPhaseCollisionManager* manager1 = new NaiveCollisionManager(); + BroadPhaseCollisionManager* manager2 = new SSaPCollisionManager(); + BroadPhaseCollisionManager* manager3 = new SaPCollisionManager(); + BroadPhaseCollisionManager* manager4 = new IntervalTreeCollisionManager(); + + + for(unsigned int i = 0; i < env.size(); ++i) + { + manager1->registerObject(env[i]); + manager2->registerObject(env[i]); + manager3->registerObject(env[i]); + manager4->registerObject(env[i]); + } + + manager1->setup(); + manager2->setup(); + manager3->setup(); + manager4->setup(); + + CollisionData self_data1; + self_data1.exhaustive = exhaustive; + CollisionData self_data2; + self_data2.exhaustive = exhaustive; + CollisionData self_data3; + self_data3.exhaustive = exhaustive; + CollisionData self_data4; + self_data4.exhaustive = exhaustive; + + manager1->collide(&self_data1, defaultCollisionFunction); + manager2->collide(&self_data2, defaultCollisionFunction); + manager3->collide(&self_data3, defaultCollisionFunction); + manager3->collide(&self_data4, defaultCollisionFunction); + + unsigned int self_res1 = self_data1.contacts.size(); + unsigned int self_res2 = self_data2.contacts.size(); + unsigned int self_res3 = self_data3.contacts.size(); + unsigned int self_res4 = self_data4.contacts.size(); + + ASSERT_TRUE(self_res1 == self_res2); + ASSERT_TRUE(self_res1 == self_res3); + ASSERT_TRUE(self_res1 == self_res4); + + + for(unsigned int i = 0; i < env.size(); ++i) + delete env[i]; + + delete manager1; + delete manager2; + delete manager3; + delete manager4; +} + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + +void generateEnvironments(std::vector<CollisionObject*>& env, int n) +{ + BVH_REAL extents[] = {-200, 200, -200, 200, -200, 200}; + BVH_REAL delta_trans[] = {1, 1, 1}; + std::vector<Transform> transforms; + std::vector<Transform> transforms2; + + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + Box box(5, 10, 20); + for(int i = 0; i < n; ++i) + { + BVHModel<OBB>* model = new BVHModel<OBB>(); + box.setLocalTransform(transforms[i].R, transforms[i].T); + generateBVHModel(*model, box, SimpleTransform()); + env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model))); + } + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + Sphere sphere(30); + for(int i = 0; i < n; ++i) + { + BVHModel<OBB>* model = new BVHModel<OBB>(); + sphere.setLocalTransform(transforms[i].R, transforms[i].T); + generateBVHModel(*model, sphere, SimpleTransform()); + env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model))); + } + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + Cylinder cylinder(10, 40); + for(int i = 0; i < n; ++i) + { + BVHModel<OBB>* model = new BVHModel<OBB>(); + cylinder.setLocalTransform(transforms[i].R, transforms[i].T); + generateBVHModel(*model, cylinder, SimpleTransform()); + env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model))); + } +} diff --git a/trunk/fcl_test/test/test_core_collision.cpp b/trunk/fcl_test/test/test_core_collision.cpp new file mode 100644 index 00000000..6623189f --- /dev/null +++ b/trunk/fcl_test/test/test_core_collision.cpp @@ -0,0 +1,847 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "fcl/collision.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> + +#if USE_PQP +#include <PQP.h> +#endif + +using namespace fcl; + +template<typename BV> +bool collide_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +template<typename BV> +bool collide_Test2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +bool collide_Test_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +bool collide_Test_RSS(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +template<typename BV> +bool test_collide_func(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method); + +int num_max_contacts = -1; +bool exhaustive = true; +bool enable_contact = true; + +std::vector<BVHCollisionPair> global_pairs; +std::vector<BVHCollisionPair> global_pairs_now; + +std::vector<std::pair<int, int> > PQP_pairs; + +TEST(collision_test, mesh_mesh) +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {1, 1, 1}; + int n = 10; + bool verbose = false; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + // collision + for(unsigned int i = 0; i < transforms.size(); ++i) + { + global_pairs.clear(); + global_pairs_now.clear(); +#if USE_PQP + PQP_pairs.clear(); + collide_PQP(transforms[i], p1, t1, p2, t2, PQP_pairs, verbose); + global_pairs.resize(PQP_pairs.size()); + for(unsigned int j = 0; j < PQP_pairs.size(); ++j) + global_pairs[j] = BVHCollisionPair(PQP_pairs[j].first, PQP_pairs[j].second); + + PQP_pairs.clear(); + collide_PQP2(transforms[i], p1, t1, p2, t2, PQP_pairs, verbose); + global_pairs_now.resize(PQP_pairs.size()); + for(unsigned int j = 0; j < PQP_pairs.size(); ++j) + global_pairs_now[j] = BVHCollisionPair(PQP_pairs[j].first, PQP_pairs[j].second); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } +#endif + + collide_Test<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + +#if USE_PQP + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } +#endif + + collide_Test<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<24> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<18> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test2<KDOP<16> >(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_OBB(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_OBB(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_OBB(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_RSS(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_RSS(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + collide_Test_RSS(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + test_collide_func<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + test_collide_func<OBB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + + test_collide_func<AABB>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN); + + ASSERT_TRUE(global_pairs.size() == global_pairs_now.size()); + for(unsigned int j = 0; j < global_pairs.size(); ++j) + { + ASSERT_TRUE(global_pairs[j].id1 == global_pairs_now[j].id1); + ASSERT_TRUE(global_pairs[j].id2 == global_pairs_now[j].id2); + } + } +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +template<typename BV> +bool collide_Test2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + std::vector<Vec3f> vertices1_new(vertices1.size()); + for(unsigned int i = 0; i < vertices1_new.size(); ++i) + { + vertices1_new[i] = tf.R * vertices1[i] + tf.T; + } + + + m1.beginModel(); + m1.addSubModel(vertices1_new, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1, pose2; + + MeshCollisionTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + + if(node.pairs.size() > 0) + { + std::vector<BVHCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHCollisionPairComp()); + + if(global_pairs.size() == 0) + { + global_pairs.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs[i] = pairs[i]; + } + else + { + global_pairs_now.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs_now[i] = pairs[i]; + } + + + if(verbose) + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + +template<typename BV> +bool collide_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + MeshCollisionTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + + if(node.pairs.size() > 0) + { + std::vector<BVHCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHCollisionPairComp()); + + if(global_pairs.size() == 0) + { + global_pairs.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs[i] = pairs[i]; + } + else + { + global_pairs_now.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs_now[i] = pairs[i]; + } + + if(verbose) + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + +bool collide_Test_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + MeshCollisionTraversalNodeOBB node; + if(!initialize(node, (const BVHModel<OBB>&)m1, pose1, (const BVHModel<OBB>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + if(node.pairs.size() > 0) + { + std::vector<BVHCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHCollisionPairComp()); + + if(global_pairs.size() == 0) + { + global_pairs.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs[i] = pairs[i]; + } + else + { + global_pairs_now.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs_now[i] = pairs[i]; + } + + + if(verbose) + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + +bool collide_Test_RSS(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + MeshCollisionTraversalNodeRSS node; + if(!initialize(node, (const BVHModel<RSS>&)m1, pose1, (const BVHModel<RSS>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + if(node.pairs.size() > 0) + { + std::vector<BVHCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHCollisionPairComp()); + + if(global_pairs.size() == 0) + { + global_pairs.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs[i] = pairs[i]; + } + else + { + global_pairs_now.resize(pairs.size()); + for(unsigned int i = 0 ; i < pairs.size(); ++i) + global_pairs_now[i] = pairs[i]; + } + + if(verbose) + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + +template<typename BV> +bool test_collide_func(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + std::vector<Contact> contacts; + int num_contacts = collide(&m1, pose1, &m2, pose2, num_max_contacts, enable_contact, exhaustive, contacts); + global_pairs_now.resize(num_contacts); + + for(int i = 0; i < num_contacts; ++i) + { + global_pairs_now[i].id1 = contacts[i].b1; + global_pairs_now[i].id2 = contacts[i].b2; + } + + std::sort(global_pairs_now.begin(), global_pairs_now.end(), BVHCollisionPairComp()); + + if(num_contacts > 0) return true; + else return false; +} diff --git a/trunk/fcl_test/test/test_core_collision_point.cpp b/trunk/fcl_test/test/test_core_collision_point.cpp new file mode 100644 index 00000000..832f8cc7 --- /dev/null +++ b/trunk/fcl_test/test/test_core_collision_point.cpp @@ -0,0 +1,516 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#if USE_SVMLIGHT + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "test_core_utility.h" + +#if USE_PQP +#include <PQP.h> +#endif + +using namespace fcl; + +template<typename BV> +bool collide_Test_PP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose = true); + +template<typename BV> +bool collide_Test_MP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose = true); +template<typename BV> +bool collide_Test_PM(const Transform& tf, + const std::vector<Vec3f>& vertices1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +bool collide_Test_PP_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose = true); + +bool collide_Test_MP_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose = true); + +bool collide_Test_PM_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose = true); + +int num_max_contacts = 1; + +int main() +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("env.obj", p1, t1); + loadOBJFile("rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + std::vector<Transform> transforms_ccd; // t0 + std::vector<Transform> transforms_ccd2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {1, 1, 1}; + int n = 10; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + std::cout << "test id " << i << std::endl; + + std::vector<std::pair<int, int> > PQP_pairs; + DistanceRes PQP_dist; + +#if USE_PQP + collide_PQP(transforms[i], p1, t1, p2, t2, PQP_pairs); + + distance_PQP(transforms[i], p1, t1, p2, t2, PQP_dist); +#endif + + collide_Test_PP<OBB>(transforms[i], p1, p2, SPLIT_METHOD_MEAN); + + collide_Test_PP<OBB>(transforms[i], p1, p2, SPLIT_METHOD_BV_CENTER); + + collide_Test_PP<OBB>(transforms[i], p1, p2, SPLIT_METHOD_MEDIAN); + + collide_Test_PM<OBB>(transforms[i], p1, p2, t2, SPLIT_METHOD_MEAN); + + collide_Test_PM<OBB>(transforms[i], p1, p2, t2, SPLIT_METHOD_BV_CENTER); + + collide_Test_PM<OBB>(transforms[i], p1, p2, t2, SPLIT_METHOD_MEDIAN); + + collide_Test_MP<OBB>(transforms[i], p1, t1, p2, SPLIT_METHOD_MEAN); + + collide_Test_MP<OBB>(transforms[i], p1, t1, p2, SPLIT_METHOD_BV_CENTER); + + collide_Test_MP<OBB>(transforms[i], p1, t1, p2, SPLIT_METHOD_MEDIAN); + + collide_Test_PP_OBB(transforms[i], p1, p2, SPLIT_METHOD_MEAN); + + collide_Test_PP_OBB(transforms[i], p1, p2, SPLIT_METHOD_BV_CENTER); + + collide_Test_PP_OBB(transforms[i], p1, p2, SPLIT_METHOD_MEDIAN); + + collide_Test_PM_OBB(transforms[i], p1, p2, t2, SPLIT_METHOD_MEAN); + + collide_Test_PM_OBB(transforms[i], p1, p2, t2, SPLIT_METHOD_BV_CENTER); + + collide_Test_PM_OBB(transforms[i], p1, p2, t2, SPLIT_METHOD_MEDIAN); + + collide_Test_MP_OBB(transforms[i], p1, t1, p2, SPLIT_METHOD_MEAN); + + collide_Test_MP_OBB(transforms[i], p1, t1, p2, SPLIT_METHOD_BV_CENTER); + + collide_Test_MP_OBB(transforms[i], p1, t1, p2, SPLIT_METHOD_MEDIAN); + + std::cout << std::endl; + } +} + +template<typename BV> +bool collide_Test_PP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudCollisionTraversalNode<BV> node; + + if(!initialize<BV, false, false>(node, m1, pose1, m2, pose2, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + +bool collide_Test_PP_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudCollisionTraversalNodeOBB node; + + if(!initialize(node, m1, pose1, m2, pose2, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + + +template<typename BV> +bool collide_Test_MP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudMeshCollisionTraversalNode<BV> node; + + if(!initialize<BV, false, false>(node, m2, pose2, m1, pose1, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + + +bool collide_Test_MP_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudMeshCollisionTraversalNodeOBB node; + + if(!initialize(node, m2, pose2, m1, pose1, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + + +template<typename BV> +bool collide_Test_PM(const Transform& tf, + const std::vector<Vec3f>& vertices1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudMeshCollisionTraversalNode<BV> node; + + if(!initialize<BV, false, false>(node, m1, pose1, m2, pose2, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + + +bool collide_Test_PM_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + PointCloudMeshCollisionTraversalNodeOBB node; + + if(!initialize(node, m1, pose1, m2, pose2, 0.6, 20)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + + collide(&node); + + if(node.pairs.size() > 0) + { + if(verbose) + { + std::cout << "in collision " << node.pairs.size() << ": " << std::endl; + + std::vector<BVHPointCollisionPair> pairs(node.pairs.size()); + for(unsigned i = 0; i < node.pairs.size(); ++i) + pairs[i] = node.pairs[i]; + + std::sort(pairs.begin(), pairs.end(), BVHPointCollisionPairComp()); + + for(unsigned i = 0; i < pairs.size(); ++i) + { + std::cout << "(" << pairs[i].id1_start << "(" << pairs[i].id1_num << ")" << " " << pairs[i].id2_start << "(" << pairs[i].id2_num << ")" << " " << pairs[i].collision_prob << ") "; + } + std::cout << std::endl; + } + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << node.max_collision_prob << std::endl; + if(verbose) std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + return false; + } +} + +#else +int main() +{ + return 1; +} +#endif + + diff --git a/trunk/fcl_test/test/test_core_collision_shape_mesh_consistency.cpp b/trunk/fcl_test/test/test_core_collision_shape_mesh_consistency.cpp new file mode 100644 index 00000000..cfa608fa --- /dev/null +++ b/trunk/fcl_test/test/test_core_collision_shape_mesh_consistency.cpp @@ -0,0 +1,1187 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/geometric_shape_to_BVH_model.h" +#include "fcl/collision.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> + +using namespace fcl; + +TEST(consistency_shapemesh, spheresphere) +{ + Sphere s1(20); + Sphere s2(10); + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb; + + + // s2 is within s1 + // both are shapes --> collision + // s1 is shape, s2 is mesh --> in collision + // s1 is mesh, s2 is shape --> collision free + // all are reasonable + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(40, 0, 0)); + pose_aabb.setTranslation(Vec3f(40, 0, 0)); + pose_obb.setTranslation(Vec3f(40, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(30, 0, 0)); + pose_aabb.setTranslation(Vec3f(30, 0, 0)); + pose_obb.setTranslation(Vec3f(30, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(29.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_obb.setTranslation(Vec3f(29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + + pose.setTranslation(Vec3f(-29.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(-29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_obb.setTranslation(Vec3f(-29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(-30, 0, 0)); + pose_aabb.setTranslation(Vec3f(-30, 0, 0)); + pose_obb.setTranslation(Vec3f(-30, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency_shapemesh, boxbox) +{ + Box s1(20, 40, 50); + Box s2(10, 10, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb; + + // s2 is within s1 + // both are shapes --> collision + // s1 is shape, s2 is mesh --> in collision + // s1 is mesh, s2 is shape --> collision free + // all are reasonable + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(15.01, 0, 0)); + pose_aabb.setTranslation(Vec3f(15.01, 0, 0)); + pose_obb.setTranslation(Vec3f(15.01, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(14.99, 0, 0)); + pose_aabb.setTranslation(Vec3f(14.99, 0, 0)); + pose_obb.setTranslation(Vec3f(14.99, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); +} + +TEST(consistency_shapemesh, spherebox) +{ + Sphere s1(20); + Box s2(5, 5, 5); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb; + + // s2 is within s1 + // both are shapes --> collision + // s1 is shape, s2 is mesh --> in collision + // s1 is mesh, s2 is shape --> collision free + // all are reasonable + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(22.4, 0, 0)); + pose_aabb.setTranslation(Vec3f(22.4, 0, 0)); + pose_obb.setTranslation(Vec3f(22.4, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(22.51, 0, 0)); + pose_aabb.setTranslation(Vec3f(22.51, 0, 0)); + pose_obb.setTranslation(Vec3f(22.51, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency_shapemesh, cylindercylinder) +{ + Cylinder s1(5, 10); + Cylinder s2(5, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb; + + pose.setTranslation(Vec3f(9.99, 0, 0)); + pose_aabb.setTranslation(Vec3f(9.99, 0, 0)); + pose_obb.setTranslation(Vec3f(9.99, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(10.01, 0, 0)); + pose_aabb.setTranslation(Vec3f(10.01, 0, 0)); + pose_obb.setTranslation(Vec3f(10.01, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency_shapemesh, conecone) +{ + Cone s1(5, 10); + Cone s2(5, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb; + + pose.setTranslation(Vec3f(9.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(9.9, 0, 0)); + pose_obb.setTranslation(Vec3f(9.9, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(10.1, 0, 0)); + pose_aabb.setTranslation(Vec3f(10.1, 0, 0)); + pose_obb.setTranslation(Vec3f(10.1, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(0, 0, 9.9)); + pose_aabb.setTranslation(Vec3f(0, 0, 9.9)); + pose_obb.setTranslation(Vec3f(0, 0, 9.9)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(0, 0, 10.1)); + pose_aabb.setTranslation(Vec3f(0, 0, 10.1)); + pose_obb.setTranslation(Vec3f(0, 0, 10.1)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_aabb, pose_aabb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2_obb, pose_obb, &s1, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_aabb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s2, pose, &s1_obb, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency, spheresphere) +{ + Sphere s1(20); + Sphere s2(10); + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb, pose_rss; + + pose.setTranslation(Vec3f(40, 0, 0)); + pose_aabb.setTranslation(Vec3f(40, 0, 0)); + pose_obb.setTranslation(Vec3f(40, 0, 0)); + pose_rss.setTranslation(Vec3f(40, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(30, 0, 0)); + pose_aabb.setTranslation(Vec3f(30, 0, 0)); + pose_obb.setTranslation(Vec3f(30, 0, 0)); + pose_rss.setTranslation(Vec3f(30, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(29.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_obb.setTranslation(Vec3f(29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_rss.setTranslation(Vec3f(29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(0, 0, 0)); + pose_aabb.setTranslation(Vec3f(0, 0, 0)); // mesh can not detect collision when ball contains ball + pose_obb.setTranslation(Vec3f(0, 0, 0)); // mesh can not detect collision when ball contains ball + pose_rss.setTranslation(Vec3f(0, 0, 0)); // mesh can not detect collision when ball contains ball + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(-29.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(-29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_obb.setTranslation(Vec3f(-29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + pose_rss.setTranslation(Vec3f(-29.8, 0, 0)); // 29.9 fails, result depends on mesh precision + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(-30, 0, 0)); + pose_aabb.setTranslation(Vec3f(-30, 0, 0)); + pose_obb.setTranslation(Vec3f(-30, 0, 0)); + pose_rss.setTranslation(Vec3f(-30, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency, boxbox) +{ + Box s1(20, 40, 50); + Box s2(10, 10, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb, pose_rss; + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + + pose.setTranslation(Vec3f(15.01, 0, 0)); + pose_aabb.setTranslation(Vec3f(15.01, 0, 0)); + pose_obb.setTranslation(Vec3f(15.01, 0, 0)); + pose_rss.setTranslation(Vec3f(15.01, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(14.99, 0, 0)); + pose_aabb.setTranslation(Vec3f(14.99, 0, 0)); + pose_obb.setTranslation(Vec3f(14.99, 0, 0)); + pose_rss.setTranslation(Vec3f(14.99, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); +} + +TEST(consistency, spherebox) +{ + Sphere s1(20); + Box s2(5, 5, 5); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb, pose_rss; + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); // mesh can not detect collision when box contains box + + pose.setTranslation(Vec3f(22.4, 0, 0)); + pose_aabb.setTranslation(Vec3f(22.4, 0, 0)); + pose_obb.setTranslation(Vec3f(22.4, 0, 0)); + pose_rss.setTranslation(Vec3f(22.4, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(22.51, 0, 0)); + pose_aabb.setTranslation(Vec3f(22.51, 0, 0)); + pose_obb.setTranslation(Vec3f(22.51, 0, 0)); + pose_rss.setTranslation(Vec3f(22.51, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency, cylindercylinder) +{ + Cylinder s1(5, 10); + Cylinder s2(5, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb, pose_rss; + + pose.setTranslation(Vec3f(9.99, 0, 0)); + pose_aabb.setTranslation(Vec3f(9.99, 0, 0)); + pose_obb.setTranslation(Vec3f(9.99, 0, 0)); + pose_rss.setTranslation(Vec3f(9.99, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(10.01, 0, 0)); + pose_aabb.setTranslation(Vec3f(10.01, 0, 0)); + pose_obb.setTranslation(Vec3f(10.01, 0, 0)); + pose_rss.setTranslation(Vec3f(10.01, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(consistency, conecone) +{ + Cone s1(5, 10); + Cone s2(5, 10); + + BVHModel<AABB> s1_aabb; + BVHModel<AABB> s2_aabb; + BVHModel<OBB> s1_obb; + BVHModel<OBB> s2_obb; + BVHModel<RSS> s1_rss; + BVHModel<RSS> s2_rss; + + generateBVHModel(s1_aabb, s1, SimpleTransform()); + generateBVHModel(s2_aabb, s2, SimpleTransform()); + generateBVHModel(s1_obb, s1, SimpleTransform()); + generateBVHModel(s2_obb, s2, SimpleTransform()); + generateBVHModel(s1_rss, s1, SimpleTransform()); + generateBVHModel(s2_rss, s2, SimpleTransform()); + + std::vector<Contact> contacts; + bool res; + + SimpleTransform pose, pose_aabb, pose_obb, pose_rss; + + pose.setTranslation(Vec3f(9.9, 0, 0)); + pose_aabb.setTranslation(Vec3f(9.9, 0, 0)); + pose_obb.setTranslation(Vec3f(9.9, 0, 0)); + pose_rss.setTranslation(Vec3f(9.9, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(10.1, 0, 0)); + pose_aabb.setTranslation(Vec3f(10.1, 0, 0)); + pose_obb.setTranslation(Vec3f(10.1, 0, 0)); + pose_rss.setTranslation(Vec3f(10.1, 0, 0)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + pose.setTranslation(Vec3f(0, 0, 9.9)); + pose_aabb.setTranslation(Vec3f(0, 0, 9.9)); + pose_obb.setTranslation(Vec3f(0, 0, 9.9)); + pose_rss.setTranslation(Vec3f(0, 0, 9.9)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + pose.setTranslation(Vec3f(0, 0, 10.1)); + pose_aabb.setTranslation(Vec3f(0, 0, 10.1)); + pose_obb.setTranslation(Vec3f(0, 0, 10.1)); + pose_rss.setTranslation(Vec3f(0, 0, 10.1)); + + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, pose, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_aabb, SimpleTransform(), &s2_aabb, pose_aabb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_obb, SimpleTransform(), &s2_obb, pose_obb, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1_rss, SimpleTransform(), &s2_rss, pose_rss, 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/trunk/fcl_test/test/test_core_conservative_advancement.cpp b/trunk/fcl_test/test/test_core_conservative_advancement.cpp new file mode 100644 index 00000000..d59131f2 --- /dev/null +++ b/trunk/fcl_test/test/test_core_conservative_advancement.cpp @@ -0,0 +1,538 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/conservative_advancement.h" +#include "test_core_utility.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" + + +using namespace fcl; + + +bool CA_linear_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool use_COM, + BVH_REAL& toc); + +bool linear_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + bool use_COM, + BVH_REAL& toc); + +bool CA_screw_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + BVH_REAL& toc); + + +bool screw_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + BVH_REAL& toc); + +// for spline test: the deBoor points are generated with screw motion, so will not pass tf1 and tf2 exactly +bool CA_spline_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + BVH_REAL& toc); + + +bool spline_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + BVH_REAL& toc); + + +unsigned int n_dcd_samples = 1000000; + +int main() +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {100, 100, 100}; + int n = 100; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + //std::cout << i << std::endl; + BVH_REAL toc; + bool res = CA_linear_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, toc); + + BVH_REAL toc2; + bool res2 = linear_interp_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, false, toc2); + + BVH_REAL toc3; + bool res3 = CA_linear_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, true, toc3); + + BVH_REAL toc4; + bool res4 = linear_interp_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, true, toc4); + + BVH_REAL toc5; + bool res5 = CA_screw_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, toc5); + + BVH_REAL toc6; + bool res6 = screw_interp_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, toc6); + + BVH_REAL toc7; + bool res7 = CA_spline_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, toc7); + + BVH_REAL toc8; + bool res8 = spline_interp_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, toc8); + + + if(!(i == 2 || i == 44 || i == 53)) + continue; + + + if(res) std::cout << "yes "; else std::cout << "no "; + if(res2) std::cout << "yes "; else std::cout << "no "; + if(res3) std::cout << "yes "; else std::cout << "no "; + if(res4) std::cout << "yes "; else std::cout << "no "; + if(res5) std::cout << "yes "; else std::cout << "no "; + if(res6) std::cout << "yes "; else std::cout << "no "; + if(res7) std::cout << "yes "; else std::cout << "no "; + if(res8) std::cout << "yes "; else std::cout << "no "; + + std::cout << std::endl; + + std::cout << toc << " " << toc2 << " " << toc3 << " " << toc4 << " " << toc5 << " " << toc6 << " " << toc7 << " " << toc8 << std::endl; + std::cout << std::endl; + } + + return 1; + +} + + +bool CA_linear_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool use_COM, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + std::vector<Contact> contacts; + + Vec3f m1_ref; + Vec3f m2_ref; + + if(use_COM) + { + for(unsigned int i = 0; i < vertices1.size(); ++i) + m1_ref += vertices1[i]; + m1_ref *= (1.0 / vertices1.size()); + + for(unsigned int i = 0; i < vertices2.size(); ++i) + m2_ref += vertices2[i]; + m2_ref *= (1.0 / vertices2.size()); + } + + InterpMotion<RSS> motion1(tf1.R, tf1.T, tf2.R, tf2.T, m1_ref); + InterpMotion<RSS> motion2(R2, T2, R2, T2, m2_ref); + + int b = conservativeAdvancement(&m1, &motion1, + &m2, &motion2, + 1, false, false, contacts, toc); + + return (b > 0); +} + +bool CA_screw_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + std::vector<Contact> contacts; + + Vec3f m1_ref; + Vec3f m2_ref; + + + ScrewMotion<RSS> motion1(tf1.R, tf1.T, tf2.R, tf2.T); + ScrewMotion<RSS> motion2(R2, T2, R2, T2); + + int b = conservativeAdvancement(&m1, &motion1, + &m2, &motion2, + 1, false, false, contacts, toc); + + + return (b > 0); + +} +bool linear_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + bool use_COM, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + Vec3f m1_ref; + Vec3f m2_ref; + + if(use_COM) + { + for(unsigned int i = 0; i < vertices1.size(); ++i) + m1_ref += vertices1[i]; + m1_ref *= (1.0 / vertices1.size()); + + for(unsigned int i = 0; i < vertices2.size(); ++i) + m2_ref += vertices2[i]; + m2_ref *= (1.0 / vertices2.size()); + } + + InterpMotion<RSS> motion1(tf1.R, tf1.T, tf2.R, tf2.T, m1_ref); + + for(unsigned int i = 0; i <= nsamples; ++i) + { + BVH_REAL curt = i / (BVH_REAL)nsamples; + + SimpleTransform pose; + motion1.integrate(curt); + motion1.getCurrentTransform(pose); + + MeshCollisionTraversalNodeRSS node; + if(!initialize(node, (const BVHModel<RSS>&)m1, pose, (const BVHModel<RSS>&)m2, SimpleTransform(R2, T2))) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = 1; + node.exhaustive = false; + node.enable_contact = false; + + collide(&node); + + if(node.pairs.size() > 0) + { + toc = curt; + return true; + } + } + + toc = 1; + return false; +} + +bool screw_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + + Vec3f m1_ref; + Vec3f m2_ref; + + + ScrewMotion<RSS> motion1(tf1.R, tf1.T, tf2.R, tf2.T); + + for(unsigned int i = 0; i <= nsamples; ++i) + { + BVH_REAL curt = i / (BVH_REAL)nsamples; + + SimpleTransform pose; + motion1.integrate(curt); + motion1.getCurrentTransform(pose); + + MeshCollisionTraversalNodeRSS node; + if(!initialize(node, (const BVHModel<RSS>&)m1, pose, (const BVHModel<RSS>&)m2, SimpleTransform(R2, T2))) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = 1; + node.exhaustive = false; + node.enable_contact = false; + + collide(&node); + + if(node.pairs.size() > 0) + { + toc = curt; + return true; + } + } + + toc = 1; + return false; +} + + +bool CA_spline_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + ScrewMotion<RSS> motion(tf1.R, tf1.T, tf2.R, tf2.T); + Vec3f Td_1[4]; + Vec3f Rd_1[4]; + Vec3f Td_2[4]; + Vec3f Rd_2[4]; + + for(int i = 0; i < 4; ++i) + { + motion.integrate(i / 4.0); + Matrix3f R; + Vec3f T; + motion.getCurrentTransform(R, T); + SimpleQuaternion q; + q.fromRotation(R); + Vec3f axis; + BVH_REAL angle; + q.toAxisAngle(axis, angle); + Td_1[i] = T; + Rd_1[i] = axis * angle; + } + + for(int i = 0; i < 4; ++i) + { + Td_2[i].setValue(0); + Rd_2[i].setValue(0); + } + + SplineMotion<RSS> motion1(Td_1[0], Td_1[1], Td_1[2], Td_1[3], + Rd_1[0], Rd_1[1], Rd_1[2], Rd_1[3]); + + SplineMotion<RSS> motion2(Td_2[0], Td_2[1], Td_2[2], Td_2[3], + Rd_2[0], Rd_2[1], Rd_2[2], Rd_2[3]); + + std::vector<Contact> contacts; + + int b = conservativeAdvancement(&m1, &motion1, + &m2, &motion2, + 1, false, false, contacts, toc); + + + return (b > 0); + +} + +bool spline_interp_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + BVH_REAL& toc) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + + ScrewMotion<RSS> motion(tf1.R, tf1.T, tf2.R, tf2.T); + Vec3f Td_1[4]; + Vec3f Rd_1[4]; + Vec3f Td_2[4]; + Vec3f Rd_2[4]; + + for(int i = 0; i < 4; ++i) + { + motion.integrate(i / 4.0); + Matrix3f R; + Vec3f T; + motion.getCurrentTransform(R, T); + SimpleQuaternion q; + q.fromRotation(R); + Vec3f axis; + BVH_REAL angle; + q.toAxisAngle(axis, angle); + Td_1[i] = T; + Rd_1[i] = axis * angle; + } + + for(int i = 0; i < 4; ++i) + { + Td_2[i].setValue(0); + Rd_2[i].setValue(0); + } + + SplineMotion<RSS> motion1(Td_1[0], Td_1[1], Td_1[2], Td_1[3], + Rd_1[0], Rd_1[1], Rd_1[2], Rd_1[3]); + + SplineMotion<RSS> motion2(Td_2[0], Td_2[1], Td_2[2], Td_2[3], + Rd_2[0], Rd_2[1], Rd_2[2], Rd_2[3]); + + + for(unsigned int i = 0; i < nsamples; ++i) + { + BVH_REAL curt = i / (BVH_REAL)nsamples; + + motion1.integrate(curt); + motion2.integrate(curt); + + SimpleTransform tf1, tf2; + motion1.getCurrentTransform(tf1); + motion2.getCurrentTransform(tf2); + + MeshCollisionTraversalNodeRSS node; + if(!initialize(node, (const BVHModel<RSS>&)m1, tf1, (const BVHModel<RSS>&)m2, tf2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = 1; + node.exhaustive = false; + node.enable_contact = false; + + collide(&node); + + if(node.pairs.size() > 0) + { + toc = curt; + return true; + } + } + + toc = 1; + return false; +} diff --git a/trunk/fcl_test/test/test_core_continuous_collision.cpp b/trunk/fcl_test/test/test_core_continuous_collision.cpp new file mode 100644 index 00000000..45556607 --- /dev/null +++ b/trunk/fcl_test/test/test_core_continuous_collision.cpp @@ -0,0 +1,296 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> +#include <boost/timer.hpp> + +using namespace fcl; + +template<typename BV> +bool continuous_collide_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool refit_bottomup, bool verbose); + +template<typename BV> +bool discrete_continuous_collide_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + bool verbose); + +int num_max_contacts = -1; +bool exhaustive = true; +bool enable_contact = true; +unsigned int n_dcd_samples = 10; + + + +TEST(ccd_test, mesh_mesh_bottomup) +{ + double t_ccd = 0; + double t_dcd = 0; + + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {10, 10, 10}; + int n = 100; + bool verbose = false; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + bool res, res2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + boost::timer timer1; + res = discrete_continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, verbose); + t_dcd += timer1.elapsed(); + + boost::timer timer2; + res2 = continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, true, verbose); + t_ccd += timer2.elapsed(); + if(res) + ASSERT_TRUE(res == res2); + else + { + if(res2) + std::cout << "CCD detects collision missed in DCD" << std::endl; + } + } + + std::cout << "dcd timing: " << t_dcd << " sec" << std::endl; + std::cout << "ccd timing: " << t_ccd << " sec" << std::endl; +} + + +TEST(ccd_test, mesh_mesh_topdown) +{ + double t_ccd = 0; + double t_dcd = 0; + + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {10, 10, 10}; + int n = 100; + bool verbose = false; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + bool res, res2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + boost::timer timer1; + res = discrete_continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, n_dcd_samples, verbose); + t_dcd += timer1.elapsed(); + + boost::timer timer2; + res2 = continuous_collide_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + t_ccd += timer2.elapsed(); + if(res) + ASSERT_TRUE(res == res2); + else + { + if(res2) + std::cout << "CCD detects collision missed in DCD" << std::endl; + } + } + std::cout << "dcd timing: " << t_dcd << " sec" << std::endl; + std::cout << "ccd timing: " << t_ccd << " sec" << std::endl; +} + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +template<typename BV> +bool continuous_collide_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool refit_bottomup, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + std::vector<Vec3f> vertices1_new(vertices1.size()); + for(unsigned int i = 0; i < vertices1_new.size(); ++i) + { + vertices1_new[i] = tf1.R * vertices1[i] + tf1.T; + } + + m1.beginModel(); + m1.addSubModel(vertices1_new, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1, pose2; + + MeshCollisionTraversalNode<BV> node0; + + if(!initialize<BV>(node0, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node0.enable_statistics = verbose; + node0.num_max_contacts = num_max_contacts; + node0.exhaustive = exhaustive; + node0.enable_contact = enable_contact; + + collide(&node0); + if(node0.pairs.size() > 0) + return true; + + // update + for(unsigned int i = 0; i < vertices1_new.size(); ++i) + { + vertices1_new[i] = tf2.R * vertices1[i] + tf2.T; + } + + m1.beginUpdateModel(); + m1.updateSubModel(vertices1_new); + m1.endUpdateModel(true, refit_bottomup); + + m2.beginUpdateModel(); + m2.updateSubModel(vertices2); + m2.endUpdateModel(true, refit_bottomup); + + SimpleTransform pose11, pose21; + + MeshContinuousCollisionTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose11, m2, pose21)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + if(node.pairs.size() > 0) + return true; + else + return false; +} + +template<typename BV> +bool discrete_continuous_collide_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + unsigned int nsamples, + bool verbose) +{ + std::vector<Vec3f> vertices1_t1(vertices1.size()); + for(unsigned int i = 0; i < vertices1_t1.size(); ++i) + { + vertices1_t1[i] = tf1.R * vertices1[i] + tf1.T; + } + + std::vector<Vec3f> vertices1_t2(vertices1.size()); + for(unsigned int i = 0; i < vertices1_t2.size(); ++i) + { + vertices1_t2[i] = tf2.R * vertices1[i] + tf2.T; + } + + std::vector<Vec3f> vertices1_t(vertices1.size()); + + for(unsigned int i = 0; i <= nsamples; ++i) + { + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + BVH_REAL delta = i / (BVH_REAL)nsamples; + + for(unsigned int j = 0; j < vertices1_t.size(); ++j) + vertices1_t[j] = vertices1_t1[j] * (1 - delta) + vertices1_t2[j] * delta; + + m1.beginModel(); + m1.addSubModel(vertices1_t, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1, pose2; + + MeshCollisionTraversalNode<BV> node; + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = num_max_contacts; + node.exhaustive = exhaustive; + node.enable_contact = enable_contact; + + collide(&node); + + if(node.pairs.size() > 0) return true; + } + + return false; +} diff --git a/trunk/fcl_test/test/test_core_deformable_object.cpp b/trunk/fcl_test/test/test_core_deformable_object.cpp new file mode 100644 index 00000000..ef208829 --- /dev/null +++ b/trunk/fcl_test/test/test_core_deformable_object.cpp @@ -0,0 +1,357 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include <assimp/assimp.hpp> +#include <assimp/aiScene.h> +#include <assimp/aiPostProcess.h> +#include <cstdlib> +#include <cstdio> +#include <boost/timer.hpp> + +#define _strdup strdup + +using namespace fcl; + +unsigned int n_dcd_samples = 10; + +bool loadPLYFile(const std::string& fileName, float scalarFactor, std::vector<Vec3f>& vert_list, + std::vector<Triangle>& tri_list); + +void lionTest(); + +void ballTest(); + +void lionTest_DCD(); + +void ballTest_DCD(); + +int main() +{ + lionTest(); + ballTest(); + lionTest_DCD(); + ballTest_DCD(); + + return 1; +} + +void lionTest() +{ + std::vector<Vec3f> p; + std::vector<Triangle> t; + + + std::string base = std::string("test/deformable_data/breakinglion/"); + + BVHModel<AABB> m; + m.bv_splitter.reset(new BVSplitter<AABB>(SPLIT_METHOD_MEDIAN)); + + double timing = 0; + + for(int i = 16; i <= 60; ++i) + { + char buffer[10]; + sprintf(buffer, "%d", i); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p, t); + // std::cout << p.size() << " " << t.size() << std::endl; + + boost::timer timer; + + if(i == 16) + { + m.beginModel(); + m.addSubModel(p, t); + m.endModel(); + } + else + { + m.beginUpdateModel(); + m.updateSubModel(p); + m.endUpdateModel(true, true); + } + + SimpleTransform tf1, tf2; + + MeshCollisionTraversalNode<AABB> node; + initialize(node, m, tf1, m, tf2); + selfCollide(&node); + + timing += timer.elapsed(); + + // if(node.pairs.size() > 0) std::cout << "collision" << std::endl; + // else std::cout << "collision free" << std::endl; + } + + std::cout << "timing: " << timing << " sec" << std::endl; +} + + +void lionTest_DCD() +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + + std::string base = std::string("test/deformable_data/breakinglion/"); + + + double timing = 0; + + for(int i = 17; i <= 60; ++i) + { + { + char buffer[10]; + sprintf(buffer, "%d", i - 1); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p1, t1); + } + + { + char buffer[10]; + sprintf(buffer, "%d", i); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p2, t2); + } + + std::vector<Vec3f> p(p1.size()); + + boost::timer timer; + + for(unsigned int n = 0; n <= n_dcd_samples; ++n) + { + // std::cout << i << " " << n << std::endl; + double delta = n / (double)n_dcd_samples; + for(unsigned int j = 0; j < p.size(); ++j) + { + p[j] = p1[j] * (1 - delta) + p2[j] * delta; + } + + BVHModel<AABB> m; + m.bv_splitter.reset(new BVSplitter<AABB>(SPLIT_METHOD_MEDIAN)); + + m.beginModel(); + m.addSubModel(p, t1); + m.endModel(); + + SimpleTransform tf1, tf2; + + MeshCollisionTraversalNode<AABB> node; + initialize(node, m, tf1, m, tf2); + selfCollide(&node); + + if(node.pairs.size() > 0) break; + } + + timing += timer.elapsed(); + + //if(node.pairs.size() > 0) std::cout << "collision" << std::endl; + //else std::cout << "collision free" << std::endl; + } + + std::cout << "timing: " << timing << " sec" << std::endl; +} + + +void ballTest() +{ + std::vector<Vec3f> p; + std::vector<Triangle> t; + + + std::string base = std::string("test/deformable_data/balls16/balls16_"); + + BVHModel<AABB> m; + m.bv_splitter.reset(new BVSplitter<AABB>(SPLIT_METHOD_MEDIAN)); + + double timing = 0; + + for(int i = 0; i <= 75; ++i) + { + char buffer[10]; + sprintf(buffer, "%d", i); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p, t); + // std::cout << p.size() << " " << t.size() << std::endl; + + boost::timer timer; + + if(i == 0) + { + m.beginModel(); + m.addSubModel(p, t); + m.endModel(); + } + else + { + m.beginUpdateModel(); + m.updateSubModel(p); + m.endUpdateModel(true, true); + } + + SimpleTransform tf1, tf2; + + MeshCollisionTraversalNode<AABB> node; + initialize(node, m, tf1, m, tf2); + selfCollide(&node); + + timing += timer.elapsed(); + + // if(node.pairs.size() > 0) std::cout << "collision" << std::endl; + // else std::cout << "collision free" << std::endl; + } + + std::cout << "timing: " << timing << " sec" << std::endl; +} + + +void ballTest_DCD() +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + + + std::string base = std::string("test/deformable_data/balls16/balls16_"); + + double timing = 0; + + for(int i = 1; i <= 75; ++i) + { + { + char buffer[10]; + sprintf(buffer, "%d", i - 1); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p1, t1); + } + + { + char buffer[10]; + sprintf(buffer, "%d", i); + std::string filename = base + std::string(buffer) + std::string(".ply"); + loadPLYFile(filename, 1.0, p2, t2); + } + + std::vector<Vec3f> p(p1.size()); + + boost::timer timer; + + for(unsigned int n = 0; n <= n_dcd_samples; ++n) + { + // std::cout << i << " " << n << std::endl; + double delta = n / (double)n_dcd_samples; + for(unsigned int j = 0; j < p.size(); ++j) + { + p[j] = p1[j] * (1 - delta) + p2[j] * delta; + } + + BVHModel<AABB> m; + m.bv_splitter.reset(new BVSplitter<AABB>(SPLIT_METHOD_MEDIAN)); + + m.beginModel(); + m.addSubModel(p, t1); + m.endModel(); + + SimpleTransform tf1, tf2; + + MeshCollisionTraversalNode<AABB> node; + initialize(node, m, tf1, m, tf2); + selfCollide(&node); + + if(node.pairs.size() > 0) break; + } + + timing += timer.elapsed(); + + //if(node.pairs.size() > 0) std::cout << "collision" << std::endl; + //else std::cout << "collision free" << std::endl; + } + + std::cout << "timing: " << timing << " sec" << std::endl; +} + +bool loadPLYFile(const std::string& fileName, float scalarFactor, std::vector<Vec3f>& vert_list, + std::vector<Triangle>& tri_list) +{ + Assimp::Importer importer; + + const aiScene* scene = importer.ReadFile(fileName, + 0); + + if(!scene) return false; + + int mNumMeshes = scene->mNumMeshes; + + int numVertices = 0; + int numTriangles = 0; + for(int i = 0; i < mNumMeshes; ++i) + { + aiMesh* mesh = scene->mMeshes[i]; + numVertices += mesh->mNumVertices; + numTriangles += mesh->mNumFaces; + } + + vert_list.resize(numVertices); + tri_list.resize(numTriangles); + + + + int v_index = 0; + int t_index = 0; + + for(int i = 0; i < mNumMeshes; ++i) + { + aiMesh* mesh = scene->mMeshes[i]; + + for(int j = 0 ; j < mesh->mNumVertices; ++j) + { + vert_list[v_index + j].setValue(mesh->mVertices[j].x, mesh->mVertices[j].y, mesh->mVertices[j].z); + } + + + for(int j = 0; j < mesh->mNumFaces; ++j) + { + tri_list[t_index + j].set(mesh->mFaces[j].mIndices[0] + v_index, + mesh->mFaces[j].mIndices[1] + v_index, + mesh->mFaces[j].mIndices[2] + v_index); + } + v_index += mesh->mNumVertices; + t_index += mesh->mNumFaces; + } + + return true; +} diff --git a/trunk/fcl_test/test/test_core_distance.cpp b/trunk/fcl_test/test/test_core_distance.cpp new file mode 100644 index 00000000..62a57431 --- /dev/null +++ b/trunk/fcl_test/test/test_core_distance.cpp @@ -0,0 +1,329 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> +#include <boost/timer.hpp> + + +#if USE_PQP +#include <PQP.h> +#endif + +using namespace fcl; + + +void distance_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, + int qsize, + DistanceRes& distance_result, + bool verbose = true); + +template<typename BV> +void distance_Test2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, + int qsize, + DistanceRes& distance_result, + bool verbose = true); + +bool collide_Test_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose); + + +bool verbose = false; +BVH_REAL DELTA = 0.001; + +inline bool nearlyEqual(const Vec3f& a, const Vec3f& b) +{ + if(fabs(a[0] - b[0]) > DELTA) return false; + if(fabs(a[1] - b[1]) > DELTA) return false; + if(fabs(a[2] - b[2]) > DELTA) return false; + return true; +} + +TEST(collision_core, mesh_distance) +{ + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + std::vector<Transform> transforms_ccd; // t0 + std::vector<Transform> transforms_ccd2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {1, 1, 1}; + int n = 10; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + double dis_time = 0; + double col_time = 0; + + DistanceRes res, res_now; + for(unsigned int i = 0; i < transforms.size(); ++i) + { + boost::timer timer_col; + collide_Test_OBB(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + col_time += timer_col.elapsed(); + +#if USE_PQP + distance_PQP(transforms[i], p1, t1, p2, t2, res, verbose); + + distance_PQP2(transforms[i], p1, t1, p2, t2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); +#endif + + boost::timer timer_dist; +#if USE_PQP + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 2, res_now, verbose); + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); +#else + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 2, res, verbose); +#endif + dis_time += timer_dist.elapsed(); + + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, 2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, 2, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + + distance_Test2<RSS>(transforms[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, 20, res_now, verbose); + + ASSERT_TRUE(fabs(res.distance - res_now.distance) < DELTA); + ASSERT_TRUE(fabs(res.distance) < DELTA || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); + } + + std::cout << "distance timing: " << dis_time << " sec" << std::endl; + std::cout << "collision timing: " << col_time << " sec" << std::endl; + +} + + +int main(int argc, char **argv) +{ + srand(time(NULL)); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +void distance_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, + int qsize, + DistanceRes& distance_result, + bool verbose) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + MeshDistanceTraversalNodeRSS node; + + if(!initialize(node, (const BVHModel<RSS>&)m1, SimpleTransform(tf.R, tf.T), (const BVHModel<RSS>&)m2, SimpleTransform())) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + + distance(&node, NULL, qsize); + + // points are in local coordinate, to global coordinate + Vec3f p1 = tf.R * node.p1 + tf.T; + Vec3f p2 = node.p2; + + + distance_result.distance = node.min_distance; + distance_result.p1 = p1; + distance_result.p2 = p2; + + if(verbose) + { + std::cout << "distance " << node.min_distance << std::endl; + + std::cout << p1[0] << " " << p1[1] << " " << p1[2] << std::endl; + std::cout << p2[0] << " " << p2[1] << " " << p2[2] << std::endl; + std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + } +} + +template<typename BV> +void distance_Test2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, + int qsize, + DistanceRes& distance_result, + bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + MeshDistanceTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + + distance(&node, NULL, qsize); + + distance_result.distance = node.min_distance; + distance_result.p1 = node.p1; + distance_result.p2 = node.p2; + + if(verbose) + { + std::cout << "distance " << node.min_distance << std::endl; + + std::cout << node.p1[0] << " " << node.p1[1] << " " << node.p1[2] << std::endl; + std::cout << node.p2[0] << " " << node.p2[1] << " " << node.p2[2] << std::endl; + std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; + } +} + + +bool collide_Test_OBB(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + MeshCollisionTraversalNodeOBB node; + if(!initialize(node, (const BVHModel<OBB>&)m1, SimpleTransform(tf.R, tf.T), (const BVHModel<OBB>&)m2, SimpleTransform())) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = 1; + node.exhaustive = false; + node.enable_contact = false; + + collide(&node); + + if(node.pairs.size() > 0) + return true; + else + return false; +} + diff --git a/trunk/fcl_test/test/test_core_front_list.cpp b/trunk/fcl_test/test/test_core_front_list.cpp new file mode 100644 index 00000000..6f146989 --- /dev/null +++ b/trunk/fcl_test/test/test_core_front_list.cpp @@ -0,0 +1,412 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> + +using namespace fcl; + +template<typename BV> +bool collide_front_list_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool refit_bottomup, bool verbose); + +bool collide_front_list_OBB_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, bool verbose); + +bool collide_front_list_RSS_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, bool verbose); + +template<typename BV> +bool collide_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose); + +// TODO: randomly still have some runtime error +TEST(collision_test, front_list) +{ + //srand(time(NULL)); + std::vector<Vec3f> p1, p2; + std::vector<Triangle> t1, t2; + loadOBJFile("test/env.obj", p1, t1); + loadOBJFile("test/rob.obj", p2, t2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {1, 1, 1}; + int n = 10; + bool verbose = false; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + bool res, res2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<AABB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<AABB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<AABB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<AABB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<OBB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<OBB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<OBB>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<RSS>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<RSS>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<RSS>(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<KDOP<16> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<KDOP<16> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<16> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<KDOP<16> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<16> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<KDOP<16> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<KDOP<18> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<KDOP<18> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<18> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<KDOP<18> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<18> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<KDOP<18> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<KDOP<24> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_Test<KDOP<24> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<24> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_Test<KDOP<24> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, false, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<KDOP<24> >(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_Test<KDOP<24> >(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, false, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_OBB_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_OBB_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<OBB>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_OBB_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + ASSERT_TRUE(res == res2); + } + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + res2 = collide_front_list_RSS_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEDIAN, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + res2 = collide_front_list_RSS_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_MEAN, verbose); + ASSERT_TRUE(res == res2); + res = collide_Test<RSS>(transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + res2 = collide_front_list_RSS_Test(transforms[i], transforms2[i], p1, t1, p2, t2, SPLIT_METHOD_BV_CENTER, verbose); + ASSERT_TRUE(res == res2); + } +} + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + +template<typename BV> +bool collide_front_list_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, + bool refit_bottomup, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + BVHFrontList front_list; + + + std::vector<Vec3f> vertices1_new(vertices1.size()); + for(unsigned int i = 0; i < vertices1_new.size(); ++i) + { + vertices1_new[i] = tf1.R * vertices1[i] + tf1.T; + } + + m1.beginModel(); + m1.addSubModel(vertices1_new, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1, pose2; + + MeshCollisionTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = std::numeric_limits<int>::max(); // front technique needs all the contacts; + node.exhaustive = true; + node.enable_contact = false; + + collide(&node, &front_list); + + if(verbose) std::cout << "front list size " << front_list.size() << std::endl; + + + // update the mesh + for(unsigned int i = 0; i < vertices1.size(); ++i) + { + vertices1_new[i] = tf2.R * vertices1[i] + tf2.T; + } + + m1.beginReplaceModel(); + m1.replaceSubModel(vertices1_new); + m1.endReplaceModel(true, refit_bottomup); + + m2.beginReplaceModel(); + m2.replaceSubModel(vertices2); + m2.endReplaceModel(true, refit_bottomup); + + node.pairs.clear(); + collide(&node, &front_list); + + if(node.pairs.size() > 0) + return true; + else + return false; +} + + +bool collide_front_list_OBB_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, bool verbose) +{ + BVHModel<OBB> m1; + BVHModel<OBB> m2; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + BVHFrontList front_list; + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf1.R, tf1.T), pose2; + + MeshCollisionTraversalNodeOBB node; + + if(!initialize(node, (const BVHModel<OBB>&)m1, pose1, (const BVHModel<OBB>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = std::numeric_limits<int>::max(); // front technique needs all the contacts; + node.exhaustive = true; + node.enable_contact = false; + + collide(&node, &front_list); + + if(verbose) std::cout << "front list size " << front_list.size() << std::endl; + + + // update the mesh + pose1.setTransform(tf2.R, tf2.T); + if(!initialize(node, (const BVHModel<OBB>&)m1, pose1, (const BVHModel<OBB>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.pairs.clear(); + collide(&node, &front_list); + + if(node.pairs.size() > 0) + return true; + else + return false; +} + + +bool collide_front_list_RSS_Test(const Transform& tf1, const Transform& tf2, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + SplitMethodType split_method, bool verbose) +{ + BVHModel<RSS> m1; + BVHModel<RSS> m2; + m1.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + m2.bv_splitter.reset(new BVSplitter<RSS>(split_method)); + + BVHFrontList front_list; + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf1.R, tf1.T), pose2; + + MeshCollisionTraversalNodeRSS node; + + if(!initialize(node, (const BVHModel<RSS>&)m1, pose1, (const BVHModel<RSS>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = std::numeric_limits<int>::max(); // front technique needs all the contacts; + node.exhaustive = true; + node.enable_contact = false; + + collide(&node, &front_list); + + if(verbose) std::cout << "front list size " << front_list.size() << std::endl; + + + // update the mesh + pose1.setTransform(tf2.R, tf2.T); + if(!initialize(node, (const BVHModel<RSS>&)m1, pose1, (const BVHModel<RSS>&)m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.pairs.clear(); + collide(&node, &front_list); + + if(node.pairs.size() > 0) + return true; + else + return false; +} + + +template<typename BV> +bool collide_Test(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, SplitMethodType split_method, bool verbose) +{ + BVHModel<BV> m1; + BVHModel<BV> m2; + m1.bv_splitter.reset(new BVSplitter<BV>(split_method)); + m2.bv_splitter.reset(new BVSplitter<BV>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + SimpleTransform pose1(tf.R, tf.T), pose2; + + MeshCollisionTraversalNode<BV> node; + + if(!initialize<BV>(node, m1, pose1, m2, pose2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = verbose; + node.num_max_contacts = std::numeric_limits<int>::max(); + node.exhaustive = true; + node.enable_contact = false; + + collide(&node); + + + if(node.pairs.size() > 0) + return true; + else + return false; +} + diff --git a/trunk/fcl_test/test/test_core_geometric_shapes.cpp b/trunk/fcl_test/test/test_core_geometric_shapes.cpp new file mode 100644 index 00000000..8a44b8a9 --- /dev/null +++ b/trunk/fcl_test/test/test_core_geometric_shapes.cpp @@ -0,0 +1,500 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#include "fcl/geometric_shapes_intersect.h" +#include "fcl/collision.h" +#include "test_core_utility.h" +#include <gtest/gtest.h> + +using namespace fcl; + +BVH_REAL extents [6] = {0, 0, 0, 10, 10, 10}; + +TEST(shapeIntersection, spheresphere) +{ + Sphere s1(20); + Sphere s2(10); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + bool res; + + s2.setLocalTranslation(Vec3f(40, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + s2.setLocalTranslation(Vec3f(30, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + s2.setLocalTranslation(Vec3f(29.9, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(0, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(-29.9, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(-30, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(shapeIntersection, boxbox) +{ + Box s1(20, 40, 50); + Box s2(10, 10, 10); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + + bool res; + + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(15, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + SimpleQuaternion q; + q.fromAxisAngle(Vec3f(0, 0, 1), (BVH_REAL)3.140 / 6); + Matrix3f R; + q.toRotation(R); + s2.setLocalRotation(R); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); +} + +TEST(shapeIntersection, spherebox) +{ + Sphere s1(20); + Box s2(5, 5, 5); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + + bool res; + + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(22.5, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + s2.setLocalTranslation(Vec3f(22.4, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); +} + +TEST(shapeIntersection, cylindercylinder) +{ + Cylinder s1(5, 10); + Cylinder s2(5, 10); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + + bool res; + + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(9.9, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(10, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(shapeIntersection, conecone) +{ + Cone s1(5, 10); + Cone s2(5, 10); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + + bool res; + + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(9.9, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(10.001, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + s2.setLocalTranslation(Vec3f(0, 0, 9.9)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(0, 0, 10)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(shapeIntersection, conecylinder) +{ + Cylinder s1(5, 10); + Cone s2(5, 10); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + std::vector<Contact> contacts; + + bool res; + + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(9.9, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(10, 0, 0)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + s2.setLocalTranslation(Vec3f(0, 0, 9.9)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_TRUE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_TRUE(res); + + s2.setLocalTranslation(Vec3f(0, 0, 10)); + res = shapeIntersect(s1, SimpleTransform(), s2, SimpleTransform()); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(), &s2, SimpleTransform(), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); + + res = shapeIntersect(s1, SimpleTransform(transform.R, transform.T), s2, SimpleTransform(transform.R, transform.T)); + ASSERT_FALSE(res); + contacts.clear(); + res = (collide(&s1, SimpleTransform(transform.R, transform.T), &s2, SimpleTransform(transform.R, transform.T), 1, false, false, contacts) > 0); + ASSERT_FALSE(res); +} + +TEST(shapeIntersection, spheretriangle) +{ + Sphere s(10); + Vec3f t[3]; + t[0].setValue(20, 0, 0); + t[1].setValue(-20, 0, 0); + t[2].setValue(0, 20, 0); + + Transform transform; + generateRandomTransform(extents, transform); + Transform identity; + + bool res; + + res = shapeTriangleIntersect(s, SimpleTransform(), t[0], t[1], t[2]); + ASSERT_TRUE(res); + + res = shapeTriangleIntersect(s, SimpleTransform(transform.R, transform.T), t[0], t[1], t[2], transform.R, transform.T); + ASSERT_TRUE(res); + + t[0].setValue(30, 0, 0); + t[1].setValue(10, -20, 0); + t[2].setValue(10, 20, 0); + res = shapeTriangleIntersect(s, SimpleTransform(), t[0], t[1], t[2]); + ASSERT_FALSE(res); + + res = shapeTriangleIntersect(s, SimpleTransform(transform.R, transform.T), t[0], t[1], t[2], transform.R, transform.T); + ASSERT_FALSE(res); + + t[0].setValue(30, 0, 0); + t[1].setValue(9.9, -20, 0); + t[2].setValue(9.9, 20, 0); + res = shapeTriangleIntersect(s, SimpleTransform(), t[0], t[1], t[2]); + ASSERT_TRUE(res); + + res = shapeTriangleIntersect(s, SimpleTransform(transform.R, transform.T), t[0], t[1], t[2], transform.R, transform.T); + ASSERT_TRUE(res); +} + + + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/trunk/fcl_test/test/test_core_utility.h b/trunk/fcl_test/test/test_core_utility.h new file mode 100644 index 00000000..693b6f50 --- /dev/null +++ b/trunk/fcl_test/test/test_core_utility.h @@ -0,0 +1,665 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + + +#ifndef FCL_TEST_CORE_UTILITY_H +#define FCL_TEST_CORE_UTILITY_H + +#include "fcl/vec_3f.h" +#include "fcl/matrix_3f.h" +#include "fcl/primitive.h" +#include <cstdio> +#include <vector> +#include <iostream> +#include <string.h> +using namespace fcl; + +#if USE_PQP +#include <PQP.h> +#endif + +struct Transform +{ + Matrix3f R; + Vec3f T; + + Transform() + { + R.setIdentity(); + } +}; + + +#if USE_PQP + +struct CollisionPairComp_PQP +{ + bool operator()(const CollisionPair& a, const CollisionPair& b) + { + if(a.id1 == b.id1) + return a.id2 < b.id2; + return a.id1 < b.id1; + } +}; + +inline void sortCollisionPair_PQP(CollisionPair* pairs, int n) +{ + std::vector<CollisionPair> pair_array(n); + for(int i = 0; i < n; ++i) + pair_array[i] = pairs[i]; + + std::sort(pair_array.begin(), pair_array.end(), CollisionPairComp_PQP()); + + for(int i = 0; i < n; ++i) + pairs[i] = pair_array[i]; +} + +inline bool collide_PQP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + std::vector<std::pair<int, int> >& results, + bool verbose = true) +{ + PQP_Model m1, m2; + + m1.BeginModel(); + for(unsigned int i = 0; i < triangles1.size(); ++i) + { + const Triangle& t = triangles1[i]; + const Vec3f& p1_ = vertices1[t[0]]; + const Vec3f& p2_ = vertices1[t[1]]; + const Vec3f& p3_ = vertices1[t[2]]; + + Vec3f p1 = tf.R * p1_ + tf.T; + Vec3f p2 = tf.R * p2_ + tf.T; + Vec3f p3 = tf.R * p3_ + tf.T; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m1.AddTri(q1, q2, q3, i); + } + + m1.EndModel(); + + + m2.BeginModel(); + for(unsigned int i = 0; i < triangles2.size(); ++i) + { + const Triangle& t = triangles2[i]; + const Vec3f& p1 = vertices2[t[0]]; + const Vec3f& p2 = vertices2[t[1]]; + const Vec3f& p3 = vertices2[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m2.AddTri(q1, q2, q3, i); + } + + m2.EndModel(); + + + PQP_CollideResult res; + PQP_REAL R1[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL R2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL T1[3] = {0, 0, 0}; + PQP_REAL T2[3] = {0, 0, 0}; + PQP_Collide(&res, R1, T1, &m1, R2, T2, &m2); + + if(res.NumPairs() > 0) + { + sortCollisionPair_PQP(res.pairs, res.NumPairs()); + results.resize(res.NumPairs()); + + for(int i = 0; i < res.NumPairs(); ++i) + { + results[i] = std::make_pair(res.Id1(i), res.Id2(i)); + } + + if(verbose) + std::cout << "in collision " << res.NumPairs() << ": " << std::endl; + if(verbose) std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + return false; + } +} + + +inline bool collide_PQP2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + std::vector<std::pair<int, int> >& results, bool verbose = true) +{ + PQP_Model m1, m2; + + m1.BeginModel(); + for(unsigned int i = 0; i < triangles1.size(); ++i) + { + const Triangle& t = triangles1[i]; + const Vec3f& p1 = vertices1[t[0]]; + const Vec3f& p2 = vertices1[t[1]]; + const Vec3f& p3 = vertices1[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m1.AddTri(q1, q2, q3, i); + } + + m1.EndModel(); + + + m2.BeginModel(); + for(unsigned int i = 0; i < triangles2.size(); ++i) + { + const Triangle& t = triangles2[i]; + const Vec3f& p1 = vertices2[t[0]]; + const Vec3f& p2 = vertices2[t[1]]; + const Vec3f& p3 = vertices2[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m2.AddTri(q1, q2, q3, i); + } + + m2.EndModel(); + + + PQP_CollideResult res; + PQP_REAL R1[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL R2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL T1[3] = {0, 0, 0}; + PQP_REAL T2[3] = {0, 0, 0}; + T1[0] = tf.T[0]; + T1[1] = tf.T[1]; + T1[2] = tf.T[2]; + for(int i = 0; i < 3; ++i) + { + R1[i][0] = tf.R[i][0]; + R1[i][1] = tf.R[i][1]; + R1[i][2] = tf.R[i][2]; + } + + PQP_Collide(&res, R1, T1, &m1, R2, T2, &m2); + + if(res.NumPairs() > 0) + { + sortCollisionPair_PQP(res.pairs, res.NumPairs()); + results.resize(res.NumPairs()); + for(int i = 0; i < res.NumPairs(); ++i) + { + results[i] = std::make_pair(res.Id1(i), res.Id2(i)); + } + + if(verbose) + std::cout << "in collision " << res.NumPairs() << ": " << std::endl; + if(verbose) std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + return true; + } + else + { + if(verbose) std::cout << "collision free " << std::endl; + if(verbose) std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + return false; + } +} + +#endif + + +struct DistanceRes +{ + double distance; + Vec3f p1; + Vec3f p2; +}; + +#if USE_PQP +inline bool distance_PQP(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + DistanceRes& distance_result, + bool verbose = true) +{ + PQP_Model m1, m2; + + m1.BeginModel(); + for(unsigned int i = 0; i < triangles1.size(); ++i) + { + const Triangle& t = triangles1[i]; + const Vec3f& p1_ = vertices1[t[0]]; + const Vec3f& p2_ = vertices1[t[1]]; + const Vec3f& p3_ = vertices1[t[2]]; + + Vec3f p1 = tf.R * p1_ + tf.T; + Vec3f p2 = tf.R * p2_ + tf.T; + Vec3f p3 = tf.R * p3_ + tf.T; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m1.AddTri(q1, q2, q3, i); + } + + m1.EndModel(); + + + m2.BeginModel(); + for(unsigned int i = 0; i < triangles2.size(); ++i) + { + const Triangle& t = triangles2[i]; + const Vec3f& p1 = vertices2[t[0]]; + const Vec3f& p2 = vertices2[t[1]]; + const Vec3f& p3 = vertices2[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m2.AddTri(q1, q2, q3, i); + } + + m2.EndModel(); + + + PQP_DistanceResult res; + PQP_REAL R1[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL R2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL T1[3] = {0, 0, 0}; + PQP_REAL T2[3] = {0, 0, 0}; + + PQP_Distance(&res, R1, T1, &m1, R2, T2, &m2, 0.01, 0.01); + + + distance_result.distance = res.distance; + distance_result.p1.setValue(res.p1[0], res.p1[1], res.p1[2]); + distance_result.p2.setValue(res.p2[0], res.p2[1], res.p2[2]); + + + if(verbose) + { + std::cout << "distance " << res.distance << std::endl; + std::cout << res.p1[0] << " " << res.p1[1] << " " << res.p1[2] << std::endl; + std::cout << res.p2[0] << " " << res.p2[1] << " " << res.p2[2] << std::endl; + std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + } + + return true; +} + + +inline bool distance_PQP2(const Transform& tf, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2, + DistanceRes& distance_result, bool verbose = true) +{ + PQP_Model m1, m2; + + m1.BeginModel(); + for(unsigned int i = 0; i < triangles1.size(); ++i) + { + const Triangle& t = triangles1[i]; + const Vec3f& p1 = vertices1[t[0]]; + const Vec3f& p2 = vertices1[t[1]]; + const Vec3f& p3 = vertices1[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m1.AddTri(q1, q2, q3, i); + } + + m1.EndModel(); + + + m2.BeginModel(); + for(unsigned int i = 0; i < triangles2.size(); ++i) + { + const Triangle& t = triangles2[i]; + const Vec3f& p1 = vertices2[t[0]]; + const Vec3f& p2 = vertices2[t[1]]; + const Vec3f& p3 = vertices2[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m2.AddTri(q1, q2, q3, i); + } + + m2.EndModel(); + + + PQP_DistanceResult res; + PQP_REAL R1[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL R2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL T1[3] = {0, 0, 0}; + PQP_REAL T2[3] = {0, 0, 0}; + + T1[0] = tf.T[0]; + T1[1] = tf.T[1]; + T1[2] = tf.T[2]; + for(int i = 0; i < 3; ++i) + { + R1[i][0] = tf.R[i][0]; + R1[i][1] = tf.R[i][1]; + R1[i][2] = tf.R[i][2]; + } + + PQP_Distance(&res, R1, T1, &m1, R2, T2, &m2, 0.01, 0.01); + + + Vec3f p1_temp(res.p1[0], res.p1[1], res.p1[2]); + Vec3f p2_temp(res.p2[0], res.p2[1], res.p2[2]); + + Vec3f p1 = tf.R * p1_temp + tf.T; + Vec3f p2 = p2_temp; + + + distance_result.distance = res.distance; + distance_result.p1 = p1; + distance_result.p2 = p2; + + + if(verbose) + { + std::cout << "distance " << res.distance << std::endl; + std::cout << p1[0] << " " << p1[1] << " " << p1[2] << std::endl; + std::cout << p2[0] << " " << p2[1] << " " << p2[2] << std::endl; + std::cout << res.num_bv_tests << " " << res.num_tri_tests << std::endl; + } + + return true; +} + +#endif + +inline BVH_REAL rand_interval(BVH_REAL rmin, BVH_REAL rmax) +{ + BVH_REAL t = rand() / ((BVH_REAL)RAND_MAX + 1); + return (t * (rmax - rmin) + rmin); +} + +inline void loadOBJFile(const char* filename, std::vector<Vec3f>& points, std::vector<Triangle>& triangles) +{ + + FILE* file = fopen(filename, "rb"); + if(!file) + { + std::cerr << "file not exist" << std::endl; + return; + } + + bool has_normal = false; + bool has_texture = false; + char line_buffer[2000]; + while(fgets(line_buffer, 2000, file)) + { + char* first_token = strtok(line_buffer, "\r\n\t "); + if(!first_token || first_token[0] == '#' || first_token[0] == 0) + continue; + + switch(first_token[0]) + { + case 'v': + { + if(first_token[1] == 'n') + { + strtok(NULL, "\t "); + strtok(NULL, "\t "); + strtok(NULL, "\t "); + has_normal = true; + } + else if(first_token[1] == 't') + { + strtok(NULL, "\t "); + strtok(NULL, "\t "); + has_texture = true; + } + else + { + BVH_REAL x = (BVH_REAL)atof(strtok(NULL, "\t ")); + BVH_REAL y = (BVH_REAL)atof(strtok(NULL, "\t ")); + BVH_REAL z = (BVH_REAL)atof(strtok(NULL, "\t ")); + Vec3f p(x, y, z); + points.push_back(p); + } + } + break; + case 'f': + { + Triangle tri; + char* data[30]; + int n = 0; + while((data[n] = strtok(NULL, "\t \r\n")) != NULL) + { + if(strlen(data[n])) + n++; + } + + for(int t = 0; t < (n - 2); ++t) + { + if((!has_texture) && (!has_normal)) + { + tri[0] = atoi(data[0]) - 1; + tri[1] = atoi(data[1]) - 1; + tri[2] = atoi(data[2]) - 1; + } + else + { + const char *v1; + for(int i = 0; i < 3; i++) + { + // vertex ID + if(i == 0) + v1 = data[0]; + else + v1 = data[t + i]; + + tri[i] = atoi(v1) - 1; + + // texture coordinate + const char *v2 = strchr(v1 + 1, '/'); + + if(v2) + { + strchr(v2 + 1, '/'); + } + } + } + triangles.push_back(tri); + } + } + } + } +} + + +inline void eulerToMatrix(BVH_REAL a, BVH_REAL b, BVH_REAL c, Matrix3f& R) +{ + BVH_REAL c1 = cos(a); + BVH_REAL c2 = cos(b); + BVH_REAL c3 = cos(c); + BVH_REAL s1 = sin(a); + BVH_REAL s2 = sin(b); + BVH_REAL s3 = sin(c); + + R.setValue(c1 * c2, - c2 * s1, s2, + c3 * s1 + c1 * s2 * s3, c1 * c3 - s1 * s2 * s3, - c2 * s3, + s1 * s3 - c1 * c3 * s2, c3 * s1 * s2 + c1 * s3, c2 * c3); +} + +inline void generateRandomTransform(BVH_REAL extents[6], Transform& transform) +{ + BVH_REAL x = rand_interval(extents[0], extents[3]); + BVH_REAL y = rand_interval(extents[1], extents[4]); + BVH_REAL z = rand_interval(extents[2], extents[5]); + + const BVH_REAL pi = 3.1415926; + BVH_REAL a = rand_interval(0, 2 * pi); + BVH_REAL b = rand_interval(0, 2 * pi); + BVH_REAL c = rand_interval(0, 2 * pi); + + eulerToMatrix(a, b, c, transform.R); + transform.T.setValue(x, y, z); +} + +inline void generateRandomTransform(BVH_REAL extents[6], std::vector<Transform>& transforms, std::vector<Transform>& transforms2, BVH_REAL delta_trans[3], BVH_REAL delta_rot, int n) +{ + transforms.resize(n); + transforms2.resize(n); + for(int i = 0; i < n; ++i) + { + BVH_REAL x = rand_interval(extents[0], extents[3]); + BVH_REAL y = rand_interval(extents[1], extents[4]); + BVH_REAL z = rand_interval(extents[2], extents[5]); + + const BVH_REAL pi = 3.1415926; + BVH_REAL a = rand_interval(0, 2 * pi); + BVH_REAL b = rand_interval(0, 2 * pi); + BVH_REAL c = rand_interval(0, 2 * pi); + + eulerToMatrix(a, b, c, transforms[i].R); + transforms[i].T.setValue(x, y, z); + + BVH_REAL deltax = rand_interval(-delta_trans[0], delta_trans[0]); + BVH_REAL deltay = rand_interval(-delta_trans[1], delta_trans[1]); + BVH_REAL deltaz = rand_interval(-delta_trans[2], delta_trans[2]); + + BVH_REAL deltaa = rand_interval(-delta_rot, delta_rot); + BVH_REAL deltab = rand_interval(-delta_rot, delta_rot); + BVH_REAL deltac = rand_interval(-delta_rot, delta_rot); + + eulerToMatrix(a + deltaa, b + deltab, c + deltac, transforms2[i].R); + transforms2[i].T.setValue(x + deltax, y + deltay, z + deltaz); + } +} + + +inline void generateRandomTransform_ccd(BVH_REAL extents[6], std::vector<Transform>& transforms, std::vector<Transform>& transforms2, BVH_REAL delta_trans[3], BVH_REAL delta_rot, int n, + const std::vector<Vec3f>& vertices1, const std::vector<Triangle>& triangles1, + const std::vector<Vec3f>& vertices2, const std::vector<Triangle>& triangles2) +{ + transforms.resize(n); + transforms2.resize(n); + + for(int i = 0; i < n;) + { + BVH_REAL x = rand_interval(extents[0], extents[3]); + BVH_REAL y = rand_interval(extents[1], extents[4]); + BVH_REAL z = rand_interval(extents[2], extents[5]); + + const BVH_REAL pi = 3.1415926; + BVH_REAL a = rand_interval(0, 2 * pi); + BVH_REAL b = rand_interval(0, 2 * pi); + BVH_REAL c = rand_interval(0, 2 * pi); + + Transform tf; + + eulerToMatrix(a, b, c, tf.R); + tf.T.setValue(x, y, z); + + std::vector<std::pair<int, int> > results; +#if USE_PQP + if(!collide_PQP(tf, vertices1, triangles1, vertices2, triangles2, results, false)) +#endif + { + transforms[i] = tf; + + BVH_REAL deltax = rand_interval(-delta_trans[0], delta_trans[0]); + BVH_REAL deltay = rand_interval(-delta_trans[1], delta_trans[1]); + BVH_REAL deltaz = rand_interval(-delta_trans[2], delta_trans[2]); + + BVH_REAL deltaa = rand_interval(-delta_rot, delta_rot); + BVH_REAL deltab = rand_interval(-delta_rot, delta_rot); + BVH_REAL deltac = rand_interval(-delta_rot, delta_rot); + + eulerToMatrix(a + deltaa, b + deltab, c + deltac, transforms2[i].R); + transforms2[i].T.setValue(x + deltax, y + deltay, z + deltaz); + ++i; + } + } +} + + + + +#endif diff --git a/trunk/fcl_test/test/timer.cpp b/trunk/fcl_test/test/timer.cpp new file mode 100644 index 00000000..40a5ddcb --- /dev/null +++ b/trunk/fcl_test/test/timer.cpp @@ -0,0 +1,121 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "timer.h" +#include <cstddef> + + +Timer::Timer() +{ +#ifdef _WIN32 + QueryPerformanceFrequency(&frequency); + startCount.QuadPart = 0; + endCount.QuadPart = 0; +#else + startCount.tv_sec = startCount.tv_usec = 0; + endCount.tv_sec = endCount.tv_usec = 0; +#endif + + stopped = 0; + startTimeInMicroSec = 0; + endTimeInMicroSec = 0; +} + + +Timer::~Timer() +{ +} + + +void Timer::start() +{ + stopped = 0; // reset stop flag +#ifdef _WIN32 + QueryPerformanceCounter(&startCount); +#else + gettimeofday(&startCount, NULL); +#endif +} + + +void Timer::stop() +{ + stopped = 1; // set timer stopped flag + +#ifdef _WIN32 + QueryPerformanceCounter(&endCount); +#else + gettimeofday(&endCount, NULL); +#endif +} + + +double Timer::getElapsedTimeInMicroSec() +{ +#ifdef _WIN32 + if(!stopped) + QueryPerformanceCounter(&endCount); + + startTimeInMicroSec = startCount.QuadPart * (1000000.0 / frequency.QuadPart); + endTimeInMicroSec = endCount.QuadPart * (1000000.0 / frequency.QuadPart); +#else + if(!stopped) + gettimeofday(&endCount, NULL); + + startTimeInMicroSec = (startCount.tv_sec * 1000000.0) + startCount.tv_usec; + endTimeInMicroSec = (endCount.tv_sec * 1000000.0) + endCount.tv_usec; +#endif + + return endTimeInMicroSec - startTimeInMicroSec; +} + + +double Timer::getElapsedTimeInMilliSec() +{ + return this->getElapsedTimeInMicroSec() * 0.001; +} + + +double Timer::getElapsedTimeInSec() +{ + return this->getElapsedTimeInMicroSec() * 0.000001; +} + + +double Timer::getElapsedTime() +{ + return this->getElapsedTimeInMilliSec(); +} diff --git a/trunk/fcl_test/test/timer.h b/trunk/fcl_test/test/timer.h new file mode 100644 index 00000000..7eb04c0b --- /dev/null +++ b/trunk/fcl_test/test/timer.h @@ -0,0 +1,70 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#ifdef _WIN32 +#include <windows.h> +#else +#include <sys/time.h> +#endif + +/** Timer for CPU + */ +class Timer +{ +public: + Timer(); + ~Timer(); + + void start(); ///< start timer + void stop(); ///< stop the timer + double getElapsedTime(); ///< get elapsed time in milli-second + double getElapsedTimeInSec(); ///< get elapsed time in second (same as getElapsedTime) + double getElapsedTimeInMilliSec(); ///< get elapsed time in milli-second + double getElapsedTimeInMicroSec(); ///< get elapsed time in micro-second + +private: + double startTimeInMicroSec; ///< starting time in micro-second + double endTimeInMicroSec; ///< ending time in micro-second + int stopped; ///< stop flag +#ifdef _WIN32 + LARGE_INTEGER frequency; ///< ticks per second + LARGE_INTEGER startCount; + LARGE_INTEGER endCount; +#else + timeval startCount; + timeval endCount; +#endif +}; diff --git a/trunk/fcl_test/test/timing_test.cpp b/trunk/fcl_test/test/timing_test.cpp new file mode 100644 index 00000000..d02db47d --- /dev/null +++ b/trunk/fcl_test/test/timing_test.cpp @@ -0,0 +1,247 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \author Jia Pan */ + +#include "fcl/traversal_node_bvhs.h" +#include "fcl/collision_node.h" +#include "fcl/simple_setup.h" +#include "fcl/collision.h" +#include "test_core_utility.h" +#include "timer.h" + +#if USE_PQP +#include <PQP.h> +#endif + + +int main() +{ + std::vector<Vec3f> vertices1, vertices2; + std::vector<Triangle> triangles1, triangles2; + loadOBJFile("test/env.obj", vertices1, triangles1); + loadOBJFile("test/rob.obj", vertices2, triangles2); + + std::vector<Transform> transforms; // t0 + std::vector<Transform> transforms2; // t1 + BVH_REAL extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; + BVH_REAL delta_trans[] = {1, 1, 1}; + int n = 100000; + bool verbose = false; + + generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + + std::cout << "FCL timing 2" << std::endl; + { + double t_fcl = 0; + + BVHModel<OBB> m1; + BVHModel<OBB> m2; + SplitMethodType split_method = SPLIT_METHOD_MEAN; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + m1.makeParentRelative(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + m2.makeParentRelative(); + + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + Transform& tf = transforms[i]; + + MeshCollisionTraversalNodeOBB node; + if(!initialize(node, (const BVHModel<OBB>&)m1, SimpleTransform(tf.R, tf.T), (const BVHModel<OBB>&)m2, SimpleTransform(R2, T2))) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = -1; + node.exhaustive = false; + node.enable_contact = false; + + Timer timer; + timer.start(); + collide2(&node); + timer.stop(); + t_fcl += timer.getElapsedTime(); + + //std::cout << node.pairs.size() << std::endl; + } + + std::cout << "fcl timing " << t_fcl << " ms" << std::endl; + } + + + std::cout << "PQP timing" << std::endl; +#if USE_PQP + { + double t_pqp = 0; + + PQP_Model m1, m2; + + m1.BeginModel(); + for(unsigned int i = 0; i < triangles1.size(); ++i) + { + const Triangle& t = triangles1[i]; + const Vec3f& p1 = vertices1[t[0]]; + const Vec3f& p2 = vertices1[t[1]]; + const Vec3f& p3 = vertices1[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m1.AddTri(q1, q2, q3, i); + } + m1.EndModel(); + + + m2.BeginModel(); + for(unsigned int i = 0; i < triangles2.size(); ++i) + { + const Triangle& t = triangles2[i]; + const Vec3f& p1 = vertices2[t[0]]; + const Vec3f& p2 = vertices2[t[1]]; + const Vec3f& p3 = vertices2[t[2]]; + + PQP_REAL q1[3]; + PQP_REAL q2[3]; + PQP_REAL q3[3]; + + q1[0] = p1[0]; q1[1] = p1[1]; q1[2] = p1[2]; + q2[0] = p2[0]; q2[1] = p2[1]; q2[2] = p2[2]; + q3[0] = p3[0]; q3[1] = p3[1]; q3[2] = p3[2]; + + m2.AddTri(q1, q2, q3, i); + } + m2.EndModel(); + + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + Transform& tf = transforms[i]; + PQP_CollideResult res; + PQP_REAL R1[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL R2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + PQP_REAL T1[3] = {0, 0, 0}; + PQP_REAL T2[3] = {0, 0, 0}; + T1[0] = tf.T[0]; + T1[1] = tf.T[1]; + T1[2] = tf.T[2]; + for(int i = 0; i < 3; ++i) + { + R1[i][0] = tf.R[i][0]; + R1[i][1] = tf.R[i][1]; + R1[i][2] = tf.R[i][2]; + } + + Timer timer; + timer.start(); + PQP_Collide(&res, R1, T1, &m1, R2, T2, &m2, PQP_FIRST_CONTACT); + timer.stop(); + t_pqp += timer.getElapsedTime(); + + //std::cout << res.NumPairs() << std::endl; + } + + std::cout << "pqp timing " << t_pqp << " ms" << std::endl; + } +#endif + + std::cout << "FCL timing" << std::endl; + { + double t_fcl = 0; + + BVHModel<OBB> m1; + BVHModel<OBB> m2; + SplitMethodType split_method = SPLIT_METHOD_MEAN; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + Transform& tf = transforms[i]; + + MeshCollisionTraversalNodeOBB node; + if(!initialize(node, (const BVHModel<OBB>&)m1, SimpleTransform(tf.R, tf.T), (const BVHModel<OBB>&)m2, SimpleTransform(R2, T2))) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = -1; + node.exhaustive = false; + node.enable_contact = false; + + Timer timer; + timer.start(); + collide(&node); + timer.stop(); + t_fcl += timer.getElapsedTime(); + + //std::cout << node.pairs.size() << std::endl; + } + + std::cout << "fcl timing " << t_fcl << " ms" << std::endl; + } + + + + return 1; + +} -- GitLab