diff --git a/.github/workflows/build_doc.yml b/.github/workflows/build_doc.yml index a2ee453953d..9e445535ac4 100644 --- a/.github/workflows/build_doc.yml +++ b/.github/workflows/build_doc.yml @@ -159,7 +159,8 @@ jobs: with: script: | const error = process.env.ERRORMSG - const msg = "There was an error while building the doc: \n"+error + const job_url = `${context.serverUrl}/CGAL/cgal/actions/runs/${context.runId}` + const msg = "There was an error while building the doc: \n"+error + "\n" + job_url github.rest.issues.createComment({ owner: "CGAL", repo: "cgal", diff --git a/.github/workflows/list_workflow_last_run.css b/.github/workflows/list_workflow_last_run.css new file mode 100644 index 00000000000..a3955383311 --- /dev/null +++ b/.github/workflows/list_workflow_last_run.css @@ -0,0 +1,30 @@ +table { + margin-left: auto; + margin-right: auto; + margin-bottom: 24px; + border-spacing: 0; + border-bottom: 2px solid black; + border-top: 2px solid black; +} +table th { + padding: 3px 10px; + background-color: white; + border-top: none; + border-left: none; + border-right: none; + border-bottom: 1px solid black; +} +table td { + padding: 3px 10px; + border-top: none; + border-left: none; + border-bottom: none; + border-right: none; +} + +table tr.odd { + background-color: #f0f0f0; +} +table tr.even { + background-color: #e0e0e0; +} diff --git a/.github/workflows/list_workflow_last_run.yml b/.github/workflows/list_workflow_last_run.yml new file mode 100644 index 00000000000..79b1d2c0634 --- /dev/null +++ b/.github/workflows/list_workflow_last_run.yml @@ -0,0 +1,43 @@ + name: List workflow last run + on: + workflow_dispatch: + schedule: + - cron: "0 10 * * 1" + env: + GH_TOKEN: ${{ github.token }} + jobs: + list_workflow: + runs-on: ubuntu-latest + outputs: + messages: ${{ steps.cat_output.outputs.message }} + steps: + - name: checkout + uses: actions/checkout@v3 + - name: run script + run: | + chmod +x ./Scripts/developer_scripts/list_cgal_workflows_last_run.sh + ./Scripts/developer_scripts/list_cgal_workflows_last_run.sh > output.md + - name: convert markdown to html + run: | + sudo apt-get update && sudo apt-get install -y pandoc + pandoc -f markdown -t html --self-contained --css=.github/workflows/list_workflow_last_run.css -o output.html output.md + - name: set_output + id: cat_output + run: | + delimiter="$(openssl rand -hex 8)" + echo "message<<${delimiter}" >> "${GITHUB_OUTPUT}" + echo "Subject:List workflow run \nContent-Type: text/html; charset=\"UTF-8\"\n" >> "${GITHUB_OUTPUT}" + echo "" >> "${GITHUB_OUTPUT}" + cat output.html >> "${GITHUB_OUTPUT}" + echo "" >> "${GITHUB_OUTPUT}" + echo "${delimiter}" >> "${GITHUB_OUTPUT}" + call_send_email: + needs: list_workflow + uses: ./.github/workflows/send_email.yml + with: + message: ${{needs.list_workflow.outputs.messages}} + secrets: + email: ${{ secrets.CGAL_SEND_WORKFLOW_LIST_EMAIL_TO }} + private_key: ${{ secrets.CGAL_SEND_WORKFLOW_LIST_EMAIL_SSH_PRIVATE_KEY }} + user: ${{ secrets.CGAL_SEND_WORKFLOW_LIST_EMAIL_SSH_USER }} + host: ${{ secrets.CGAL_SEND_WORKFLOW_LIST_EMAIL_SSH_HOST }} diff --git a/.github/workflows/send_email.yml b/.github/workflows/send_email.yml new file mode 100644 index 00000000000..cb990eca146 --- /dev/null +++ b/.github/workflows/send_email.yml @@ -0,0 +1,31 @@ +name: Send Email using SSH + +on: + workflow_call: + inputs: + message: + description: 'Message to send' + required: true + type: string + secrets: + email: + required: true + private_key: + required: true + user: + required: true + host: + required: true + +jobs: + send_email: + runs-on: ubuntu-latest + steps: + - name: install ssh keys + run: | + install -m 600 -D /dev/null ~/.ssh/id_rsa + echo "${{ secrets.private_key }}" > ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.host }} > ~/.ssh/known_hosts + - name: send email via ssh + run: | + echo -e '${{ inputs.message }}' | ssh ${{ secrets.user }}@${{ secrets.host }} "/sbin/sendmail -t ${{ secrets.email }}" diff --git a/.github/workflows/wiki_notification.yml b/.github/workflows/wiki_notification.yml new file mode 100644 index 00000000000..456fefa51e3 --- /dev/null +++ b/.github/workflows/wiki_notification.yml @@ -0,0 +1,38 @@ +name: Wiki Notification + +on: gollum + +jobs: + prepare_email: + runs-on: ubuntu-latest + outputs: + messages: ${{ steps.set-result.outputs.result }} + steps: + - name: get informations and prepare email + uses: actions/github-script@v6 + id: set-result + with: + result-encoding: string + script: | + const payload = context.payload; + const actor = payload.sender; + const pages = payload.pages; + let messages = "Subject:Updates to CGAL Wiki \nContent-Type: text/html\n"; + messages += ""; + messages += `

The following CGAL Wiki page were modified by "${actor.login}":

"; + console.log( messages ); + return messages; + call_send_email: + needs: prepare_email + uses: ./.github/workflows/send_email.yml + with: + message: ${{needs.prepare_email.outputs.messages}} + secrets: + email: ${{ secrets.CGAL_SEND_WIKI_EMAIL_TO }} + private_key: ${{ secrets.CGAL_SEND_WIKI_EMAIL_SSH_PRIVATE_KEY }} + user: ${{ secrets.CGAL_SEND_WIKI_EMAIL_SSH_USER }} + host: ${{ secrets.CGAL_SEND_WIKI_EMAIL_SSH_HOST }} diff --git a/AABB_tree/doc/AABB_tree/PackageDescription.txt b/AABB_tree/doc/AABB_tree/PackageDescription.txt index d59794e62d5..c032420bb76 100644 --- a/AABB_tree/doc/AABB_tree/PackageDescription.txt +++ b/AABB_tree/doc/AABB_tree/PackageDescription.txt @@ -8,7 +8,7 @@ \cgalPkgDescriptionBegin{3D Fast Intersection and Distance Computation,PkgAABBTree} \cgalPkgPicture{aabb-teaser-thumb.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Stéphane Tayeb, Camille Wormser} +\cgalPkgAuthors{Pierre Alliez, Stéphane Tayeb, and Camille Wormser} \cgalPkgDesc{The AABB (axis-aligned bounding box) tree component offers a static data structure and algorithms to perform efficient intersection and distance queries on sets of finite 3D geometric objects.} \cgalPkgManuals{Chapter_3D_Fast_Intersection_and_Distance_Computation,PkgAABBTreeRef} \cgalPkgSummaryEnd diff --git a/AABB_tree/include/CGAL/AABB_tree/internal/triangle_datum_covering.h b/AABB_tree/include/CGAL/AABB_tree/internal/triangle_datum_covering.h index 6f7df8ae57c..69babb2c160 100644 --- a/AABB_tree/include/CGAL/AABB_tree/internal/triangle_datum_covering.h +++ b/AABB_tree/include/CGAL/AABB_tree/internal/triangle_datum_covering.h @@ -143,18 +143,18 @@ struct AABB_covered_triangle_tree_traits // Primitive ID --> box vector pos --> Bounding Box using BPMB = internal::Vector_property_map; - using BPM = CGAL::Property_map_binder; + using BPM = CGAL::Compose_property_map; // Primitive ID --> point vector pos --> Reference Point using RPPMB = internal::Vector_property_map; - using RPPM = CGAL::Property_map_binder; + using RPPM = CGAL::Compose_property_map; // Primitive ID --> Datum pos vector pos --> Datum pos --> Datum // The vector of data has size nf, but the vector of datum pos has size tree.size() using DPPMB = internal::Vector_property_map; // pos --> Datum pos - using DPPM = CGAL::Property_map_binder; // PID --> Datum pos + using DPPM = CGAL::Compose_property_map; // PID --> Datum pos using DPMB = internal::Vector_property_map; // Datum pos --> Datum - using DPM = CGAL::Property_map_binder; // PID --> Datum + using DPM = CGAL::Compose_property_map; // PID --> Datum using Primitive = CGAL::AABB_primitive box vector pos --> Bounding Box using BPMB = internal::Vector_property_map; - using BPM = CGAL::Property_map_binder; + using BPM = CGAL::Compose_property_map; // Primitive ID --> point vector pos --> Reference Point using RPPMB = internal::Vector_property_map; - using RPPM = CGAL::Property_map_binder; + using RPPM = CGAL::Compose_property_map; // Primitive ID --> Datum pos vector pos --> Datum pos --> Datum // The vector of data has size nf, but the vector of datum pos has size tree.size() using DPPMB = internal::Vector_property_map; // pos --> Datum pos - using DPPM = CGAL::Property_map_binder; // PID --> Datum pos + using DPPM = CGAL::Compose_property_map; // PID --> Datum pos using DPMB = internal::Vector_property_map; // Datum pos --> Datum - using DPM = CGAL::Property_map_binder; // PID --> Datum + using DPM = CGAL::Compose_property_map; // PID --> Datum using Primitive = CGAL::AABB_primitive 1) ? argv[1] : CGAL::data_file_path("meshes/polygon_mesh.off"); // mesh + const std::string tm_filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/building.off"); // mesh const std::string ts_filename = (argc > 2) ? argv[2] : CGAL::data_file_path("meshes/oblong-shuffled.off"); // triangle soup const std::string ss_filename = (argc > 3) ? argv[3] : CGAL::data_file_path("images/420.polylines.txt"); // segment soup const std::string ps_filename = (argc > 4) ? argv[4] : CGAL::data_file_path("points_3/b9_training.ply"); // point set diff --git a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h index 25a75abed29..e1e9f6f0a6f 100644 --- a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h +++ b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h @@ -588,31 +588,31 @@ struct Face_filtered_graph return selected_halfedges.count(); } - Property_map_binder::value_type>::type> + Compose_property_map::value_type>::type> get_face_index_map() const { is_imap_in_use.set(0); initialize_face_indices(); - return bind_property_maps(fimap, make_property_map(face_indices)); + return make_compose_property_map(fimap, make_property_map(face_indices)); } - Property_map_binder::value_type>::type> + Compose_property_map::value_type>::type> get_vertex_index_map() const { is_imap_in_use.set(1); initialize_vertex_indices(); - return bind_property_maps(vimap, make_property_map(vertex_indices) ); + return make_compose_property_map(vimap, make_property_map(vertex_indices) ); } - Property_map_binder::value_type >::type> + Compose_property_map::value_type >::type> get_halfedge_index_map() const { is_imap_in_use.set(2); initialize_halfedge_indices(); - return bind_property_maps(himap, make_property_map(halfedge_indices) ); + return make_compose_property_map(himap, make_property_map(halfedge_indices) ); } /// returns `true` if around any vertex of a selected face there is at most a single umbrella @@ -1322,7 +1322,7 @@ struct property_map, boost typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::FIM FIM; - typedef typename CGAL::Property_map_binder::value_type>::type> type; typedef type const_type; @@ -1334,7 +1334,7 @@ struct property_map, boost typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::VIM VIM; - typedef typename CGAL::Property_map_binder::value_type>::type> type; typedef type const_type; @@ -1346,7 +1346,7 @@ struct property_map, boost typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::HIM HIM; - typedef typename CGAL::Property_map_binder::value_type>::type> type; typedef type const_type; diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index b70872a7334..1d68f2a6f87 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -276,34 +278,37 @@ public: typedef typename CGAL::Identity_property_map const_type; }; -template +template struct Point_set_processing_3_np_helper { typedef typename std::iterator_traits::value_type Value_type; - typedef CGAL::Identity_property_map DefaultPMap; - typedef CGAL::Identity_property_map DefaultConstPMap; + typedef typename Default::Get>::type DefaultPMap; + typedef typename Default::Get>::type DefaultConstPMap; - typedef typename internal_np::Lookup_named_param_def::type Point_map; - typedef typename internal_np::Lookup_named_param_def::type Const_point_map; + typedef typename internal_np::Lookup_named_param_def ::type Point_map; // public + typedef typename internal_np::Lookup_named_param_def ::type Const_point_map; // public typedef typename boost::property_traits::value_type Point; typedef typename Kernel_traits::Kernel Default_geom_traits; - typedef typename internal_np::Lookup_named_param_def::type Geom_traits; + typedef typename internal_np::Lookup_named_param_def < + internal_np::geom_traits_t, + NamedParameters, + Default_geom_traits + > ::type Geom_traits; // public - typedef typename Geom_traits::FT FT; + typedef typename Geom_traits::FT FT; // public typedef Constant_property_map DummyNormalMap; + typedef typename Default::Get::type DefaultNMap; - typedef typename internal_np::Lookup_named_param_def::type Normal_map; + typedef typename internal_np::Lookup_named_param_def< + internal_np::normal_t, + NamedParameters, + DefaultNMap + > ::type Normal_map; // public static Point_map get_point_map(PointRange&, const NamedParameters& np) { diff --git a/Boolean_set_operations_2/doc/Boolean_set_operations_2/CGAL/Boolean_set_operations_2.h b/Boolean_set_operations_2/doc/Boolean_set_operations_2/CGAL/Boolean_set_operations_2.h index 9b35c3ed574..7e7f330a744 100644 --- a/Boolean_set_operations_2/doc/Boolean_set_operations_2/CGAL/Boolean_set_operations_2.h +++ b/Boolean_set_operations_2/doc/Boolean_set_operations_2/CGAL/Boolean_set_operations_2.h @@ -737,7 +737,7 @@ namespace CGAL { /*! determines whether two polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -755,7 +755,7 @@ bool do_intersect(const Polygon_2& pgn1, * bso_ssectraits_sel for more information. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -766,7 +766,7 @@ bool do_intersect(const Polygon_2& pgn1, /*! determines whether two polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -785,7 +785,7 @@ bool do_intersect(const Polygon_2& pgn1, * information. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -796,7 +796,7 @@ bool do_intersect(const Polygon_2& pgn1, /*! determines whether two polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -815,7 +815,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, * information. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -826,7 +826,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, /*! determines whether two polygons with holes intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -844,7 +844,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, * \ref bso_ssectraits_sel for more information. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. */ template @@ -855,7 +855,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, /*! determines whether two general polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `%ArrTraits` must be a model of the concept * `ArrangementDirectionalXMonotoneTraits_2`. @@ -867,7 +867,7 @@ bool do_intersect(const General_polygon_2& pgn1, /*! determines whether two general polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `%ArrTraits` must be a model of the concept * `ArrangementDirectionalXMonotoneTraits_2`. @@ -880,7 +880,7 @@ do_intersect(const General_polygon_2& pgn1, /*! determines whether two general polygons intersect in their interior. * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `%ArrTraits` must be a model of the concept * `ArrangementDirectionalXMonotoneTraits_2`. @@ -893,7 +893,7 @@ bool do_intersect(const General_polygon_with_holes_2 @@ -1001,7 +1001,7 @@ bool do_intersect(InputIterator1 begin1, InputIterator1 end1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. */ @@ -1014,7 +1014,7 @@ bool do_intersect(const Polygon_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. */ @@ -1028,7 +1028,7 @@ bool do_intersect(const Polygon_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. */ @@ -1041,7 +1041,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. */ @@ -1054,7 +1054,7 @@ bool do_intersect(const Polygon_with_holes_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. * \pre `%ArrTraits` must be a model of the concept @@ -1069,7 +1069,7 @@ bool do_intersect(const General_polygon_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. * \pre `%ArrTraits` must be a model of the concept @@ -1085,7 +1085,7 @@ do_intersect(const General_polygon_2& pgn1, * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. * \pre `%ArrTraits` must be a model of the concept @@ -1102,7 +1102,7 @@ do_intersect(const General_polygon_with_holes_2>& p * \param pgn1 the 1st input polygon. * \param pgn2 the 2nd input polygon. * \param traits a traits object. - * \return `true` if `pgn1` and `pgn2` intersect in their interiro and `false` + * \return `true` if `pgn1` and `pgn2` intersect in their interior and `false` * otherwise. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. * \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`. diff --git a/Cartesian_kernel/include/CGAL/Cartesian/plane_constructions_3.h b/Cartesian_kernel/include/CGAL/Cartesian/plane_constructions_3.h index ac4ef1519c7..fe9d91a491d 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/plane_constructions_3.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/plane_constructions_3.h @@ -41,6 +41,23 @@ plane_from_points(const typename R::Point_3 &p, return PlaneC3(a, b, c, d); } + +template +CGAL_KERNEL_LARGE_INLINE +PlaneC3 +plane_from_points(Origin, + const typename R::Point_3 &q, + const typename R::Point_3 &r) +{ + typename R::FT a, b, c, d(0); + plane_from_pointsC3( /* origin, */ + q.x(), q.y(), q.z(), + r.x(), r.y(), r.z(), + a, b, c); + return PlaneC3(a, b, c, d); +} + + template CGAL_KERNEL_LARGE_INLINE PlaneC3 @@ -53,7 +70,7 @@ plane_from_point_direction(const typename R::Point_3 &p, return PlaneC3(A, B, C, D); } - template +template CGAL_KERNEL_LARGE_INLINE PlaneC3 plane_from_point_direction(Origin, diff --git a/Cartesian_kernel/include/CGAL/constructions/kernel_ftC3.h b/Cartesian_kernel/include/CGAL/constructions/kernel_ftC3.h index 7b0b79f2e90..dbc6c1c2fa1 100644 --- a/Cartesian_kernel/include/CGAL/constructions/kernel_ftC3.h +++ b/Cartesian_kernel/include/CGAL/constructions/kernel_ftC3.h @@ -240,6 +240,22 @@ plane_from_pointsC3(const FT &px, const FT &py, const FT &pz, pd = - pa*rx - pb*ry - pc*rz; } + +template +CGAL_KERNEL_MEDIUM_INLINE +void +plane_from_pointsC3( /* origin */ + const FT &qx, const FT &qy, const FT &qz, + const FT &rx, const FT &ry, const FT &rz, + FT &pa, FT &pb, FT &pc /* , zero */ ) +{ + pa = qy*rz - ry*qz; + pb = qz*rx - rz*qx; + pc = qx*ry - rx*qy; +} + + + template CGAL_KERNEL_MEDIUM_INLINE void diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index 32736fae273..0771dcd89c2 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -65,7 +65,7 @@ Data structures specialized to classify clusters. \cgalPkgPicture{data_classif.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Simon Giraudot, Florent Lafarge} +\cgalPkgAuthors{Simon Giraudot and Florent Lafarge} \cgalPkgDesc{This component implements an algorithm that classifies a data set into a user-defined set of labels (such as ground, vegetation, buildings, etc.). A flexible API is provided so that users can classify any type of data, compute their own local features on the input data set, and define their own labels.} \cgalPkgManuals{Chapter_Classification, PkgClassificationRef} \cgalPkgSummaryEnd diff --git a/Classification/examples/Classification/example_cluster_classification.cpp b/Classification/examples/Classification/example_cluster_classification.cpp index 578c7f3bca6..51c7e642b78 100644 --- a/Classification/examples/Classification/example_cluster_classification.cpp +++ b/Classification/examples/Classification/example_cluster_classification.cpp @@ -30,9 +30,9 @@ typedef Point_set::Property_map Imap; typedef Point_set::Property_map UCmap; -typedef CGAL::Shape_detection::Point_set::Sphere_neighbor_query Neighbor_query; -typedef CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region Region_type; -typedef CGAL::Shape_detection::Region_growing Region_growing; +typedef CGAL::Shape_detection::Point_set::Sphere_neighbor_query_for_point_set Neighbor_query; +typedef CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region_for_point_set Region_type; +typedef CGAL::Shape_detection::Region_growing Region_growing; namespace Classification = CGAL::Classification; namespace Feature = CGAL::Classification::Feature; @@ -111,25 +111,24 @@ int main (int argc, char** argv) const double max_accepted_angle = 25.0; const std::size_t min_region_size = 10; - Neighbor_query neighbor_query ( - pts, - search_sphere_radius, - pts.point_map()); - Region_type region_type ( - pts, - max_distance_to_plane, max_accepted_angle, min_region_size, - pts.point_map(), pts.normal_map()); + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_sphere_neighbor_query ( + pts, CGAL::parameters::sphere_radius(search_sphere_radius) + .point_map(pts.point_map())); + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_region( + pts, CGAL::parameters::maximum_distance(max_distance_to_plane) + .maximum_angle(max_accepted_angle) + .minimum_region_size(min_region_size)); Region_growing region_growing ( pts, neighbor_query, region_type); std::vector clusters; region_growing.detect (boost::make_function_output_iterator - ([&](const std::vector& region) -> void { + ([&](const std::pair>& region) -> void { // Create a new cluster. Classification::Cluster cluster (pts, pts.point_map()); - for (const std::size_t idx : region) + for (Point_set::Index idx : region.second) cluster.insert(idx); clusters.push_back(cluster); })); diff --git a/Cone_spanners_2/doc/Cone_spanners_2/PackageDescription.txt b/Cone_spanners_2/doc/Cone_spanners_2/PackageDescription.txt index 9dfe45083f8..6b59b805a38 100644 --- a/Cone_spanners_2/doc/Cone_spanners_2/PackageDescription.txt +++ b/Cone_spanners_2/doc/Cone_spanners_2/PackageDescription.txt @@ -7,7 +7,7 @@ \cgalPkgPicture{Logo-ConeSpanners.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Weisheng Si, Quincy Tse and Frédérik Paradis} +\cgalPkgAuthors{Weisheng Si, Quincy Tse, and Frédérik Paradis} \cgalPkgDesc{This package provides functors for constructing two kinds of cone-based spanners: Yao graph and Theta graph, given a set of vertices on the plane and the directions of cone boundaries. Both exact and inexact constructions are supported. diff --git a/Data/data/meshes/am.off b/Data/data/meshes/am.off new file mode 100644 index 00000000000..876a1b694c5 --- /dev/null +++ b/Data/data/meshes/am.off @@ -0,0 +1,10986 @@ +OFF +3662 7320 0 + +-0.26157850027084351 -0.66797298192977905 -0.69669848680496216 +-0.21234190464019775 -0.65114235877990723 -0.73132127523422241 +-0.22672553360462189 -0.71133261919021606 -0.66821229457855225 +0.23078745603561401 -0.49966663122177124 -1.0429263114929199 +0.28002405166625977 -0.48283600807189941 -1.0775490999221802 +0.18155086040496826 -0.51649725437164307 -1.0083035230636597 +0.32926064729690552 -0.46600538492202759 -1.1121718883514404 +0.37849724292755127 -0.44917473196983337 -1.1467946767807007 +0.42773383855819702 -0.43234410881996155 -1.1814174652099609 +0.47697043418884277 -0.41551345586776733 -1.2160402536392212 +0.083077669143676758 -0.55015856027603149 -0.93905794620513916 +0.033841073513031006 -0.56698918342590332 -0.90443515777587891 +0.13231426477432251 -0.53332793712615967 -0.97368073463439941 +-0.015395522117614746 -0.58381980657577515 -0.86981242895126343 +-0.11386871337890625 -0.6174810528755188 -0.80056685209274292 +-0.163105309009552 -0.6343117356300354 -0.76594406366348267 +-0.064632117748260498 -0.60065042972564697 -0.83518964052200317 +-0.19187256693840027 -0.75469225645065308 -0.63972610235214233 +-0.15701961517333984 -0.79805189371109009 -0.61123991012573242 +0.2612159252166748 -1.318367600440979 -0.26940575242042542 +0.29606890678405762 -1.361727237701416 -0.2409195601940155 +0.22636297345161438 -1.275007963180542 -0.29789191484451294 +0.31241756677627563 -1.3199789524078369 -0.19737592339515686 +0.52620702981948853 -0.39868283271789551 -1.2506630420684814 +0.54255568981170654 -0.35693454742431641 -1.2071194648742676 +-0.052460730075836182 -0.9281308650970459 -0.52578139305114746 +-0.087313681840896606 -0.88477116823196411 -0.55426758527755737 +-0.017607763409614563 -0.97149050235748291 -0.49729520082473755 +-0.12216664850711823 -0.8414115309715271 -0.58275377750396729 +0.086951136589050293 -1.1015694141387939 -0.4118366539478302 +0.05209815502166748 -1.0582097768783569 -0.44032284617424011 +0.12180408835411072 -1.144929051399231 -0.38335046172142029 +0.017245203256607056 -1.0148501396179199 -0.46880900859832764 +0.19151002168655396 -1.231648325920105 -0.32637810707092285 +0.15665704011917114 -1.188288688659668 -0.35486429929733276 +0.54129874706268311 -0.73550254106521606 0.41223526000976562 +0.55764740705490112 -0.69375425577163696 0.45577892661094666 +0.52495008707046509 -0.77725088596343994 0.36869162321090698 +0.60688400268554688 -0.67692363262176514 0.4211561381816864 +0.50860142707824707 -0.81899917125701904 0.32514795660972595 +0.49225276708602905 -0.86074751615524292 0.28160429000854492 +0.44320681691169739 -0.985992431640625 0.15097334980964661 +0.45955547690391541 -0.9442441463470459 0.19451698660850525 +0.42685815691947937 -1.0277407169342041 0.10742968320846558 +0.47590410709381104 -0.90249580144882202 0.23806065320968628 +0.37781220674514771 -1.152985692024231 -0.023201286792755127 +0.39416083693504333 -1.1112374067306519 0.020342379808425903 +0.36146354675292969 -1.1947339773178101 -0.066744953393936157 +0.41050949692726135 -1.0694890022277832 0.063886016607284546 +0.32876622676849365 -1.2782306671142578 -0.15383222699165344 +0.34511488676071167 -1.2364823818206787 -0.1102885901927948 +0.65612059831619263 -0.66009300947189331 0.38653334975242615 +0.70535719394683838 -0.64326232671737671 0.35191059112548828 +1.2961963415145874 -0.44129472970962524 -0.063562840223312378 +1.3454329967498779 -0.42446410655975342 -0.098185628652572632 +1.2469596862792969 -0.45812538266181946 -0.028940051794052124 +1.3105800151824951 -0.38110446929931641 -0.12667182087898254 +1.1977231502532959 -0.47495600581169128 0.0056827366352081299 +1.1484866142272949 -0.4917866587638855 0.040305525064468384 +1.0007767677307129 -0.54227852821350098 0.14417386054992676 +1.0500133037567139 -0.52544790506362915 0.1095510721206665 +0.95154017210006714 -0.55910921096801758 0.17879664897918701 +1.0992499589920044 -0.50861728191375732 0.07492828369140625 +0.80383038520812988 -0.60960108041763306 0.28266501426696777 +0.85306698083877563 -0.59277045726776123 0.24804222583770752 +0.75459378957748413 -0.62643170356750488 0.31728780269622803 +0.90230357646942139 -0.5759398341178894 0.21341943740844727 +0.82263851165771484 0.22593051195144653 -0.52547836303710938 +0.78778553009033203 0.26929014921188354 -0.55396455526351929 +0.85749143362045288 0.18257087469100952 -0.49699220061302185 +0.77143687009811401 0.22754183411598206 -0.59750819206237793 +1.2757270336151123 -0.33774483203887939 -0.15515798330307007 +1.2408740520477295 -0.29438519477844238 -0.18364417552947998 +0.89234441518783569 0.13921122252941132 -0.46850600838661194 +0.92719739675521851 0.095851585268974304 -0.44001981616020203 +1.0317562818527222 -0.034227341413497925 -0.35456126928329468 +0.99690330028533936 0.0091322958469390869 -0.38304746150970459 +1.066609263420105 -0.077586978673934937 -0.32607507705688477 +0.96205031871795654 0.052491948008537292 -0.4115336537361145 +1.1363151073455811 -0.16430625319480896 -0.26910272240638733 +1.1711680889129639 -0.20766589045524597 -0.24061653017997742 +1.1014621257781982 -0.12094661593437195 -0.29758891463279724 +1.2060210704803467 -0.25102555751800537 -0.21213036775588989 +0.755088210105896 0.18579351902008057 -0.64105188846588135 +0.73873955011367798 0.14404521882534027 -0.68459552526473999 +0.68969357013702393 0.018800288438796997 -0.81522649526596069 +0.70604223012924194 0.060548588633537292 -0.77168285846710205 +0.67334496974945068 -0.022948026657104492 -0.85877013206481934 +0.72239089012145996 0.10229690372943878 -0.72813916206359863 +0.62429893016815186 -0.14819297194480896 -0.98940110206604004 +0.64064764976501465 -0.10644465684890747 -0.9458574652671814 +0.60795032978057861 -0.18994128704071045 -1.0329447984695435 +0.65699625015258789 -0.064696341753005981 -0.90231382846832275 +0.55890434980392456 -0.31518620252609253 -1.1635756492614746 +0.57525300979614258 -0.27343791723251343 -1.1200320720672607 +0.5916016697883606 -0.23168957233428955 -1.0764884948730469 +0.49171668291091919 1.6310174465179443 -0.31304499506950378 +-1.0838544368743896 1.0924370288848877 0.7948840856552124 +0.031440377235412598 -0.29507142305374146 1.7064419984817505 +-1.6070115566253662 -0.24350887537002563 -0.59851288795471191 +1.6070115566253662 0.24350887537002563 0.59851288795471191 +-0.031440377235412598 0.29507142305374146 -1.7064419984817505 +-0.49171668291091919 -1.6310174465179443 0.31304499506950378 +0.34015974402427673 -0.43817317485809326 -1.0831427574157715 +-0.053733021020889282 -0.57281821966171265 -0.80616050958633423 +0.23053331673145294 -0.35511422157287598 -0.82258802652359009 +0.2142481803894043 -0.43300062417984009 -0.92121624946594238 +-0.16335947811603546 -0.48975929617881775 -0.54560571908950806 +-0.17294856905937195 -0.52988612651824951 -0.50353306531906128 +-0.032570227980613708 -0.15577282011508942 -0.19725647568702698 +-0.042159315198659897 -0.19589966535568237 -0.15518383681774139 +0.055258020758628845 -0.29449617862701416 -0.51586949825286865 +-0.048664718866348267 -0.34207352995872498 -0.46113848686218262 +0.019521705806255341 -0.47959285974502563 -0.20537540316581726 +-0.044734664261341095 -0.37895745038986206 -0.24783320724964142 +0.18604728579521179 0.03949032723903656 -0.16752023994922638 +0.22018168866634369 0.038416109979152679 -0.11950035393238068 +0.57994002103805542 0.17413540184497833 -0.44450250267982483 +0.6140744686126709 0.17306119203567505 -0.39648261666297913 +0.29567372798919678 -0.04356858879327774 -0.42807507514953613 +0.31195884943008423 0.034317813813686371 -0.32944679260253906 +0.56612902879714966 -0.027573063969612122 -0.18611940741539001 +0.51283526420593262 0.064756430685520172 -0.25463271141052246 +0.68956649303436279 0.091076478362083435 -0.70505732297897339 +0.55877727270126343 -0.2429099977016449 -1.0534065961837769 +0.47094899415969849 -0.10418666899204254 -0.73479354381561279 +0.57487177848815918 -0.056609302759170532 -0.78952455520629883 +0.46901744604110718 -0.83184105157852173 0.26261353492736816 +0.33822822570800781 -1.1658275127410889 -0.085735738277435303 +0.27654719352722168 -0.88213443756103516 -0.03554418683052063 +0.34080356359481812 -0.98276978731155396 0.0069136619567871094 +1.125251293182373 -0.46288019418716431 0.021314740180969238 +0.73135846853256226 -0.59752523899078369 0.29829698801040649 +0.7793039083480835 -0.39689105749130249 0.087933748960494995 +0.83259761333465576 -0.48922055959701538 0.15644708275794983 +0.89437299966812134 0.084631159901618958 -0.41693797707557678 +1.1731966733932495 -0.26224598288536072 -0.18904852867126465 +0.89289820194244385 -0.17381595075130463 -0.1685931384563446 +1.0029890537261963 -0.15460789203643799 -0.22834333777427673 +0.40733644366264343 -0.54814791679382324 0.31280508637428284 +0.45105993747711182 -0.50909531116485596 0.31875231862068176 +0.12851274013519287 -0.20127077400684357 0.084915623068809509 +0.17223624885082245 -0.16221813857555389 0.090862870216369629 +0.23666439950466156 -0.54277682304382324 0.072705641388893127 +0.28097933530807495 -0.47373339533805847 0.16928833723068237 +0.45253479480743408 -0.2506481409072876 0.07040753960609436 +0.34244394302368164 -0.26985621452331543 0.1301577091217041 +-0.11126755177974701 -0.81357932090759277 -0.55372464656829834 +0.16755613684654236 -1.1604564189910889 -0.32583516836166382 +0.059404537081718445 -0.81895041465759277 -0.31362521648406982 +0.015089556574821472 -0.88799381256103516 -0.41020786762237549 +0.22996141016483307 -0.029871337115764618 -0.32682675123214722 +-0.097964853048324585 -0.32276606559753418 -0.37143111228942871 +0.10956291854381561 -0.046920817345380783 -0.20547020435333252 +0.29624563455581665 -0.36881151795387268 -0.92383629083633423 +0.46043115854263306 -0.34884747862815857 -1.0943300724029541 +0.62417185306549072 -0.075916767120361328 -0.87923192977905273 +0.37266644835472107 -0.24626222252845764 -0.83080172538757324 +-0.021226316690444946 -0.38090729713439941 -0.55381941795349121 +-0.097647152841091156 -0.50345659255981445 -0.64685404300689697 +0.14321336150169373 -0.50549566745758057 -0.94465160369873047 +0.54743337631225586 -0.017775505781173706 -0.69684356451034546 +0.24111467599868774 -0.14659152925014496 -0.51813602447509766 +0.62385416030883789 0.10477374494075775 -0.60380899906158447 +0.3829936683177948 0.10681286454200745 -0.3060113787651062 +0.037008613348007202 -0.170215904712677 -0.030114945024251938 +0.011916503310203552 -0.36665266752243042 -0.16128882765769958 +0.26792460680007935 -0.37470933794975281 0.19886036217212677 +0.11575683951377869 -0.45444619655609131 -0.056296572089195251 +0.28415241837501526 -0.99507451057434082 -0.07963070273399353 +0.25906029343605042 -1.1915113925933838 -0.21080458164215088 +0.028144299983978271 -0.98701786994934082 -0.43977987766265869 +0.18031205236911774 -0.90728104114532471 -0.18462300300598145 +0.3111012876033783 -0.57329452037811279 0.16372624039649963 +0.41494166851043701 -0.66108804941177368 0.26871851086616516 +0.4036228358745575 -0.99883425235748291 0.088438898324966431 +-0.015032410621643066 -0.78843271732330322 -0.40464580059051514 +-0.11887276172637939 -0.70063918828964233 -0.50963807106018066 +-0.10755394399166107 -0.36289292573928833 -0.32935845851898193 +0.58641469478607178 -0.57337373495101929 0.32956099510192871 +0.73209589719772339 -0.46830174326896667 0.17412459850311279 +0.31164810061454773 -0.33565670251846313 0.20480760931968689 +0.6063302755355835 -0.36389642953872681 0.12124328315258026 +0.61333703994750977 0.043837621808052063 -0.27231022715568542 +0.75901824235916138 0.14890959858894348 -0.42774662375450134 +1.0337848663330078 -0.088807404041290283 -0.30299323797225952 +0.73910266160964966 -0.060567647218704224 -0.21942894160747528 +0.34520989656448364 -0.195212721824646 0.057553350925445557 +0.21944427490234375 -0.090807452797889709 0.0046720504760742188 +0.41712808609008789 0.10573864728212357 -0.2579914927482605 +1.0002230405807495 -0.22925135493278503 -0.15573897957801819 +1.1259887218475342 -0.3336566686630249 -0.10285767912864685 +0.92830485105514526 -0.53020274639129639 0.15980586409568787 +0.3454822301864624 -0.35198086500167847 -0.95845907926559448 +0.39471882581710815 -0.33515024185180664 -0.99308180809020996 +-0.16316884756088257 -0.59817361831665039 -0.71085947751998901 +-0.13040798902511597 -0.55081510543823242 -0.67885673046112061 +-0.037384346127510071 -0.53106987476348877 -0.76261687278747559 +0.16488449275493622 -0.37755507230758667 -0.77642428874969482 +0.10393396019935608 -0.40355563163757324 -0.74142718315124512 +0.15564225614070892 -0.45819967985153198 -0.88786792755126953 +0.21393045783042908 -0.25231015682220459 -0.64579331874847412 +0.26316702365875244 -0.23547951877117157 -0.68041610717773438 +0.32887938618659973 -0.24917677044868469 -0.78166437149047852 +0.2797698974609375 -0.33828359842300415 -0.85721081495285034 +-0.19947776198387146 -0.64175206422805786 -0.59563952684402466 +-0.037574976682662964 -0.4226556122303009 -0.59736311435699463 +-0.15917524695396423 -0.6711956262588501 -0.55263876914978027 +-0.13809560239315033 -0.57324576377868652 -0.47504690289497375 +0.065775878727436066 -0.049835354089736938 -0.15633288025856018 +0.016666367650032043 -0.1389421820640564 -0.23187926411628723 +0.028265155851840973 -0.32490438222885132 -0.11774517595767975 +0.077056236565113068 -0.23883174359798431 -0.45781129598617554 +-0.037014342844486237 -0.29676556587219238 -0.40642818808555603 +0.19732764363288879 -0.14950606226921082 -0.46899864077568054 +0.16469386219978333 -0.26914077997207642 -0.61117053031921387 +0.038909360766410828 -0.33624446392059326 -0.55941313505172729 +0.13161531090736389 -0.13580881059169769 -0.36775034666061401 +-0.0022765100002288818 -0.53525727987289429 -0.26343363523483276 +-0.026718184351921082 -0.57876336574554443 -0.31934076547622681 +-0.068397857248783112 -0.42047560214996338 -0.30166688561439514 +0.10228237509727478 -0.66533619165420532 -0.17797508835792542 +0.11102583259344101 -0.51064771413803101 -0.090344846248626709 +0.035870358347892761 -0.43784451484680176 -0.16183176636695862 +0.065712332725524902 -0.013697255402803421 -0.10124829411506653 +0.11691395938396454 -0.01530858501791954 -0.029218455776572227 +0.18072479963302612 -0.046701975166797638 -0.29220396280288696 +0.16817912459373474 -0.053058013319969177 -0.012273203581571579 +0.25503465533256531 -0.0049435272812843323 -0.091014169156551361 +0.68937587738037109 0.19949077069759369 -0.53980356454849243 +0.65661501884460449 0.15213224291801453 -0.57180631160736084 +0.5635913610458374 0.13238710165023804 -0.48804616928100586 +0.66257363557815552 0.060668259859085083 -0.30693301558494568 +0.71181023120880127 0.077498897910118103 -0.34155577421188354 +0.36132258176803589 -0.021127745509147644 -0.47423875331878662 +0.42227303981781006 0.0048727542161941528 -0.50923579931259155 +0.3705647885799408 0.059516876935958862 -0.36279517412185669 +0.31227660179138184 -0.14637267589569092 -0.60486972332000732 +0.24643714725971222 -0.06039922684431076 -0.39345225691795349 +0.50048023462295532 -0.050013907253742218 -0.13995569944381714 +0.43688622117042542 -0.063856147229671478 -0.10280753672122955 +0.45158588886260986 0.051715649664402008 -0.21913325786590576 +0.60503911972045898 -0.18009284138679504 -0.05449715256690979 +0.65427565574645996 -0.16326220333576202 -0.089119911193847656 +0.70148372650146484 -0.091851502656936646 -0.17531076073646545 +0.61536562442779541 -0.010742425918579102 -0.22074219584465027 +0.56378203630447388 0.023972809314727783 -0.65329992771148682 +0.50421822071075439 -0.34593290090560913 -1.1434674263000488 +0.50954067707061768 -0.25974065065383911 -1.0187838077545166 +0.44859015941619873 -0.28574120998382568 -0.98378670215606689 +0.44915080070495605 -0.15985108911991119 -0.79285180568695068 +0.43672192096710205 -0.20714706182479858 -0.84963560104370117 +0.56322139501571655 -0.10191729664802551 -0.84423494338989258 +0.36151319742202759 -0.1295420378446579 -0.63949251174926758 +0.4872976541519165 -0.062438353896141052 -0.69124990701675415 +0.49554666876792908 -0.71997511386871338 0.35471996665000916 +0.45524415373802185 -0.69053161144256592 0.31171926856040955 +0.43416452407836914 -0.78848141431808472 0.23412732779979706 +0.26780375838279724 -1.0368227958679199 -0.12317436933517456 +0.25145509839057922 -1.0785712003707886 -0.1667180061340332 +0.29834538698196411 -0.8264700174331665 0.022514045238494873 +0.32278710603713989 -0.78296387195587158 0.078421205282211304 +0.36446675658226013 -0.94125163555145264 0.060747295618057251 +0.19378650188446045 -0.69639104604721069 -0.062944501638412476 +0.17743785679340363 -0.73813939094543457 -0.10648813843727112 +0.18504306674003601 -0.85107952356338501 -0.15057471394538879 +0.26019853353500366 -0.92388272285461426 -0.079087823629379272 +1.2285189628601074 -0.40915554761886597 -0.068967163562774658 +1.1772538423538208 -0.37140610814094543 -0.085912406444549561 +1.0903983116149902 -0.41952055692672729 -0.0071714520454406738 +0.68285930156707764 -0.48513239622116089 0.20874738693237305 +0.84495270252227783 -0.3744502067565918 0.041770040988922119 +0.90854668617248535 -0.36060798168182373 0.0046219527721405029 +0.89384710788726807 -0.47617977857589722 0.12094762921333313 +0.74039387702941895 -0.24437126517295837 -0.043688505887985229 +0.64394921064376831 -0.33261260390281677 0.077125132083892822 +0.73006731271743774 -0.41372168064117432 0.12255655229091644 +0.79663717746734619 0.1801934540271759 -0.47186478972434998 +0.84513640403747559 0.067800521850585938 -0.38231515884399414 +0.78154242038726807 0.053958296775817871 -0.34516704082489014 +1.0350760221481323 -0.27261099219322205 -0.12725278735160828 +0.8464275598526001 -0.11600308120250702 -0.20657472312450409 +0.81196975708007812 -0.061980098485946655 -0.24543298780918121 +0.97019088268280029 -0.10264962911605835 -0.26584511995315552 +0.78963041305541992 -0.22754062712192535 -0.078311294317245483 +0.92775112390518188 -0.21717558801174164 -0.14010694622993469 +0.34595426917076111 -0.6166541576385498 0.19221243262290955 +0.50029653310775757 -0.49226465821266174 0.2841295599937439 +0.56389057636260986 -0.47842240333557129 0.2469814121723175 +0.11216409504413605 -0.24301907420158386 0.041371971368789673 +0.087722405791282654 -0.28652521967887878 -0.014535173773765564 +0.31035694479942322 -0.15185308456420898 0.029067158699035645 +0.1901937872171402 -0.48496395349502563 0.034724056720733643 +0.24348293244838715 -0.41821545362472534 0.14295323193073273 +0.21013516187667847 -0.65464270114898682 -0.019400864839553833 +0.27151733636856079 -0.58613646030426025 0.10119183361530304 +0.49900540709495544 -0.30846101045608521 0.10838912427425385 +0.37524211406707764 -0.32181450724601746 0.1676594614982605 +0.55580252408981323 -0.19692346453666687 -0.019874349236488342 +0.41768181324005127 -0.20728851854801178 0.041921362280845642 +-0.049885377287864685 -0.74507308006286621 -0.43313199281692505 +0.25432929396629333 -1.2477128505706787 -0.24485290050506592 +0.18390481173992157 -1.1187081336975098 -0.28229153156280518 +0.20834650099277496 -1.0752019882202148 -0.22638437151908875 +0.10587514936923981 -0.87676328420639038 -0.27564361691474915 +0.14503121376037598 -0.93434596061706543 -0.24795204401016235 +0.052586004137992859 -0.94351178407669067 -0.38387280702590942 +0.085933715105056763 -0.7070845365524292 -0.22151872515678406 +0.024551555514335632 -0.77559077739715576 -0.34211137890815735 +0.02198883518576622 -0.052749883383512497 -0.10719554126262665 +0.089485131204128265 -0.19153574109077454 -0.40102750062942505 +-0.049045968800783157 -0.12524493038654327 -0.1306309700012207 +0.098663821816444397 -0.074753031134605408 -0.23449932038784027 +0.17361839115619659 -0.0078056603670120239 -0.22430403530597687 +0.19726409018039703 -0.1133679673075676 -0.41391405463218689 +0.23021557927131653 -0.17442373931407928 -0.54716503620147705 +0.33547747135162354 0.001031726598739624 -0.40888765454292297 +-0.11444059014320374 -0.29223817586898804 -0.30480557680130005 +-0.010517850518226624 -0.24466079473495483 -0.35953661799430847 +0.26929983496665955 0.012503638863563538 -0.31045728921890259 +0.077616885304450989 -0.1129416823387146 -0.26687633991241455 +0.27362138032913208 0.045319389551877975 -0.26579490303993225 +0.32849812507629395 -0.032348170876502991 -0.45115691423416138 +0.32151883840560913 -0.065728068351745605 -0.49342614412307739 +0.24618297815322876 0.084153175354003906 -0.17311392724514008 +0.19694638252258301 0.067322537302970886 -0.13849113881587982 +0.35258859395980835 -0.39087715744972229 -1.0263590812683105 +0.32881587743759155 -0.21303866803646088 -0.72657984495162964 +0.19072958827018738 -0.39971452951431274 -0.84177541732788086 +0.36176735162734985 -0.27409446239471436 -0.85983085632324219 +0.46036761999130249 -0.31270939111709595 -1.03924560546875 +0.25690716505050659 -0.41118645668029785 -0.94020569324493408 +0.25258564949035645 -0.44400221109390259 -0.98486816883087158 +0.19770888984203339 -0.36633464694023132 -0.79950618743896484 +0.20468822121620178 -0.3329547643661499 -0.75723695755004883 +0.34072038531303406 -0.31228309869766235 -0.8922078013420105 +0.53672486543655396 -0.15402200818061829 -0.89112639427185059 +0.14840875566005707 -0.34702721238136292 -0.70979875326156616 +0.0216187983751297 -0.28705427050590515 -0.46338427066802979 +0.055448651313781738 -0.40291047096252441 -0.68112325668334961 +0.077246874570846558 -0.34724602103233337 -0.62306499481201172 +-0.18509413301944733 -0.58156180381774902 -0.65874850749969482 +-0.051896326243877411 -0.37210607528686523 -0.50289797782897949 +-0.053923636674880981 -0.46440395712852478 -0.64090675115585327 +-0.097837775945663452 -0.39504227042198181 -0.48160025477409363 +0.066157132387161255 -0.26666396856307983 -0.48684036731719971 +0.098981514573097229 -0.25544354319572449 -0.50992226600646973 +-0.17983521521091461 -0.45923143625259399 -0.47898021340370178 +-0.19618387520313263 -0.5009797215461731 -0.52252388000488281 +-0.10240895301103592 -0.46375879645347595 -0.58060276508331299 +0.099362790584564209 -0.472272127866745 -0.84042972326278687 +0.37779825925827026 -0.05165565013885498 -0.54086422920227051 +0.20916864275932312 -0.21261239051818848 -0.57954210042953491 +0.50458818674087524 -0.11162859201431274 -0.78727877140045166 +0.47075837850570679 0.0042276233434677124 -0.56953984498977661 +0.44896018505096436 -0.051436781883239746 -0.62759804725646973 +0.71130114793777466 0.1828790009021759 -0.59191453456878662 +0.73854893445968628 0.25245952606201172 -0.51934176683425903 +0.64007574319839478 0.21879824995994568 -0.45009618997573853 +0.57810342311859131 -0.026576757431030273 -0.74776506423950195 +0.58013069629669189 0.065721109509468079 -0.6097562313079834 +0.62404477596282959 -0.0036405473947525024 -0.76906281709671021 +0.46004989743232727 -0.13201887905597687 -0.76382267475128174 +0.4272255003452301 -0.14323930442333221 -0.74074077606201172 +0.62861603498458862 0.065075978636741638 -0.67006027698516846 +0.44312936067581177 0.15147571265697479 -0.3116050660610199 +0.42684420943260193 0.07358928769826889 -0.41023328900337219 +-0.006878487765789032 -0.16883477568626404 -0.09185481071472168 +0.03485296294093132 -0.04335964098572731 0.028486182913184166 +-0.017486907541751862 -0.30937695503234863 -0.17526046931743622 +0.10455888509750366 -0.13007892668247223 0.085458546876907349 +0.044613812118768692 -0.28315606713294983 -0.074201524257659912 +-0.065394625067710876 -0.16699324548244476 -0.17417462170124054 +0.066412016749382019 -0.22749164700508118 -0.0161433145403862 +-0.0030032172799110413 -0.25348234176635742 -0.12749223411083221 +0.061979860067367554 -0.63589262962341309 -0.22097581624984741 +0.1186310350894928 -0.62358784675598145 -0.134431391954422 +-0.018915846943855286 -0.46429562568664551 -0.25260072946548462 +0.14042924344539642 -0.56792342662811279 -0.07637321949005127 +0.10342063754796982 -0.39770755171775818 -0.046258270740509033 +0.24397073686122894 -0.30351749062538147 0.19940328598022461 +0.27882370352745056 -0.34687712788581848 0.22788946330547333 +0.19965577125549316 -0.37256088852882385 0.10282056778669357 +-0.024685144424438477 -0.35423073172569275 -0.20730105042457581 +0.15103766322135925 -0.42738127708435059 0.0070324540138244629 +-0.13078925013542175 -0.33398649096488953 -0.34834924340248108 +-0.051621317863464355 -0.30830270051956177 -0.22328037023544312 +0.0086226016283035278 -0.50742506980895996 -0.23440450429916382 +0.036161035299301147 -0.55055451393127441 -0.2162083238363266 +-0.081743285059928894 -0.20874156057834625 -0.21771827340126038 +0.29907214641571045 -1.1082448959350586 -0.11342728137969971 +0.15563963353633881 -0.79380381107330322 -0.16454637050628662 +0.31498473882675171 -0.89743167161941528 0.011681109666824341 +0.20354737341403961 -0.9361875057220459 -0.16563218832015991 +0.2296568751335144 -1.1342356204986572 -0.22477626800537109 +0.32075405120849609 -1.0074964761734009 -0.033618509769439697 +0.34769025444984436 -1.0534244775772095 -0.017639189958572388 +0.2874462902545929 -0.85430216789245605 -0.0065150558948516846 +0.25990787148475647 -0.8111727237701416 -0.024711251258850098 +0.23575685918331146 -0.96738874912261963 -0.13499492406845093 +0.096413135528564453 -0.98916631937026978 -0.34374013543128967 +0.2743915319442749 -0.75527811050415039 0.023056983947753906 +0.23242121934890747 -0.48428034782409668 0.095107436180114746 +0.3248746395111084 -0.71460402011871338 0.11462053656578064 +0.27840399742126465 -0.65679115056991577 0.076638936996459961 +0.48321047425270081 -0.66323643922805786 0.36475828289985657 +0.30559200048446655 -0.51677078008651733 0.18336856365203857 +0.38080722093582153 -0.66001379489898682 0.22069862484931946 +0.32673144340515137 -0.48926082253456116 0.22680363059043884 +0.21342907845973969 -0.51387035846710205 0.053714841604232788 +0.20252996683120728 -0.54170256853103638 0.02468574047088623 +0.38338258862495422 -0.47695603966712952 0.31334802508354187 +0.41823554039001465 -0.52031570672988892 0.34183418750762939 +0.38289475440979004 -0.59165400266647339 0.25689795613288879 +0.37895041704177856 -0.88535702228546143 0.10851553082466125 +0.021677359938621521 -0.60644906759262085 -0.26397651433944702 +0.063647717237472534 -0.87744688987731934 -0.33602696657180786 +-0.028805702924728394 -0.64712321758270264 -0.35554009675979614 +0.017664909362792969 -0.70493602752685547 -0.31755852699279785 +-0.18714156746864319 -0.69849073886871338 -0.60567790269851685 +-0.24522984027862549 -0.62622469663619995 -0.65315485000610352 +-0.21253253519535065 -0.54272806644439697 -0.56606751680374146 +-0.0095230937004089355 -0.84495645761489868 -0.42428809404373169 +-0.08473832905292511 -0.7017134428024292 -0.46161818504333496 +-0.030662521719932556 -0.87246644496917725 -0.46772319078445435 +0.082639828324317932 -0.84785687923431396 -0.29463440179824829 +0.093538939952850342 -0.82002460956573486 -0.26560527086257935 +-0.086825862526893616 -0.77007317543029785 -0.49781754612922668 +-0.14713791012763977 -0.37573480606079102 -0.39189291000366211 +-0.082881532609462738 -0.47637015581130981 -0.34943509101867676 +0.65849137306213379 -0.59611284732818604 0.32430103421211243 +0.52279442548751831 -0.65039461851119995 0.42729273438453674 +0.75053668022155762 -0.51727157831192017 0.21415171027183533 +0.45308852195739746 -0.56367534399032593 0.37032037973403931 +0.63362270593643188 -0.50196301937103271 0.24337016046047211 +0.56797391176223755 -0.52440387010574341 0.28953388333320618 +0.69690066576004028 -0.5435023307800293 0.25943875312805176 +0.79165899753570557 -0.28212070465087891 -0.026743233203887939 +0.69115722179412842 -0.26120191812515259 -0.0090657174587249756 +0.8349684476852417 -0.42524039745330811 0.094214737415313721 +0.62550842761993408 -0.28364273905754089 0.037098005414009094 +0.5967411994934082 -0.40402328968048096 0.16331595182418823 +0.31367665529251099 -0.39023676514625549 0.25637564063072205 +0.42376750707626343 -0.37102869153022766 0.19662544131278992 +0.78623777627944946 -0.49401313066482544 0.17844806611537933 +0.5334632396697998 -0.36248400807380676 0.14724732935428619 +0.80659639835357666 -0.53495758771896362 0.21006065607070923 +0.81212830543518066 -0.38567063212394714 0.064851909875869751 +0.78928816318511963 -0.34610086679458618 0.035489082336425781 +0.64853227138519287 0.11903818696737289 -0.35762438178062439 +0.71992450952529907 -0.14082135260105133 -0.13528364896774292 +0.51046448945999146 0.0007762908935546875 -0.19240039587020874 +0.71586740016937256 -0.031661227345466614 -0.23841972649097443 +0.77745902538299561 0.099939748644828796 -0.38771951198577881 +0.59083914756774902 0.20196761190891266 -0.41547340154647827 +0.55919516086578369 0.069549009203910828 -0.27663367986679077 +0.39389276504516602 0.13464507460594177 -0.27698227763175964 +0.53883659839630127 0.1104934960603714 -0.30824628472328186 +0.53330463171005249 -0.038793489336967468 -0.16303753852844238 +0.55614477396011353 -0.078363269567489624 -0.13367469608783722 +0.54160255193710327 0.18513697385787964 -0.38085064291954041 +0.67895960807800293 0.0030997991561889648 -0.25789031386375427 +0.92166543006896973 -0.053435385227203369 -0.29481109976768494 +0.50250875949859619 -0.10459397733211517 -0.088387638330459595 +0.42858830094337463 -0.28778660297393799 0.11500555276870728 +0.39721250534057617 -0.10373860597610474 -0.049673795700073242 +0.44368308782577515 -0.16155144572257996 -0.011692225933074951 +0.10732486844062805 -0.055435430258512497 0.012854184955358505 +0.13941185176372528 -0.17343856394290924 0.11394473165273666 +0.049236595630645752 0.016830634325742722 -0.034622784703969955 +0.14770978689193726 0.050491902977228165 -0.10386835038661957 +0.3244088888168335 -0.23180237412452698 0.10044419765472412 +0.27550399303436279 -0.10849344730377197 0.00058098882436752319 +0.27476656436920166 -0.23771700263023376 0.12475337833166122 +0.47577008605003357 -0.27955460548400879 0.089398324489593506 +0.50859445333480835 -0.26833418011665344 0.066316470503807068 +0.1742648184299469 -0.21679820120334625 0.14243091642856598 +0.23583024740219116 -0.14837589859962463 0.053714729845523834 +0.34465616941452026 0.11781443655490875 -0.24235948920249939 +0.39794990420341492 0.025484941899776459 -0.17384618520736694 +0.84292411804199219 -0.31987011432647705 -0.0097979605197906494 +0.91684460639953613 -0.13667753338813782 -0.21319115161895752 +0.94822049140930176 -0.32072550058364868 -0.04851183295249939 +0.90174984931945801 -0.26291263103485107 -0.086493432521820068 +1.2381080389022827 -0.36902862787246704 -0.11103981733322144 +1.0210241079330444 -0.19266173243522644 -0.19862982630729675 +1.0699288845062256 -0.31597062945365906 -0.098766595125198364 +1.0706663131713867 -0.18674708902835846 -0.22293904423713684 +0.86966288089752197 -0.14490951597690582 -0.18758393824100494 +0.8368384838104248 -0.15612994134426117 -0.1645020991563797 +1.109602689743042 -0.27608814835548401 -0.15190038084983826 +0.94748300313949585 -0.44994908571243286 0.075660586357116699 +0.49989664554595947 -0.37874871492385864 -1.1881299018859863 +0.4042152464389801 -0.39905798435211182 -1.1019766330718994 +0.19789952039718628 -0.47474896907806396 -0.9647599458694458 +0.29637271165847778 -0.44108772277832031 -1.0340055227279663 +0.29630917310714722 -0.40494957566261292 -0.97892087697982788 +0.41664409637451172 -0.35176202654838562 -1.0451928377151489 +0.053421348333358765 -0.49520832300186157 -0.81913203001022339 +0.0064026862382888794 -0.52815538644790649 -0.81175422668457031 +-0.20911028981208801 -0.62110984325408936 -0.68956178426742554 +-0.10221832990646362 -0.57217305898666382 -0.74585652351379395 +-0.024955466389656067 -0.48377394676208496 -0.7058330774307251 +-0.075721859931945801 -0.52006834745407104 -0.69896501302719116 +0.077437490224838257 -0.45566034317016602 -0.78831875324249268 +0.039099991321563721 -0.44465875625610352 -0.72466695308685303 +-0.064822748303413391 -0.49223616719245911 -0.66993588209152222 +0.099426329135894775 -0.50841027498245239 -0.89551436901092529 +0.050189733505249023 -0.52524089813232422 -0.86089158058166504 +0.24700899422168732 -0.38564217090606689 -0.88921350240707397 +0.13193300366401672 -0.31649932265281677 -0.6431732177734375 +0.18116959929466248 -0.29966866970062256 -0.67779600620269775 +0.38509529829025269 -0.19896627962589264 -0.77401793003082275 +0.28509235382080078 -0.25209128856658936 -0.73252707719802856 +0.27266347408294678 -0.29938727617263794 -0.78931081295013428 +0.23040619492530823 -0.28283804655075073 -0.71241879463195801 +0.32894295454025269 -0.2853148877620697 -0.83674895763397217 +0.022751331329345703 -0.48640710115432739 -0.76821058988571167 +0.13212363421916962 -0.42491364479064941 -0.80842697620391846 +0.066347762942314148 -0.37507826089859009 -0.65209412574768066 +0.099172160029411316 -0.36385783553123474 -0.67517602443695068 +-0.22061720490455627 -0.66926205158233643 -0.63907462358474731 +-0.22888118028640747 -0.58447635173797607 -0.6096111536026001 +-0.15859764814376831 -0.52945709228515625 -0.61185693740844727 +-0.097901314496994019 -0.35890418291091919 -0.42651569843292236 +-0.10402095317840576 -0.50388014316558838 -0.39287012815475464 +-0.16348657011985779 -0.4174831211566925 -0.43543654680252075 +-0.13336458802223206 -0.5170443058013916 -0.44099864363670349 +0.026480481028556824 -0.38354045152664185 -0.61619693040847778 +-0.13059861958026886 -0.44240081310272217 -0.51360297203063965 +-0.0759124755859375 -0.41165405511856079 -0.53371125459671021 +-0.17503610253334045 -0.59824597835540771 -0.53973239660263062 +-0.098939515650272369 -0.63082849979400635 -0.44735530018806458 +-0.13120895624160767 -0.64390057325363159 -0.49959975481033325 +-0.07054533064365387 -0.53310883045196533 -0.35947340726852417 +-0.063658677041530609 -0.60376358032226562 -0.38402628898620605 +-0.10797365009784698 -0.67280697822570801 -0.48060896992683411 +-0.098091937601566315 -0.25048986077308655 -0.26126194000244141 +-0.006196342408657074 -0.21184507012367249 -0.31487423181533813 +-0.079587623476982117 -0.33559781312942505 -0.27631938457489014 +-0.016094490885734558 -0.18630070984363556 -0.26388198137283325 +-0.016348656266927719 -0.041748311370611191 -0.043543655425310135 +0.014803445897996426 -0.06808636337518692 -0.012045977637171745 +0.12199181318283081 0.00037516653537750244 -0.14868642389774323 +0.026310354471206665 -0.019934143871068954 -0.062533155083656311 +0.0095599517226219177 -0.10004587471485138 -0.16397935152053833 +-0.032697312533855438 -0.083496622741222382 -0.08708731085062027 +0.22989785671234131 0.006266765296459198 -0.27174216508865356 +0.065839409828186035 -0.085973456501960754 -0.21141746640205383 +0.033205650746822357 -0.20560815930366516 -0.35358935594558716 +0.082378700375556946 -0.15263944864273071 -0.33312755823135376 +-0.046890322118997574 -0.25210121273994446 -0.18923209607601166 +0.055512916296720505 -0.2553238570690155 -0.045172423124313354 +0.032277610152959824 -0.2264174222946167 -0.064163215458393097 +-0.065203994512557983 -0.27540755271911621 -0.3394283652305603 +-0.048855341970920563 -0.23365922272205353 -0.29588472843170166 +-0.0048776715993881226 -0.33915898203849792 -0.51027578115463257 +0.34503743052482605 -0.099014148116111755 -0.57286703586578369 +0.19739118218421936 -0.18564414978027344 -0.52408319711685181 +0.14111170172691345 -0.19971659779548645 -0.47664511203765869 +0.10374334454536438 -0.29514133930206299 -0.57617348432540894 +0.14821812510490417 -0.23861289024353027 -0.54454505443572998 +0.00076250731945037842 -0.43365716934204102 -0.66101503372192383 +0.033142097294330597 -0.16947008669376373 -0.29850476980209351 +0.033269196748733521 -0.24174627661705017 -0.40867394208908081 +0.15354059636592865 -0.15242058038711548 -0.4198613166809082 +-0.11228494346141815 -0.41909444332122803 -0.3634067177772522 +-0.12863360345363617 -0.46084275841712952 -0.40695035457611084 +-0.0044321566820144653 -0.4084010124206543 -0.20483249425888062 +0.13432928919792175 -0.73477029800415039 -0.16615450382232666 +0.045631200075149536 -0.67764097452163696 -0.26451945304870605 +0.12953014671802521 -0.59575569629669189 -0.10540229082107544 +0.078328520059585571 -0.59414434432983398 -0.17743214964866638 +0.10629484057426453 -0.5668492317199707 -0.12439307570457458 +0.067138731479644775 -0.50926655530929565 -0.15208469331264496 +0.060312047600746155 -0.39433839917182922 -0.10592460632324219 +0.08162243664264679 -0.45337194204330444 -0.10431645810604095 +0.092521533370018005 -0.4255397617816925 -0.075287356972694397 +-0.098511636257171631 -0.56040394306182861 -0.41251245141029358 +-0.042579025030136108 -0.50581371784210205 -0.30643436312675476 +-0.0055703967809677124 -0.67602962255477905 -0.33654928207397461 +0.0053287148475646973 -0.64819741249084473 -0.30752015113830566 +0.067271649837493896 -0.021223206073045731 -0.0049092806875705719 +0.098473191261291504 0.033661268651485443 -0.069245569407939911 +0.32830750942230225 0.076066121459007263 -0.28590315580368042 +0.34830760955810547 0.019570335745811462 -0.14953702688217163 +0.29541957378387451 0.10098380595445633 -0.20773670077323914 +0.29265359044075012 0.026340320706367493 -0.13513234257698059 +0.18548662960529327 -0.086399741470813751 -0.35845518112182617 +0.22983431816101074 0.042404863983392715 -0.21665757894515991 +0.13148821890354156 -0.063532605767250061 -0.25758117437362671 +0.18050795793533325 -0.0014663524925708771 -0.066366605460643768 +0.28949248790740967 -0.058966532349586487 -0.052155926823616028 +0.22903336584568024 -0.050680588930845261 -0.037400595843791962 +0.38836079835891724 -0.014641903340816498 -0.13177354633808136 +0.36235952377319336 -0.060378953814506531 -0.078159987926483154 +0.25226867198944092 -0.079587027430534363 -0.018409803509712219 +0.49236595630645752 0.16830635070800781 -0.34622785449028015 +0.47278565168380737 0.096525505185127258 -0.43153098225593567 +0.47798231244087219 0.10811607539653778 -0.28311887383460999 +0.51980435848236084 0.12947255373001099 -0.43890884518623352 +0.68931233882904053 0.2356288731098175 -0.48471897840499878 +0.73531728982925415 0.22242698073387146 -0.56110125780105591 +0.77627861499786377 0.22113792598247528 -0.50347739458084106 +0.68694150447845459 0.17164874076843262 -0.42248669266700745 +0.62842535972595215 0.17349027097225189 -0.5048065185546875 +0.55116254091262817 0.085091099143028259 -0.54482996463775635 +0.60192888975143433 0.12138552963733673 -0.55169802904129028 +0.44876953959465027 0.056977517902851105 -0.46234428882598877 +0.4871070384979248 0.045975938439369202 -0.52599614858627319 +0.59102976322174072 0.093553319573402405 -0.58072715997695923 +0.57645553350448608 0.14177733659744263 -0.35236445069313049 +0.59489625692367554 0.092807494103908539 -0.31233736872673035 +0.72139930725097656 0.11762575805187225 -0.38362842798233032 +0.42678070068359375 0.1097273975610733 -0.35514873266220093 +0.4760172963142395 0.12655803561210632 -0.38977152109146118 +0.27919799089431763 -0.013040706515312195 -0.36144953966140747 +0.31703841686248779 -0.18607047200202942 -0.67112100124359131 +0.3942740261554718 -0.082183510065078735 -0.60748982429504395 +0.2630399763584137 -0.16320331394672394 -0.57024693489074707 +0.2958008348941803 -0.11584478616714478 -0.53824424743652344 +0.25354355573654175 -0.099295534193515778 -0.46135216951370239 +0.13155175745487213 -0.099670708179473877 -0.31266576051712036 +0.16443969309329987 -0.12458838522434235 -0.39083218574523926 +0.50345569849014282 0.087724253535270691 -0.48245251178741455 +0.39408338069915771 0.026230782270431519 -0.4422360360622406 +0.45985925197601318 -0.023604586720466614 -0.59856891632080078 +0.42703485488891602 -0.03482501208782196 -0.57548701763153076 +0.37950912117958069 0.074454799294471741 -0.21387331187725067 +0.33027252554893494 0.057624164968729019 -0.17925052344799042 +0.56410038471221924 0.027006983757019043 -0.23768743872642517 +0.6214250922203064 -0.23766133189201355 -0.0054544508457183838 +0.50453734397888184 -0.15917405486106873 -0.036819607019424438 +0.55377393960952759 -0.14234341681003571 -0.071442395448684692 +0.77356046438217163 -0.11459065973758698 -0.18057067692279816 +0.66386479139328003 -0.12313534319400787 -0.13119256496429443 +0.62940698862075806 -0.069112345576286316 -0.17005081474781036 +0.60301053524017334 -0.12551277875900269 -0.10606518387794495 +0.68304300308227539 -0.04288165271282196 -0.21533785760402679 +0.32750654220581055 -0.017019316554069519 -0.10664617270231247 +0.44921505451202393 -0.012264490127563477 -0.15690094232559204 +0.42044779658317566 -0.13264502584934235 -0.030683010816574097 +0.45327219367027283 -0.1214246079325676 -0.053764864802360535 +0.68480467796325684 0.13077424466609955 -0.63880610466003418 +0.62410831451416016 -0.039778649806976318 -0.82414734363555908 +0.49972653388977051 -0.015142366290092468 -0.63446605205535889 +0.65680563449859619 0.043717965483665466 -0.7370600700378418 +0.60211950540542603 0.012971207499504089 -0.71695184707641602 +0.53240334987640381 -0.18683777749538422 -0.93578881025314331 +0.54230153560638428 -0.21238212287425995 -0.98678112030029297 +0.46049469709396362 -0.38498562574386597 -1.1494147777557373 +0.51664704084396362 -0.29863697290420532 -1.0866837501525879 +0.39465528726577759 -0.29901212453842163 -0.93799728155136108 +0.42754322290420532 -0.32392981648445129 -1.01616370677948 +0.49300137162208557 -0.19307467341423035 -0.89707362651824951 +0.44382834434509277 -0.24604339897632599 -0.91753548383712769 +0.59141099452972412 -0.1232752799987793 -0.91123467683792114 +0.57506239414215088 -0.16502359509468079 -0.95477831363677979 +0.53108471632003784 -0.059523820877075195 -0.7403872013092041 +0.26310351490974426 -0.19934141635894775 -0.62533152103424072 +0.295991450548172 -0.22425909340381622 -0.70349800586700439 +0.42246365547180176 -0.1035415381193161 -0.67448955774307251 +0.37798890471458435 -0.16006994247436523 -0.70611798763275146 +0.52544450759887695 0.034974366426467896 -0.58964800834655762 +0.49306493997573853 -0.22921276092529297 -0.95215827226638794 +0.492937833070755 -0.15693655610084534 -0.84198909997940063 +0.39459174871444702 -0.26287403702735901 -0.88291275501251221 +0.5166860818862915 -0.69246518611907959 0.39815506339073181 +0.40008985996246338 -0.85784715414047241 0.15195056796073914 +0.42943352460861206 -0.84468293190002441 0.20007908344268799 +0.47110497951507568 -0.7634812593460083 0.29881283640861511 +0.39500844478607178 -0.73089879751205444 0.20643575489521027 +0.42727786302566528 -0.71782666444778442 0.25868019461631775 +0.36661422252655029 -0.82861840724945068 0.11855381727218628 +0.35972756147384644 -0.75796365737915039 0.14310672879219055 +0.40404254198074341 -0.68892025947570801 0.2396894097328186 +0.37565651535987854 -1.0261294841766357 0.035399824380874634 +0.28126543760299683 -1.2936408519744873 -0.22887358069419861 +0.30294734239578247 -1.1928925514221191 -0.14906474947929382 +0.34295922517776489 -1.1096260547637939 -0.051687479019165039 +0.31355580687522888 -1.0523502826690674 -0.065659105777740479 +0.26379132270812988 -1.1353098154067993 -0.176756352186203 +0.40835383534431458 -0.94263279438018799 0.12248715758323669 +0.42470249533653259 -0.90088450908660889 0.16603079438209534 +0.30050104856491089 -0.95332622528076172 -0.036087065935134888 +0.16173964738845825 -0.62695705890655518 -0.074765041470527649 +0.25043770670890808 -0.68408626317977905 0.023599892854690552 +0.23408904671669006 -0.72583460807800293 -0.019943743944168091 +0.14115597307682037 -0.84969842433929443 -0.21231454610824585 +0.18977406620979309 -0.79487800598144531 -0.11652645468711853 +0.22893014550209045 -0.85246068239212036 -0.088834881782531738 +0.21774038672447205 -0.76758289337158203 -0.063487410545349121 +0.21444648504257202 -0.9083552360534668 -0.13660305738449097 +0.39458054304122925 -0.8013232946395874 0.17159289121627808 +0.33864793181419373 -0.85591351985931396 0.065514802932739258 +0.30163931846618652 -0.68569761514663696 0.095629751682281494 +0.29074019193649292 -0.71352982521057129 0.066600650548934937 +1.2781612873077393 -0.40324091911315918 -0.093276351690292358 +0.99712526798248291 -0.44403445720672607 0.051351398229598999 +1.0527794361114502 -0.45080441236495972 0.036946713924407959 +1.1649249792098999 -0.42299777269363403 -0.031819045543670654 +1.0559405088424683 -0.36549758911132812 -0.04602968692779541 +1.1163995265960693 -0.37378349900245667 -0.060785025358200073 +0.95707213878631592 -0.40982216596603394 0.033587902784347534 +0.98307341337203979 -0.36408513784408569 -0.020025640726089478 +1.0931642055511475 -0.34487709403038025 -0.079775810241699219 +0.86745059490203857 -0.53258019685745239 0.18493324518203735 +0.56915426254272461 -0.64560204744338989 0.40529176592826843 +0.76897740364074707 -0.56624144315719604 0.25417882204055786 +0.60079830884933472 -0.51318341493606567 0.26645201444625854 +0.62403362989425659 -0.54208981990814209 0.28544282913208008 +0.96592378616333008 -0.49891889095306396 0.11568766832351685 +1.0151603221893311 -0.48208826780319214 0.081064879894256592 +0.78133249282836914 -0.45147112011909485 0.13950182497501373 +0.72400790452957153 -0.18680280447006226 -0.092731162905693054 +0.84089559316635132 -0.26529005169868469 -0.061366021633148193 +0.65833282470703125 -0.27242231369018555 0.014016151428222656 +0.74242240190505981 -0.29895132780075073 0.0078795552253723145 +0.68156814575195312 -0.30132877826690674 0.033006966114044189 +0.7160259485244751 -0.35535174608230591 0.071865171194076538 +0.66647332906723022 -0.42756387591362 0.15970470011234283 +0.66238999366760254 -0.38158243894577026 0.11715224385261536 +0.62956559658050537 -0.39280286431312561 0.14023409783840179 +1.0179264545440674 -0.40744477510452271 0.0084605216979980469 +0.89621788263320923 -0.41219961643218994 0.058715313673019409 +0.92498517036437988 -0.29181906580924988 -0.067502617835998535 +0.89216077327728271 -0.30303949117660522 -0.044420748949050903 +0.74057751893997192 0.19787944853305817 -0.46777370572090149 +0.90130680799484253 -0.012490913271903992 -0.32642367482185364 +0.89640152454376221 0.030051112174987793 -0.36536997556686401 +0.83109498023986816 0.12617044150829315 -0.43300655484199524 +0.7302510142326355 0.028529047966003418 -0.30152866244316101 +0.74463462829589844 0.08871932327747345 -0.36463764309883118 +0.86560571193695068 -0.0357494056224823 -0.29072001576423645 +0.7979283332824707 -0.0036101639270782471 -0.29612433910369873 +1.0522255897521973 -0.13777723908424377 -0.26296612620353699 +1.1895825862884521 -0.31981444358825684 -0.14000579714775085 +0.96220886707305908 -0.271198570728302 -0.10124874114990234 +1.1219315528869629 -0.2244965136051178 -0.20599374175071716 +1.061077356338501 -0.2268739640712738 -0.18086636066436768 +0.98251968622207642 -0.051057964563369751 -0.31993848085403442 +0.9476667046546936 -0.0076983273029327393 -0.34842467308044434 +0.9653700590133667 -0.18589171767234802 -0.1842251718044281 +0.6871001124382019 -0.15204177796840668 -0.11220178008079529 +0.85322439670562744 -0.21369843184947968 -0.1154593825340271 +0.78760182857513428 -0.17296057939529419 -0.12987931072711945 +1.0090746879577637 -0.31834810972213745 -0.073639214038848877 +0.84716498851776123 0.013220474123954773 -0.33074712753295898 +0.88404649496078491 -0.084719240665435791 -0.25069290399551392 +0.74869179725646973 -0.020440801978111267 -0.26150161027908325 +0.60485541820526123 -0.62234354019165039 0.36958810687065125 +0.54879570007324219 -0.60465753078460693 0.37367916107177734 +0.43938335776329041 -0.61758196353912354 0.32462567090988159 +0.29732799530029297 -0.43198508024215698 0.21283198893070221 +0.44412609934806824 -0.41197320818901062 0.22823804616928101 +0.3485296368598938 -0.4335964024066925 0.28486183285713196 +0.44903138279914856 -0.45451518893241882 0.26718431711196899 +0.31067341566085815 -0.64371907711029053 0.12888340651988983 +0.36703392863273621 -0.51870435476303101 0.26980435848236084 +0.33906763792037964 -0.54599946737289429 0.21676531434059143 +0.51433795690536499 -0.55063456296920776 0.334820955991745 +0.48794147372245789 -0.60703498125076294 0.39880657196044922 +0.61518192291259766 -0.45299315452575684 0.20334304869174957 +0.47982722520828247 -0.38871470093727112 0.19253440201282501 +0.54750454425811768 -0.42085391283035278 0.19793874025344849 +0.20911777019500732 -0.26015785336494446 0.1709170937538147 +0.17271959781646729 -0.32663285732269287 0.086841292679309845 +0.29320734739303589 -0.28668686747550964 0.16478049755096436 +0.15246661007404327 -0.27246260643005371 0.084372706711292267 +0.041739612817764282 -0.11401437222957611 0.0039333142340183258 +0.0076052024960517883 -0.11294016242027283 -0.044086575508117676 +0 0 0 +0.15585029125213623 -0.10464967787265778 0.041820202022790909 +0.080895714461803436 -0.17159704864025116 0.031624920666217804 +0.06970592588186264 -0.08671928197145462 0.056972365826368332 +0.074017226696014404 -0.340431809425354 -0.060229890048503876 +0.16552135348320007 -0.37148669362068176 0.054800674319267273 +0.11976929754018784 -0.35595923662185669 -0.0027146041393280029 +0.38322398066520691 -0.15326552093029022 0.0030631124973297119 +0.22350141406059265 -0.19996756315231323 0.10780812799930573 +0.28435567021369934 -0.19759014248847961 0.082680739462375641 +0.22762207686901093 -0.34526580572128296 0.15585963428020477 +0.19276911020278931 -0.30190616846084595 0.12737344205379486 +0.27624833583831787 -0.52993488311767578 0.13524004817008972 +0.15491294860839844 -0.51202887296676636 -0.028604969382286072 +0.23457686603069305 -0.61113661527633667 0.036506325006484985 +0.18618132174015045 -0.58345091342926025 -0.018857911229133606 +0.35284090042114258 -0.68730896711349487 0.16765956580638885 +0.13611795008182526 -0.3142109215259552 0.04082905501127243 +0.19492477178573608 -0.42876243591308594 0.068772315979003906 +0.36291325092315674 -0.37340614199638367 0.22175285220146179 +0.39776623249053955 -0.41676577925682068 0.2502390444278717 +0.38006287813186646 -0.23857235908508301 0.086039528250694275 +0.67271649837493896 -0.21223205327987671 -0.049092814326286316 +0.57187247276306152 -0.30987349152565002 0.082385078072547913 +0.49220854043960571 -0.21076571941375732 0.017273783683776855 +0.5578310489654541 -0.25150352716445923 0.031693682074546814 +0.33635824918746948 -0.10611602663993835 -0.024546407163143158 +0.49826797842979431 -0.437684565782547 0.23256152868270874 +0.46138644218444824 -0.33974486589431763 0.15250729024410248 +-0.1433144211769104 -0.74414527416229248 -0.56554520130157471 +-0.0012591034173965454 -0.92974221706390381 -0.45375156402587891 +-0.014604538679122925 -0.71800810098648071 -0.36980295181274414 +-0.070965021848678589 -0.84302288293838501 -0.51072394847869873 +-0.042998701333999634 -0.81572777032852173 -0.45768484473228455 +0.12334930896759033 -1.0350943803787231 -0.32776081562042236 +0.14360229671001434 -1.0892646312713623 -0.32529225945472717 +0.28846371173858643 -1.2487870454788208 -0.19683298468589783 +0.21517321467399597 -1.1901302337646484 -0.27254441380500793 +0.22205166518688202 -1.021295428276062 -0.18068969249725342 +0.24055598676204681 -1.1064033508300781 -0.19574713706970215 +0.13054755330085754 -0.99024057388305664 -0.29572024941444397 +0.17629960179328918 -1.0057679414749146 -0.23820498585700989 +0.068446815013885498 -1.0164614915847778 -0.39677920937538147 +0.10329979658126831 -1.0598211288452148 -0.36829301714897156 +0.019820541143417358 -0.83179235458374023 -0.37615963816642761 +0.14803445339202881 -0.68086361885070801 -0.12045978009700775 +0.16653874516487122 -0.76597154140472412 -0.13551726937294006 +0.061492055654525757 -0.75059062242507935 -0.27742582559585571 +0.10988759994506836 -0.77827632427215576 -0.22206161916255951 +-0.056772023439407349 -0.67441827058792114 -0.40857914090156555 +0.15995094180107117 -1.0475163459777832 -0.28174862265586853 +0.10114412009716034 -0.93296480178833008 -0.30969187617301941 +0.1926482617855072 -0.96401965618133545 -0.19466128945350647 +-0.55764740705490112 0.69375425577163696 -0.45577892661094666 +0.26157850027084351 0.66797298192977905 0.69669848680496216 +-0.78778553009033203 -0.26929014921188354 0.55396455526351929 +-1.3454329967498779 0.42446410655975342 0.098185628652572632 +-0.29606890678405762 1.361727237701416 0.2409195601940155 +-0.81922590732574463 0.02578127384185791 -1.1524773836135864 +0.23013812303543091 0.96304440498352051 -1.0097434520721436 +-0.52620702981948853 0.39868283271789551 1.2506630420684814 +1.0493640899658203 0.9372631311416626 0.14273393154144287 +0.81922590732574463 -0.02578127384185791 1.1524773836135864 +-0.23013812303543091 -0.96304440498352051 1.0097434520721436 +-1.0493640899658203 -0.9372631311416626 -0.14273393154144287 +-0.9342949390411377 -0.45574089884757996 -0.64760565757751465 +-0.39923164248466492 -1.1474270820617676 -0.18533025681972504 +0.36945003271102905 0.30402693152427673 -1.1319878101348877 +1.1966761350631714 0.27799388766288757 0.031744256615638733 +0.63975107669830322 0.95015370845794678 -0.43350476026535034 +1.0790599584579468 -0.21418702602386475 0.54779154062271118 +0.29454389214515686 -0.49441283941268921 1.0811104774475098 +0.019448280334472656 -1.1606030464172363 0.4036637544631958 +-0.16684606671333313 -0.17497801780700684 -1.2049345970153809 +-0.032965362071990967 1.1623858213424683 -0.38441196084022522 +-1.0823295116424561 0.22512269020080566 -0.5271458625793457 +-0.82075095176696777 0.89309567213058472 0.16955259442329407 +-0.29454389214515686 0.49441283941268921 -1.0811104774475098 +0.14650943875312805 0.18645080924034119 1.2015701532363892 +0.37664756178855896 1.1494951248168945 0.19182674586772919 +-0.41113796830177307 0.88020503520965576 0.74579125642776489 +0.9342949390411377 0.45574089884757996 0.64760565757751465 +-1.1973985433578491 -0.2563994824886322 -0.02227415144443512 +-0.37817254662513733 -0.2821807861328125 1.1302032470703125 +-0.93581998348236084 0.41157346963882446 0.67442435026168823 +-0.63975107669830322 -0.95015370845794678 0.43350476026535034 +0.36377191543579102 0.15716627240180969 -1.2114535570144653 +1.2667337656021118 0.12874984741210938 0.058822602033615112 +1.1847770214080811 -0.21420937776565552 0.41841226816177368 +0.028153836727142334 -1.2472734451293945 0.261089026927948 +-0.0099273920059204102 -0.17661169171333313 -1.2622839212417603 +-0.26358875632286072 -1.2380921840667725 -0.14933103322982788 +0.32797184586524963 0.10986673831939697 -1.2853572368621826 +1.3237366676330566 0.078529775142669678 0.11547297239303589 +1.2630558013916016 -0.17539793252944946 0.38171392679214478 +-0.012440741062164307 -1.3146364688873291 0.20822158455848694 +0.051284104585647583 -0.13726317882537842 -1.322992205619812 +-0.22844758629798889 -1.3078386783599854 -0.095654278993606567 +0.30562540888786316 0.09692266583442688 -1.3234282732009888 +1.3520585298538208 0.063991069793701172 0.14868158102035522 +1.3008167743682861 -0.15043675899505615 0.3735072910785675 +-0.039581775665283203 -1.3476438522338867 0.19118696451187134 +0.071977943181991577 -0.1117648184299469 -1.3552087545394897 +-0.22198754549026489 -1.3419035673141479 -0.065419316291809082 +0.29711046814918518 0.075178772211074829 -1.3461071252822876 +1.370211124420166 0.041407942771911621 0.16351813077926636 +1.3264608383178711 -0.14167076349258423 0.35547459125518799 +-0.048096716403961182 -1.3693878650665283 0.16850799322128296 +0.097622007131576538 -0.10299888253211975 -1.3732415437698364 +-0.20383495092391968 -1.3644866943359375 -0.050582766532897949 +0.31455564498901367 0.031486451625823975 -1.3425381183624268 +1.3984318971633911 0.041777610778808594 0.20383024215698242 +1.3329997062683105 -0.16354215145111084 0.31418323516845703 +-0.02106243371963501 -1.3729532957077026 0.13000446557998657 +0.10437589883804321 -0.069105356931686401 -1.408273458480835 +-0.15866678953170776 -1.3686227798461914 -0.06357574462890625 +0.28178361058235168 0.036039739847183228 -1.3869293928146362 +1.3905344009399414 -0.025267243385314941 0.16000792384147644 +1.3726201057434082 -0.12589210271835327 0.32301574945449829 +-0.063423573970794678 -1.4085268974304199 0.12768584489822388 +0.16496509313583374 -0.11682787537574768 -1.3852670192718506 +-0.17116031050682068 -1.4051363468170166 -0.023876965045928955 +0.27156570553779602 0.0099470317363739014 -1.4141441583633423 +1.4246687889099121 -0.026341497898101807 0.20802778005599976 +1.403393030166626 -0.11537295579910278 0.30137652158737183 +-0.073641479015350342 -1.434619665145874 0.10047107934951782 +0.17455419898033142 -0.07670101523399353 -1.4273395538330078 +-0.14937722682952881 -1.4322361946105957 -0.0060731172561645508 +0.26066663861274719 -0.017885178327560425 -1.4431732892990112 +1.447904109954834 -0.055247962474822998 0.22701859474182129 +1.4362175464630127 -0.10415250062942505 0.27829462289810181 +-0.08454054594039917 -1.462451696395874 0.071441948413848877 +0.20737859606742859 -0.065480589866638184 -1.4504214525222778 +-0.12614190578460693 -1.4611425399780273 0.012917697429656982 +0.24738332629203796 -0.051805704832077026 -1.4785524606704712 +1.4762222766876221 -0.090477645397186279 0.25016361474990845 +-0.097823858261108398 -1.4963722229003906 0.036062717437744141 +-1.4762222766876221 0.090477645397186279 -0.25016361474990845 +-1.2146437168121338 0.75845062732696533 0.4465349018573761 +-0.95154017210006714 0.55910921096801758 -0.17879664897918701 +-1.066609263420105 0.077586978673934937 0.32607507705688477 +-0.68996167182922363 1.2270822525024414 0.51790177822113037 +0.097823858261108398 1.4963722229003906 -0.036062717437744141 +-0.42685815691947937 1.0277407169342041 -0.10742968320846558 +-0.017245203256607056 1.0148501396179199 0.46880900859832764 +-0.42533314228057861 0.16042631864547729 -1.4294596910476685 +-1.2131186723709106 -0.10886377096176147 -0.87549513578414917 +-0.68843662738800049 0.35976776480674744 -0.80412817001342773 +-0.54040217399597168 -0.32109585404396057 -0.92458796501159668 +0.36092740297317505 1.2970309257507324 -0.66139423847198486 +0.099348843097686768 0.62905788421630859 -1.3580927848815918 +-0.16375464200973511 0.82839930057525635 -0.7327612042427063 +0.50896179676055908 0.61616730690002441 -0.78185403347015381 +-0.8050307035446167 0.7455599308013916 1.0227736234664917 +-0.24738332629203796 0.051805704832077026 1.4785524606704712 +-0.13231426477432251 0.53332793712615967 0.97368073463439941 +-0.65699625015258789 0.064696341753005981 0.90231382846832275 +1.3281878232955933 0.5903860330581665 0.37062340974807739 +0.77054035663604736 1.2841402292251587 -0.085155531764030457 +0.65547126531600952 0.80261802673339844 0.41971620917320251 +0.91857481002807617 0.60327661037445068 -0.20561531186103821 +0.42533314228057861 -0.16042631864547729 1.4294596910476685 +1.2131186723709106 0.10886377096176147 0.87549513578414917 +0.54040217399597168 0.32109585404396057 0.92458796501159668 +0.68843662738800049 -0.35976776480674744 0.80412817001342773 +-0.36092740297317505 -1.2970309257507324 0.66139423847198486 +-0.099348843097686768 -0.62905788421630859 1.3580927848815918 +-0.50896179676055908 -0.61616730690002441 0.78185403347015381 +0.16375464200973511 -0.82839930057525635 0.7327612042427063 +-0.77054035663604736 -1.2841402292251587 0.085155531764030457 +-1.3281878232955933 -0.5903860330581665 -0.37062340974807739 +-0.65547126531600952 -0.80261802673339844 -0.41971620917320251 +-0.91857481002807617 -0.60327661037445068 0.20561531186103821 +-1.270653247833252 -0.3496248722076416 -0.62305927276611328 +-0.59793674945831299 -0.56185698509216309 -0.67215204238891602 +-0.991829514503479 -0.69650202989578247 -0.39516982436180115 +-0.87676042318344116 -0.21497982740402222 -0.90004152059555054 +-0.33414790034294128 -0.94208598136901855 -0.40664094686508179 +-0.42677584290504456 -1.3994700908660889 0.066662400960922241 +-0.71300578117370605 -1.0433791875839233 -0.16728034615516663 +0.16989201307296753 0.279754638671875 -1.4275757074356079 +0.5623355507850647 0.26714015007019043 -0.87561905384063721 +0.30415534973144531 0.6226125955581665 -1.069973349571228 +1.4096112251281738 0.24074029922485352 0.31644681096076965 +1.0172833204269409 0.25282275676727295 -0.23560389876365662 +1.1233812570571899 0.59683132171630859 0.082504056394100189 +0.71376830339431763 0.60972195863723755 -0.4937346875667572 +0.56573385000228882 1.2905855178833008 -0.37327486276626587 +0.84455752372741699 0.94370841979980469 -0.14538541436195374 +0.43494462966918945 0.95659911632537842 -0.72162413597106934 +1.3551331758499146 0.012769579887390137 0.55547207593917847 +0.85262072086334229 -0.43623045086860657 0.48686230182647705 +0.95077764987945557 -0.12545198202133179 0.83981168270111084 +0.42609566450119019 -0.59408354759216309 0.76844465732574463 +0.16299211978912354 -0.39474213123321533 1.3937761783599854 +0.03220289945602417 -0.72872865200042725 1.0454269647598267 +0.55688488483428955 -0.26009708642959595 1.1167939901351929 +0.26986837387084961 -0.95672881603240967 0.4075966477394104 +-0.23284971714019775 -1.4055731296539307 0.33947542309761047 +-0.098586380481719971 -1.0627150535583496 0.69707769155502319 +-0.18847891688346863 -0.40346676111221313 -0.977744460105896 +-0.078512132167816162 0.057886838912963867 -1.4613634347915649 +-0.48286765813827515 -0.080334722995758057 -1.1770238876342773 +0.22937560081481934 1.3967015743255615 -0.34872844815254211 +-0.29530638456344604 0.928070068359375 -0.42009544372558594 +-0.16451716423034668 1.2620565891265869 -0.071746200323104858 +0.098586380481719971 1.0627150535583496 -0.69707769155502319 +-0.8199884295463562 0.45943847298622131 -0.49146240949630737 +-1.3446704149246216 -0.0091930627822875977 -0.56282937526702881 +-1.213881254196167 0.32479339838027954 -0.21448014676570892 +-0.95077764987945557 0.12545198202133179 -0.83981168270111084 +-0.68919914960861206 0.79342496395111084 -0.14311316609382629 +-0.95230269432067871 0.99276638031005859 0.48221835494041443 +-0.5584099292755127 1.1274113655090332 0.20523610711097717 +-1.0830919742584229 0.65877985954284668 0.13386908173561096 +-0.42609566450119019 0.59408354759216309 -0.76844465732574463 +-0.16299211978912354 0.39474213123321533 -1.3937761783599854 +-0.55688488483428955 0.26009708642959595 -1.1167939901351929 +-0.03220289945602417 0.72872865200042725 -1.0454269647598267 +0.088974893093109131 -0.054310321807861328 1.4540060758590698 +0.20404396951198578 0.42721188068389893 0.94913434982299805 +-0.18984879553318024 0.29256683588027954 1.2261166572570801 +0.48286765813827515 0.080334722995758057 1.1770238876342773 +0.31911301612854004 0.90873408317565918 0.44426259398460388 +0.43418210744857788 1.3902562856674194 -0.060609102249145508 +0.040289342403411865 1.2556111812591553 0.21637314558029175 +0.71300578117370605 1.0433791875839233 0.16728034615516663 +-0.074779734015464783 0.77408897876739502 0.7212449312210083 +-0.74749618768692017 0.9863210916519165 0.77033770084381104 +-0.46867251396179199 0.63944393396377563 0.99822717905044556 +-0.35360342264175415 1.1209661960601807 0.49335545301437378 +0.59793674945831299 0.56185698509216309 0.67215204238891602 +1.270653247833252 0.3496248722076416 0.62305927276611328 +0.991829514503479 0.69650202989578247 0.39516982436180115 +0.87676042318344116 0.21497982740402222 0.90004152059555054 +-1.4022049903869629 -0.24995416402816772 -0.31039351224899292 +-0.99259203672409058 -0.26284486055374146 0.26584520936012268 +-1.2714157104492188 0.084032297134399414 0.037955760955810547 +-1.1233812570571899 -0.59683132171630859 -0.082504056394100189 +-0.58297902345657349 -0.27573546767234802 0.84208387136459351 +-0.17336612939834595 -0.28862613439559937 1.4183226823806763 +-0.45218980312347412 0.05825100839138031 1.1904332637786865 +-0.30415534973144531 -0.6226125955581665 1.069973349571228 +-0.86180275678634644 0.071141660213470459 0.61419445276260376 +-1.0098371505737305 0.75200527906417847 0.73465430736541748 +-1.1406264305114746 0.41801881790161133 0.38630497455596924 +-0.73101353645324707 0.4051281213760376 0.962543785572052 +-0.71376830339431763 -0.60972195863723755 0.4937346875667572 +-0.56573385000228882 -1.2905855178833008 0.37327486276626587 +-0.43494462966918945 -0.95659911632537842 0.72162413597106934 +-0.84455752372741699 -0.94370841979980469 0.14538541436195374 +0.55477762222290039 0.20371963083744049 -0.91719669103622437 +1.0644762516021729 0.17341557145118713 -0.20709246397018433 +0.90492153167724609 -0.43040561676025391 0.43173810839653015 +0.26158729195594788 -1.0141758918762207 0.33028668165206909 +-0.24396133422851562 -1.0022282600402832 -0.38283926248550415 +-0.10249347984790802 -0.39249873161315918 -1.0205438137054443 +0.16027182340621948 0.23312801122665405 -1.4639222621917725 +1.4419572353363037 0.1901516318321228 0.33785375952720642 +1.3988754749298096 0.021695435047149658 0.51553952693939209 +-0.2276882529258728 -1.439064621925354 0.2821820080280304 +-0.0231589674949646 0.067596018314361572 -1.4914548397064209 +-0.38567721843719482 -1.4375858306884766 0.08777579665184021 +0.54046046733856201 0.10097850859165192 -0.98750090599060059 +1.0975064039230347 0.090932160615921021 -0.20021708309650421 +0.99234825372695923 -0.41860032081604004 0.34274035692214966 +0.27380555868148804 -1.0555758476257324 0.25232166051864624 +-0.017199568450450897 -0.40019148588180542 -1.0451921224594116 +-0.16670054197311401 -1.0593041181564331 -0.35712465643882751 +0.54392248392105103 0.043638691306114197 -1.0104513168334961 +1.1305954456329346 0.046810448169708252 -0.17460983991622925 +1.0262302160263062 -0.42509829998016357 0.2913949191570282 +0.26026374101638794 -1.0953421592712402 0.2083604633808136 +0.032304584980010986 -0.38590151071548462 -1.0774794816970825 +-0.11231201887130737 -1.0879251956939697 -0.35010409355163574 +0.50297611951828003 0.027317732572555542 -1.0766144990921021 +0.17362979054450989 0.1789986789226532 -1.4712390899658203 +1.1933634281158447 0.033766239881515503 -0.091689318418502808 +1.4473916292190552 0.1213034987449646 0.31211397051811218 +1.0904688835144043 -0.37903290987014771 0.28291597962379456 +1.4177234172821045 0.0040317773818969727 0.46559247374534607 +0.18961507081985474 -1.1761856079101562 0.17174530029296875 +-0.23110044002532959 -1.4664468765258789 0.24467754364013672 +0.042466849088668823 0.034755527973175049 -1.4846079349517822 +0.077635005116462708 -0.31987035274505615 -1.1578075885772705 +-0.10737901926040649 -1.1461185216903687 -0.29616221785545349 +-0.33179587125778198 -1.4525618553161621 0.081904381513595581 +0.45332556962966919 -0.017533347010612488 -1.1690245866775513 +1.2524365186691284 -0.042681574821472168 -0.044844627380371094 +1.1851416826248169 -0.32428610324859619 0.25041520595550537 +0.16154330968856812 -1.2385361194610596 0.11118593811988831 +0.1464802622795105 -0.29159915447235107 -1.210761547088623 +-0.078007161617279053 -1.2309973239898682 -0.22581082582473755 +0.13574886322021484 0.17050552368164062 -1.5292377471923828 +0.43843662738800049 -0.055554136633872986 -1.2086803913116455 +1.2841775417327881 -0.082169830799102783 -0.018901854753494263 +1.492058277130127 0.12782210111618042 0.37880265712738037 +1.4727303981781006 0.046941399574279785 0.46360531449317932 +1.2299821376800537 -0.30895823240280151 0.21888376772403717 +-0.26459556818008423 -1.5047904253005981 0.2272951602935791 +0.14665433764457703 -1.2765568494796753 0.071530133485794067 +0.19132071733474731 -0.27627122402191162 -1.2422930002212524 +0.047618627548217773 0.091790080070495605 -1.5412251949310303 +-0.33339780569076538 -1.5026252269744873 0.13050505518913269 +-0.046266078948974609 -1.2704856395721436 -0.19986805319786072 +0.42500734329223633 -0.089847370982170105 -1.2444484233856201 +1.3128068447113037 -0.117786705493927 0.004497528076171875 +1.2704265117645264 -0.29513305425643921 0.19044360518455505 +0.13322508335113525 -1.3108501434326172 0.035762101411819458 +0.23176509141921997 -0.26244604587554932 -1.270733118057251 +-0.01763683557510376 -1.3061025142669678 -0.17646867036819458 +0.42221724987030029 -0.13478957116603851 -1.2702631950378418 +0.11818939447402954 0.14772558212280273 -1.5652824640274048 +1.5198336839675903 0.103615403175354 0.40653437376022339 +1.3353128433227539 -0.16352492570877075 0.0142689049243927 +1.3041481971740723 -0.29393723607063293 0.15100505948066711 +1.5108439922332764 0.065996468067169189 0.44597747921943665 +-0.28455233573913574 -1.5376021862030029 0.20176860690116882 +0.13454461097717285 -1.3385951519012451 -0.0080837905406951904 +0.28011584281921387 -0.26171064376831055 -1.2895917892456055 +0.077198624610900879 0.11111372709274292 -1.5708580017089844 +0.023607760667800903 -1.3351038694381714 -0.1641484797000885 +-0.31655335426330566 -1.5365951061248779 0.15674996376037598 +0.40995579957962036 -0.16610078513622284 -1.302920937538147 +1.361452579498291 -0.1960446834564209 0.03563353419303894 +1.3410756587982178 -0.28131425380706787 0.12503793835639954 +0.12228313088417053 -1.3699063062667847 -0.040741533041000366 +0.31704330444335938 -0.24908767640590668 -1.315558910369873 +0.049747467041015625 -1.3676235675811768 -0.14278385043144226 +0.39939725399017334 -0.19306330382823944 -1.331043004989624 +1.3839616775512695 -0.22404778003692627 0.054030895233154297 +1.37287437915802 -0.27044445276260376 0.10267737507820129 +0.1117246150970459 -1.3968688249588013 -0.068863540887832642 +0.072256684303283691 -1.3956267833709717 -0.1243864893913269 +0.34884196519851685 -0.23821787536144257 -1.3379194736480713 +0.38679516315460205 -0.22524426877498627 -1.3646078109741211 +0.10797148942947388 0.12163287401199341 -1.5924972295761108 +1.41082763671875 -0.25747084617614746 0.075988978147506714 +1.5416167974472046 0.076515614986419678 0.42433825135231018 +0.099122524261474609 -1.4290497303009033 -0.10242840647697449 +-0.29477024078369141 -1.5636948347091675 0.17455384135246277 +-1.5416167974472046 -0.076515614986419678 -0.42433825135231018 +-1.41082763671875 0.25747084617614746 -0.075988978147506714 +-1.2792758941650391 0.15780013799667358 -0.38865476846694946 +-1.3368103504180908 -0.082960903644561768 -0.13621887564659119 +-1.2800383567810059 0.59145736694335938 0.27236023545265198 +-1.1492490768432617 0.92544382810592651 0.62070953845977783 +-1.0176973342895508 0.82577311992645264 0.30804374814033508 +-1.0752317905426025 0.58501207828521729 0.56047964096069336 +-1.1484866142272949 0.4917866587638855 -0.040305525064468384 +-0.75459378957748413 0.62643170356750488 -0.31728780269622803 +-1.0366294384002686 0.38538369536399841 -0.33912217617034912 +-0.86645090579986572 0.73283469676971436 -0.01847115159034729 +-1.2060210704803467 0.25102555751800537 0.21213036775588989 +-0.92719739675521851 -0.095851585268974304 0.44001981616020203 +-1.0151557922363281 0.26192408800125122 0.48885524272918701 +-1.1180627346038818 -0.10675013065338135 0.1632949560880661 +-0.88690805435180664 1.1597596406936646 0.65639293193817139 +-0.49301528930664062 1.2944047451019287 0.37941071391105652 +-0.7553563117980957 1.0600888729095459 0.34372726082801819 +-0.55054980516433716 1.0536437034606934 0.63184654712677002 +-0.099122524261474609 1.4290497303009033 0.10242840647697449 +0.29477024078369141 1.5636948347091675 -0.17455384135246277 +0.032429218292236328 1.3293790817260742 -0.21023732423782349 +0.23723572492599487 1.3229336738586426 0.07788202166557312 +-0.36146354675292969 1.1947339773178101 0.066744953393936157 +-0.49225276708602905 0.86074751615524292 -0.28160429000854492 +-0.61726510524749756 0.97711753845214844 0.048478871583938599 +-0.23645123839378357 1.0783638954162598 -0.26333826780319214 +-0.15665704011917114 1.188288688659668 0.35486429929733276 +0.12216664850711823 0.8414115309715271 0.58275377750396729 +0.16576001048088074 1.0995165109634399 0.31892341375350952 +-0.20025038719177246 0.93018370866775513 0.61869466304779053 +-0.22838675975799561 0.22774887084960938 -1.5679508447647095 +-0.62227952480316162 0.09310382604598999 -1.2909685373306274 +-0.35993850231170654 0.32741960883140564 -1.2552851438522339 +-0.30561593174934387 -0.019744455814361572 -1.3016657829284668 +-1.0161722898483276 -0.04154127836227417 -1.0139862298965454 +-1.4100650548934937 -0.17618632316589355 -0.73700404167175293 +-1.1477240324020386 0.058129489421844482 -0.70132052898406982 +-1.0737068653106689 -0.28230232000350952 -0.7615504264831543 +-0.75383126735687256 0.19277453422546387 -0.97830283641815186 +-0.62304204702377319 0.52676099538803101 -0.62995356321334839 +-0.49802970886230469 0.41039097309112549 -0.9600367546081543 +-0.87884354591369629 0.30914455652236938 -0.64821958541870117 +-0.67981404066085815 -0.14765727519989014 -1.0385327339172363 +-0.40099036693572998 -0.49453443288803101 -0.81064319610595703 +-0.7512897253036499 -0.37107455730438232 -0.79749125242233276 +-0.34345582127571106 -0.25377330183982849 -1.0630791187286377 +0.42632198333740234 1.4640240669250488 -0.48721960186958313 +0.29553276300430298 1.1300376653671265 -0.83556890487670898 +0.16398102045059204 1.2297084331512451 -0.52290308475494385 +0.50033926963806152 1.1235923767089844 -0.54744946956634521 +0.16474348306655884 0.79605114459991455 -1.1839181184768677 +0.033954262733459473 0.46206468343734741 -1.5322674512863159 +-0.097597509622573853 0.56173539161682129 -1.2196016311645508 +0.24530017375946045 0.47231867909431458 -1.2267305850982666 +0.0331917405128479 0.89572185277938843 -0.87125229835510254 +-0.36070102453231812 0.76107680797576904 -0.59427005052566528 +-0.078665375709533691 1.0021247863769531 -0.57243567705154419 +-0.24884390830993652 0.65467381477355957 -0.89308667182922363 +0.36954998970031738 0.78960585594177246 -0.89579874277114868 +0.64837366342544556 0.44272869825363159 -0.66790926456451416 +0.42962601780891418 0.4665178656578064 -0.96742308139801025 +0.58829766511917114 0.76581668853759766 -0.59628492593765259 +-0.94444257020950317 0.91899853944778442 0.90882885456085205 +-0.665618896484375 0.57212138175964355 1.1367182731628418 +-0.60808432102203369 0.81288254261016846 0.88428241014480591 +-0.87042534351348877 0.57856667041778564 0.84859901666641235 +-0.38679516315460205 0.22524426877498627 1.3646078109741211 +-0.10797148942947388 -0.12163287401199341 1.5924972295761108 +-0.050436943769454956 0.11912825703620911 1.3400613069534302 +-0.31277796626091003 -0.11518755555152893 1.3043779134750366 +-0.32926064729690552 0.46600538492202759 1.1121718883514404 +0.064632117748260498 0.60065042972564697 0.83518964052200317 +-0.29142075777053833 0.70003420114517212 0.87358516454696655 +0.026792243123054504 0.36662161350250244 1.0737763643264771 +-0.5916016697883606 0.23168957233428955 1.0764884948730469 +-0.72239089012145996 -0.10229690372943878 0.72813916206359863 +-0.51104497909545898 -0.092042908072471619 1.0336760282516479 +-0.80294758081436157 0.22143559157848358 0.77095162868499756 +1.467599630355835 0.41694742441177368 0.48456811904907227 +1.188775897026062 0.76382458209991455 0.25667867064476013 +1.1312413215637207 0.52306342124938965 0.50911456346511841 +1.2488518953323364 0.44073659181594849 0.18505431711673737 +0.90995222330093384 1.1107016801834106 0.028789199888706207 +0.63112854957580566 1.4575788974761963 -0.19910025596618652 +0.57359397411346436 1.2168177366256714 0.053335621953010559 +0.70514571666717529 1.1171469688415527 -0.259330153465271 +0.85241764783859253 0.86994057893753052 0.28122508525848389 +0.45852488279342651 0.73529553413391113 0.55820733308792114 +0.81457775831222534 0.63591176271438599 0.51981180906295776 +0.4963647723197937 0.96932435035705566 0.31962057948112488 +0.98396939039230347 0.77026987075805664 -0.031440675258636475 +0.8531801700592041 0.4362834095954895 -0.37978994846343994 +0.78570234775543213 0.79341447353363037 -0.30214262008666992 +1.0579866170883179 0.42983806133270264 -0.091670580208301544 +0.22838675975799561 -0.22774887084960938 1.5679508447647095 +0.62227952480316162 -0.09310382604598999 1.2909685373306274 +0.28592127561569214 0.013012230396270752 1.3155149221420288 +0.35993850231170654 -0.32741960883140564 1.2552851438522339 +1.0161722898483276 0.04154127836227417 1.0139862298965454 +1.4100650548934937 0.17618632316589355 0.73700404167175293 +1.0737068653106689 0.28230232000350952 0.7615504264831543 +1.1280293464660645 -0.064861714839935303 0.71516966819763184 +0.67981404066085815 0.14765727519989014 1.0385327339172363 +0.40099036693572998 0.49453443288803101 0.81064319610595703 +0.35739699006080627 0.23642945289611816 1.0744736194610596 +0.72340738773345947 0.40576225519180298 0.77470231056213379 +0.75383126735687256 -0.19277453422546387 0.97830283641815186 +0.62304204702377319 -0.52676099538803101 0.62995356321334839 +0.8919224739074707 -0.2757459282875061 0.68305444717407227 +0.48495081067085266 -0.44378960132598877 0.9252018928527832 +-0.42632198333740234 -1.4640240669250488 0.48721960186958313 +-0.29553276300430298 -1.1300376653671265 0.83556890487670898 +-0.50033926963806152 -1.1235923767089844 0.54744946956634521 +-0.15744155645370483 -1.2130091190338135 0.54032051563262939 +-0.16474348306655884 -0.79605114459991455 1.1839181184768677 +-0.033954262733459473 -0.46206468343734741 1.5322674512863159 +-0.23876070976257324 -0.45561936497688293 1.2441480159759521 +0.097597509622573853 -0.56173539161682129 1.2196016311645508 +-0.36954998970031738 -0.78960585594177246 0.89579874277114868 +-0.64837366342544556 -0.44272869825363159 0.66790926456451416 +-0.56041526794433594 -0.80050438642501831 0.61907386779785156 +-0.457508385181427 -0.43183016777038574 0.94463413953781128 +-0.0331917405128479 -0.89572185277938843 0.87125229835510254 +0.36070102453231812 -0.76107680797576904 0.59427005052566528 +0.20945465564727783 -0.66813832521438599 0.92078495025634766 +0.098360002040863037 -0.9953925609588623 0.55858659744262695 +-0.63112854957580566 -1.4575788974761963 0.19910025596618652 +-0.90995222330093384 -1.1107016801834106 -0.028789199888706207 +-0.58753514289855957 -1.1994738578796387 -0.064730092883110046 +-0.70514571666717529 -1.1171469688415527 0.259330153465271 +-1.188775897026062 -0.76382458209991455 -0.25667867064476013 +-1.467599630355835 -0.41694742441177368 -0.48456811904907227 +-1.1312413215637207 -0.52306342124938965 -0.50911456346511841 +-1.2627930641174316 -0.42339274287223816 -0.19644878804683685 +-0.85241764783859253 -0.86994057893753052 -0.28122508525848389 +-0.45852488279342651 -0.73529553413391113 -0.55820733308792114 +-0.53575402498245239 -0.98278886079788208 -0.29192236065864563 +-0.77518850564956665 -0.62244725227355957 -0.54751002788543701 +-0.98396939039230347 -0.77026987075805664 0.031440675258636475 +-0.8531801700592041 -0.4362834095954895 0.37978994846343994 +-1.0645260810852051 -0.44653737545013428 0.074253149330615997 +-0.77262347936630249 -0.76001584529876709 0.3369775116443634 +-1.4108024835586548 -0.30540990829467773 -0.61283159255981445 +-1.1024740934371948 -0.40268293023109436 -0.63533246517181396 +-1.2853529453277588 -0.46519669890403748 -0.50673353672027588 +-1.2319279909133911 -0.24163281917572021 -0.7411382794380188 +-0.77607381343841553 -0.49641045928001404 -0.66801780462265015 +-0.40172776579856873 -0.62375801801681519 -0.68647080659866333 +-0.62190943956375122 -0.6621740460395813 -0.56697046756744385 +-0.58323705196380615 -0.44628515839576721 -0.78847777843475342 +-0.96306222677230835 -0.57612144947052002 -0.52138769626617432 +-1.0205967426300049 -0.81688261032104492 -0.26895186305046082 +-1.1459410190582275 -0.63863527774810791 -0.39278882741928101 +-0.83360838890075684 -0.73717159032821655 -0.41558191180229187 +-0.91959530115127563 -0.34016916155815125 -0.76393139362335205 +-0.84799313545227051 -0.094599246978759766 -1.0262594223022461 +-0.73661112785339355 -0.25919485092163086 -0.91026914119720459 +-1.0349816083908081 -0.17431026697158813 -0.87962943315505981 +-0.30503574013710022 -0.79238802194595337 -0.56109702587127686 +-0.36922866106033325 -1.013710618019104 -0.32479825615882874 +-0.49208670854568481 -0.87573951482772827 -0.4109531044960022 +-0.43802022933959961 -1.2683544158935547 -0.054825514554977417 +-0.4930134117603302 -1.5122771263122559 0.19968748092651367 +-0.58829361200332642 -1.3323894739151001 0.062990099191665649 +-0.57285654544830322 -1.0875941514968872 -0.17750801146030426 +-0.88118493556976318 -0.99032115936279297 -0.15500713884830475 +-0.68903309106826782 -0.94306200742721558 -0.27246195077896118 +-0.74177306890487671 -1.163759708404541 -0.041062414646148682 +0.056090891361236572 0.32005178928375244 -1.5698215961456299 +0.26208946108818054 0.31665059924125671 -1.2785272598266602 +0.14631542563438416 0.44645354151725769 -1.3800687789916992 +0.46553349494934082 0.30672627687454224 -0.99403655529022217 +0.67571622133255005 0.28564679622650146 -0.70538556575775146 +0.52890324592590332 0.44648849964141846 -0.83597886562347412 +0.33499589562416077 0.48076599836349487 -1.0950691699981689 +0.26714673638343811 0.79282850027084351 -1.0398584604263306 +0.38949140906333923 0.6199270486831665 -0.94992363452911377 +0.20175209641456604 0.62583529949188232 -1.2140331268310547 +1.5073367357254028 0.27438062429428101 0.47177404165267944 +1.2999889850616455 0.28398764133453369 0.18157756328582764 +1.360525369644165 0.40824201703071594 0.32806739211082458 +1.0980868339538574 0.28681963682174683 -0.10416793823242188 +0.88946264982223511 0.26697081327438354 -0.41049835085868835 +0.96175146102905273 0.40469139814376831 -0.24074941873550415 +1.154221773147583 0.45498469471931458 0.057408228516578674 +1.0863726139068604 0.7670472264289856 0.11261896789073944 +1.2257844209671021 0.59360861778259277 0.22656369209289551 +1.0209780931472778 0.60005402565002441 -0.061555642634630203 +0.75694507360458374 0.41113674640655518 -0.52886873483657837 +0.68143075704574585 0.79186594486236572 -0.45117866992950439 +0.80621355772018433 0.61888778209686279 -0.35781389474868774 +0.62843227386474609 0.61240744590759277 -0.61378437280654907 +0.60274249315261841 1.1203696727752686 -0.40338984131813049 +0.53489327430725098 1.4324321746826172 -0.34817907214164734 +0.66346603631973267 1.2754348516464233 -0.24165627360343933 +0.47328862547874451 1.2814197540283203 -0.50919568538665771 +0.73219633102416992 0.9593195915222168 -0.29758399724960327 +0.94696074724197388 0.94048577547073364 -0.0013257674872875214 +0.87539809942245483 0.80186182260513306 -0.17048123478889465 +0.80287790298461914 1.1019963026046753 -0.12771153450012207 +0.53734785318374634 0.9533764123916626 -0.57756447792053223 +0.33254137635231018 0.95982176065444946 -0.86568379402160645 +0.40789398550987244 1.1144266128540039 -0.68337023258209229 +0.4766242504119873 0.79831123352050781 -0.73929798603057861 +1.4763219356536865 0.14459532499313354 0.6078527569770813 +1.2103908061981201 -0.09094768762588501 0.57469391822814941 +1.2742235660552979 0.047100365161895752 0.70672118663787842 +0.95215290784835815 -0.32386088371276855 0.53612512350082397 +0.69260972738265991 -0.56496882438659668 0.48667997121810913 +0.77607429027557373 -0.39007681608200073 0.6507689356803894 +1.0055909156799316 -0.16698145866394043 0.70953422784805298 +0.8850017786026001 -0.075616657733917236 0.99614453315734863 +0.8414689302444458 -0.22308358550071716 0.82494354248046875 +1.0819481611251831 -0.0082941055297851562 0.85765337944030762 +0.50283420085906982 -0.65222477912902832 0.58605635166168213 +0.34625217318534851 -0.54905694723129272 0.93466979265213013 +0.29959619045257568 -0.69931334257125854 0.76304399967193604 +0.53540438413619995 -0.4964519739151001 0.78331279754638672 +0.22876802086830139 -0.44457748532295227 1.2374433279037476 +0.10817891359329224 -0.35321265459060669 1.524053692817688 +0.045889198780059814 -0.50709128379821777 1.3660422563552856 +0.28949159383773804 -0.28951233625411987 1.3991769552230835 +0.16804444789886475 -0.59964263439178467 1.0757098197937012 +-0.098967611789703369 -0.8458864688873291 1.0275852680206299 +0.087016105651855469 -0.77025806903839111 0.91514956951141357 +-0.01950538158416748 -0.67408454418182373 1.1918675899505615 +0.4257144033908844 -0.37725493311882019 1.0989521741867065 +0.68805539608001709 -0.14293915033340454 1.1346356868743896 +0.48643797636032104 -0.22218978404998779 1.2606858015060425 +0.6085931658744812 -0.31474116444587708 0.97035324573516846 +0.42681750655174255 -0.81004238128662109 0.43884435296058655 +0.14190179109573364 -1.0475549697875977 0.42591521143913269 +0.24049317836761475 -0.88654053211212158 0.55037283897399902 +-0.11907678842544556 -1.2783915996551514 0.39386039972305298 +-0.38260990381240845 -1.5157516002655029 0.35500183701515198 +-0.28108388185501099 -1.342057466506958 0.49516913294792175 +-0.043773114681243896 -1.104244589805603 0.56680035591125488 +-0.16436225175857544 -1.0128797292709351 0.85341060161590576 +-0.22975689172744751 -1.179872989654541 0.67923593521118164 +0.032584130764007568 -0.94555723667144775 0.71491944789886475 +-0.23383700847625732 -0.54794305562973022 -0.82219511270523071 +-0.19988352060317993 -0.28760597109794617 -1.0845462083816528 +-0.3441932201385498 -0.38299688696861267 -0.93890672922134399 +-0.14645203948020935 -0.048247426748275757 -1.3340969085693359 +-0.085327327251434326 0.19374090433120728 -1.5890572071075439 +-0.24719604849815369 0.09497988224029541 -1.4335939884185791 +-0.34271839261054993 -0.12454980611801147 -1.1872514486312866 +-0.6510467529296875 -0.027276754379272461 -1.1647505760192871 +-0.45410040020942688 0.040045797824859619 -1.3032417297363281 +-0.5116349458694458 -0.2007153332233429 -1.050805926322937 +0.33868438005447388 1.4943332672119141 -0.33386033773422241 +0.098205149173736572 1.2795436382293701 -0.36657023429870605 +0.15892869234085083 1.4346089363098145 -0.20483666658401489 +0.28108388185501099 1.342057466506958 -0.49516913294792175 +-0.15006831288337708 1.0500366687774658 -0.41214591264724731 +-0.44833865761756897 0.79138582944869995 -0.44091081619262695 +-0.35011965036392212 0.96959948539733887 -0.28981804847717285 +-0.22485947608947754 0.89016276597976685 -0.56398725509643555 +-0.098741263151168823 1.2122211456298828 -0.22807908058166504 +-0.23029303550720215 1.3118917942047119 0.084586650133132935 +-0.038017690181732178 1.3672863245010376 -0.066345512866973877 +-0.28162002563476562 1.1497074365615845 -0.099480181932449341 +0.037481546401977539 1.1244785785675049 -0.52830380201339722 +0.16436225175857544 1.0128797292709351 -0.85341060161590576 +-0.01072239875793457 0.9650835394859314 -0.71194583177566528 +0.21568930149078369 1.1750643253326416 -0.66934370994567871 +-0.66695618629455566 0.59612268209457397 -0.47064703702926636 +-0.96522653102874756 0.33747184276580811 -0.499411940574646 +-0.89043533802032471 0.49734574556350708 -0.34757059812545776 +-0.76517516374588013 0.41790902614593506 -0.62173980474472046 +-1.2135000228881836 0.10796481370925903 -0.54498761892318726 +-1.4539792537689209 -0.10682469606399536 -0.5776975154876709 +-1.396378755569458 0.045450985431671143 -0.41638872027397156 +-1.2742235660552979 -0.047100365161895752 -0.70672118663787842 +-1.1527763605117798 0.26302996277809143 -0.38325405120849609 +-1.2796571254730225 0.37462875247001648 -0.058147251605987549 +-1.1045724153518677 0.42242497205734253 -0.19961202144622803 +-1.3309841156005859 0.2124442458152771 -0.24221411347389221 +-1.016553521156311 0.17528730630874634 -0.68347877264022827 +-0.8850017786026001 0.075616657733917236 -0.99614453315734863 +-1.0772771835327148 0.020222187042236328 -0.84521234035491943 +-0.83367478847503662 0.23780110478401184 -0.81207764148712158 +-0.61246061325073242 0.73528373241424561 -0.32550153136253357 +-0.75030398368835449 0.85518836975097656 0.02566075325012207 +-0.57209628820419312 0.90577411651611328 -0.11537918448448181 +-0.7985079288482666 0.69579339027404785 -0.157981276512146 +-0.88652682304382324 0.94293105602264404 0.32588544487953186 +-1.0071158409118652 1.0342957973480225 0.6124957799911499 +-0.82580322027206421 1.0979962348937988 0.4876190721988678 +-1.0694055557250977 0.88041722774505615 0.45448437333106995 +-0.70364797115325928 1.0054447650909424 0.19728651642799377 +-0.42723941802978516 1.2445693016052246 0.22307780385017395 +-0.50359666347503662 1.0858819484710693 0.074958652257919312 +-0.6288568377494812 1.1653187274932861 0.34912791848182678 +-0.95192146301269531 0.77593779563903809 0.15171089768409729 +-1.2142624855041504 0.54162204265594482 0.11602738499641418 +-1.1348001956939697 0.7134239673614502 0.2803097665309906 +-1.0126450061798096 0.6208726167678833 -0.010022729635238647 +-0.50283420085906982 0.65222477912902832 -0.58605635166168213 +-0.36499083042144775 0.53232014179229736 -0.93721860647201538 +-0.54319852590560913 0.48173442482948303 -0.79617869853973389 +-0.31678688526153564 0.69171512126922607 -0.75357657670974731 +-0.22876802086830139 0.44457748532295227 -1.2374433279037476 +-0.10817891359329224 0.35321265459060669 -1.524053692817688 +-0.28949159383773804 0.28951233625411987 -1.3991769552230835 +-0.045889198780059814 0.50709128379821777 -1.3660422563552856 +-0.41164681315422058 0.38206368684768677 -1.1088443994522095 +-0.68805539608001709 0.14293915033340454 -1.1346356868743896 +-0.61169815063476562 0.3016265332698822 -0.98651647567749023 +-0.48643797636032104 0.22218978404998779 -1.2606858015060425 +-0.16337338089942932 0.61157071590423584 -1.063268780708313 +0.098967611789703369 0.8458864688873291 -1.0275852680206299 +0.01950538158416748 0.67408454418182373 -1.1918675899505615 +-0.10264980792999268 0.76663589477539062 -0.90153515338897705 +0.065002202987670898 -0.15462744235992432 1.5591877698898315 +0.11774218082427979 0.066070228815078735 1.3277881145477295 +-0.065136611461639404 0.0035564601421356201 1.4563870429992676 +0.24719604849815369 -0.09497988224029541 1.4335939884185791 +0.18523469567298889 0.29444286227226257 1.0834912061691284 +0.23760578036308289 0.56765586137771606 0.80188006162643433 +0.063894703984260559 0.47142690420150757 0.95936203002929688 +0.35815548896789551 0.36934509873390198 0.94675338268280029 +-0.021669685840606689 0.23950877785682678 1.2138433456420898 +-0.35802790522575378 0.34562483429908752 1.2383898496627808 +-0.20454847812652588 0.17699500918388367 1.3424422740936279 +-0.1511235386133194 0.40055888891220093 1.1080375909805298 +0.30062097311019897 0.12858399748802185 1.1991891860961914 +0.6510467529296875 0.027276754379272461 1.1647505760192871 +0.50684034824371338 0.18065190315246582 1.0718421936035156 +0.44414243102073669 -0.02765733003616333 1.2951028347015381 +0.28555122017860413 0.76829010248184204 0.59151691198348999 +0.33792230486869812 1.0415030717849731 0.3099057674407959 +0.1650015115737915 0.96660089492797852 0.44664359092712402 +0.45926231145858765 0.86451905965805054 0.43403494358062744 +0.40541481971740723 1.2698757648468018 0.065608799457550049 +0.45815479755401611 1.4905734062194824 -0.16579073667526245 +0.27596095204353333 1.4309258460998535 -0.040197014808654785 +0.58829361200332642 1.3323894739151001 -0.062990099191665649 +0.22253602743148804 1.2073619365692139 0.19420772790908813 +-0.12788978219032288 1.3086692094802856 0.22864633798599243 +0.016316622495651245 1.1552940607070923 0.3215547502040863 +0.079014569520950317 1.3636033535003662 0.09829413890838623 +0.5448266863822937 1.0964372158050537 0.17955353856086731 +0.88118493556976318 0.99032115936279297 0.15500713884830475 +0.72770547866821289 1.1589509248733521 0.050954639911651611 +0.67428052425384521 0.93538707494735718 0.28535935282707214 +0.12142923474311829 0.71218794584274292 0.70692616701126099 +-0.25702643394470215 0.82233822345733643 0.74341028928756714 +-0.11350499093532562 0.66609692573547363 0.83932387828826904 +-0.050807014107704163 0.87440609931945801 0.61606329679489136 +-0.57931709289550781 0.93326306343078613 0.75806450843811035 +-0.88764548301696777 1.0305360555648804 0.78056538105010986 +-0.762195885181427 0.87074923515319824 0.88666343688964844 +-0.7087709903717041 1.0943131446838379 0.65225863456726074 +-0.44986322522163391 0.77221298217773438 0.86387032270431519 +-0.49743977189064026 0.51906341314315796 1.1244450807571411 +-0.32852321863174438 0.59522891044616699 0.98799943923950195 +-0.62278401851654053 0.6973106861114502 1.0006082057952881 +-0.3823707103729248 1.0005855560302734 0.61957335472106934 +-0.32483616471290588 1.2413467168807983 0.36713749170303345 +-0.51182460784912109 1.1616356372833252 0.51376748085021973 +-0.19949193298816681 1.0630993843078613 0.49097445607185364 +0.40172776579856873 0.62375801801681519 0.68647080659866333 +0.78018343448638916 0.51360774040222168 0.6499866247177124 +0.63666200637817383 0.66984903812408447 0.55407309532165527 +0.57396399974822998 0.46153983473777771 0.77733367681503296 +1.1024740934371948 0.40268293023109436 0.63533246517181396 +1.4108024835586548 0.30540990829467773 0.61283159255981445 +1.2853529453277588 0.46519669890403748 0.50673353672027588 +1.2319279909133911 0.24163281917572021 0.7411382794380188 +0.97302019596099854 0.56373298168182373 0.52952665090560913 +1.0205967426300049 0.81688261032104492 0.26895186305046082 +0.8516802191734314 0.74071699380874634 0.40539747476577759 +1.1459410190582275 0.63863527774810791 0.39278882741928101 +0.90552771091461182 0.33536037802696228 0.77382361888885498 +0.84799313545227051 0.094599246978759766 1.0262594223022461 +1.0349816083908081 0.17431026697158813 0.87962943315505981 +0.72264891862869263 0.27284660935401917 0.90242254734039307 +-1.4875409603118896 -0.2472686767578125 -0.43044325709342957 +-1.2998018264770508 -0.25317689776420593 -0.16633382439613342 +-1.4292556047439575 -0.092126786708831787 -0.27213963866233826 +-1.360525369644165 -0.40824201703071594 -0.32806739211082458 +-1.0996663570404053 -0.27155026793479919 0.109344482421875 +-0.87312155961990356 -0.26660460233688354 0.43391481041908264 +-1.0234324932098389 -0.12099823355674744 0.29094099998474121 +-0.96554142236709595 -0.42067229747772217 0.22759133577346802 +-1.2344071865081787 -0.086183637380599976 0.0078407824039459229 +-1.3084243535995483 0.25424820184707642 0.068070679903030396 +-1.3638609647750854 0.07486647367477417 -0.097965031862258911 +-1.1736835241317749 0.06888154149055481 0.16957435011863708 +-1.1703479290008545 -0.41422697901725769 -0.060527995228767395 +-1.0863726139068604 -0.7670472264289856 -0.11261896789073944 +-1.0380452871322632 -0.59951680898666382 0.037545718252658844 +-1.2211134433746338 -0.5816805362701416 -0.21412265300750732 +-0.7024495005607605 -0.27197569608688354 0.67401427030563354 +-0.47590476274490356 -0.26703006029129028 0.99858462810516357 +-0.61002963781356812 -0.1179080456495285 0.88033777475357056 +-0.5521385669708252 -0.41758203506469727 0.81698811054229736 +-0.27576929330825806 -0.28540343046188354 1.2742629051208496 +-0.088030040264129639 -0.29131162166595459 1.5383723974227905 +-0.2150457501411438 -0.13033828139305115 1.4359965324401855 +-0.14631542563438416 -0.44645354151725769 1.3800687789916992 +-0.40522316098213196 -0.12435334920883179 1.1684571504592896 +-0.48919841647148132 0.22846692800521851 1.2205480337142944 +-0.53752583265304565 0.06093655526638031 1.0703834295272827 +-0.35445761680603027 0.043100267648696899 1.3220517635345459 +-0.34116393327713013 -0.4523966908454895 1.100088357925415 +-0.26714673638343811 -0.79282850027084351 1.0398584604263306 +-0.21171006560325623 -0.61344683170318604 1.2058941125869751 +-0.40188753604888916 -0.60746181011199951 0.9383547306060791 +-0.81862598657608032 -0.12744355201721191 0.57906037569046021 +-0.90876936912536621 0.25374603271484375 0.63617050647735596 +-0.95953494310379028 0.086292415857315063 0.48257583379745483 +-0.7764667272567749 0.068456098437309265 0.73424416780471802 +-0.97282856702804565 0.58178937435150146 0.70453929901123047 +-1.0406777858734131 0.8938518762588501 0.75975000858306885 +-1.1022824048995972 0.74283945560455322 0.59873342514038086 +-0.9121050238609314 0.73685455322265625 0.86627292633056641 +-1.0335521697998047 0.42672419548034668 0.54280567169189453 +-1.2430297136306763 0.42124146223068237 0.24224531650543213 +-1.1097859144210815 0.27617216110229492 0.36120918393135071 +-1.1676770448684692 0.57584619522094727 0.4245588481426239 +-0.83341670036315918 0.40835082530975342 0.81848400831222534 +-0.62861025333404541 0.40190547704696655 1.1066032648086548 +-0.77269315719604492 0.5634160041809082 0.98021763563156128 +-0.70396286249160767 0.24730072915554047 0.92428982257843018 +-0.75694507360458374 -0.41113674640655518 0.52886873483657837 +-0.66680169105529785 -0.79232633113861084 0.47175860404968262 +-0.61603611707687378 -0.62487268447875977 0.62535327672958374 +-0.79910433292388916 -0.60703641176223755 0.37368494272232056 +-0.60274249315261841 -1.1203696727752686 0.40338984131813049 +-0.53489327430725098 -1.4324321746826172 0.34817907214164734 +-0.47328862547874451 -1.2814197540283203 0.50919568538665771 +-0.66346603631973267 -1.2754348516464233 0.24165627360343933 +-0.54201889038085938 -0.96530449390411377 0.56512343883514404 +-0.33254137635231018 -0.95982176065444946 0.86568379402160645 +-0.46578511595726013 -0.81475245952606201 0.74671989679336548 +-0.40789398550987244 -1.1144266128540039 0.68337023258209229 +-0.74215435981750488 -0.94693112373352051 0.28944510221481323 +-0.94696074724197388 -0.94048577547073364 0.0013257674872875214 +-0.80287790298461914 -1.1019963026046753 0.12771153450012207 +-0.8716081976890564 -0.78588104248046875 0.1836392879486084 +0.26282662153244019 0.25235268473625183 -1.3087350130081177 +0.66941159963607788 0.18760931491851807 -0.76200872659683228 +0.95335650444030762 0.16974297165870667 -0.36689960956573486 +1.3273937702178955 0.21885049343109131 0.1888853907585144 +1.2524788379669189 -0.094640552997589111 0.5175778865814209 +0.76645511388778687 -0.5621107816696167 0.40068015456199646 +-0.11114782094955444 -1.3125944137573242 0.33209815621376038 +0.40872299671173096 -0.8873634934425354 0.34329035878181458 +-0.078763186931610107 -0.052745968103408813 -1.3551979064941406 +-0.12701772153377533 -0.52722126245498657 -0.8821682333946228 +-0.21511919796466827 -0.85591274499893188 -0.5339510440826416 +-0.3778228759765625 -1.3042020797729492 -0.043057233095169067 +0.47980320453643799 0.22404079139232635 -1.0139384269714355 +1.1352901458740234 0.1887965202331543 -0.098911970853805542 +0.98893237113952637 -0.34383231401443481 0.46072617173194885 +0.16911676526069641 -1.0760691165924072 0.3492152988910675 +-0.1170225590467453 -0.30902761220932007 -1.0951182842254639 +-0.29681801795959473 -1.061406135559082 -0.30625623464584351 +0.63228654861450195 0.092805854976177216 -0.86088913679122925 +0.26128232479095459 0.22193688154220581 -1.3257167339324951 +1.0208873748779297 0.10346885025501251 -0.3030816912651062 +1.3422764539718628 0.18791770935058594 0.19501322507858276 +0.87826323509216309 -0.52389121055603027 0.3220575749874115 +1.2748532295227051 -0.094224274158477783 0.490836501121521 +0.36516943573951721 -0.96746832132339478 0.27464848756790161 +-0.10981541872024536 -1.3309721946716309 0.30249461531639099 +-0.046148538589477539 -0.052651941776275635 -1.3675334453582764 +-0.048173986375331879 -0.48447757959365845 -0.95275187492370605 +-0.34982296824455261 -1.3234190940856934 -0.03514525294303894 +-0.13597391545772552 -0.95437526702880859 -0.46926367282867432 +0.26562613248825073 0.17126083374023438 -1.344173789024353 +0.59663814306259155 0.067953705787658691 -0.92366522550582886 +1.3600608110427856 0.13681864738464355 0.19546401500701904 +1.069719672203064 0.053065687417984009 -0.25813958048820496 +1.3031256198883057 -0.10143446922302246 0.44527032971382141 +0.94131582975387573 -0.48425790667533875 0.3052394688129425 +-0.098759233951568604 -1.3535594940185547 0.25458672642707825 +0.33533543348312378 -1.0255029201507568 0.22281433641910553 +0.0060178637504577637 -0.060614109039306641 -1.3794856071472168 +0.011153079569339752 -0.45498540997505188 -1.0033025741577148 +-0.30143222212791443 -1.3471813201904297 -0.030531376600265503 +-0.12174569070339203 -1.0111184120178223 -0.42020207643508911 +0.43156719207763672 0.10968825221061707 -1.13812255859375 +1.1984665393829346 0.13976582884788513 -0.032904207706451416 +1.1282950639724731 -0.29378309845924377 0.36639678478240967 +0.13136357069015503 -1.1833665370941162 0.2320859283208847 +0.014990761876106262 -0.26942861080169678 -1.1826496124267578 +-0.20222169160842896 -1.1842963695526123 -0.22394934296607971 +0.56740033626556396 0.050648003816604614 -0.97365635633468628 +1.1069374084472656 0.033668607473373413 -0.21464197337627411 +0.99096941947937012 -0.45161548256874084 0.29417407512664795 +0.29986479878425598 -1.0688910484313965 0.20017039775848389 +0.038619264960289001 -0.42164477705955505 -1.0455808639526367 +-0.11294826865196228 -1.0558997392654419 -0.3805701732635498 +0.57247442007064819 -0.015811465680599213 -0.99874758720397949 +0.4189268946647644 0.042113363742828369 -1.188947319984436 +0.22364193201065063 0.17119854688644409 -1.4039092063903809 +0.068941682577133179 0.26021528244018555 -1.5806341171264648 +1.1308920383453369 -0.033385008573532104 -0.21317219734191895 +1.2611935138702393 0.015606999397277832 -0.0040564835071563721 +1.3819172382354736 0.11376678943634033 0.21533992886543274 +1.5205075740814209 0.21453404426574707 0.46141186356544495 +1.0288581848144531 -0.46035978198051453 0.23450705409049988 +1.1899945735931396 -0.28233486413955688 0.30833292007446289 +1.357830286026001 -0.053462386131286621 0.45135855674743652 +1.499651312828064 0.12725818157196045 0.55291986465454102 +0.31356900930404663 -1.0992364883422852 0.13721382617950439 +0.11111712455749512 -1.2459585666656494 0.16158458590507507 +-0.13410627841949463 -1.3893721103668213 0.24332258105278015 +-0.35969060659408569 -1.5334548950195312 0.30001318454742432 +-0.02615693211555481 0.17527580261230469 -1.593569278717041 +0.033031165599822998 -0.04769521951675415 -1.4020140171051025 +0.094279900193214417 -0.2478523850440979 -1.2331056594848633 +0.10722900182008743 -0.43135583400726318 -1.0620300769805908 +-0.049642503261566162 -1.0878059864044189 -0.37374785542488098 +-0.14233091473579407 -1.2379825115203857 -0.19496312737464905 +-0.31193521618843079 -1.3973262310028076 0.021489411592483521 +-0.43393296003341675 -1.531118631362915 0.19556993246078491 +0.40044498443603516 0.10080632567405701 -1.1866986751556396 +1.2454782724380493 0.062062382698059082 -0.0038222968578338623 +1.174762487411499 -0.25861382484436035 0.36307591199874878 +0.10047602653503418 -1.2259414196014404 0.20507261157035828 +0.046967968344688416 -0.24007326364517212 -1.222800612449646 +-0.20176061987876892 -1.2265151739120483 -0.18364447355270386 +0.24008136987686157 0.10602909326553345 -1.4122107028961182 +1.4103529453277588 0.12599098682403564 0.26172024011611938 +1.3800578117370605 -0.07513660192489624 0.39117223024368286 +-0.14164978265762329 -1.4215996265411377 0.20349764823913574 +0.028774678707122803 -0.006773829460144043 -1.4396501779556274 +-0.24697446823120117 -1.4149307012557983 0.013978302478790283 +0.59430998563766479 -0.0041719749569892883 -0.96203738451004028 +1.1036593914031982 -0.020201355218887329 -0.24549058079719543 +0.99263572692871094 -0.48479503393173218 0.24163174629211426 +0.34019911289215088 -1.0675334930419922 0.15288767218589783 +0.088073790073394775 -0.45632818341255188 -1.030895471572876 +-0.055013388395309448 -1.0550961494445801 -0.4030926525592804 +0.38327890634536743 0.05697062611579895 -1.232419490814209 +1.2908275127410889 0.028409838676452637 0.044309347867965698 +1.2264609336853027 -0.24094170331954956 0.32672199606895447 +0.063962280750274658 -1.2792534828186035 0.16859957575798035 +0.089784905314445496 -0.2051701545715332 -1.2723402976989746 +-0.16516503691673279 -1.2720427513122559 -0.1537339985370636 +0.38282448053359985 0.029338032007217407 -1.2464983463287354 +0.54346710443496704 -0.073340125381946564 -1.0679640769958496 +1.303386926651001 0.00036764144897460938 0.048538118600845337 +1.19097900390625 -0.0977897047996521 -0.15903139114379883 +1.2455527782440186 -0.24164742231369019 0.30228874087333679 +1.1051414012908936 -0.42976382374763489 0.1877453625202179 +0.066384553909301758 -1.2948479652404785 0.14189893007278442 +0.29350554943084717 -1.1686210632324219 0.056149095296859741 +0.1191171407699585 -0.20619815587997437 -1.2823677062988281 +0.1824553906917572 -0.39642885327339172 -1.1237610578536987 +-0.13948860764503479 -1.2883691787719727 -0.1477210521697998 +-0.0032453238964080811 -1.1552881002426147 -0.32646819949150085 +0.07665744423866272 0.21814984083175659 -1.5901103019714355 +0.20628756284713745 0.1079731285572052 -1.4593234062194824 +0.36783820390701294 -0.0089312493801116943 -1.2864134311676025 +0.52836710214614868 -0.12844493985176086 -1.1162247657775879 +1.2249224185943604 -0.15036571025848389 -0.13631883263587952 +1.3353354930877686 -0.039378643035888672 0.074650436639785767 +1.443203330039978 0.054078996181488037 0.27347901463508606 +1.5311033725738525 0.17237800359725952 0.45598739385604858 +1.5177686214447021 0.11657661199569702 0.51449465751647949 +1.4227554798126221 -0.036434590816497803 0.39784079790115356 +1.2906863689422607 -0.22621935606002808 0.27055120468139648 +1.1616944074630737 -0.41495212912559509 0.14109766483306885 +-0.34526246786117554 -1.547431468963623 0.261086106300354 +-0.16768687963485718 -1.4569740295410156 0.18150967359542847 +0.051398277282714844 -1.3331172466278076 0.10198390483856201 +0.26946169137954712 -1.2118699550628662 0.019736677408218384 +0.24006524682044983 -0.38594821095466614 -1.1554394960403442 +0.16425067186355591 -0.19077005982398987 -1.3141052722930908 +0.1041567325592041 -0.0086426138877868652 -1.4661608934402466 +0.015854448080062866 0.16384229063987732 -1.5983805656433105 +-0.39273065328598022 -1.5459377765655518 0.19430848956108093 +-0.25728973746299744 -1.4541542530059814 0.055457472801208496 +-0.1075400710105896 -1.3281154632568359 -0.12160873413085938 +0.044387906789779663 -1.2047867774963379 -0.29689449071884155 +0.56174558401107788 -0.043208800256252289 -1.0273231267929077 +1.1631031036376953 -0.055718779563903809 -0.1782219409942627 +1.0611696243286133 -0.44931468367576599 0.21178585290908813 +0.2867685854434967 -1.1313742399215698 0.12108635902404785 +0.1361766904592514 -0.40566819906234741 -1.0975271463394165 +-0.026770234107971191 -1.1162607669830322 -0.35505378246307373 +0.36036834120750427 0.024937987327575684 -1.2805716991424561 +1.3280789852142334 -0.0055161714553833008 0.080792129039764404 +1.2777361869812012 -0.21618211269378662 0.3016735315322876 +0.038174986839294434 -1.3233242034912109 0.13306906819343567 +0.13081994652748108 -0.1800883412361145 -1.3117947578430176 +-0.14103066921234131 -1.3176846504211426 -0.11903539299964905 +0.51304024457931519 -0.16758400201797485 -1.157046914100647 +0.35591733455657959 -0.039372712373733521 -1.3181638717651367 +1.2575970888137817 -0.19101542234420776 -0.10961303114891052 +1.3550809621810913 -0.088778376579284668 0.078716278076171875 +1.2078537940979004 -0.39917340874671936 0.10863879323005676 +1.3265879154205322 -0.21394699811935425 0.24530541896820068 +0.25413483381271362 -1.2510089874267578 -0.021085530519485474 +0.039477407932281494 -1.3635587692260742 0.070233345031738281 +0.21532441675662994 -0.19542084634304047 -1.328822135925293 +0.28622457385063171 -0.37016949057579041 -1.1878982782363892 +0.07706257700920105 -1.245436429977417 -0.27018868923187256 +-0.082126468420028687 -1.359731912612915 -0.10083755850791931 +0.36255896091461182 -0.022412508726119995 -1.3004744052886963 +1.3585753440856934 -0.043455839157104492 0.10571753978729248 +1.3065855503082275 -0.22078442573547363 0.25937092304229736 +0.046119034290313721 -1.3465986251831055 0.087922930717468262 +0.1739020049571991 -0.16536152362823486 -1.3420897722244263 +-0.096285462379455566 -1.3421170711517334 -0.11241006851196289 +0.49873510003089905 -0.20411378145217896 -1.1951476335525513 +0.19606965780258179 0.081880420446395874 -1.4865381717681885 +0.04918333888053894 0.21417182683944702 -1.6311144828796387 +1.5606977939605713 0.16660404205322266 0.49526631832122803 +1.4697098731994629 0.041798651218414307 0.30520397424697876 +1.2880934476852417 -0.22895509004592896 -0.084687620401382446 +1.2509357929229736 -0.38444662094116211 0.078343868255615234 +1.4535284042358398 -0.025915443897247314 0.37620154023170471 +1.5562028884887695 0.14779460430145264 0.51498782634735107 +-0.3799283504486084 -1.5815047025680542 0.2516363263130188 +-0.17790478467941284 -1.4830667972564697 0.15429490804672241 +0.23982971906661987 -1.2875387668609619 -0.059186249971389771 +0.32930657267570496 -0.35544270277023315 -1.2181931734085083 +0.12228620052337646 0.015979111194610596 -1.4965741634368896 +0.028687924146652222 0.1958659291267395 -1.6339021921157837 +0.10755890607833862 -1.2833760976791382 -0.24526327848434448 +-0.23550665378570557 -1.481253981590271 0.073261350393295288 +-0.39592885971069336 -1.5810011625289917 0.22912701964378357 +0.46365359425544739 -0.29369866847991943 -1.2885850667953491 +1.362882137298584 -0.32199764251708984 -0.023561030626296997 +1.3565893173217773 -0.34833088517189026 0.0040491223335266113 +0.2047482430934906 -1.3771235942840576 -0.15262362360954285 +0.18234753608703613 -1.3764185905456543 -0.18413668870925903 +0.43496009707450867 -0.3193269670009613 -1.2924879789352417 +0.33616268634796143 -0.089818626642227173 -1.370779275894165 +0.47964301705360413 -0.23080763220787048 -1.2352744340896606 +1.4028630256652832 -0.12338793277740479 0.12984243035316467 +1.3191362619400024 -0.25722673535346985 -0.054285317659378052 +1.3860821723937988 -0.19361001253128052 0.20346954464912415 +1.2936651706695557 -0.36381366848945618 0.057470113039016724 +0.01972275972366333 -1.4140046834945679 0.017618060111999512 +0.21834033727645874 -1.3242642879486084 -0.088794976472854614 +0.36350247263908386 -0.33454117178916931 -1.2510719299316406 +0.25964653491973877 -0.15816071629524231 -1.3811869621276855 +0.12767082452774048 -1.3214108943939209 -0.21634781360626221 +-0.040012478828430176 -1.4121247529983521 -0.066416740417480469 +0.34706181287765503 -0.061986416578292847 -1.3417501449584961 +1.3796278238296509 -0.094481527805328369 0.11085164546966553 +1.3532578945159912 -0.20483040809631348 0.22655141353607178 +0.030621886253356934 -1.3861725330352783 0.046647191047668457 +0.22682219743728638 -0.16938114166259766 -1.358104944229126 +-0.063247740268707275 -1.3832182884216309 -0.085407525300979614 +0.46908453106880188 -0.25777009129524231 -1.2633963823318481 +0.3252636194229126 -0.1176508367061615 -1.3998081684112549 +0.18551117181777954 0.054917961359024048 -1.514660120010376 +1.4922192096710205 0.013795554637908936 0.32360127568244934 +1.4260983467102051 -0.15229439735412598 0.14883321523666382 +1.3416454792022705 -0.28522983193397522 -0.035887986421585083 +1.3254637718200684 -0.35294389724731445 0.035109579563140869 +1.4189066886901855 -0.18238955736160278 0.1803877055644989 +1.4853270053863525 -0.015045702457427979 0.35384103655815125 +-0.18846327066421509 -1.5100291967391968 0.12617295980453491 +0.008823692798614502 -1.4418368339538574 -0.011411011219024658 +0.20778185129165649 -1.351226806640625 -0.11691692471504211 +-0.2129974365234375 -1.5092570781707764 0.091658651828765869 +-0.016777157783508301 -1.4410312175750732 -0.047425955533981323 +0.15018001198768616 -1.3494139909744263 -0.19795048236846924 +0.15408486127853394 0.026848882436752319 -1.5189347267150879 +0.29247099161148071 -0.14694029092788696 -1.404268741607666 +0.39530107378959656 -0.32367140054702759 -1.2734323740005493 +0.45650109648704529 -0.31196355819702148 -1.3076354265213013 +0.3170892596244812 -0.13852497935295105 -1.4215800762176514 +0.17767739295959473 0.034913569688796997 -1.535524845123291 +0.03826555609703064 0.20835214853286743 -1.6494696140289307 +1.3781301975250244 -0.34096747636795044 -0.011098325252532959 +1.4435248374938965 -0.17397421598434448 0.16307631134986877 +1.5089194774627686 -0.0069809556007385254 0.33725091814994812 +1.5743141174316406 0.16001224517822266 0.51142549514770508 +0.19759571552276611 -1.3953884840011597 -0.171673983335495 +0.00064933300018310547 -1.4627110958099365 -0.033182859420776367 +-0.1962970495223999 -1.5300335884094238 0.10530829429626465 +-0.39324343204498291 -1.5973560810089111 0.24379941821098328 +-1.5743141174316406 -0.16001224517822266 -0.51142549514770508 +-1.5089194774627686 0.0069809556007385254 -0.33725091814994812 +-1.4431436061859131 -0.042854368686676025 -0.49358382821083069 +-1.471910834312439 -0.1632348895072937 -0.36736589670181274 +-1.4435248374938965 0.17397421598434448 -0.16307631134986877 +-1.3781301975250244 0.34096747636795044 0.011098325252532959 +-1.3123543262481689 0.29113215208053589 -0.14523455500602722 +-1.3411216735839844 0.17075157165527344 -0.019016623497009277 +-1.377748966217041 0.12413889169692993 -0.31940919160842896 +-1.180802583694458 0.19146138429641724 -0.45790031552314758 +-1.3119730949401855 0.074303507804870605 -0.47574207186698914 +-1.2465784549713135 0.24129676818847656 -0.30156746506690979 +-1.4065163135528564 0.0037583708763122559 -0.19319126009941101 +-1.2671043872833252 -0.16968020796775818 -0.07924652099609375 +-1.3041130304336548 0.00053566694259643555 -0.049131572246551514 +-1.3695076704025269 -0.16645759344100952 -0.22330617904663086 +-1.3127355575561523 0.5079607367515564 0.18527296185493469 +-1.2473409175872803 0.67495393753051758 0.35944756865501404 +-1.1815650463104248 0.62511861324310303 0.20311465859413147 +-1.2103323936462402 0.50473809242248535 0.32933259010314941 +-1.1819462776184082 0.84194719791412354 0.533622145652771 +-1.1165517568588257 1.0089404582977295 0.70779669284820557 +-1.0507758855819702 0.95910513401031494 0.55146396160125732 +-1.0795431137084961 0.83872455358505249 0.67768192291259766 +-1.1161704063415527 0.79211187362670898 0.37728932499885559 +-0.91922414302825928 0.85943436622619629 0.23879817128181458 +-1.0503946542739868 0.74227648973464966 0.22095641493797302 +-0.98500001430511475 0.90926975011825562 0.39513102173805237 +-1.1449377536773682 0.67173135280609131 0.50350725650787354 +-1.0055258274078369 0.49829274415969849 0.61745202541351318 +-1.0425344705581665 0.66850864887237549 0.64756691455841064 +-1.1079291105270386 0.50151538848876953 0.4733923077583313 +-1.2469596862792969 0.45812538266181946 0.028940051794052124 +-1.0500133037567139 0.52544790506362915 -0.1095510721206665 +-1.1593221426010132 0.42781633138656616 -0.12441918253898621 +-1.1048265695571899 0.56697738170623779 0.02072635293006897 +-0.85306698083877563 0.59277045726776123 -0.24804222583770752 +-0.65612059831619263 0.66009300947189331 -0.38653334975242615 +-0.79825377464294434 0.55124098062515259 -0.37831962108612061 +-0.74375826120376587 0.69040203094482422 -0.23317408561706543 +-0.96237576007843018 0.49513888359069824 -0.26291033625602722 +-1.0496320724487305 0.30861932039260864 -0.44005858898162842 +-1.0935462713241577 0.37798097729682922 -0.28075206279754639 +-0.91846162080764771 0.42577719688415527 -0.42221683263778687 +-0.9407045841217041 0.62307947874069214 -0.094682961702346802 +-0.85344827175140381 0.80959904193878174 0.082465320825576782 +-0.80953407287597656 0.74023735523223877 -0.076841205358505249 +-0.98461872339248657 0.69244116544723511 0.064623564481735229 +-1.2757270336151123 0.33774483203887939 0.15515798330307007 +-1.1363151073455811 0.16430625319480896 0.26910272240638733 +-1.1671556234359741 0.30615285038948059 0.29419851303100586 +-1.2216511964797974 0.16699180006980896 0.14905297756195068 +-0.99690330028533936 -0.0091322958469390869 0.38304746150970459 +-0.85749143362045288 -0.18257087469100952 0.49699220061302185 +-0.91156727075576782 -0.011817842721939087 0.50309717655181885 +-0.96606284379959106 -0.15097889304161072 0.35795164108276367 +-1.0277438163757324 0.13271427154541016 0.40814325213432312 +-0.96851730346679688 0.32807683944702148 0.58733701705932617 +-1.064752459526062 0.30293017625808716 0.43825814127922058 +-0.93150866031646729 0.15786094963550568 0.55722206830978394 +-1.1054747104644775 0.022459656000137329 0.2440069317817688 +-1.1647012233734131 -0.172902911901474 0.064813151955604553 +-1.0684659481048584 -0.14775621891021729 0.21389198303222656 +-1.2017097473144531 -0.0026870071887969971 0.094928115606307983 +-0.98538124561309814 1.1260983943939209 0.72563850879669189 +-0.78843486309051514 1.1934208869934082 0.58714735507965088 +-0.91960537433624268 1.0762629508972168 0.56930553913116455 +-0.81720209121704102 1.0730403661727905 0.71336531639099121 +-0.59148848056793213 1.2607433795928955 0.44865623116493225 +-0.39454209804534912 1.3280659914016724 0.31016513705253601 +-0.52571260929107666 1.210908055305481 0.29232338070869446 +-0.42330935597419739 1.2076854705810547 0.43638306856155396 +-0.72265899181365967 1.1435855627059937 0.43081453442573547 +-0.78805363178253174 0.9765923023223877 0.25663986802101135 +-0.85382950305938721 1.0264276266098022 0.4129728376865387 +-0.6568831205368042 1.0937502384185791 0.27448168396949768 +-0.62025570869445801 1.1403629779815674 0.5748741626739502 +-0.48084390163421631 0.96692430973052979 0.68881893157958984 +-0.45207661390304565 1.0873048305511475 0.56260097026824951 +-0.64902299642562866 1.0199823379516602 0.70109212398529053 +-0.19759571552276611 1.3953884840011597 0.171673983335495 +-0.00064933300018310547 1.4627110958099365 0.033182859420776367 +-0.13181984424591064 1.3455531597137451 0.015341073274612427 +-0.029416590929031372 1.3423304557800293 0.15940076112747192 +0.1962970495223999 1.5300335884094238 -0.10530829429626465 +0.39324343204498291 1.5973560810089111 -0.24379941821098328 +0.26207292079925537 1.4801981449127197 -0.26164117455482483 +0.36447617411613464 1.4769755601882935 -0.11758148670196533 +0.065126538276672363 1.4128756523132324 -0.1231500506401062 +-0.00026804208755493164 1.245882511138916 -0.29732465744018555 +-0.066043972969055176 1.295717716217041 -0.14099174737930298 +0.13090240955352783 1.3630403280258179 -0.27948290109634399 +0.16752979159355164 1.4096529483795166 0.020909637212753296 +0.30694162845611572 1.2362143993377686 0.13485437631607056 +0.33570891618728638 1.3565950393676758 0.0086364448070526123 +0.13876253366470337 1.2892725467681885 0.14712759852409363 +-0.32876622676849365 1.2782306671142578 0.15383222699165344 +-0.39416083693504333 1.1112374067306519 -0.020342379808425903 +-0.44897407293319702 1.1527668237686157 0.10993501543998718 +-0.28485208749771118 1.2088689804077148 -0.0054742395877838135 +-0.45955547690391541 0.9442441463470459 -0.19451698660850525 +-0.52495008707046509 0.77725088596343994 -0.36869162321090698 +-0.56886422634124756 0.84661257266998291 -0.20938509702682495 +-0.40474224090576172 0.90271466970443726 -0.32479438185691833 +-0.51436871290206909 0.98577356338500977 -0.064239621162414551 +-0.72227776050567627 0.92675697803497314 0.10030701756477356 +-0.58014458417892456 1.0356090068817139 0.092093318700790405 +-0.65650182962417603 0.87692159414291382 -0.056025832891464233 +-0.33934760093688965 1.0697078704833984 -0.15061977505683899 +-0.13143858313560486 1.1287245750427246 -0.31516638398170471 +-0.27357172966003418 1.0198725461959839 -0.30695265531539917 +-0.19721445441246033 1.1785598993301392 -0.15883353352546692 +-0.22636297345161438 1.275007963180542 0.29789191484451294 +-0.086951136589050293 1.1015694141387939 0.4118366539478302 +-0.062978416681289673 1.2018865346908569 0.30665504932403564 +-0.22710040211677551 1.1457843780517578 0.42206430435180664 +0.052460730075836182 0.9281308650970459 0.52578139305114746 +0.19187256693840027 0.75469225645065308 0.63972610235214233 +0.19260998070240021 0.88391584157943726 0.51555371284484863 +0.028487995266914368 0.82781368494033813 0.63096296787261963 +0.076433449983596802 1.0284479856491089 0.42059978842735291 +0.27817437052726746 1.1158338785171509 0.26107233762741089 +0.10520070791244507 1.1488285064697266 0.29438182711601257 +0.24940711259841919 0.9954533576965332 0.38729023933410645 +-0.11092382669448853 1.0012521743774414 0.51701825857162476 +-0.31266477704048157 0.91386628150939941 0.67654567956924438 +-0.13969111442565918 0.88087171316146851 0.64323616027832031 +-0.2838975191116333 1.0342468023300171 0.55032777786254883 +-0.1299135684967041 0.26141014695167542 -1.63719642162323 +-0.32685995101928711 0.19408762454986572 -1.498705267906189 +-0.19568943977355957 0.31124550104141235 -1.4808634519577026 +-0.15406492352485657 0.14260748028755188 -1.5142242908477783 +-0.52380633354187012 0.12676507234573364 -1.3602141141891479 +-0.72075271606445312 0.059442520141601562 -1.2217229604721069 +-0.58958220481872559 0.17660045623779297 -1.2038812637329102 +-0.552573561668396 0.0063845515251159668 -1.2339961528778076 +-0.39263582229614258 0.24392297863960266 -1.3423724174499512 +-0.3272412121295929 0.41091620922088623 -1.1681977510452271 +-0.26146531105041504 0.36108088493347168 -1.3245307207107544 +-0.45841169357299805 0.2937583327293396 -1.1860395669937134 +-0.35562720894813538 0.073707044124603271 -1.3724873065948486 +-0.18459534645080566 -0.10734724998474121 -1.2631126642227173 +-0.35636463761329651 -0.055516481399536133 -1.2483148574829102 +-0.18385788798332214 0.021876305341720581 -1.3872851133346558 +-0.91769909858703613 -0.0078799724578857422 -1.0832318067550659 +-1.1146454811096191 -0.075202524662017822 -0.94474071264266968 +-0.9834749698638916 0.041955351829528809 -0.92689895629882812 +-0.94646632671356201 -0.12826055288314819 -0.95701390504837036 +-1.3115918636322021 -0.1425250768661499 -0.80624955892562866 +-1.5085382461547852 -0.20984762907028198 -0.66775846481323242 +-1.3773677349090576 -0.092689692974090576 -0.64991664886474609 +-1.340359091758728 -0.26290559768676758 -0.68003165721893311 +-1.1804213523864746 -0.025367200374603271 -0.78840780258178711 +-1.1150267124176025 0.14162606000900269 -0.61423319578170776 +-1.0492508411407471 0.091790735721588135 -0.77056610584259033 +-1.2461972236633301 0.024468183517456055 -0.63207495212554932 +-1.143412709236145 -0.1955830454826355 -0.81852281093597412 +-1.0040009021759033 -0.36902162432670593 -0.70457804203033447 +-1.1721799373626709 -0.31596362590789795 -0.69230484962463379 +-0.97523361444473267 -0.24864107370376587 -0.8307960033416748 +-0.78652858734130859 0.10927790403366089 -1.0653901100158691 +-0.72113394737243652 0.27627113461494446 -0.89121544361114502 +-0.66632074117660522 0.23474165797233582 -1.0214928388595581 +-0.83044272661209106 0.17863953113555908 -0.90608358383178711 +-0.65573936700820923 0.44326439499855042 -0.71704089641571045 +-0.59034472703933716 0.61025762557983398 -0.54286623001098633 +-0.54643058776855469 0.54089593887329102 -0.70217275619506836 +-0.71055257320404053 0.48479384183883667 -0.58676350116729736 +-0.60092610120773315 0.40173491835594177 -0.84731823205947876 +-0.39301708340644836 0.46075156331062317 -1.0118649005889893 +-0.53515022993087769 0.35189956426620483 -1.0036511421203613 +-0.45879295468330383 0.51058691740036011 -0.85553205013275146 +-0.7759472131729126 0.3178006112575531 -0.76093804836273193 +-0.983856201171875 0.2587839663028717 -0.59639143943786621 +-0.84172308444976807 0.36763596534729004 -0.60460519790649414 +-0.91808032989501953 0.20894861221313477 -0.752724289894104 +-0.749519944190979 -0.060938000679016113 -1.0955049991607666 +-0.6101081371307373 -0.23437657952308655 -0.9815603494644165 +-0.75025737285614014 -0.19016158580780029 -0.97133266925811768 +-0.5861353874206543 -0.13405942916870117 -1.0867419242858887 +-0.47069627046585083 -0.40781512856483459 -0.86761558055877686 +-0.33128443360328674 -0.58125370740890503 -0.75367087125778198 +-0.49466902017593384 -0.50813227891921997 -0.76243400573730469 +-0.32849550247192383 -0.45132887363433838 -0.87928587198257446 +-0.61084556579589844 -0.36360016465187073 -0.85738790035247803 +-0.83582174777984619 -0.4220796525478363 -0.71685123443603516 +-0.77902466058731079 -0.31054210662841797 -0.84511470794677734 +-0.66764265298843384 -0.47513768076896667 -0.72912442684173584 +-0.4699588418006897 -0.2785915732383728 -0.99178797006607056 +-0.21131107211112976 -0.2270265519618988 -1.1383373737335205 +-0.27028793096542358 -0.33930918574333191 -1.0085411071777344 +-0.38513189554214478 -0.17589700222015381 -1.1220970153808594 +0.4590192437171936 1.5475207567214966 -0.40013232827186584 +0.39362472295761108 1.3805274963378906 -0.57430696487426758 +0.32784879207611084 1.4303629398345947 -0.41797402501106262 +0.49602791666984558 1.3773047924041748 -0.43024724721908569 +0.32823008298873901 1.2135343551635742 -0.74848151206970215 +0.26283544301986694 1.0465409755706787 -0.92265617847442627 +0.19705957174301147 1.0963764190673828 -0.76632332801818848 +0.36523869633674622 1.0433183908462524 -0.77859652042388916 +0.26245421171188354 1.2633695602416992 -0.59214866161346436 +0.065507829189300537 1.1960470676422119 -0.45365753769874573 +0.19667834043502808 1.3132050037384033 -0.43581578135490417 +0.13128370046615601 1.1462117433547974 -0.60999035835266113 +0.43063333630561829 1.2103116512298584 -0.60442185401916504 +0.57004517316818237 1.0368729829788208 -0.49047714471817017 +0.46764194965362549 1.0400958061218262 -0.63453680276870728 +0.53303658962249756 1.2070889472961426 -0.46036219596862793 +0.19744080305099487 0.87954777479171753 -1.0968308448791504 +0.1320461630821228 0.71255457401275635 -1.271005392074585 +0.066270291805267334 0.7623898983001709 -1.1146725416183472 +0.23444941639900208 0.70933187007904053 -1.1269457340240479 +0.066651523113250732 0.54556131362915039 -1.4451800584793091 +0.0012569427490234375 0.37856805324554443 -1.6193546056747437 +-0.064518928527832031 0.42840340733528137 -1.4630218744277954 +0.10212746262550354 0.37143146991729736 -1.479377269744873 +0.00087565183639526367 0.59539663791656494 -1.2888472080230713 +-0.19607070088386536 0.52807414531707764 -1.1503560543060303 +-0.064900189638137817 0.64523202180862427 -1.1325142383575439 +-0.13029482960700989 0.47823876142501831 -1.3066889047622681 +0.16905477643013 0.54233860969543457 -1.301120400428772 +0.3134426474571228 0.33748659491539001 -1.1953698396682739 +0.20487129688262939 0.36907857656478882 -1.3344104290008545 +0.27762612700462341 0.51074665784835815 -1.1620798110961914 +0.1316649317741394 0.92938315868377686 -0.94049787521362305 +-0.065281450748443604 0.86206060647964478 -0.80200678110122681 +0.044027328491210938 0.95969218015670776 -0.78713870048522949 +-0.010468244552612305 0.82053112983703613 -0.93228423595428467 +-0.26222783327102661 0.7947380542755127 -0.66351562738418579 +-0.45917421579360962 0.72741550207138062 -0.52502447366714478 +-0.31704103946685791 0.83626753091812134 -0.53323823213577271 +-0.37153655290603638 0.69710648059844971 -0.67838376760482788 +-0.15291908383369446 0.89236962795257568 -0.64864754676818848 +-0.06566271185874939 1.0788891315460205 -0.47149926424026489 +-0.021748542785644531 1.0095275640487671 -0.63080579042434692 +-0.19683319330215454 0.96173131465911865 -0.48934102058410645 +-0.17459022998809814 0.76442903280258179 -0.81687486171722412 +-0.26184657216072083 0.57790946960449219 -0.99402320384979248 +-0.3057607114315033 0.64727115631103516 -0.83471667766571045 +-0.13067609071731567 0.69506734609603882 -0.97618138790130615 +0.29984405636787415 0.87632513046264648 -0.95277112722396851 +0.43925589323043823 0.70288658142089844 -0.83882641792297363 +0.35391983389854431 0.70557212829589844 -0.95887613296508789 +0.40841540694236755 0.84473311901092529 -0.81373059749603271 +0.57866775989532471 0.52944803237915039 -0.72488164901733398 +0.71807962656021118 0.35600942373275757 -0.61093693971633911 +0.63206237554550171 0.35695546865463257 -0.73280096054077148 +0.66400378942489624 0.52676248550415039 -0.60483193397521973 +0.49333170056343079 0.53213351964950562 -0.84493136405944824 +0.41516473889350891 0.33252441883087158 -1.0531244277954102 +0.38381925225257874 0.52350485324859619 -1.0048620700836182 +0.52191740274429321 0.34671151638031006 -0.89441639184951782 +0.52459198236465454 0.70020103454589844 -0.7187766432762146 +0.60705375671386719 0.86665713787078857 -0.5205920934677124 +0.62699514627456665 0.69697833061218262 -0.57471698522567749 +0.5046505331993103 0.86987984180450439 -0.66465175151824951 +-1.014148473739624 1.0057177543640137 0.85185647010803223 +-0.87473666667938232 0.83227920532226562 0.96580123901367188 +-0.84596937894821167 0.95265984535217285 0.83958327770233154 +-0.97713989019393921 0.83550190925598145 0.82174146175384521 +-0.73532480001449585 0.65884065628051758 1.0797460079193115 +-0.59591293334960938 0.48540210723876953 1.1936906576156616 +-0.5671457052230835 0.60578268766403198 1.0674726963043213 +-0.69831621646881104 0.48862475156784058 1.049630880355835 +-0.7065575122833252 0.77922123670578003 0.95352798700332642 +-0.50961112976074219 0.84654378890991211 0.8150368332862854 +-0.67779028415679932 0.89960181713104248 0.82731008529663086 +-0.53837841749191284 0.72616326808929443 0.94125479459762573 +-0.83772802352905273 0.6620633602142334 0.93568617105484009 +-0.9031226634979248 0.49507009983062744 0.76151162385940552 +-0.80071943998336792 0.49184742569923401 0.90557140111923218 +-0.94013130664825439 0.66528594493865967 0.7916266918182373 +-0.45650109648704529 0.31196355819702148 1.3076354265213013 +-0.3170892596244812 0.13852497935295105 1.4215800762176514 +-0.28832197189331055 0.25890552997589111 1.2953622341156006 +-0.41949248313903809 0.14174763858318329 1.2775204181671143 +-0.17767739295959473 -0.034913569688796997 1.535524845123291 +-0.03826555609703064 -0.20835214853286743 1.6494696140289307 +-0.009498298168182373 -0.087971597909927368 1.5232516527175903 +-0.14066880941390991 -0.20512950420379639 1.505409836769104 +-0.14891013503074646 0.085466980934143066 1.4093068838119507 +0.048036247491836548 0.15278950333595276 1.2708157300949097 +-0.12014287710189819 0.20584753155708313 1.2830889225006104 +0.019268989562988281 0.032408982515335083 1.39703369140625 +-0.280080646276474 -0.031690925359725952 1.3914650678634644 +-0.34547522664070129 -0.19868415594100952 1.2172905206680298 +-0.2430720329284668 -0.20190683007240295 1.3613502979278564 +-0.38248389959335327 -0.028468281030654907 1.2474055290222168 +-0.42773383855819702 0.43234410881996155 1.1814174652099609 +-0.23078745603561401 0.49966663122177124 1.0429263114929199 +-0.37093672156333923 0.54388165473937988 1.0531539916992188 +-0.25476017594337463 0.39934951066970825 1.1481080055236816 +-0.033841073513031006 0.56698918342590332 0.90443515777587891 +0.163105309009552 0.6343117356300354 0.76594406366348267 +-0.0098683647811412811 0.66730624437332153 0.79925364255905151 +0.10630817711353302 0.52277415990829468 0.89420753717422485 +-0.17399033904075623 0.61120414733886719 0.91466289758682251 +-0.34143203496932983 0.79348576068878174 0.80276364088058472 +-0.34216949343681335 0.66426217555999756 0.92693608999252319 +-0.17325292527675629 0.74042773246765137 0.79049044847488403 +-0.090638160705566406 0.45545163750648499 1.0326986312866211 +0.076803505420684814 0.27317008376121521 1.1445977687835693 +0.077540934085845947 0.40239360928535461 1.0204254388809204 +-0.091375604271888733 0.32622808218002319 1.1568710803985596 +-0.55890434980392456 0.31518620252609253 1.1635756492614746 +-0.62429893016815186 0.14819297194480896 0.98940110206604004 +-0.5389629602432251 0.14550742506980896 1.1094508171081543 +-0.65513944625854492 0.29003956913948059 1.0144968032836914 +-0.68969357013702393 -0.018800288438796997 0.81522649526596069 +-0.755088210105896 -0.18579351902008057 0.64105188846588135 +-0.65885311365127563 -0.16064685583114624 0.79013067483901978 +-0.77502959966659546 -0.0161147341132164 0.69517678022384644 +-0.60435760021209717 -0.0214858278632164 0.93527621030807495 +-0.44787847995758057 -0.19546151161193848 1.0732309818267822 +-0.50195431709289551 -0.024708479642868042 1.0793359279632568 +-0.55028170347213745 -0.19223885238170624 0.92917120456695557 +-0.70963495969772339 0.15087851881980896 0.86935138702392578 +-0.86611402034759521 0.32485419511795044 0.73139673471450806 +-0.81203824281692505 0.15410116314888 0.72529172897338867 +-0.76371079683303833 0.32163155078887939 0.87545639276504517 +1.5373055934906006 0.33022814989089966 0.54154050350189209 +1.3978936672210693 0.50366675853729248 0.42759576439857483 +1.3691263198852539 0.38328617811203003 0.55381369590759277 +1.4381697177886963 0.32938581705093384 0.40015137195587158 +1.2584818601608276 0.67710530757904053 0.31365102529525757 +1.1190700531005859 0.85054385662078857 0.1997063010931015 +1.0903027057647705 0.7301633358001709 0.32592424750328064 +1.1560784578323364 0.68032795190811157 0.16959133744239807 +1.2297145128250122 0.55672478675842285 0.4398689866065979 +1.0327681303024292 0.48940220475196838 0.57836008071899414 +1.2009472846984863 0.43634417653083801 0.56608688831329346 +1.0615353584289551 0.60978269577026367 0.45214217901229858 +1.2954903841018677 0.50688934326171875 0.28353607654571533 +1.2388052940368652 0.30836519598960876 0.10641942918300629 +1.1992552280426025 0.4817427396774292 0.13445726037025452 +1.3350403308868408 0.33351179957389832 0.25549829006195068 +0.97965818643569946 1.0239824056625366 0.085761561989784241 +0.84024631977081299 1.1974209547042847 -0.028183162212371826 +0.81147897243499756 1.077040433883667 0.098034776747226715 +0.87725478410720825 1.0272051095962524 -0.058298133313655853 +0.70083445310592651 1.3708595037460327 -0.14212790131568909 +0.56142258644104004 1.5442981719970703 -0.25607264041900635 +0.53265529870986938 1.4239175319671631 -0.12985467910766602 +0.59843111038208008 1.3740822076797485 -0.28618758916854858 +0.67206716537475586 1.250478982925415 -0.015909954905509949 +0.47512075304985046 1.1831564903259277 0.12258116900920868 +0.64329987764358521 1.1300984621047974 0.11030799150466919 +0.50388801097869873 1.3035370111465454 -0.0036367475986480713 +0.73784291744232178 1.2006436586380005 -0.17224286496639252 +0.67244839668273926 1.0336503982543945 -0.34641748666763306 +0.63543975353240967 1.2038662433624268 -0.31630250811576843 +0.77485162019729614 1.0304276943206787 -0.20235776901245117 +0.95089083909988403 0.90360188484191895 0.21197950839996338 +0.75394445657730103 0.83627933263778687 0.35047063231468201 +0.89409369230270386 0.792064368724823 0.34024295210838318 +0.77791720628738403 0.93659645318984985 0.24528899788856506 +0.55699807405471802 0.76895678043365479 0.48896178603172302 +0.36005169153213501 0.70163422822952271 0.62745290994644165 +0.53302532434463501 0.66863971948623657 0.5941433310508728 +0.4168488085269928 0.81317180395126343 0.49918940663337708 +0.69714730978012085 0.72474181652069092 0.47873410582542419 +0.86458903551101685 0.54246020317077637 0.59063327312469482 +0.86532646417617798 0.67168378829956055 0.46646088361740112 +0.69640994071960449 0.59551823139190674 0.60290652513504028 +0.61379522085189819 0.88049429655075073 0.36069831252098083 +0.4463534951210022 1.0627758502960205 0.24879911541938782 +0.44561606645584106 0.93355238437652588 0.37297153472900391 +0.61453258991241455 1.0097179412841797 0.23652589321136475 +1.0166666507720947 0.85376650094985962 0.055646598339080811 +0.95127213001251221 0.68677330017089844 -0.11852800846099854 +0.92043161392211914 0.82861983776092529 -0.093432210385799408 +1.036608099937439 0.68408775329589844 0.0015217289328575134 +0.88587749004364014 0.51978003978729248 -0.29270261526107788 +0.82048285007476807 0.35278677940368652 -0.46687725186347961 +0.8005414605140686 0.52246552705764771 -0.41275236010551453 +0.91817021369934082 0.37612676620483398 -0.31661149859428406 +0.85503697395324707 0.66162657737731934 -0.26760685443878174 +0.70945703983306885 0.86343443393707275 -0.37653240561485291 +0.81802833080291748 0.83184254169464111 -0.23749187588691711 +0.74646562337875366 0.69321858882904053 -0.40664735436439514 +0.9821125864982605 0.54492670297622681 -0.14362379908561707 +1.1378542184829712 0.30978119373321533 -0.036453351378440857 +1.0277400016784668 0.34329277276992798 -0.17675495147705078 +1.0968520641326904 0.48496538400650024 -0.0096024125814437866 +0.1299135684967041 -0.26141014695167542 1.63719642162323 +0.32685995101928711 -0.19408762454986572 1.498705267906189 +0.15868082642555237 -0.14102959632873535 1.5109784603118896 +0.19568943977355957 -0.31124550104141235 1.4808634519577026 +0.52380633354187012 -0.12676507234573364 1.3602141141891479 +0.72075271606445312 -0.059442520141601562 1.2217229604721069 +0.552573561668396 -0.0063845515251159668 1.2339961528778076 +0.58958220481872559 -0.17660045623779297 1.2038812637329102 +0.35562720894813538 -0.073707044124603271 1.3724873065948486 +0.21621537208557129 0.099731534719467163 1.258542537689209 +0.18744808435440063 -0.020649075508117676 1.3847604990005493 +0.38439446687698364 0.046673476696014404 1.2462693452835083 +0.39263582229614258 -0.24392297863960266 1.3423724174499512 +0.3272412121295929 -0.41091620922088623 1.1681977510452271 +0.45841169357299805 -0.2937583327293396 1.1860395669937134 +0.26146531105041504 -0.36108088493347168 1.3245307207107544 +0.91769909858703613 0.0078799724578857422 1.0832318067550659 +1.1146454811096191 0.075202524662017822 0.94474071264266968 +0.94646632671356201 0.12826055288314819 0.95701390504837036 +0.9834749698638916 -0.041955351829528809 0.92689895629882812 +1.3115918636322021 0.1425250768661499 0.80624955892562866 +1.5085382461547852 0.20984762907028198 0.66775846481323242 +1.340359091758728 0.26290559768676758 0.68003165721893311 +1.3819836378097534 0.094267547130584717 0.64667081832885742 +1.143412709236145 0.1955830454826355 0.81852281093597412 +1.0040009021759033 0.36902162432670593 0.70457804203033447 +0.97523361444473267 0.24864107370376587 0.8307960033416748 +1.1721799373626709 0.31596362590789795 0.69230484962463379 +1.1804213523864746 0.025367200374603271 0.78840780258178711 +1.1295795440673828 -0.14870470762252808 0.58565318584442139 +1.249787449836731 -0.023240983486175537 0.62955033779144287 +1.060213565826416 -0.10009658336639404 0.74451065063476562 +0.749519944190979 0.060938000679016113 1.0955049991607666 +0.6101081371307373 0.23437657952308655 0.9815603494644165 +0.5861353874206543 0.13405942916870117 1.0867419242858887 +0.75025737285614014 0.19016158580780029 0.97133266925811768 +0.47069627046585083 0.40781512856483459 0.86761558055877686 +0.33128443360328674 0.58125370740890503 0.75367087125778198 +0.330547034740448 0.45203012228012085 0.87784326076507568 +0.49466902017593384 0.50813227891921997 0.76243400573730469 +0.44672355055809021 0.30749800801277161 0.97279715538024902 +0.24498263001441956 0.22011205554008484 1.1323245763778687 +0.41795629262924194 0.18711745738983154 1.0990151166915894 +0.27374988794326782 0.34049257636070251 1.0061067342758179 +0.63408082723617554 0.33469372987747192 0.87637871503829956 +0.83582174777984619 0.4220796525478363 0.71685123443603516 +0.66284811496734619 0.4550742506980896 0.750160813331604 +0.80705451965332031 0.30169913172721863 0.84306919574737549 +0.78652858734130859 -0.10927790403366089 1.0653901100158691 +0.72113394737243652 -0.27627113461494446 0.89121544361114502 +0.83044272661209106 -0.17863953113555908 0.90608358383178711 +0.66632074117660522 -0.23474165797233582 1.0214928388595581 +0.65573936700820923 -0.44326439499855042 0.71704089641571045 +0.59034472703933716 -0.61025762557983398 0.54286623001098633 +0.70170497894287109 -0.51192474365234375 0.55629175901412964 +0.54643058776855469 -0.54089593887329102 0.70217275619506836 +0.76504808664321899 -0.34563282132148743 0.73190897703170776 +1.0004606246948242 -0.26516133546829224 0.56636875867843628 +0.91340929269790649 -0.22087669372558594 0.74028325080871582 +0.85197120904922485 -0.38651746511459351 0.56332647800445557 +0.61182522773742676 -0.37390270829200745 0.87634730339050293 +0.39301708340644836 -0.46075156331062317 1.0118649005889893 +0.48065471649169922 -0.49106061458587646 0.85850560665130615 +0.52418756484985352 -0.34359365701675415 1.029706597328186 +-0.4590192437171936 -1.5475207567214966 0.40013232827186584 +-0.39362472295761108 -1.3805274963378906 0.57430696487426758 +-0.49602791666984558 -1.3773047924041748 0.43024724721908569 +-0.32938152551651001 -1.434276819229126 0.41389182209968567 +-0.32823008298873901 -1.2135343551635742 0.74848151206970215 +-0.26283544301986694 -1.0465409755706787 0.92265617847442627 +-0.36523869633674622 -1.0433183908462524 0.77859652042388916 +-0.19705957174301147 -1.0963764190673828 0.76632332801818848 +-0.43063333630561829 -1.2103116512298584 0.60442185401916504 +-0.57004517316818237 -1.0368729829788208 0.49047714471817017 +-0.53303658962249756 -1.2070889472961426 0.46036219596862793 +-0.46764194965362549 -1.0400958061218262 0.63453680276870728 +-0.26245421171188354 -1.2633695602416992 0.59214866161346436 +-0.05573725700378418 -1.2073972225189209 0.42442700266838074 +-0.12032103538513184 -1.154517650604248 0.58393490314483643 +-0.19787043333053589 -1.3162491321563721 0.43264070153236389 +-0.19744080305099487 -0.87954777479171753 1.0968308448791504 +-0.1320461630821228 -0.71255457401275635 1.271005392074585 +-0.23444941639900208 -0.70933187007904053 1.1269457340240479 +-0.066270291805267334 -0.7623898983001709 1.1146725416183472 +-0.066651523113250732 -0.54556131362915039 1.4451800584793091 +-0.0012569427490234375 -0.37856805324554443 1.6193546056747437 +-0.10366019606590271 -0.37534540891647339 1.4752950668334961 +0.064518928527832031 -0.42840340733528137 1.4630218744277954 +-0.16905477643013 -0.54233860969543457 1.301120400428772 +-0.30846661329269409 -0.36890006065368652 1.1871756315231323 +-0.27145802974700928 -0.5391160249710083 1.1570606231689453 +-0.20606338977813721 -0.37212273478507996 1.3312352895736694 +-0.00087565183639526367 -0.59539663791656494 1.2888472080230713 +0.19607070088386536 -0.52807414531707764 1.1503560543060303 +0.13029482960700989 -0.47823876142501831 1.3066889047622681 +0.064900189638137817 -0.64523202180862427 1.1325142383575439 +-0.29984405636787415 -0.87632513046264648 0.95277112722396851 +-0.43925589323043823 -0.70288658142089844 0.83882641792297363 +-0.40841540694236755 -0.84473311901092529 0.81373059749603271 +-0.35391983389854431 -0.70557212829589844 0.95887613296508789 +-0.57866775989532471 -0.52944803237915039 0.72488164901733398 +-0.71807962656021118 -0.35600942373275757 0.61093693971633911 +-0.66400378942489624 -0.52676248550415039 0.60483193397521973 +-0.609508216381073 -0.38760140538215637 0.7499774694442749 +-0.54782724380493164 -0.67129456996917725 0.69978582859039307 +-0.60705375671386719 -0.86665713787078857 0.5205920934677124 +-0.51081860065460205 -0.84151047468185425 0.66967093944549561 +-0.64406239986419678 -0.69644129276275635 0.55070704221725464 +-0.4700964093208313 -0.56103992462158203 0.86392217874526978 +-0.41086986660957336 -0.36567741632461548 1.0431159734725952 +-0.50710505247116089 -0.3908240795135498 0.89403712749481201 +-0.37386125326156616 -0.53589332103729248 1.0130009651184082 +-0.1316649317741394 -0.92938315868377686 0.94049787521362305 +0.065281450748443604 -0.86206060647964478 0.80200678110122681 +0.010468244552612305 -0.82053112983703613 0.93228423595428467 +-0.044027328491210938 -0.95969218015670776 0.78713870048522949 +0.26222783327102661 -0.7947380542755127 0.66351562738418579 +0.45917421579360962 -0.72741550207138062 0.52502447366714478 +0.37153655290603638 -0.69710648059844971 0.67838376760482788 +0.31635984778404236 -0.83800703287124634 0.53142392635345459 +0.20741459727287292 -0.75320857763290405 0.79379308223724365 +0.26184657216072083 -0.57790946960449219 0.99402320384979248 +0.14163869619369507 -0.7033732533454895 0.95012593269348145 +0.32762247323989868 -0.62774479389190674 0.83769023418426514 +0.12009471654891968 -0.90359008312225342 0.67172932624816895 +0.074752062559127808 -1.0919787883758545 0.44045442342758179 +0.19568368792533875 -0.96466672420501709 0.48627933859825134 +0.010849416255950928 -1.0373597145080566 0.60177665948867798 +-0.56142258644104004 -1.5442981719970703 0.25607264041900635 +-0.70083445310592651 -1.3708595037460327 0.14212790131568909 +-0.52938783168792725 -1.4279825687408447 0.13252526521682739 +-0.59843111038208008 -1.3740822076797485 0.28618758916854858 +-0.84024631977081299 -1.1974209547042847 0.028183162212371826 +-0.97965818643569946 -1.0239824056625366 -0.085761561989784241 +-0.81147897243499756 -1.077040433883667 -0.098034776747226715 +-0.87725478410720825 -1.0272051095962524 0.058298133313655853 +-0.67206716537475586 -1.250478982925415 0.015909954905509949 +-0.44454953074455261 -1.1951611042022705 -0.12254957854747772 +-0.5013466477394104 -1.3066986799240112 0.0057138800621032715 +-0.61527001857757568 -1.1389415264129639 -0.11235347390174866 +-0.73784291744232178 -1.2006436586380005 0.17224286496639252 +-0.67244839668273926 -1.0336503982543945 0.34641748666763306 +-0.77485162019729614 -1.0304276943206787 0.20235776901245117 +-0.63543975353240967 -1.2038662433624268 0.31630250811576843 +-1.1190700531005859 -0.85054385662078857 -0.1997063010931015 +-1.2584818601608276 -0.67710530757904053 -0.31365102529525757 +-1.0903027057647705 -0.7301633358001709 -0.32592424750328064 +-1.1560784578323364 -0.68032795190811157 -0.16959133744239807 +-1.3978936672210693 -0.50366675853729248 -0.42759576439857483 +-1.5373055934906006 -0.33022814989089966 -0.54154050350189209 +-1.3691263198852539 -0.38328617811203003 -0.55381369590759277 +-1.4349021911621094 -0.3334507942199707 -0.39748078584671021 +-1.2297145128250122 -0.55672478675842285 -0.4398689866065979 +-1.0327681303024292 -0.48940220475196838 -0.57836008071899414 +-1.0615353584289551 -0.60978269577026367 -0.45214217901229858 +-1.2009472846984863 -0.43634417653083801 -0.56608688831329346 +-1.2954903841018677 -0.50688934326171875 -0.28353607654571533 +-1.2300958633422852 -0.33989617228507996 -0.10936145484447479 +-1.3324990272521973 -0.33667346835136414 -0.25342115759849548 +-1.193087100982666 -0.51011204719543457 -0.13947641849517822 +-0.95089083909988403 -0.90360188484191895 -0.21197950839996338 +-0.75394445657730103 -0.83627933263778687 -0.35047063231468201 +-0.77791720628738403 -0.93659645318984985 -0.24528899788856506 +-0.89409369230270386 -0.792064368724823 -0.34024295210838318 +-0.55699807405471802 -0.76895678043365479 -0.48896178603172302 +-0.36005169153213501 -0.70163422822952271 -0.62745290994644165 +-0.38257220387458801 -0.80375802516937256 -0.52108436822891235 +-0.53302532434463501 -0.66863971948623657 -0.5941433310508728 +-0.58097082376480103 -0.86927390098571777 -0.38378015160560608 +-0.41433006525039673 -1.0765872001647949 -0.24758060276508331 +-0.60046499967575073 -1.0049091577529907 -0.24641811847686768 +-0.41518896818161011 -0.93236362934112549 -0.38553518056869507 +-0.72997170686721802 -0.73596221208572388 -0.45565226674079895 +-0.86458903551101685 -0.54246020317077637 -0.59063327312469482 +-0.70120447874069214 -0.61558163166046143 -0.58187019824981689 +-0.8933563232421875 -0.66284078359603882 -0.46441537141799927 +-1.0166666507720947 -0.85376650094985962 -0.055646598339080811 +-0.95127213001251221 -0.68677330017089844 0.11852800846099854 +-1.036608099937439 -0.68408775329589844 -0.0015217289328575134 +-0.92043161392211914 -0.82861983776092529 0.093432210385799408 +-0.88587749004364014 -0.51978003978729248 0.29270261526107788 +-0.82048285007476807 -0.35278677940368652 0.46687725186347961 +-0.91671794652938843 -0.37793341279029846 0.31779840588569641 +-0.8005414605140686 -0.52246552705764771 0.41275236010551453 +-0.97121345996856689 -0.51709449291229248 0.17265290021896362 +-1.1276925802230835 -0.34311875700950623 0.034698218107223511 +-1.0736167430877686 -0.51387178897857666 0.028593204915523529 +-1.0252892971038818 -0.34634149074554443 0.17875787615776062 +-0.86593610048294067 -0.68945878744125366 0.23857775330543518 +-0.70945703983306885 -0.86343443393707275 0.37653240561485291 +-0.76353281736373901 -0.69268143177032471 0.3826373815536499 +-0.81186026334762573 -0.86021184921264648 0.2324727475643158 +-1.4948921203613281 -0.27888089418411255 -0.60669493675231934 +-1.3267128467559814 -0.33193892240524292 -0.61896824836730957 +-1.4532159566879272 -0.35675716400146484 -0.54767709970474243 +-1.4244487285614014 -0.23637658357620239 -0.67389500141143799 +-1.2145935297012329 -0.36731094121932983 -0.62715029716491699 +-0.99035477638244629 -0.43805491924285889 -0.64351463317871094 +-1.1216522455215454 -0.48293662071228027 -0.55118715763092041 +-1.0832959413528442 -0.32242923974990845 -0.71947777271270752 +-1.2802423238754272 -0.38975179195404053 -0.5809866189956665 +-1.3138041496276855 -0.53019571304321289 -0.43373236060142517 +-1.3835099935531616 -0.44347646832466125 -0.490704745054245 +-1.1873010396957397 -0.50537747144699097 -0.50502347946166992 +-1.2610640525817871 -0.30949807167053223 -0.66513192653656006 +-1.2275023460388184 -0.16905409097671509 -0.812386155128479 +-1.129766583442688 -0.26461637020111084 -0.75745934247970581 +-1.3259754180908203 -0.20271533727645874 -0.7431405782699585 +-0.87823528051376343 -0.4734269380569458 -0.65169674158096313 +-0.67206829786300659 -0.54771637916564941 -0.65787655115127563 +-0.78049945831298828 -0.56898921728134155 -0.59676992893218994 +-0.74693769216537476 -0.42854523658752441 -0.74402415752410889 +-0.51384717226028442 -0.58838599920272827 -0.67828869819641113 +-0.30259585380554199 -0.65040916204452515 -0.69813799858093262 +-0.44414123892784119 -0.67510527372360229 -0.62131631374359131 +-0.41537398099899292 -0.55472469329833984 -0.74753427505493164 +-0.60752582550048828 -0.60198378562927246 -0.63007944822311401 +-0.62702006101608276 -0.73761904239654541 -0.49271738529205322 +-0.71558809280395508 -0.67577195167541504 -0.51876121759414673 +-0.54740899801254272 -0.72882997989654541 -0.53103440999984741 +-0.5883476734161377 -0.52173006534576416 -0.71422475576400757 +-0.52675598859786987 -0.39012911915779114 -0.86352455615997314 +-0.48028537631034851 -0.44794195890426636 -0.82554292678833008 +-0.68128889799118042 -0.40610438585281372 -0.79018789529800415 +-0.94388413429260254 -0.49586778879165649 -0.60553300380706787 +-0.98224043846130371 -0.65637516975402832 -0.43724244832992554 +-1.0751817226409912 -0.54074949026107788 -0.51320558786392212 +-0.85094285011291504 -0.61149346828460693 -0.52956986427307129 +-0.99214553833007812 -0.75188356637954712 -0.34195303916931152 +-1.0349804162979126 -0.87707287073135376 -0.20584289729595184 +-1.1046862602233887 -0.79035359621047974 -0.26281526684761047 +-0.93650722503662109 -0.84341156482696533 -0.27508848905563354 +-1.047889232635498 -0.67881608009338379 -0.39107871055603027 +-1.2440981864929199 -0.61691498756408691 -0.37676000595092773 +-1.1408305168151855 -0.56319034099578857 -0.46704190969467163 +-1.1743922233581543 -0.70363432168960571 -0.31978762149810791 +-0.93576979637145996 -0.71418803930282593 -0.39926087856292725 +-0.74435532093048096 -0.79615247249603271 -0.39254328608512878 +-0.81000417470932007 -0.81859332323074341 -0.34637954831123352 +-0.80447226762771606 -0.66930633783340454 -0.491588294506073 +-0.9247058629989624 -0.41561406850814819 -0.68967831134796143 +-0.87707650661468506 -0.27036139369010925 -0.8468247652053833 +-0.82143813371658325 -0.36188939213752747 -0.77996015548706055 +-1.0176471471786499 -0.29998838901519775 -0.76564145088195801 +-0.85241878032684326 -0.16717803478240967 -0.95501160621643066 +-0.83360952138900757 -0.034408986568450928 -1.089368462562561 +-0.76390361785888672 -0.12112826108932495 -1.0323960781097412 +-0.93208271265029907 -0.068070292472839355 -1.0201228857040405 +-0.82070076465606689 -0.23266583681106567 -0.90413260459899902 +-0.63444972038269043 -0.2821783721446991 -0.92659026384353638 +-0.69493508338928223 -0.33707112073898315 -0.85125136375427246 +-0.66616785526275635 -0.2166905403137207 -0.97746926546096802 +-0.93282014131546021 -0.19729381799697876 -0.89595049619674683 +-1.1290290355682373 -0.13539278507232666 -0.88163173198699951 +-1.0305559635162354 -0.10173153877258301 -0.95087730884552002 +-1.0641176700592041 -0.24217551946640015 -0.80362308025360107 +-0.28249704837799072 -0.72003328800201416 -0.63893067836761475 +-0.38837650418281555 -0.7444806694984436 -0.57573843002319336 +-0.45999971032142639 -0.99374258518218994 -0.30986255407333374 +-0.39695584774017334 -0.8639482855796814 -0.45797541737556458 +-0.56658715009689331 -0.80908364057540894 -0.44688913226127625 +-0.48697611689567566 -0.80029451847076416 -0.48520618677139282 +-0.50647032260894775 -0.93592977523803711 -0.34784412384033203 +-0.51753425598144531 -1.2345037460327148 -0.057426661252975464 +-0.56098008155822754 -1.466763973236084 0.18156918883323669 +-0.48443296551704407 -1.3797968626022339 0.069447875022888184 +-0.6864507794380188 -1.3106693029403687 0.079018920660018921 +-0.58318305015563965 -1.2569446563720703 -0.011262953281402588 +-0.61674487590789795 -1.3973885774612427 0.13599130511283875 +-0.48876690864562988 -1.1141231060028076 -0.1836446225643158 +-0.65694606304168701 -1.0610651969909668 -0.17137141525745392 +-0.50241327285766602 -1.0450899600982666 -0.24470803141593933 +-0.53118044137954712 -1.1654703617095947 -0.11849008500576019 +-0.7830277681350708 -1.012041449546814 -0.17103594541549683 +-0.96527445316314697 -0.96379214525222778 -0.14887054264545441 +-0.86680126190185547 -0.93013083934783936 -0.21811611950397491 +-0.89556854963302612 -1.0505114793777466 -0.091898173093795776 +-0.70341670513153076 -1.0032522678375244 -0.20935298502445221 +-0.68392246961593628 -0.86761707067489624 -0.34671500325202942 +-0.59535449743270874 -0.92946422100067139 -0.3206712007522583 +-0.76353353261947632 -0.87640613317489624 -0.30839797854423523 +-0.71332180500030518 -1.098760724067688 -0.1140635758638382 +-0.75615668296813965 -1.2239500284194946 0.022046566009521484 +-0.82586264610290527 -1.1372307538986206 -0.034925803542137146 +-0.65768349170684814 -1.1902886629104614 -0.047199010848999023 +0.058998048305511475 0.39365601539611816 -1.5299073457717896 +0.2510969340801239 0.39888069033622742 -1.2541863918304443 +0.15830510854721069 0.33840668201446533 -1.4155416488647461 +0.11785322427749634 0.54394996166229248 -1.3731502294540405 +0.20462632179260254 0.45669355988502502 -1.2921679019927979 +0.085155904293060303 0.4604533314704895 -1.4602375030517578 +0.45590341091156006 0.39243540167808533 -0.96606695652008057 +0.73964923620223999 0.27872928977012634 -0.61782997846603394 +0.67341744899749756 0.37432008981704712 -0.66554927825927734 +0.58086073398590088 0.35856679081916809 -0.80483078956604004 +0.54453331232070923 0.53052222728729248 -0.77290153503417969 +0.58721405267715454 0.45672851800918579 -0.74807798862457275 +0.47770160436630249 0.44809979200363159 -0.90800875425338745 +0.35350018739700317 0.39565804600715637 -1.1101266145706177 +0.31649157404899597 0.56587398052215576 -1.0800117254257202 +0.39853367209434509 0.42241603136062622 -1.0330777168273926 +0.29613041877746582 0.42563870549201965 -1.1771373748779297 +0.29560902714729309 0.6953321099281311 -1.0467770099639893 +0.2486424446105957 0.87793648242950439 -1.0248008966445923 +0.31834834814071655 0.79121720790863037 -0.96782857179641724 +0.21594512462615967 0.79443985223770142 -1.1118882894515991 +0.3382897675037384 0.62153834104537964 -1.0219534635543823 +0.44780221581459045 0.63016706705093384 -0.8620227575302124 +0.44213011860847473 0.53374487161636353 -0.9169611930847168 +0.40512144565582275 0.70396077632904053 -0.88684630393981934 +0.26291170716285706 0.61183547973632812 -1.1338644027709961 +0.15055054426193237 0.62744659185409546 -1.2860628366470337 +0.18324780464172363 0.71094322204589844 -1.1989755630493164 +0.22025644779205322 0.54072731733322144 -1.2290904521942139 +1.4721627235412598 0.34918338060379028 0.45811620354652405 +1.2751293182373047 0.36665409803390503 0.18641045689582825 +1.3956775665283203 0.29946622252464294 0.32517954707145691 +1.3466920852661133 0.50527811050415039 0.35556593537330627 +1.4163979291915894 0.41855880618095398 0.4125383198261261 +1.2969275712966919 0.42231851816177368 0.24446871876716614 +1.0830304622650146 0.36142945289611816 -0.089310571551322937 +0.83245223760604858 0.27580875158309937 -0.48727589845657349 +0.87313669919967651 0.34936878085136414 -0.39366048574447632 +0.96929091215133667 0.32908546924591064 -0.26678088307380676 +0.93240809440612793 0.5062406063079834 -0.2331138402223587 +1.0006169080734253 0.45981875061988831 -0.15868125855922699 +0.89821368455886841 0.46304139494895935 -0.30274093151092529 +1.172726035118103 0.36987677216529846 0.04235076904296875 +1.1357173919677734 0.54009270668029785 0.072465702891349792 +1.2177596092224121 0.39663475751876831 0.11939980089664459 +1.1153563261032104 0.39985746145248413 -0.024659872055053711 +1.1002058982849121 0.67001122236251831 0.085120469331741333 +1.0678683519363403 0.85215520858764648 0.12767647206783295 +1.1375741958618164 0.76543593406677246 0.18464884161949158 +1.0351710319519043 0.76865857839584351 0.040589146316051483 +1.1699118614196777 0.58329194784164429 0.14209283888339996 +1.2769861221313477 0.59199738502502441 0.29859358072280884 +1.2442888021469116 0.50850069522857666 0.21150624752044678 +1.207280158996582 0.67871665954589844 0.24162121117115021 +1.0821375846862793 0.58605420589447021 0.018613122403621674 +0.96360832452774048 0.63003462553024292 -0.12856632471084595 +0.98540651798248291 0.68569904565811157 -0.070508092641830444 +1.0394823551177979 0.51494604349136353 -0.076613098382949829 +0.77544933557510376 0.32602879405021667 -0.54392623901367188 +0.73227262496948242 0.52461397647857666 -0.50879216194152832 +0.80197852849960327 0.43789470195770264 -0.4518197774887085 +0.69957530498504639 0.44111740589141846 -0.59587943553924561 +0.69059300422668457 0.68290179967880249 -0.49111825227737427 +0.65208727121353149 0.89341515302658081 -0.44354307651519775 +0.74502849578857422 0.77778947353363037 -0.36757993698120117 +0.62555807828903198 0.78154921531677246 -0.53564953804016113 +0.74790269136428833 0.60864770412445068 -0.44571477174758911 +0.87354123592376709 0.57651859521865845 -0.28266429901123047 +0.85174304246902466 0.52085423469543457 -0.34072250127792358 +0.79149913787841797 0.71997660398483276 -0.32959836721420288 +0.67963385581970215 0.61079621315002441 -0.54175454378128052 +0.5701214075088501 0.60216748714447021 -0.70168530941009521 +0.57579350471496582 0.69858968257904053 -0.64674681425094604 +0.61280214786529541 0.52837377786636353 -0.67686176300048828 +0.62741482257843018 1.0068924427032471 -0.42346644401550293 +0.57807004451751709 1.23384690284729 -0.38331320881843567 +0.67101120948791504 1.1182212829589844 -0.30735006928443909 +0.53447365760803223 1.1225180625915527 -0.49942958354949951 +0.55339765548706055 1.3473241329193115 -0.36323654651641846 +0.51638901233673096 1.5175400972366333 -0.33312162756919861 +0.57992684841156006 1.4591901302337646 -0.27113008499145508 +0.47752362489700317 1.4624128341674805 -0.41518977284431458 +0.5998682975769043 1.2895113229751587 -0.32525494694709778 +0.71933871507644653 1.2857515811920166 -0.15718534588813782 +0.69280946254730225 1.1738855838775635 -0.2492918074131012 +0.64963281154632568 1.3724708557128906 -0.21415773034095764 +0.53159940242767334 1.2916598320007324 -0.42129480838775635 +0.4121289849281311 1.2954195737838745 -0.58936440944671631 +0.44482630491256714 1.3789162635803223 -0.50227707624435425 +0.48800301551818848 1.1803309917449951 -0.53741121292114258 +0.67388546466827393 0.94907957315444946 -0.38548487424850464 +0.80331391096115112 0.93293130397796631 -0.20927634835243225 +0.7606586217880249 0.86182314157485962 -0.30450254678726196 +0.71748185157775879 1.060408353805542 -0.26936846971511841 +0.89108812808990479 0.93016904592514038 -0.085796624422073364 +0.99816238880157471 0.93887448310852051 0.070704109966754913 +0.96546506881713867 0.85537785291671753 -0.016383221372961998 +0.92845648527145386 1.0255937576293945 0.01373174786567688 +0.85689371824264526 0.88696980476379395 -0.15542374551296234 +0.90474152565002441 0.70031267404556274 -0.17811678349971771 +0.83653265237808228 0.746734619140625 -0.25254935026168823 +0.93893587589263916 0.7435118556022644 -0.10848966240882874 +0.8322213888168335 1.0004470348358154 -0.13534705340862274 +0.78904461860656738 1.1990323066711426 -0.10021299123764038 +0.85875058174133301 1.1123130321502686 -0.04324062168598175 +0.739280104637146 1.1160727739334106 -0.21131022274494171 +0.60561668872833252 0.95122802257537842 -0.48152467608451843 +0.46907898783683777 0.95552480220794678 -0.67360424995422363 +0.51267540454864502 1.0668537616729736 -0.5574878454208374 +0.56202018260955811 0.83989918231964111 -0.59764111042022705 +0.3937009871006012 0.94582194089889526 -0.78551506996154785 +0.28133976459503174 0.9614330530166626 -0.937713623046875 +0.31403708457946777 1.0449297428131104 -0.85062634944915771 +0.35104566812515259 0.87471377849578857 -0.88074129819869995 +0.42260837554931641 1.0133377313613892 -0.71158581972122192 +0.37943166494369507 1.2119228839874268 -0.67645168304443359 +0.46620482206344604 1.1246665716171265 -0.59546941518783569 +0.34673440456390381 1.1284263134002686 -0.76353901624679565 +0.44728079438209534 0.8998604416847229 -0.73166239261627197 +0.47339034080505371 0.70181232690811157 -0.79080641269683838 +0.42691969871520996 0.75962519645690918 -0.82878804206848145 +0.54022204875946045 0.78423476219177246 -0.65569925308227539 +1.4232583045959473 0.14453643560409546 0.67268669605255127 +1.1696493625640869 -0.074741244316101074 0.64920949935913086 +1.3309512138366699 0.028609991073608398 0.60916990041732788 +1.2460066080093384 0.083946168422698975 0.79732871055603027 +1.1914474964141846 -0.019076824188232422 0.70726776123046875 +1.3444797992706299 0.11760741472244263 0.72808313369750977 +0.90730834007263184 -0.30905702710151672 0.6135261058807373 +0.61400079727172852 -0.63833105564117432 0.47119158506393433 +0.63623535633087158 -0.55841094255447388 0.56563621759414673 +0.76729023456573486 -0.45334583520889282 0.56521260738372803 +0.69946283102035522 -0.40421175956726074 0.72298812866210938 +0.69329833984375 -0.45625397562980652 0.65131545066833496 +0.8416595458984375 -0.33149784803390503 0.65968978404998779 +1.0384788513183594 -0.19189912080764771 0.63136780261993408 +0.97270292043685913 -0.14206379652023315 0.78770065307617188 +0.96193093061447144 -0.24217218160629272 0.64850246906280518 +1.0931015014648438 -0.12501424551010132 0.66634416580200195 +0.91321867704391479 -0.11246234178543091 0.90553700923919678 +0.85211384296417236 -0.050698935985565186 1.0743110179901123 +0.81941652297973633 -0.13419556617736816 0.98722362518310547 +0.95058703422546387 -0.017037630081176758 1.0050654411315918 +0.90705418586730957 -0.16450464725494385 0.83386439085006714 +0.75869297981262207 -0.28926074504852295 0.82549011707305908 +0.83063334226608276 -0.28705385327339172 0.74082982540130615 +0.76485747098922729 -0.23721849918365479 0.89716273546218872 +1.0116918087005615 -0.078801095485687256 0.83629143238067627 +1.1475334167480469 0.050284862518310547 0.86657428741455078 +1.0490602254867554 0.016623616218566895 0.93581986427307129 +1.1148360967636108 -0.033211767673492432 0.77948695421218872 +0.53572213649749756 -0.67714250087738037 0.50788986682891846 +0.45898360013961792 -0.61900120973587036 0.69027823209762573 +0.42628628015518188 -0.70249783992767334 0.60319089889526367 +0.55745679140090942 -0.58533996343612671 0.62103271484375 +0.40727531909942627 -0.56435710191726685 0.83671891689300537 +0.31646919250488281 -0.5110245943069458 1.0289995670318604 +0.27287277579307556 -0.62235349416732788 0.91288304328918457 +0.4259050190448761 -0.48566925525665283 0.93369841575622559 +0.3823721706867218 -0.63313615322113037 0.7624974250793457 +0.24030253291130066 -0.77812623977661133 0.71562659740447998 +0.305951327085495 -0.75568544864654541 0.66946291923522949 +0.25107455253601074 -0.67801785469055176 0.85482490062713623 +0.46981915831565857 -0.5550309419631958 0.77439188957214355 +0.61818039417266846 -0.43027478456497192 0.78276622295379639 +0.54623997211456299 -0.43248167634010315 0.86742651462554932 +0.61201584339141846 -0.48231703042984009 0.71109366416931152 +0.27261859178543091 -0.47780105471611023 1.1332215070724487 +0.18491742014884949 -0.4113539457321167 1.3416652679443359 +0.14132100343704224 -0.52268272638320923 1.2255488634109497 +0.31621497869491577 -0.36647224426269531 1.2493377923965454 +0.14106684923171997 -0.37813037633895874 1.4458872079849243 +0.075290977954864502 -0.32829499244689941 1.6022201776504517 +0.031630992889404297 -0.40348571538925171 1.5411882400512695 +0.16280150413513184 -0.28632780909538269 1.5590299367904663 +0.11926862597465515 -0.43379479646682739 1.3878289461135864 +-0.033763587474822998 -0.57047897577285767 1.3670135736465454 +0.0756722092628479 -0.54512357711791992 1.2717125415802002 +-0.0010663270950317383 -0.48698234558105469 1.4541009664535522 +0.20671564340591431 -0.35568952560424805 1.3997235298156738 +0.35974788665771484 -0.219005286693573 1.4205389022827148 +0.26127469539642334 -0.25266653299331665 1.4897844791412354 +0.33801320195198059 -0.31080782413482666 1.3073960542678833 +0.25082036852836609 -0.53346550464630127 1.0751632452011108 +0.093117088079452515 -0.68207776546478271 1.0419068336486816 +0.19626134634017944 -0.63648843765258789 0.98510229587554932 +0.1195228099822998 -0.57834714651107788 1.1674906015396118 +-0.019314765930175781 -0.78249883651733398 1.0266139507293701 +-0.16455286741256714 -0.9044654369354248 1.0186643600463867 +-0.066079676151275635 -0.87080419063568115 0.94941878318786621 +-0.1318555474281311 -0.8209688663482666 1.105751633644104 +0.054128170013427734 -0.74534040689468384 0.99331605434417725 +0.11679911613464355 -0.80829042196273804 0.82081985473632812 +0.1745266318321228 -0.72829091548919678 0.87195944786071777 +0.043356180191040039 -0.84544885158538818 0.854117751121521 +0.01027756929397583 -0.71211683750152588 1.0975378751754761 +-0.066460907459259033 -0.65397560596466064 1.2799263000488281 +-0.099158227443695068 -0.73747223615646362 1.1928390264511108 +0.053874015808105469 -0.60078799724578857 1.2136543989181519 +0.33826738595962524 -0.45536020398139954 1.0870577096939087 +0.51316142082214355 -0.29914969205856323 1.1108466386795044 +0.3818638026714325 -0.34403139352798462 1.2031741142272949 +0.4695650041103363 -0.41047850251197815 0.99473035335540771 +0.61779910326004028 -0.21344617009162903 1.1132737398147583 +0.75364065170288086 -0.084360182285308838 1.1435565948486328 +0.65516746044158936 -0.11802148818969727 1.2128021717071533 +0.72094333171844482 -0.16785681247711182 1.056469202041626 +0.53495961427688599 -0.24348527193069458 1.1689049005508423 +0.45822107791900635 -0.18534398078918457 1.3512933254241943 +0.40366202592849731 -0.28836697340011597 1.2612323760986328 +0.55669426918029785 -0.15168273448944092 1.2820477485656738 +0.57881021499633789 -0.27670884132385254 1.0646829605102539 +0.67741048336029053 -0.31532379984855652 0.88526821136474609 +0.69920867681503296 -0.25965934991836548 0.94332647323608398 +0.53521376848220825 -0.38803768157958984 0.94856655597686768 +0.49512752890586853 -0.74450540542602539 0.45502248406410217 +0.3929077684879303 -0.78773397207260132 0.51428931951522827 +0.11155331134796143 -1.0270425081253052 0.49426925182342529 +0.28129565715789795 -0.89850747585296631 0.48223558068275452 +0.21071016788482666 -0.84850823879241943 0.64470255374908447 +0.15298262238502502 -0.92850774526596069 0.59356296062469482 +0.28415313363075256 -0.81134986877441406 0.6114046573638916 +-0.1420556902885437 -1.2463201284408569 0.47079211473464966 +-0.3868945837020874 -1.4722425937652588 0.42647060751914978 +-0.25402569770812988 -1.3870478868484497 0.39358216524124146 +-0.32803946733474731 -1.3219485282897949 0.58322775363922119 +-0.36073672771453857 -1.4054452180862427 0.49614048004150391 +-0.20770448446273804 -1.2687609195709229 0.51695585250854492 +-0.010885179042816162 -1.1291623115539551 0.48863387107849121 +-0.076661050319671631 -1.079326868057251 0.64496678113937378 +-0.087433099746704102 -1.1794352531433105 0.5057685375213623 +0.043737351894378662 -1.0622774362564087 0.52361023426055908 +-0.11740672588348389 -1.0329886674880981 0.76535195112228394 +-0.19725018739700317 -0.98796212673187256 0.93157702684402466 +-0.22994750738143921 -1.0714586973190308 0.8444896936416626 +-0.09877699613571167 -0.95430082082748413 0.86233144998550415 +-0.15010404586791992 -1.1164853572845459 0.67826461791992188 +-0.29534214735031128 -1.2384519577026367 0.67031514644622803 +-0.19686895608901978 -1.2047905921936035 0.60106956958770752 +-0.26264482736587524 -1.1549553871154785 0.75740242004394531 +-0.037672162055969238 -1.0160642862319946 0.69355756044387817 +0.087206780910491943 -0.87867236137390137 0.74989581108093262 +0.021557927131652832 -0.90111327171325684 0.79605954885482788 +0.065472066402435303 -0.97047489881515503 0.63675302267074585 +-0.24001453816890717 -0.6053282618522644 -0.76485663652420044 +-0.31484925746917725 -0.52036213874816895 -0.81822240352630615 +-0.2733074426651001 -0.26295846700668335 -1.0806101560592651 +-0.27173051238059998 -0.4171852171421051 -0.93333441019058228 +-0.44635465741157532 -0.36001333594322205 -0.92258566617965698 +-0.38586932420730591 -0.30512058734893799 -0.9979245662689209 +-0.41463658213615417 -0.42550116777420044 -0.87170660495758057 +-0.2298615574836731 -0.030698239803314209 -1.3196060657501221 +-0.16399180889129639 0.19448763132095337 -1.560238242149353 +-0.13682848215103149 0.074801445007324219 -1.4556856155395508 +-0.34124356508255005 0.13389736413955688 -1.435596227645874 +-0.24277037382125854 0.16755861043930054 -1.5048418045043945 +-0.27633216977119446 0.027114629745483398 -1.3575875759124756 +-0.25862884521484375 -0.15107876062393188 -1.1933881044387817 +-0.42680799961090088 -0.098020792007446289 -1.1811149120330811 +-0.27227509021759033 -0.082045495510101318 -1.2544515132904053 +-0.3010423481464386 -0.20242601633071899 -1.1282336711883545 +-0.55699920654296875 -0.06619417667388916 -1.1627483367919922 +-0.73513633012771606 -0.00074774026870727539 -1.1586140394210815 +-0.63666313886642456 0.032913565635681152 -1.2278596162796021 +-0.66543042659759521 -0.087467014789581299 -1.1016416549682617 +-0.45852604508399963 -0.032532930374145508 -1.2319939136505127 +-0.43971675634384155 0.10023605823516846 -1.3663506507873535 +-0.3700108528137207 0.013516783714294434 -1.3093783855438232 +-0.53818994760513306 0.066574811935424805 -1.2971051931381226 +-0.48318368196487427 -0.13571628928184509 -1.1238070726394653 +-0.55404841899871826 -0.25206261873245239 -0.98565137386322021 +-0.60051906108856201 -0.19424974918365479 -1.0236330032348633 +-0.42754536867141724 -0.22724428772926331 -1.0569424629211426 +0.40426963567733765 1.5529121160507202 -0.32493951916694641 +0.27309912443161011 1.4357542991638184 -0.3427811861038208 +0.32765817642211914 1.5387771129608154 -0.25272026658058167 +0.39343404769897461 1.4889419078826904 -0.40905317664146423 +0.18565207719802856 1.3576489686965942 -0.35467574000358582 +0.010758161544799805 1.2014384269714355 -0.37846469879150391 +0.054354548454284668 1.3127672672271729 -0.26234832406044006 +0.1420556902885437 1.2463201284408569 -0.47079211473464966 +0.20745033025741577 1.4133133888244629 -0.29661747813224792 +0.13071179389953613 1.4714546203613281 -0.11422914266586304 +0.22918498516082764 1.5051159858703613 -0.18347471952438354 +0.0761527419090271 1.3684316873550415 -0.20429006218910217 +0.2513008713722229 1.3800897598266602 -0.40083944797515869 +0.32803946733474731 1.3219485282897949 -0.58322775363922119 +0.20770448446273804 1.2687609195709229 -0.51695585250854492 +0.36073672771453857 1.4054452180862427 -0.49614048004150391 +-0.076688885688781738 1.123333215713501 -0.39035922288894653 +-0.24378871917724609 0.98184025287628174 -0.40128237009048462 +-0.19702383875846863 1.0701456069946289 -0.32408726215362549 +-0.12028530240058899 1.0120043754577637 -0.50647562742233276 +-0.36089164018630981 0.8694911003112793 -0.42901629209518433 +-0.51392388343811035 0.73280686140060425 -0.44983166456222534 +-0.45936483144760132 0.83582985401153564 -0.35977074503898621 +-0.39358896017074585 0.78599447011947632 -0.51610362529754639 +-0.317231684923172 0.94468182325363159 -0.36798447370529175 +-0.39864125847816467 0.99089497327804565 -0.19803717732429504 +-0.30645966529846191 1.0447902679443359 -0.22878621518611908 +-0.43763017654418945 0.92763233184814453 -0.24662794172763824 +-0.27338111400604248 0.91145825386047363 -0.47220641374588013 +-0.21850433945655823 0.83379065990447998 -0.65756839513778687 +-0.28415313363075256 0.81134986877441406 -0.6114046573638916 +-0.14208352565765381 0.95633995532989502 -0.56453382968902588 +-0.054890692234039307 1.1789976358413696 -0.33230099081993103 +-0.14259189367294312 1.2454447746276855 -0.12385717034339905 +-0.011294305324554443 1.2903263568878174 -0.21618461608886719 +-0.18618828058242798 1.1341159343719482 -0.23997354507446289 +-0.20207613706588745 1.2750461101531982 -0.0060208141803741455 +-0.26318097114562988 1.3368096351623535 0.16275313496589661 +-0.16470777988433838 1.3704708814620972 0.093507558107376099 +-0.29587829113006592 1.2533129453659058 0.075665801763534546 +-0.12079364061355591 1.3011090755462646 -0.065798908472061157 +0.032238602638244629 1.4377933740615845 -0.044983565807342529 +0.010503947734832764 1.3459908962249756 -0.1581263542175293 +-0.066234588623046875 1.4041321277618408 0.024261981248855591 +-0.20824065804481506 1.2230038642883301 -0.077693462371826172 +-0.37223553657531738 1.0946255922317505 -0.072453349828720093 +-0.35043734312057495 1.1502900123596191 -0.01439511775970459 +-0.25183707475662231 1.1116750240325928 -0.19380983710289001 +-0.011040091514587402 1.1457740068435669 -0.43652293086051941 +0.061027407646179199 1.0757046937942505 -0.63135230541229248 +-0.032774746417999268 1.053971529006958 -0.54966568946838379 +0.12025749683380127 1.1906557083129883 -0.52885031700134277 +0.11740672588348389 1.0329886674880981 -0.76535195112228394 +0.19725018739700317 0.98796212673187256 -0.93157702684402466 +0.09877699613571167 0.95430082082748413 -0.86233144998550415 +0.22994750738143921 1.0714586973190308 -0.8444896936416626 +0.054862856864929199 1.0236624479293823 -0.70302498340606689 +-0.08410179615020752 0.89178705215454102 -0.73373258113861084 +-0.087333798408508301 0.95094859600067139 -0.63972663879394531 +-0.021557927131652832 0.90111327171325684 -0.79605954885482788 +0.14230984449386597 1.1017677783966064 -0.69113045930862427 +0.29534214735031128 1.2384519577026367 -0.67031514644622803 +0.26264482736587524 1.1549553871154785 -0.75740242004394531 +0.18590629100799561 1.2130966186523438 -0.57501405477523804 +-0.60137093067169189 0.65470165014266968 -0.46172618865966797 +-0.75440317392349243 0.51801741123199463 -0.48254156112670898 +-0.7217058539390564 0.60151404142379761 -0.39545422792434692 +-0.65592998266220093 0.55167865753173828 -0.55178713798522949 +-0.87150609493255615 0.40566825866699219 -0.51027548313140869 +-1.0386059284210205 0.26417532563209534 -0.52119863033294678 +-0.99500954151153564 0.37550416588783264 -0.40508222579956055 +-0.91827094554901123 0.31736290454864502 -0.58747059106826782 +-0.84191370010375977 0.47605025768280029 -0.43935143947601318 +-0.89679050445556641 0.55371785163879395 -0.25398945808410645 +-0.83114171028137207 0.57615864276885986 -0.30015316605567932 +-0.97321128845214844 0.43116855621337891 -0.34702402353286743 +-0.79806315898895264 0.44282668828964233 -0.54357337951660156 +-0.71665358543395996 0.39661353826522827 -0.71352064609527588 +-0.80883514881134033 0.34271827340126038 -0.68277162313461304 +-0.67766463756561279 0.45987617969512939 -0.66492992639541626 +-1.1260529756546021 0.1860700249671936 -0.5330931544303894 +-1.3009469509124756 0.029859542846679688 -0.55688214302062988 +-1.2573504447937012 0.14118838310241699 -0.44076573848724365 +-1.1696493625640869 0.074741244316101074 -0.64920949935913086 +-1.3883938789367676 -0.048245728015899658 -0.56877666711807251 +-1.5195643901824951 -0.16540360450744629 -0.58661830425262451 +-1.5087288618087769 -0.10143333673477173 -0.50250470638275146 +-1.4429529905319214 -0.15126866102218628 -0.65883755683898926 +-1.3665957450866699 0.0074186921119689941 -0.51071840524673462 +-1.4433343410491943 0.065559923648834229 -0.32833006978034973 +-1.3229992389678955 0.1187475323677063 -0.39460203051567078 +-1.4760315418243408 -0.01793670654296875 -0.4154173731803894 +-1.3227450847625732 -0.025804877281188965 -0.61494040489196777 +-1.2460066080093384 -0.083946168422698975 -0.79732871055603027 +-1.3444797992706299 -0.11760741472244263 -0.72808313369750977 +-1.1914474964141846 0.019076824188232422 -0.70726776123046875 +-1.1042547225952148 0.24173447489738464 -0.4750349223613739 +-1.1763222217559814 0.31180381774902344 -0.28020551800727844 +-1.0825200080871582 0.33353698253631592 -0.36189213395118713 +-1.2355523109436035 0.19685280323028564 -0.38270750641822815 +-1.2327015399932861 0.35451984405517578 -0.14620590209960938 +-1.3125450611114502 0.39954641461372375 0.020019173622131348 +-1.2140717506408691 0.43320769071578979 -0.04922640323638916 +-1.3452422618865967 0.31604981422424316 -0.067068129777908325 +-1.1701576709747314 0.36384603381156921 -0.20853288471698761 +-1.0311930179595947 0.49572145938873291 -0.17782530188560486 +-1.0279610157012939 0.43655991554260254 -0.271831214427948 +-1.0937368869781494 0.48639526963233948 -0.11549830436706543 +-1.2576045989990234 0.28574079275131226 -0.22042737901210785 +-1.4106369018554688 0.14905655384063721 -0.24124273657798767 +-1.3779397010803223 0.23255318403244019 -0.154155433177948 +-1.3012011051177979 0.17441195249557495 -0.33654379844665527 +-1.0604040622711182 0.20851090550422668 -0.57925689220428467 +-0.97270292043685913 0.14206379652023315 -0.78770065307617188 +-1.1040005683898926 0.097182095050811768 -0.69537323713302612 +-0.92910653352737427 0.25339260697364807 -0.67158430814743042 +-0.91321867704391479 0.11246234178543091 -0.90553700923919678 +-0.85211384296417236 0.050698935985565186 -1.0743110179901123 +-0.95058703422546387 0.017037630081176758 -1.0050654411315918 +-0.81941652297973633 0.13419556617736816 -0.98722362518310547 +-0.99450117349624634 0.086399376392364502 -0.84575891494750977 +-1.1475334167480469 -0.050284862518310547 -0.86657428741455078 +-1.1257987022399902 0.041517674922943115 -0.75343149900436401 +-1.0490602254867554 -0.016623616218566895 -0.93581986427307129 +-0.90705418586730957 0.16450464725494385 -0.83386439085006714 +-0.74305927753448486 0.29288294911384583 -0.83910453319549561 +-0.76485747098922729 0.23721849918365479 -0.89716273546218872 +-0.86345773935317993 0.27583342790603638 -0.71774804592132568 +-0.57957267761230469 0.71036601066589355 -0.40366795659065247 +-0.65631121397018433 0.76850730180740356 -0.22127960622310638 +-0.55783802270889282 0.80216854810714722 -0.2905251681804657 +-0.68900853395462036 0.68501067161560059 -0.30836692452430725 +-0.72675812244415283 0.80641454458236694 -0.077387779951095581 +-0.79882562160491943 0.87648391723632812 0.11744168400764465 +-0.66752803325653076 0.92136561870574951 0.025114208459854126 +-0.8205602765083313 0.78468137979507446 0.0042988359928131104 +-0.64547568559646606 0.83247756958007812 -0.13716593384742737 +-0.48148077726364136 0.96085590124130249 -0.14240601658821106 +-0.50327897071838379 0.90519148111343384 -0.20046421885490417 +-0.60187923908233643 0.94380640983581543 -0.02104949951171875 +-0.73292267322540283 0.75437235832214355 -0.14906039834022522 +-0.87188732624053955 0.6224968433380127 -0.17976799607276917 +-0.87511932849884033 0.68165844678878784 -0.085762053728103638 +-0.80934345722198486 0.63182306289672852 -0.24209496378898621 +-0.84267622232437134 0.90970742702484131 0.22166362404823303 +-0.93037736415863037 0.97615456581115723 0.43010738492012024 +-0.79907983541488647 1.0210362672805786 0.33777996897697449 +-0.97397381067276001 0.8648257851600647 0.31399098038673401 +-0.97422796487808228 1.00937819480896 0.53432929515838623 +-1.040003776550293 1.0592135190963745 0.69066226482391357 +-0.95249330997467041 1.1011806726455688 0.64747202396392822 +-1.0836638212203979 0.98402279615402222 0.62963032722473145 +-0.90857917070388794 1.0318189859390259 0.48816564679145813 +-0.7555469274520874 1.1685032844543457 0.50898098945617676 +-0.77728164196014404 1.0767006874084473 0.39583823084831238 +-0.85402011871337891 1.1348419189453125 0.57822656631469727 +-0.99602615833282471 0.95371371507644653 0.47627106308937073 +-1.1490583419799805 0.81702953577041626 0.45545575022697449 +-1.116361141204834 0.90052616596221924 0.54254305362701416 +-1.0396225452423096 0.842384934425354 0.36015471816062927 +-0.777027428150177 0.93214833736419678 0.17549988627433777 +-0.60992759466171265 1.073641300201416 0.18642297387123108 +-0.6566925048828125 0.98533588647842407 0.10922792553901672 +-0.73343098163604736 1.0434770584106445 0.29161623120307922 +-0.49749571084976196 1.1740623712539673 0.20171591639518738 +-0.36165416240692139 1.3031482696533203 0.23199871182441711 +-0.39435148239135742 1.2196516990661621 0.14491137862205505 +-0.46012735366821289 1.2694870233535767 0.30124428868293762 +-0.53648459911346436 1.1107996702194214 0.15312507748603821 +-0.45507505536079407 1.0645865201950073 -0.016822189092636108 +-0.54725664854049683 1.0106912851333618 0.013926893472671509 +-0.41608613729476929 1.1278491020202637 0.031768620014190674 +-0.58033519983291626 1.1440231800079346 0.25734707713127136 +-0.6570737361907959 1.2021645307540894 0.43973544239997864 +-0.55860054492950439 1.235825777053833 0.37048986554145813 +-0.71163278818130493 1.0991415977478027 0.34967449307441711 +-0.86447441577911377 0.85404300689697266 0.16360536217689514 +-1.0393683910369873 0.69783252477645874 0.13981637358665466 +-0.99577200412750244 0.80916136503219604 0.25593277812004089 +-0.90807086229324341 0.74271416664123535 0.047488957643508911 +-1.134609580039978 0.60500967502593994 0.11505606770515442 +-1.2798476219177246 0.48304304480552673 0.10710647702217102 +-1.2471504211425781 0.56653964519500732 0.19419381022453308 +-1.1813745498657227 0.51670432090759277 0.0378609299659729 +-1.1050171852111816 0.67539167404174805 0.18598005175590515 +-1.1817557811737061 0.73353290557861328 0.36836841702461243 +-1.0614207983016968 0.78672051429748535 0.30209651589393616 +-1.2144529819488525 0.6500362753868103 0.28128114342689514 +-1.0611666440963745 0.64216810464859009 0.081758171319961548 +-1.0062898397445679 0.56450057029724121 -0.10360383987426758 +-1.0719386339187622 0.54205965995788574 -0.057440102100372314 +-0.92986905574798584 0.68704980611801147 -0.010569244623184204 +-0.53572213649749756 0.67714250087738037 -0.50788986682891846 +-0.45898360013961792 0.61900120973587036 -0.69027823209762573 +-0.55745679140090942 0.58533996343612671 -0.62103271484375 +-0.42628628015518188 0.70249783992767334 -0.60319089889526367 +-0.38853666186332703 0.58109396696090698 -0.83417010307312012 +-0.31646919250488281 0.5110245943069458 -1.0289995670318604 +-0.44776678085327148 0.4661429226398468 -0.93667209148406982 +-0.29473453760147095 0.60282713174819946 -0.91585671901702881 +-0.46981915831565857 0.5550309419631958 -0.77439188957214355 +-0.63381403684616089 0.42665261030197144 -0.76915180683135986 +-0.61201584339141846 0.48231703042984009 -0.71109366416931152 +-0.51341557502746582 0.4437021017074585 -0.89050835371017456 +-0.3823721706867218 0.63313615322113037 -0.7624974250793457 +-0.2434074878692627 0.76501166820526123 -0.73178982734680176 +-0.24017545580863953 0.70585006475448608 -0.82579576969146729 +-0.305951327085495 0.75568544864654541 -0.66946291923522949 +-0.27261859178543091 0.47780105471611023 -1.1332215070724487 +-0.18491742014884949 0.4113539457321167 -1.3416652679443359 +-0.31621497869491577 0.36647224426269531 -1.2493377923965454 +-0.14132100343704224 0.52268272638320923 -1.2255488634109497 +-0.14106684923171997 0.37813037633895874 -1.4458872079849243 +-0.075290977954864502 0.32829499244689941 -1.6022201776504517 +-0.16280150413513184 0.28632780909538269 -1.5590299367904663 +-0.031630992889404297 0.40348571538925171 -1.5411882400512695 +-0.20671564340591431 0.35568952560424805 -1.3997235298156738 +-0.35974788665771484 0.219005286693573 -1.4205389022827148 +-0.33801320195198059 0.31080782413482666 -1.3073960542678833 +-0.26127469539642334 0.25266653299331665 -1.4897844791412354 +-0.11926862597465515 0.43379479646682739 -1.3878289461135864 +0.033763587474822998 0.57047897577285767 -1.3670135736465454 +0.0010663270950317383 0.48698234558105469 -1.4541009664535522 +-0.0756722092628479 0.54512357711791992 -1.2717125415802002 +-0.33826738595962524 0.45536020398139954 -1.0870577096939087 +-0.5053672194480896 0.3138672411441803 -1.0979808568954468 +-0.45860233902931213 0.40217262506484985 -1.0207858085632324 +-0.3818638026714325 0.34403139352798462 -1.2031741142272949 +-0.61779910326004028 0.21344617009162903 -1.1132737398147583 +-0.75364065170288086 0.084360182285308838 -1.1435565948486328 +-0.72094333171844482 0.16785681247711182 -1.056469202041626 +-0.65516746044158936 0.11802148818969727 -1.2128021717071533 +-0.57881021499633789 0.27670884132385254 -1.0646829605102539 +-0.66021978855133057 0.3229219913482666 -0.89473569393157959 +-0.56803816556930542 0.3768172562122345 -0.92548477649688721 +-0.69920867681503296 0.25965934991836548 -0.94332647323608398 +-0.53495961427688599 0.24348527193069458 -1.1689049005508423 +-0.45822107791900635 0.18534398078918457 -1.3512933254241943 +-0.55669426918029785 0.15168273448944092 -1.2820477485656738 +-0.40366202592849731 0.28836697340011597 -1.2612323760986328 +-0.25082036852836609 0.53346550464630127 -1.0751632452011108 +-0.075926393270492554 0.68967598676681519 -1.0513741970062256 +-0.1195228099822998 0.57834714651107788 -1.1674906015396118 +-0.20722395181655884 0.64479434490203857 -0.95904684066772461 +0.019314765930175781 0.78249883651733398 -1.0266139507293701 +0.16455286741256714 0.9044654369354248 -1.0186643600463867 +0.1318555474281311 0.8209688663482666 -1.105751633644104 +0.066079676151275635 0.87080419063568115 -0.94941878318786621 +-0.01027756929397583 0.71211683750152588 -1.0975378751754761 +0.066460907459259033 0.65397560596466064 -1.2799263000488281 +-0.053874015808105469 0.60078799724578857 -1.2136543989181519 +0.099158227443695068 0.73747223615646362 -1.1928390264511108 +-0.054128170013427734 0.74534040689468384 -0.99331605434417725 +-0.10900497436523438 0.82300794124603271 -0.80795401334762573 +-0.043356180191040039 0.84544885158538818 -0.854117751121521 +-0.18542572855949402 0.70045870542526245 -0.90098857879638672 +0.050618588924407959 -0.21481770277023315 1.6222966909408569 +0.079385817050933838 -0.094437181949615479 1.4960787296295166 +-0.023881912231445312 -0.14816188812255859 1.5863606929779053 +0.14429718255996704 -0.20121988654136658 1.574087381362915 +0.098563998937606812 -0.014183461666107178 1.4119335412979126 +0.13692033290863037 0.14632391929626465 1.2436429262161255 +0.0056227743625640869 0.10144221782684326 1.335970401763916 +0.2298615574836731 0.030698239803314209 1.3196060657501221 +0.032915204763412476 -0.036624312400817871 1.4580972194671631 +-0.16329377889633179 0.025276690721511841 1.4724159240722656 +-0.09358784556388855 -0.061442583799362183 1.5293883085250854 +-0.060026019811630249 0.079001367092132568 1.3821340799331665 +0.14503461122512817 -0.071996331214904785 1.4499151706695557 +0.34124356508255005 -0.13389736413955688 1.435596227645874 +0.27633216977119446 -0.027114629745483398 1.3575875759124756 +0.24277037382125854 -0.16755861043930054 1.5048418045043945 +0.15609854459762573 0.22657763957977295 1.1594976186752319 +0.17970235645771027 0.37941005825996399 1.0041043758392334 +0.091187149286270142 0.33336037397384644 1.0814888477325439 +0.2873961329460144 0.27145934104919434 1.0671701431274414 +0.21842759847640991 0.48740214109420776 0.88602542877197266 +0.25198942422866821 0.62784618139266968 0.73877114057540894 +0.14872168004512787 0.57412141561508179 0.82905304431915283 +0.31690078973770142 0.52106344699859619 0.81677985191345215 +0.14798426628112793 0.44489789009094238 0.95322543382644653 +-0.034157115966081619 0.51160764694213867 0.95765197277069092 +-0.0065486282110214233 0.4289226233959198 1.0265620946884155 +0.022218633443117142 0.54930317401885986 0.90034419298171997 +0.26010367274284363 0.40952590107917786 0.94504326581954956 +0.46110719442367554 0.36768832802772522 0.90968823432922363 +0.41463658213615417 0.42550116777420044 0.87170660495758057 +0.35304492712020874 0.29390019178390503 1.0210064649581909 +0.090449720621109009 0.20413678884506226 1.2056612968444824 +-0.13378909230232239 0.2748807966709137 1.2220256328582764 +-0.040847837924957275 0.15925508737564087 1.2979887723922729 +-0.0024915337562561035 0.31976249814033508 1.1296981573104858 +-0.25987076759338379 0.32390457391738892 1.2223609685897827 +-0.44211748242378235 0.37215381860733032 1.2445263862609863 +-0.37241154909133911 0.2854345440864563 1.3014987707138062 +-0.34364429116249084 0.40581509470939636 1.1752808094024658 +-0.19943788647651672 0.252439945936203 1.2681893110275269 +-0.23299969732761383 0.11199596524238586 1.4154435396194458 +-0.10649663209915161 0.13681423664093018 1.3441524505615234 +-0.30270561575889587 0.19871525466442108 1.358471155166626 +-0.18025970458984375 0.33269363641738892 1.1840440034866333 +-0.17472772300243378 0.48198065161705017 1.0388352870941162 +-0.2403765469789505 0.45953977108001709 1.0849989652633667 +-0.048962153494358063 0.3775753378868103 1.0917165279388428 +0.20256915688514709 0.16876477003097534 1.197479248046875 +0.41284570097923279 0.11167249083518982 1.17326819896698 +0.32907217741012573 0.19358304142951965 1.1261880397796631 +0.29551038146018982 0.053139090538024902 1.2734423875808716 +0.55699920654296875 0.06619417667388916 1.1627483367919922 +0.73513633012771606 0.00074774026870727539 1.1586140394210815 +0.66543042659759521 0.087467014789581299 1.1016416549682617 +0.63666313886642456 -0.032913565635681152 1.2278596162796021 +0.49245676398277283 0.12046164274215698 1.134951114654541 +0.53597652912139893 0.24851712584495544 0.99583584070205688 +0.43233993649482727 0.24730771780014038 1.035906195640564 +0.60051906108856201 0.19424974918365479 1.0236330032348633 +0.47327858209609985 0.040207922458648682 1.2190964221954346 +0.43971675634384155 -0.10023605823516846 1.3663506507873535 +0.53818994760513306 -0.066574811935424805 1.2971051931381226 +0.34198099374771118 -0.0046737790107727051 1.3114240169525146 +0.2711675763130188 0.70809978246688843 0.65462583303451538 +0.3047294020652771 0.84854382276535034 0.50737154483795166 +0.2062562108039856 0.81488251686096191 0.57661712169647217 +0.37443533539772034 0.76182454824447632 0.56434392929077148 +0.34345465898513794 0.9565359354019165 0.38929253816604614 +0.36705845594406128 1.1093683242797852 0.23389936983585358 +0.23576086759567261 1.0644866228103638 0.32622683048248291 +0.43196985125541687 1.0025856494903564 0.3119080662727356 +0.26305332779884338 0.92642009258270264 0.44835370779037476 +0.062049821019172668 0.96825766563415527 0.48370876908302307 +0.10852041840553284 0.91044479608535767 0.52169036865234375 +0.17011207342147827 1.0420458316802979 0.37239056825637817 +0.37517273426055908 0.89104807376861572 0.44017153978347778 +0.55731409788131714 0.82433831691741943 0.4357450008392334 +0.52970564365386963 0.90702331066131592 0.36683487892150879 +0.50093835592269897 0.78664278984069824 0.49305281043052673 +0.38623669743537903 1.1896220445632935 0.14975407719612122 +0.4245930016040802 1.3501293659210205 -0.018536478281021118 +0.2932954728603363 1.3052477836608887 0.073790937662124634 +0.51753425598144531 1.2345037460327148 0.057426661252975464 +0.44377118349075317 1.4303832054138184 -0.10268178582191467 +0.47253841161727905 1.5507636070251465 -0.228899747133255 +0.37885981798171997 1.5371658802032471 -0.18069043755531311 +0.54703891277313232 1.4841078519821167 -0.19296365976333618 +0.37812238931655884 1.4079422950744629 -0.056518077850341797 +0.18191343545913696 1.4698433876037598 -0.042199313640594482 +0.24682486057281494 1.3630605936050415 0.035809338092803955 +0.28038662672042847 1.5035045146942139 -0.11144489049911499 +0.49024179577827454 1.372570276260376 -0.064700186252593994 +0.6864507794380188 1.3106693029403687 -0.079018920660018921 +0.61674487590789795 1.3973885774612427 -0.13599130511283875 +0.58318305015563965 1.2569446563720703 0.011262953281402588 +0.32058784365653992 1.1671812534332275 0.19591778516769409 +0.11031129956245422 1.2242734432220459 0.22012874484062195 +0.19408482313156128 1.1423629522323608 0.26720890402793884 +0.22764661908149719 1.2828068733215332 0.11995464563369751 +-0.033842235803604126 1.2697517871856689 0.23064863681793213 +-0.21197932958602905 1.3351981639862061 0.23478296399116516 +-0.1422734260559082 1.248478889465332 0.2917553186416626 +-0.11350613832473755 1.3688595294952393 0.16553738713264465 +0.030700236558914185 1.2154843807220459 0.25844582915306091 +-0.012819558382034302 1.0874288082122803 0.39756113290786743 +0.090817064046859741 1.0886383056640625 0.35749080777168274 +-0.077362060546875 1.1416962146759033 0.36976402997970581 +0.049878418445587158 1.2957379817962646 0.17430049180984497 +0.083440244197845459 1.4361820220947266 0.027046263217926025 +-0.015032947063446045 1.4025207757949829 0.096291810274124146 +0.18117600679397583 1.3406198024749756 0.081973046064376831 +0.43270730972290039 1.1318092346191406 0.1877356618642807 +0.65694606304168701 1.0610651969909668 0.17137141525745392 +0.56400483846664429 1.1766908168792725 0.095408245921134949 +0.52564859390258789 1.0161834955215454 0.26369881629943848 +0.7830277681350708 1.012041449546814 0.17103594541549683 +0.96527445316314697 0.96379214525222778 0.14887054264545441 +0.89556854963302612 1.0505114793777466 0.091898173093795776 +0.86680126190185547 0.93013083934783936 0.21811611950397491 +0.72259485721588135 1.0835059881210327 0.12520770728588104 +0.75615668296813965 1.2239500284194946 -0.022046566009521484 +0.62965363264083862 1.1991317272186279 0.049244537949562073 +0.82586264610290527 1.1372307538986206 0.034925803542137146 +0.70341670513153076 1.0032522678375244 0.20935298502445221 +0.69788467884063721 0.85396528244018555 0.35456171631813049 +0.76353353261947632 0.87640613317489624 0.30839797854423523 +0.57211917638778687 0.9583706259727478 0.30168038606643677 +0.20551879703998566 0.68565899133682251 0.70078951120376587 +0.0093098282814025879 0.74755996465682983 0.71510827541351318 +0.079015746712684631 0.66084069013595581 0.77208065986633301 +0.10778301954269409 0.78122127056121826 0.64586269855499268 +-0.14480170607566833 0.80542671680450439 0.71748930215835571 +-0.35507827997207642 0.8625190258026123 0.74170029163360596 +-0.2621370255947113 0.74689328670501709 0.81766343116760254 +-0.2285752147436142 0.887337327003479 0.67040914297103882 +-0.084368802607059479 0.73396217823028564 0.7633175253868103 +-0.089900776743888855 0.584675133228302 0.90852624177932739 +-0.024251986294984818 0.6071159839630127 0.8623625636100769 +-0.21566641330718994 0.68908047676086426 0.85564500093460083 +-0.065190643072128296 0.81421589851379395 0.67917221784591675 +-0.02167084813117981 0.94227135181427002 0.54005688428878784 +-0.12530750036239624 0.94106197357177734 0.58012723922729492 +0.042871624231338501 0.88800400495529175 0.56785404682159424 +-0.4671977162361145 0.89789104461669922 0.74988234043121338 +-0.6914365291595459 0.96863502264022827 0.76624667644500732 +-0.5984952449798584 0.85300934314727783 0.84220981597900391 +-0.56013894081115723 1.0135166645050049 0.6739192008972168 +-0.80355590581893921 1.00400710105896 0.77442878484725952 +-0.97173506021499634 1.0570650100708008 0.78670203685760498 +-0.93005895614624023 0.97918879985809326 0.84571987390518188 +-0.90129166841506958 1.0995693206787109 0.71950197219848633 +-0.75708532333374023 0.94619417190551758 0.81241035461425781 +-0.79064708948135376 0.80575025081634521 0.95966458320617676 +-0.66414403915405273 0.83056849241256714 0.88837349414825439 +-0.86035299301147461 0.89246952533721924 0.90269219875335693 +-0.73790711164474487 1.0264478921890259 0.72826510667800903 +-0.70434528589248657 1.1668918132781982 0.58101081848144531 +-0.80281847715377808 1.1332306861877441 0.65025639533996582 +-0.60660958290100098 1.0713295936584473 0.63593763113021851 +-0.42072710394859314 0.84007817506790161 0.78786396980285645 +-0.44433087110519409 0.68724572658538818 0.94325709342956543 +-0.35581567883491516 0.73329544067382812 0.86587262153625488 +-0.55202466249465942 0.79519647359848022 0.88019144535064697 +-0.46898853778839111 0.58406239748001099 1.0514439344406128 +-0.51182341575622559 0.45887309312820435 1.1875541210174561 +-0.41335019469261169 0.49253436923027039 1.1183085441589355 +-0.58152931928634644 0.54559236764907837 1.1305817365646362 +-0.41261279582977295 0.62175792455673218 0.99413615465164185 +-0.2304714173078537 0.55504816770553589 0.98970955610275269 +-0.25807994604110718 0.63773322105407715 0.92079949378967285 +-0.28684717416763306 0.5173526406288147 1.0470174551010132 +-0.52473223209381104 0.65712988376617432 1.002318263053894 +-0.72094118595123291 0.71903097629547119 1.0166369676589966 +-0.65123522281646729 0.63231164216995239 1.0736093521118164 +-0.61767345666885376 0.77275562286376953 0.92635512351989746 +-0.40154889225959778 0.92033189535140991 0.70371866226196289 +-0.36319249868392944 1.0808392763137817 0.53542804718017578 +-0.4944901168346405 1.0359575748443604 0.62775552272796631 +-0.27025127410888672 0.9652135968208313 0.61139118671417236 +-0.32926180958747864 1.1687679290771484 0.43838536739349365 +-0.31045252084732056 1.301537036895752 0.30402854084968567 +-0.40892571210861206 1.2678756713867188 0.37327411770820618 +-0.24074661731719971 1.2148177623748779 0.36100089550018311 +-0.40966314077377319 1.1386520862579346 0.49744647741317749 +-0.60587209463119507 1.2005531787872314 0.5117652416229248 +-0.54096072912216187 1.0937705039978027 0.58977395296096802 +-0.50739890336990356 1.2342144250869751 0.44251969456672668 +-0.2975437343120575 1.1032800674438477 0.48926433920860291 +-0.096540212631225586 1.0614426136016846 0.45390930771827698 +-0.14301085472106934 1.1192554235458374 0.4159277081489563 +-0.20460250973701477 0.98765444755554199 0.56522750854492188 +0.31763821840286255 0.6502869725227356 0.69260746240615845 +0.51384717226028442 0.58838599920272827 0.67828869819641113 +0.44414123892784119 0.67510527372360229 0.62131631374359131 +0.41537398099899292 0.55472469329833984 0.74753427505493164 +0.66795873641967773 0.53051924705505371 0.6759076714515686 +0.87823528051376343 0.4734269380569458 0.65169674158096313 +0.7852940559387207 0.58905267715454102 0.57573354244232178 +0.7517322301864624 0.44860866665840149 0.7229878306388855 +0.60752582550048828 0.60198378562927246 0.63007944822311401 +0.61305779218673706 0.7512708306312561 0.48487070202827454 +0.54740899801254272 0.72882997989654541 0.53103440999984741 +0.73882341384887695 0.64686548709869385 0.53775197267532349 +0.5883476734161377 0.52173006534576416 0.71422475576400757 +0.54482781887054443 0.3936745822429657 0.85334008932113647 +0.64846450090408325 0.39488399028778076 0.81326973438262939 +0.48028537631034851 0.44794195890426636 0.82554292678833008 +0.99035477638244629 0.43805491924285889 0.64351463317871094 +1.2145935297012329 0.36731094121932983 0.62715029716491699 +1.1216522455215454 0.48293662071228027 0.55118715763092041 +1.0832959413528442 0.32242923974990845 0.71947777271270752 +1.3267128467559814 0.33193892240524292 0.61896824836730957 +1.4948921203613281 0.27888089418411255 0.60669493675231934 +1.4532159566879272 0.35675716400146484 0.54767709970474243 +1.4244487285614014 0.23637658357620239 0.67389500141143799 +1.2802423238754272 0.38975179195404053 0.5809866189956665 +1.3138041496276855 0.53019571304321289 0.43373236060142517 +1.1873010396957397 0.50537747144699097 0.50502347946166992 +1.3835099935531616 0.44347646832466125 0.490704745054245 +1.2610640525817871 0.30949807167053223 0.66513192653656006 +1.2275023460388184 0.16905409097671509 0.812386155128479 +1.3259754180908203 0.20271533727645874 0.7431405782699585 +1.129766583442688 0.26461637020111084 0.75745934247970581 +0.94388413429260254 0.49586778879165649 0.60553300380706787 +0.9674878716468811 0.64870023727416992 0.4501398503780365 +0.87897264957427979 0.60265052318572998 0.52752435207366943 +1.0751817226409912 0.54074949026107788 0.51320558786392212 +0.99214553833007812 0.75188356637954712 0.34195303916931152 +1.0349804162979126 0.87707287073135376 0.20584289729595184 +0.93650722503662109 0.84341156482696533 0.27508848905563354 +1.1046862602233887 0.79035359621047974 0.26281526684761047 +0.93576979637145996 0.71418803930282593 0.39926087856292725 +0.7536284327507019 0.78089779615402222 0.40368738770484924 +0.78123694658279419 0.69821274280548096 0.47259747982025146 +0.81000417470932007 0.81859332323074341 0.34637954831123352 +1.047889232635498 0.67881608009338379 0.39107871055603027 +1.2440981864929199 0.61691498756408691 0.37676000595092773 +1.1743922233581543 0.70363432168960571 0.31978762149810791 +1.1408305168151855 0.56319034099578857 0.46704190969467163 +0.9247058629989624 0.41561406850814819 0.68967831134796143 +0.88634955883026123 0.25510668754577637 0.85796892642974854 +1.0176471471786499 0.29998838901519775 0.76564145088195801 +0.79340827465057373 0.37073236703872681 0.78200578689575195 +0.85241878032684326 0.16717803478240967 0.95501160621643066 +0.83360952138900757 0.034408986568450928 1.089368462562561 +0.93208271265029907 0.068070292472839355 1.0201228857040405 +0.76390361785888672 0.12112826108932495 1.0323960781097412 +0.93282014131546021 0.19729381799697876 0.89595049619674683 +1.1290290355682373 0.13539278507232666 0.88163173198699951 +1.0641176700592041 0.24217551946640015 0.80362308025360107 +1.0305559635162354 0.10173153877258301 0.95087730884552002 +0.82070076465606689 0.23266583681106567 0.90413260459899902 +0.6196972131729126 0.27450340986251831 0.93948769569396973 +0.66616785526275635 0.2166905403137207 0.97746926546096802 +0.72775948047637939 0.34829151630401611 0.82816946506500244 +-1.5387426614761353 -0.24565732479095459 -0.50247311592102051 +-1.4363393783569336 -0.24887996912002563 -0.3584134578704834 +-1.5231125354766846 -0.16162359714508057 -0.43939569592475891 +-1.486103892326355 -0.33183950185775757 -0.46951067447662354 +-1.3680704832077026 -0.25102841854095459 -0.26237359642982483 +-1.2315329313278198 -0.2553253173828125 -0.070294082164764404 +-1.3244740962982178 -0.13969963788986206 -0.14625722169876099 +-1.2751293182373047 -0.36665409803390503 -0.18641045689582825 +-1.4145411252975464 -0.19321554899215698 -0.30035519599914551 +-1.4577178955078125 0.0053696632385253906 -0.26522108912467957 +-1.490415096282959 -0.078126966953277588 -0.35230839252471924 +-1.3709447383880615 -0.081886768341064453 -0.18423882126808167 +-1.3898687362670898 -0.30669283866882324 -0.32043185830116272 +-1.3466920852661133 -0.50527811050415039 -0.35556593537330627 +-1.2969275712966919 -0.42231851816177368 -0.24446871876716614 +-1.4163979291915894 -0.41855880618095398 -0.4125383198261261 +-1.1632640361785889 -0.25747376680374146 0.025745734572410583 +-1.0391225814819336 -0.24930541217327118 0.20625640451908112 +-1.1134995222091675 -0.17451420426368713 0.1368429958820343 +-1.0703228712081909 -0.37309947609901428 0.10170890390872955 +-0.94139039516448975 -0.26445615291595459 0.33787503838539124 +-0.82191997766494751 -0.26821592450141907 0.50594460964202881 +-0.90869307518005371 -0.18095953762531281 0.4249623715877533 +-0.8716844916343689 -0.35117542743682861 0.39484739303588867 +-1.0049282312393188 -0.20610621571540833 0.27588349580764771 +-1.03814697265625 -0.019909441471099854 0.31915652751922607 +-1.086970329284668 -0.062648296356201172 0.22894947230815887 +-0.98456716537475586 -0.065870940685272217 0.37300911545753479 +-0.98025578260421753 -0.3195834755897522 0.25580686330795288 +-0.92001187801361084 -0.51870578527450562 0.24468272924423218 +-0.89821368455886841 -0.46304139494895935 0.30274093151092529 +-1.0238522291183472 -0.4309123158454895 0.13969047367572784 +-1.2097346782684326 -0.19966089725494385 -0.012235850095748901 +-1.2590794563293457 0.027293652296066284 0.027917414903640747 +-1.3026759624481201 -0.084035217761993408 -0.088198989629745483 +-1.1661382913589478 -0.088332027196884155 0.10388055443763733 +-1.2799620628356934 0.15675181150436401 0.061152100563049316 +-1.3269286155700684 0.33935615420341492 0.083128184080123901 +-1.3596259355545044 0.25585955381393433 -0.0039591491222381592 +-1.2572226524353027 0.25263687968254089 0.14010053873062134 +-1.3055500984191895 0.085106521844863892 -0.010064184665679932 +-1.4250204563140869 0.088866293430328369 -0.1781337559223175 +-1.3491466045379639 -0.026222348213195801 -0.12618058919906616 +-1.3923232555389404 0.17236292362213135 -0.091046452522277832 +-1.237281322479248 0.082958042621612549 0.085975617170333862 +-1.1239789724349976 0.10756760835647583 0.25906440615653992 +-1.1704496145248413 0.16538047790527344 0.22108280658721924 +-1.1443400382995605 -0.032667636871337891 0.16193875670433044 +-1.1850622892379761 -0.31313818693161011 -0.032312497496604919 +-1.1319276094436646 -0.52411186695098877 -0.059307664632797241 +-1.1091881990432739 -0.4282267689704895 0.019640728831291199 +-1.2286586761474609 -0.42446696758270264 -0.14842887222766876 +-1.1002058982849121 -0.67001122236251831 -0.085120469331741333 +-1.0678683519363403 -0.85215520858764648 -0.12767647206783295 +-1.0351710319519043 -0.76865857839584351 -0.040589146316051483 +-1.1375741958618164 -0.76543593406677246 -0.18464884161949158 +-1.0892467498779297 -0.59790551662445068 -0.034484133124351501 +-0.97444748878479004 -0.61359339952468872 0.12114442139863968 +-1.0224151611328125 -0.51548314094543457 0.10062302649021149 +-0.98540651798248291 -0.68569904565811157 0.070508092641830444 +-1.1575156450271606 -0.5957571268081665 -0.13052396476268768 +-1.2769861221313477 -0.59199738502502441 -0.29859358072280884 +-1.207280158996582 -0.67871665954589844 -0.24162121117115021 +-1.2504569292068481 -0.48013138771057129 -0.20648713409900665 +-0.75365108251571655 -0.27036437392234802 0.60198450088500977 +-0.63418066501617432 -0.2741241455078125 0.77005410194396973 +-0.70388656854629517 -0.18740485608577728 0.7130817174911499 +-0.66687798500061035 -0.35762077569961548 0.68296670913696289 +-0.53644847869873047 -0.28927487134933472 0.90167272090911865 +-0.41230696439743042 -0.28110656142234802 1.0821833610534668 +-0.50524818897247314 -0.1654808521270752 1.0062202215194702 +-0.46207147836685181 -0.36406606435775757 0.97108614444732666 +-0.59531527757644653 -0.21899683773517609 0.85212224721908569 +-0.65555918216705322 -0.019874505698680878 0.8632463812828064 +-0.67735737562179565 -0.075538910925388336 0.80518823862075806 +-0.55171883106231689 -0.10766799747943878 0.96823865175247192 +-0.57064282894134521 -0.33247411251068115 0.83204561471939087 +-0.53742408752441406 -0.51867085695266724 0.7887725830078125 +-0.48860073089599609 -0.47593200206756592 0.87897962331771851 +-0.5910038948059082 -0.47270935773849487 0.73492002487182617 +-0.34403815865516663 -0.28325501084327698 1.1782232522964478 +-0.20750054717063904 -0.2875518798828125 1.3703027963638306 +-0.30044177174568176 -0.17192620038986206 1.294339656829834 +-0.2510969340801239 -0.39888069033622742 1.2541863918304443 +-0.13923168182373047 -0.28970032930374146 1.4663426876068115 +-0.036828398704528809 -0.2929229736328125 1.6104021072387695 +-0.089467167854309082 -0.20674079656600952 1.5774397850036621 +-0.052458584308624268 -0.37695670127868652 1.5473247766494751 +-0.18570229411125183 -0.23188745975494385 1.4283610582351685 +-0.22887903451919556 -0.033302217721939087 1.463495135307312 +-0.27864351868629456 -0.11626178026199341 1.3523979187011719 +-0.15917310118675232 -0.12002149224281311 1.5204675197601318 +-0.16102993488311768 -0.34536474943161011 1.4082844257354736 +-0.11785322427749634 -0.54394996166229248 1.3731502294540405 +-0.085155904293060303 -0.4604533314704895 1.4602375030517578 +-0.20462632179260254 -0.45669355988502502 1.2921679019927979 +-0.39050877094268799 -0.22544214129447937 1.1402416229248047 +-0.44364351034164429 -0.014468461275100708 1.1672368049621582 +-0.46638283133506775 -0.11035354435443878 1.088288426399231 +-0.34691238403320312 -0.11411333084106445 1.2563580274581909 +-0.47536516189575195 0.13143090903759003 1.1930495500564575 +-0.50770270824432373 0.31357491016387939 1.2356055974960327 +-0.54040002822875977 0.23007827997207642 1.1485182046890259 +-0.43799680471420288 0.22685562074184418 1.2925779819488525 +-0.4863242506980896 0.059325233101844788 1.1424132585525513 +-0.60112357139587402 0.075013101100921631 0.98678469657897949 +-0.55315595865249634 -0.02309715747833252 1.0073060989379883 +-0.59016454219818115 0.14711874723434448 1.0374209880828857 +-0.41805538535118103 0.057176798582077026 1.2384531497955322 +-0.29858493804931641 0.053417056798934937 1.4065227508544922 +-0.36829087138175964 0.14013634622097015 1.3495503664016724 +-0.32511413097381592 -0.058448910713195801 1.3144162893295288 +-0.36583635210990906 -0.33891943097114563 1.1201649904251099 +-0.31649157404899597 -0.56587398052215576 1.0800117254257202 +-0.27289512753486633 -0.45454511046409607 1.1961281299591064 +-0.4094327986240387 -0.45024827122688293 1.0040485858917236 +-0.29560902714729309 -0.6953321099281311 1.0467770099639893 +-0.2486424446105957 -0.87793648242950439 1.0248008966445923 +-0.21594512462615967 -0.79443985223770142 1.1118882894515991 +-0.31834834814071655 -0.79121720790863037 0.96782857179641724 +-0.27002096176147461 -0.62368679046630859 1.1179933547973633 +-0.15055054426193237 -0.62744659185409546 1.2860628366470337 +-0.22642451524734497 -0.51235795021057129 1.23410964012146 +-0.18324780464172363 -0.71094322204589844 1.1989755630493164 +-0.3382897675037384 -0.62153834104537964 1.0219534635543823 +-0.4515920877456665 -0.64614790678024292 0.84886467456817627 +-0.40512144565582275 -0.70396077632904053 0.88684630393981934 +-0.43123099207878113 -0.5059126615524292 0.94599032402038574 +-0.8001217246055603 -0.21255150437355042 0.5640028715133667 +-0.84329843521118164 -0.013966292142868042 0.59913694858551025 +-0.87599575519561768 -0.097462907433509827 0.51204967498779297 +-0.77359253168106079 -0.10068558156490326 0.65610933303833008 +-0.87034904956817627 0.14386115968227386 0.6373908519744873 +-0.92348378896713257 0.35483482480049133 0.66438603401184082 +-0.96708023548126221 0.24350598454475403 0.54826962947845459 +-0.8476097583770752 0.23974622786045074 0.71633923053741455 +-0.89593720436096191 0.072215870022773743 0.56617456674575806 +-1.0092394351959229 0.047606319189071655 0.39308580756187439 +-0.96276891231536865 -0.010206520557403564 0.43106737732887268 +-0.98887842893600464 0.18784157931804657 0.49021142721176147 +-0.82766836881637573 0.070067420601844788 0.66221433877944946 +-0.71286892890930176 0.05437958613038063 0.81784290075302124 +-0.76083660125732422 0.15248984098434448 0.79732155799865723 +-0.7238280177116394 -0.017726056277751923 0.76720660924911499 +-0.94815623760223389 0.46831211447715759 0.68446266651153564 +-0.99750101566314697 0.69526660442352295 0.72461593151092529 +-1.0410974025726318 0.58393776416778564 0.60849952697753906 +-0.90455985069274902 0.57964092493057251 0.80057907104492188 +-1.0221734046936035 0.80874389410018921 0.74469262361526489 +-1.0591820478439331 0.97895979881286621 0.77480745315551758 +-1.0980474948883057 0.92383253574371338 0.69273936748504639 +-0.995644211769104 0.92060989141464233 0.83679908514022827 +-1.0439716577529907 0.75307947397232056 0.686634361743927 +-1.1634421348571777 0.75683927536010742 0.51856470108032227 +-1.0875680446624756 0.64175069332122803 0.57051795721054077 +-1.1307446956634521 0.8403359055519104 0.6056520938873291 +-0.97570276260375977 0.7509310245513916 0.78267419338226318 +-0.85623234510421753 0.74717128276824951 0.95074379444122314 +-0.92593824863433838 0.83389055728912354 0.89377140998840332 +-0.88276159763336182 0.63530534505844116 0.85863733291625977 +-0.96995437145233154 0.41264769434928894 0.62640440464019775 +-1.0940958261489868 0.40447938442230225 0.445893794298172 +-1.0197188854217529 0.32968819141387939 0.51530718803405762 +-1.062895655632019 0.52827334403991699 0.55044126510620117 +-1.1818701028823853 0.40724164247512817 0.32241404056549072 +-1.2942312955856323 0.4228527843952179 0.17021545767784119 +-1.2245254516601562 0.33613350987434387 0.22718781232833862 +-1.2615339756011963 0.50634938478469849 0.25730279088020325 +-1.1282902956008911 0.36128014326095581 0.37626668810844421 +-1.09507155418396 0.17508339881896973 0.33299362659454346 +-1.046248197555542 0.21782225370407104 0.42320069670677185 +-1.1486513614654541 0.22104489803314209 0.27914106845855713 +-1.1529626846313477 0.47475740313529968 0.39634329080581665 +-1.1961393356323242 0.67334264516830444 0.43147739768028259 +-1.2288366556167603 0.58984601497650146 0.34439012408256531 +-1.1093661785125732 0.58608627319335938 0.51245969533920288 +-0.90168559551239014 0.41049924492835999 0.72244429588317871 +-0.76514792442321777 0.40620234608650208 0.91452383995056152 +-0.85808920860290527 0.5218280553817749 0.83856070041656494 +-0.80874431133270264 0.29487353563308716 0.79840743541717529 +-0.68448293209075928 0.39158874750137329 1.0221325159072876 +-0.57740867137908936 0.40029418468475342 1.1786333322525024 +-0.64711457490921021 0.48701345920562744 1.1216609477996826 +-0.61010599136352539 0.31679755449295044 1.0915459394454956 +-0.74334967136383057 0.46186676621437073 0.97258210182189941 +-0.78652644157409668 0.66045200824737549 1.007716178894043 +-0.83629095554351807 0.57749247550964355 0.89661896228790283 +-0.71682047843933105 0.57373273372650146 1.0646885633468628 +-0.7186773419380188 0.34838950634002686 0.95250540971755981 +-0.65843337774276733 0.14926716685295105 0.94138115644454956 +-0.6366351842880249 0.20493161678314209 0.99943941831588745 +-0.76227372884750366 0.23706068098545074 0.83638900518417358 +-0.77544933557510376 -0.32602879405021667 0.54392623901367188 +-0.73227262496948242 -0.52461397647857666 0.50879216194152832 +-0.69957530498504639 -0.44111740589141846 0.59587943553924561 +-0.80197852849960327 -0.43789470195770264 0.4518197774887085 +-0.70522201061248779 -0.68244147300720215 0.47053828835487366 +-0.65208727121353149 -0.89341515302658081 0.44354307651519775 +-0.60849082469940186 -0.78208625316619873 0.55965948104858398 +-0.72796130180358887 -0.77832651138305664 0.39158987998962402 +-0.67963385581970215 -0.61079621315002441 0.54175454378128052 +-0.56633156538009644 -0.58618664741516113 0.7148432731628418 +-0.61280214786529541 -0.52837377786636353 0.67686176300048828 +-0.58669263124465942 -0.72642189264297485 0.6177176833152771 +-0.74790269136428833 -0.60864770412445068 0.44571477174758911 +-0.8627021312713623 -0.59295988082885742 0.29008620977401733 +-0.81473445892333984 -0.69107019901275635 0.31060755252838135 +-0.85174304246902466 -0.52085423469543457 0.34072250127792358 +-0.62741482257843018 -1.0068924427032471 0.42346644401550293 +-0.57807004451751709 -1.23384690284729 0.38331320881843567 +-0.53447365760803223 -1.1225180625915527 0.49942958354949951 +-0.67101120948791504 -1.1182212829589844 0.30735006928443909 +-0.55339765548706055 -1.3473241329193115 0.36323654651641846 +-0.51638901233673096 -1.5175400972366333 0.33312162756919861 +-0.47752362489700317 -1.4624128341674805 0.41518977284431458 +-0.57992684841156006 -1.4591901302337646 0.27113008499145508 +-0.53159940242767334 -1.2916598320007324 0.42129480838775635 +-0.4121289849281311 -1.2954195737838745 0.58936440944671631 +-0.48800301551818848 -1.1803309917449951 0.53741121292114258 +-0.44482630491256714 -1.3789162635803223 0.50227707624435425 +-0.5998682975769043 -1.2895113229751587 0.32525494694709778 +-0.71933871507644653 -1.2857515811920166 0.15718534588813782 +-0.64963281154632568 -1.3724708557128906 0.21415773034095764 +-0.69280946254730225 -1.1738855838775635 0.2492918074131012 +-0.60561668872833252 -0.95122802257537842 0.48152467608451843 +-0.48147520422935486 -0.94305968284606934 0.66203534603118896 +-0.55585217475891113 -0.86826848983764648 0.59262192249298096 +-0.51267540454864502 -1.0668537616729736 0.5574878454208374 +-0.3937009871006012 -0.94582194089889526 0.78551506996154785 +-0.28133976459503174 -0.9614330530166626 0.937713623046875 +-0.35104566812515259 -0.87471377849578857 0.88074129819869995 +-0.31403708457946777 -1.0449297428131104 0.85062634944915771 +-0.44728079438209534 -0.8998604416847229 0.73166239261627197 +-0.48049953579902649 -0.71366369724273682 0.77493548393249512 +-0.52932286262512207 -0.75640255212783813 0.68472838401794434 +-0.42691969871520996 -0.75962519645690918 0.82878804206848145 +-0.42260837554931641 -1.0133377313613892 0.71158581972122192 +-0.37943166494369507 -1.2119228839874268 0.67645168304443359 +-0.34673440456390381 -1.1284263134002686 0.76353901624679565 +-0.46620482206344604 -1.1246665716171265 0.59546941518783569 +-0.67388546466827393 -0.94907957315444946 0.38548487424850464 +-0.81042313575744629 -0.94478261470794678 0.19340531527996063 +-0.71748185157775879 -1.060408353805542 0.26936846971511841 +-0.76682674884796143 -0.83345389366149902 0.30952167510986328 +-0.89108812808990479 -0.93016904592514038 0.085796624422073364 +-0.99816238880157471 -0.93887448310852051 -0.070704109966754913 +-0.92845648527145386 -1.0255937576293945 -0.01373174786567688 +-0.96546506881713867 -0.85537785291671753 0.016383221372961998 +-0.8322213888168335 -1.0004470348358154 0.13534705340862274 +-0.78904461860656738 -1.1990323066711426 0.10021299123764038 +-0.739280104637146 -1.1160727739334106 0.21131022274494171 +-0.85875058174133301 -1.1123130321502686 0.04324062168598175 +-0.85689371824264526 -0.88696980476379395 0.15542374551296234 +-0.91713768243789673 -0.68784743547439575 0.16654789447784424 +-0.93893587589263916 -0.7435118556022644 0.10848966240882874 +-0.8132973313331604 -0.77564102411270142 0.27154010534286499 +0.32186204195022583 0.27074575424194336 -1.2158404588699341 +1.2594916820526123 0.2412382960319519 0.10320591926574707 +1.1633011102676392 -0.16128414869308472 0.52524715662002563 +-0.037728846073150635 -1.234011173248291 0.36188369989395142 +-0.11673936247825623 -0.12100091576576233 -1.2754988670349121 +-0.38013964891433716 -1.2232353687286377 -0.11981585621833801 +0.72377055883407593 0.20036357641220093 -0.67850559949874878 +0.88286131620407104 0.19535696506500244 -0.4546985924243927 +0.68714118003845215 -0.62366074323654175 0.40403416752815247 +0.48335841298103333 -0.80567389726638794 0.37631574273109436 +-0.16137658059597015 -0.58765953779220581 -0.81132179498672485 +-0.21334934234619141 -0.7837483286857605 -0.60380458831787109 +0.51489925384521484 0.25630629062652588 -0.94834411144256592 +0.21346095204353333 0.30277261137962341 -1.3544274568557739 +1.0701167583465576 0.23883345723152161 -0.16727058589458466 +1.3553637266159058 0.26683661341667175 0.25198802351951599 +0.92163574695587158 -0.38250574469566345 0.48419803380966187 +1.2829961776733398 -0.035995721817016602 0.56950497627258301 +0.21044564247131348 -1.0177211761474609 0.38746234774589539 +-0.17969167232513428 -1.3424282073974609 0.37055101990699768 +-0.11651483178138733 0.0080472826957702637 -1.3993105888366699 +-0.16213186085224152 -0.34839925169944763 -1.0404335260391235 +-0.2862250804901123 -1.0017054080963135 -0.36747244000434875 +-0.43729981780052185 -1.3343212604522705 0.0081509053707122803 +0.43554228544235229 0.25220012664794922 -1.06319260597229 +1.1612615585327148 0.22892135381698608 -0.042473137378692627 +1.0277068614959717 -0.29200753569602966 0.49216952919960022 +0.10951328277587891 -1.1121127605438232 0.36727732419967651 +-0.13286320865154266 -0.25548407435417175 -1.1405068635940552 +-0.33423405885696411 -1.0981478691101074 -0.2569812536239624 +0.11645561456680298 0.29456794261932373 -1.4963657855987549 +0.31183308362960815 0.22307547926902771 -1.2532756328582764 +1.2905306816101074 0.19227558374404907 0.1235446035861969 +1.4572980403900146 0.25237125158309937 0.38991555571556091 +1.4147891998291016 0.074487447738647461 0.57642507553100586 +1.208274245262146 -0.15193754434585571 0.48444902896881104 +-0.30272454023361206 -1.4595487117767334 0.34280985593795776 +-0.045360445976257324 -1.2716495990753174 0.31393030285835266 +-0.45404362678527832 -1.4547865390777588 0.12993592023849487 +-0.33816969394683838 -1.2624349594116211 -0.097990334033966064 +-0.063232600688934326 -0.11192286014556885 -1.3042919635772705 +-0.077372252941131592 0.12144619226455688 -1.5227302312850952 +-0.30952394008636475 -0.86860722303390503 -0.48633527755737305 +0.61711347103118896 0.27466124296188354 -0.79406404495239258 +0.94606143236160278 0.27638423442840576 -0.32543399930000305 +0.77626490592956543 -0.49849110841751099 0.48551517724990845 +0.346824049949646 -0.87429982423782349 0.43890854716300964 +-0.22838559746742249 -0.47501367330551147 -0.8941643238067627 +0.61290103197097778 0.18196657299995422 -0.84511458873748779 +1.0089180469512939 0.18044683337211609 -0.28268307447433472 +0.84380918741226196 -0.4977869987487793 0.40394625067710876 +0.3292161226272583 -0.95037841796875 0.34465047717094421 +-0.12303169071674347 -0.45479279756546021 -0.95310699939727783 +-0.23529575765132904 -0.93492436408996582 -0.45062175393104553 +0.66215270757675171 0.13377659022808075 -0.79850035905838013 +0.98075699806213379 0.080958902835845947 -0.3710930347442627 +0.8119475245475769 -0.55620265007019043 0.35401296615600586 +0.43248945474624634 -0.92260962724685669 0.26056283712387085 +-0.037259325385093689 -0.54523229598999023 -0.89860010147094727 +-0.1667008101940155 -0.89532619714736938 -0.51434159278869629 +0.21832302212715149 0.23325073719024658 -1.3813087940216064 +0.51752841472625732 0.17477960884571075 -0.98423653841018677 +1.1153110265731812 0.1515648365020752 -0.14542290568351746 +1.3854436874389648 0.18543654680252075 0.25519448518753052 +1.3232111930847168 -0.044633567333221436 0.50715380907058716 +0.97279524803161621 -0.38912433385848999 0.41152980923652649 +-0.16592544317245483 -1.3746895790100098 0.30460226535797119 +0.21003007888793945 -1.073232889175415 0.30347472429275513 +-0.37118908762931824 -1.3682297468185425 0.01583978533744812 +-0.24135075509548187 -1.0445183515548706 -0.34327304363250732 +-0.069311857223510742 -0.34430715441703796 -1.0792065858840942 +-0.032974213361740112 -0.0025478899478912354 -1.4205179214477539 +0.38144800066947937 0.21491003036499023 -1.158246636390686 +1.2342463731765747 0.20021021366119385 0.04736056923866272 +1.123103141784668 -0.23184770345687866 0.46702271699905396 +0.044459998607635498 -1.1952621936798096 0.32030627131462097 +-0.31303697824478149 -1.184011697769165 -0.18261632323265076 +-0.076477587223052979 -0.19409653544425964 -1.2205334901809692 +0.3016338050365448 0.17497032880783081 -1.2911646366119385 +1.3219327926635742 0.14286124706268311 0.14418011903762817 +1.2537603378295898 -0.14241558313369751 0.44329029321670532 +-0.053162455558776855 -1.3097231388092041 0.26552334427833557 +-0.0092129409313201904 -0.10266947746276855 -1.3334457874298096 +-0.29583683609962463 -1.3020861148834229 -0.075868040323257446 +0.565513014793396 0.14289312064647675 -0.93149870634078979 +1.0598905086517334 0.11703336238861084 -0.24102200567722321 +0.93166792392730713 -0.4453694224357605 0.37623697519302368 +0.30530622601509094 -1.0114353895187378 0.28096789121627808 +-0.051023155450820923 -0.43017798662185669 -1.0037428140640259 +-0.19951927661895752 -1.0054610967636108 -0.39642578363418579 +0.65434837341308594 0.038842838257551193 -0.85574746131896973 +1.0252326726913452 0.035975754261016846 -0.3297116756439209 +0.88566744327545166 -0.55149340629577637 0.27098441123962402 +0.40469902753829956 -0.97542572021484375 0.2141716480255127 +0.015913177281618118 -0.51784402132034302 -0.94482296705245972 +-0.080058306455612183 -0.95886784791946411 -0.48594999313354492 +0.47295522689819336 0.14184382557868958 -1.063633918762207 +1.1603294610977173 0.095558643341064453 -0.10862825810909271 +1.052879810333252 -0.3396511971950531 0.38885045051574707 +0.15607050061225891 -1.1280530691146851 0.28605115413665771 +-0.046336814761161804 -0.29434043169021606 -1.1357392072677612 +-0.22182273864746094 -1.1165310144424438 -0.28156149387359619 +0.10702657699584961 0.22952079772949219 -1.5413950681686401 +0.62280583381652832 0.002415291965007782 -0.91831165552139282 +1.0718866586685181 -0.011717438697814941 -0.28654995560646057 +1.4953371286392212 0.18583029508590698 0.41166397929191589 +1.4706152677536011 0.082378208637237549 0.52013254165649414 +0.95112407207489014 -0.51706492900848389 0.24330244958400726 +-0.3077014684677124 -1.5059654712677002 0.27824681997299194 +0.37588679790496826 -1.0308511257171631 0.16505894064903259 +0.07216297835111618 -0.48940381407737732 -0.99320977926254272 +-0.005698084831237793 0.12883821129798889 -1.5567278861999512 +-0.3957042396068573 -1.5031960010528564 0.15444552898406982 +-0.053993463516235352 -1.0173226594924927 -0.43969157338142395 +0.61141449213027954 -0.048734035342931747 -0.95937550067901611 +0.45381805300712585 0.03414762020111084 -1.1432013511657715 +0.35765981674194336 0.11949816346168518 -1.2384564876556396 +0.031378865242004395 0.27900683879852295 -1.6249167919158936 +1.105830192565918 -0.064293414354324341 -0.26383739709854126 +1.2191362380981445 -0.018992811441421509 -0.080685019493103027 +1.2894226312637329 0.09017530083656311 0.072336494922637939 +1.5503602027893066 0.23120409250259399 0.51196849346160889 +1.0002003908157349 -0.50631576776504517 0.1996191143989563 +1.1498996019363403 -0.32255780696868896 0.29616469144821167 +1.2179539203643799 -0.20889508724212646 0.38590919971466064 +1.5359766483306885 0.17101383209228516 0.57507741451263428 +0.36689275503158569 -1.071968674659729 0.11347696185112 +0.21262302994728088 -1.1858841180801392 0.12883266806602478 +0.024439036846160889 -1.2749098539352417 0.22356791794300079 +-0.40971916913986206 -1.5668282508850098 0.31042495369911194 +-0.034206390380859375 0.22042793035507202 -1.6338375806808472 +0.031783118844032288 -0.17156597971916199 -1.2827820777893066 +0.11599387228488922 -0.31781274080276489 -1.1741825342178345 +0.12977282702922821 -0.47892320156097412 -1.0248881578445435 +-0.0091191232204437256 -1.0601354837417603 -0.41549217700958252 +-0.12611925601959229 -1.2008888721466064 -0.23661401867866516 +-0.22996905446052551 -1.2669035196304321 -0.13433033227920532 +-0.46092081069946289 -1.5652168989181519 0.23839512467384338 +0.52112579345703125 0.038368880748748779 -1.0454319715499878 +1.1592259407043457 0.01828765869140625 -0.14776009321212769 +1.0594394207000732 -0.39928236603736877 0.29005837440490723 +0.21989595890045166 -1.1387901306152344 0.19161733984947205 +0.053589507937431335 -0.34835678339004517 -1.1214677095413208 +-0.1131279468536377 -1.1181439161300659 -0.3208250105381012 +0.59302222728729248 -0.095700889825820923 -1.0083620548248291 +1.1502654552459717 -0.13199156522750854 -0.23355567455291748 +1.0555915832519531 -0.48738127946853638 0.16066849231719971 +0.31660842895507812 -1.1350352764129639 0.079004615545272827 +0.20413598418235779 -0.4645581841468811 -1.0665808916091919 +0.030090451240539551 -1.1089150905609131 -0.38344523310661316 +0.51434433460235596 -0.29661464691162109 -1.2179158926010132 +1.3127696514129639 -0.32174131274223328 -0.09470069408416748 +1.2925426959991455 -0.40638387203216553 -0.005953669548034668 +0.26982259750366211 -1.3198492527008057 -0.14506348967552185 +0.42211511731147766 -0.37899127602577209 -1.2304608821868896 +0.19782030582427979 -1.3175833225250244 -0.24635547399520874 +3 1902 2899 2906 +3 1966 2963 2970 +3 2094 3155 3162 +3 2158 3219 3226 +3 1982 2421 2428 +3 1854 3411 3418 +3 2286 3475 3482 +3 2046 2479 2486 +3 2350 2450 2457 +3 1768 1786 1107 +3 3622 1634 1611 +3 3602 3644 1046 +3 2169 1296 2501 +3 2501 1296 3513 +3 2174 2556 2563 +3 71 1751 3657 +3 3513 73 69 +3 1576 1589 3597 +3 3550 955 3555 +3 1708 1077 1729 +3 71 72 1729 +3 72 82 1708 +3 81 77 3624 +3 3513 1558 74 +3 1558 1576 3561 +3 75 3597 3610 +3 1647 1614 3624 +3 1661 1059 1674 +3 1674 1066 1708 +3 1774 1790 1109 +3 2238 2601 2608 +3 3630 1636 1619 +3 3604 3646 1050 +3 2302 2649 2656 +3 36 2616 2680 +3 3515 1563 40 +3 3515 39 37 +3 2680 1344 3515 +3 3599 3563 1580 +3 1580 1593 3599 +3 3593 1593 1580 +3 46 3653 1665 +3 1665 3633 1061 +3 49 1755 3659 +3 49 50 1735 +3 50 47 1712 +3 48 43 3632 +3 1563 1580 3563 +3 1649 1622 3632 +3 1685 1071 1712 +3 1686 1072 1715 +3 8 1756 3660 +3 3639 12 1650 +3 6 4 1686 +3 1667 1062 1686 +3 1715 1080 1736 +3 3564 16 1565 +3 3600 11 3564 +3 3516 14 15 +3 2709 1354 3516 +3 2709 15 1 +3 3516 15 2709 +3 1608 1038 1044 +3 1778 1794 1111 +3 1736 1090 1756 +3 3642 1639 1631 +3 10 3600 3616 +3 3607 3649 1056 +3 3516 1565 16 +3 111 338 556 +3 125 353 658 +3 143 402 783 +3 149 416 815 +3 145 464 792 +3 137 481 742 +3 105 328 509 +3 119 316 616 +3 129 392 684 +3 113 377 568 +3 121 451 630 +3 133 439 713 +3 104 13 499 +3 109 389 540 +3 108 347 527 +3 117 460 600 +3 116 324 587 +3 124 91 649 +3 127 44 669 +3 131 62 699 +3 135 78 729 +3 141 476 768 +3 140 411 756 +3 148 31 806 +3 212 346 559 +3 115 470 543 +3 103 7 493 +3 250 363 512 +3 107 421 523 +3 198 334 337 +3 123 84 643 +3 234 323 351 +3 292 410 784 +3 110 311 367 +3 128 50 678 +3 304 426 688 +3 139 433 752 +3 260 398 401 +3 147 18 800 +3 218 388 415 +3 296 475 794 +3 132 52 430 +3 118 358 604 +3 281 489 634 +3 142 370 772 +3 239 459 463 +3 136 72 736 +3 271 448 480 +3 103 326 495 +3 104 197 501 +3 105 204 514 +3 494 332 106 +3 107 349 529 +3 108 208 531 +3 109 210 545 +3 110 374 551 +3 111 216 560 +3 524 344 112 +3 113 223 574 +3 539 386 114 +3 115 313 589 +3 116 228 591 +3 117 231 605 +3 118 449 611 +3 119 238 621 +3 584 321 120 +3 121 245 636 +3 599 457 122 +3 123 364 646 +3 124 248 651 +3 125 254 661 +3 644 361 126 +3 127 257 670 +3 128 390 679 +3 129 266 690 +3 676 396 130 +3 131 269 700 +3 132 436 708 +3 133 276 719 +3 706 446 134 +3 135 278 730 +3 136 490 738 +3 137 285 744 +3 735 487 138 +3 139 413 758 +3 140 287 760 +3 141 289 773 +3 142 477 779 +3 143 295 785 +3 753 408 144 +3 145 299 795 +3 767 473 146 +3 147 427 803 +3 148 302 808 +3 149 308 818 +3 801 424 150 +3 540 538 563 +3 224 209 543 +3 560 510 215 +3 616 319 151 +3 152 213 554 +3 559 214 565 +3 164 478 584 +3 543 209 153 +3 509 331 154 +3 661 618 253 +3 650 155 493 +3 649 648 664 +3 160 5 494 +3 493 155 497 +3 156 252 656 +3 512 203 157 +3 556 342 158 +3 514 203 513 +3 341 196 523 +3 499 498 517 +3 152 428 524 +3 523 196 159 +3 160 200 507 +3 337 510 520 +3 658 359 161 +3 621 214 162 +3 356 230 643 +3 600 598 624 +3 156 87 644 +3 643 230 163 +3 164 236 614 +3 351 618 627 +3 768 766 788 +3 770 165 367 +3 785 686 294 +3 568 383 166 +3 167 293 781 +3 784 222 168 +3 178 317 539 +3 367 165 553 +3 684 395 169 +3 818 570 307 +3 807 170 678 +3 806 805 821 +3 175 48 676 +3 678 170 681 +3 171 306 813 +3 688 265 172 +3 783 406 173 +3 690 265 689 +3 405 256 752 +3 669 668 693 +3 167 442 753 +3 752 256 174 +3 175 262 682 +3 401 686 696 +3 815 422 176 +3 574 222 573 +3 419 207 800 +3 527 525 578 +3 171 27 801 +3 800 207 177 +3 178 220 566 +3 415 570 581 +3 756 754 798 +3 750 179 430 +3 795 632 298 +3 713 444 180 +3 181 297 790 +3 794 275 182 +3 192 66 706 +3 430 179 710 +3 630 455 183 +3 744 715 284 +3 727 184 604 +3 729 728 747 +3 189 365 599 +3 604 184 613 +3 185 283 740 +3 634 244 186 +3 792 471 187 +3 636 244 635 +3 467 227 772 +3 587 585 639 +3 181 380 767 +3 772 227 188 +3 189 241 628 +3 463 632 642 +3 742 485 190 +3 719 275 718 +3 484 268 736 +3 699 698 723 +3 185 81 735 +3 736 268 191 +3 192 273 711 +3 480 715 726 +3 8 9 650 +3 495 326 496 +3 194 652 193 +3 497 194 326 +3 507 200 350 +3 501 196 195 +3 503 196 501 +3 517 502 197 +3 198 199 518 +3 106 328 200 +3 202 659 201 +3 513 202 515 +3 516 203 514 +3 154 335 204 +3 339 562 505 +3 520 339 199 +3 522 420 341 +3 531 207 205 +3 529 349 530 +3 566 220 429 +3 343 562 206 +3 159 343 349 +3 533 207 531 +3 578 532 208 +3 554 213 318 +3 551 374 369 +3 545 209 309 +3 546 541 770 +3 548 209 545 +3 563 320 210 +3 371 775 211 +3 553 371 374 +3 212 310 564 +3 112 338 213 +3 558 214 559 +3 215 352 561 +3 340 510 560 +3 158 528 216 +3 217 622 550 +3 565 217 310 +3 218 219 579 +3 114 377 220 +3 376 816 221 +3 573 376 572 +3 576 222 574 +3 166 575 223 +3 417 820 535 +3 581 417 219 +3 583 469 224 +3 591 227 225 +3 589 313 547 +3 628 241 479 +3 590 622 226 +3 153 590 313 +3 593 227 591 +3 639 592 228 +3 614 236 366 +3 611 449 612 +3 605 230 229 +3 601 357 727 +3 607 230 605 +3 624 606 231 +3 233 731 232 +3 613 233 449 +3 234 235 625 +3 120 316 236 +3 619 659 237 +3 162 619 620 +3 314 214 621 +3 151 588 238 +3 354 663 609 +3 627 354 235 +3 239 240 640 +3 122 451 241 +3 243 793 242 +3 635 243 637 +3 638 244 636 +3 183 461 245 +3 465 797 595 +3 642 465 240 +3 83 70 356 +3 646 364 647 +3 360 663 246 +3 163 360 364 +3 656 252 336 +3 651 155 247 +3 330 155 651 +3 664 249 248 +3 250 251 665 +3 126 353 252 +3 327 203 512 +3 253 617 662 +3 355 618 661 +3 161 645 254 +3 666 652 655 +3 157 666 251 +3 670 256 255 +3 682 262 414 +3 672 256 670 +3 693 671 257 +3 679 390 680 +3 49 22 807 +3 259 809 258 +3 681 259 390 +3 260 261 694 +3 130 392 262 +3 264 816 263 +3 689 264 691 +3 692 265 690 +3 169 399 266 +3 403 787 674 +3 696 403 261 +3 700 268 267 +3 711 273 491 +3 702 268 700 +3 723 701 269 +3 708 436 432 +3 51 38 750 +3 434 762 270 +3 710 434 436 +3 271 272 724 +3 134 439 273 +3 438 793 274 +3 718 438 717 +3 721 275 719 +3 180 720 276 +3 482 746 704 +3 726 482 272 +3 730 184 277 +3 740 283 462 +3 453 184 730 +3 747 279 278 +3 738 490 739 +3 71 56 484 +3 486 746 280 +3 191 486 490 +3 281 282 748 +3 138 481 283 +3 450 244 634 +3 284 714 745 +3 483 715 744 +3 190 737 285 +3 749 731 734 +3 186 749 282 +3 761 431 405 +3 760 179 751 +3 758 413 759 +3 790 297 443 +3 407 787 286 +3 174 407 413 +3 435 179 760 +3 798 288 287 +3 781 293 382 +3 779 477 780 +3 773 165 769 +3 774 368 467 +3 373 165 773 +3 788 290 289 +3 472 797 291 +3 188 472 477 +3 292 384 789 +3 144 402 293 +3 378 222 784 +3 294 685 786 +3 404 686 785 +3 173 757 295 +3 379 775 777 +3 168 379 384 +3 296 445 799 +3 146 464 297 +3 440 275 794 +3 298 631 796 +3 466 632 795 +3 187 778 299 +3 441 762 764 +3 182 441 445 +3 17 2 419 +3 803 427 804 +3 423 820 300 +3 177 423 427 +3 813 306 400 +3 808 170 301 +3 394 170 808 +3 821 303 302 +3 304 305 822 +3 150 416 306 +3 391 265 688 +3 307 569 819 +3 418 570 818 +3 176 802 308 +3 823 809 812 +3 172 823 305 +3 545 210 548 +3 544 309 224 +3 550 310 217 +3 543 583 224 +3 311 372 109 +3 548 320 312 +3 115 325 470 +3 224 309 209 +3 559 561 558 +3 226 313 590 +3 201 515 202 +3 621 238 314 +3 345 338 111 +3 558 352 315 +3 234 316 322 +3 314 565 214 +3 540 389 555 +3 314 588 623 +3 317 385 152 +3 318 213 564 +3 109 372 389 +3 555 537 554 +3 112 342 556 +3 549 563 538 +3 547 319 321 +3 590 320 622 +3 164 456 478 +3 321 586 589 +3 119 323 322 +3 584 586 321 +3 324 325 115 +3 616 316 120 +3 514 204 516 +3 237 620 619 +3 193 326 194 +3 512 662 327 +3 198 328 333 +3 516 335 329 +3 362 353 125 +3 327 513 203 +3 493 8 650 +3 655 251 666 +3 492 24 247 +3 651 248 330 +3 103 6 7 +3 650 9 492 +3 94 95 124 +3 330 497 155 +3 496 331 332 +3 330 249 653 +3 160 12 5 +3 332 3 495 +3 105 334 333 +3 494 3 332 +3 4 6 103 +3 509 328 106 +3 649 91 657 +3 666 335 652 +3 90 92 156 +3 336 252 665 +3 124 95 91 +3 657 89 656 +3 126 359 658 +3 654 664 648 +3 520 199 337 +3 327 617 660 +3 504 199 505 +3 337 334 511 +3 212 338 345 +3 519 339 520 +3 333 328 105 +3 560 216 340 +3 195 15 501 +3 505 199 339 +3 500 195 341 +3 501 197 503 +3 107 348 421 +3 500 1 195 +3 14 16 104 +3 523 522 341 +3 530 342 344 +3 506 343 159 +3 152 385 428 +3 344 526 529 +3 111 346 345 +3 524 526 344 +3 347 348 107 +3 556 338 112 +3 499 13 508 +3 206 349 343 +3 10 12 160 +3 350 200 518 +3 104 16 13 +3 508 11 507 +3 106 331 509 +3 504 517 498 +3 627 235 351 +3 619 352 659 +3 608 235 609 +3 351 323 557 +3 250 353 362 +3 626 354 627 +3 322 316 119 +3 661 254 355 +3 229 601 605 +3 609 235 354 +3 602 229 356 +3 605 231 607 +3 123 88 84 +3 602 357 229 +3 358 454 117 +3 643 83 356 +3 647 359 361 +3 610 360 163 +3 156 92 87 +3 361 85 646 +3 125 363 362 +3 644 85 361 +3 86 88 123 +3 658 353 126 +3 600 460 615 +3 246 364 360 +3 365 456 164 +3 366 236 625 +3 117 454 460 +3 615 597 614 +3 120 319 616 +3 608 624 598 +3 553 374 367 +3 542 368 769 +3 166 369 211 +3 367 546 770 +3 370 468 141 +3 552 371 553 +3 110 372 311 +3 773 289 373 +3 573 572 574 +3 211 374 371 +3 307 375 221 +3 574 223 576 +3 409 402 143 +3 571 376 573 +3 218 377 387 +3 784 786 378 +3 768 476 782 +3 577 379 168 +3 380 381 167 +3 382 293 789 +3 141 468 476 +3 782 765 781 +3 144 406 783 +3 776 788 766 +3 369 383 386 +3 777 384 379 +3 178 385 317 +3 386 537 551 +3 113 388 387 +3 539 537 386 +3 389 372 110 +3 568 377 114 +3 690 266 692 +3 221 572 376 +3 258 390 259 +3 688 819 391 +3 260 392 397 +3 692 399 393 +3 425 416 149 +3 391 689 265 +3 678 49 807 +3 812 305 823 +3 677 19 301 +3 808 302 394 +3 128 47 50 +3 807 22 677 +3 33 34 148 +3 394 681 170 +3 680 395 396 +3 394 303 810 +3 175 43 48 +3 396 46 679 +3 129 398 397 +3 676 46 396 +3 45 47 128 +3 684 392 130 +3 806 31 814 +3 823 399 809 +3 30 32 171 +3 400 306 822 +3 148 34 31 +3 814 29 813 +3 150 422 815 +3 811 821 805 +3 696 261 401 +3 391 569 817 +3 673 261 674 +3 401 398 687 +3 292 402 409 +3 695 403 696 +3 397 392 129 +3 785 295 404 +3 255 37 670 +3 674 261 403 +3 667 255 405 +3 670 257 672 +3 139 412 433 +3 667 35 255 +3 39 40 127 +3 752 761 405 +3 759 406 408 +3 675 407 174 +3 167 381 442 +3 408 755 758 +3 143 410 409 +3 753 755 408 +3 411 412 139 +3 783 402 144 +3 669 44 683 +3 286 413 407 +3 41 43 175 +3 414 262 694 +3 127 40 44 +3 683 42 682 +3 130 395 684 +3 673 693 668 +3 581 219 415 +3 263 691 264 +3 534 219 535 +3 415 388 375 +3 304 416 425 +3 580 417 581 +3 387 377 113 +3 818 308 418 +3 205 522 531 +3 535 219 417 +3 521 205 419 +3 531 208 533 +3 147 28 18 +3 521 420 205 +3 421 348 108 +3 800 17 419 +3 804 422 424 +3 536 423 177 +3 171 32 27 +3 424 25 803 +3 149 426 425 +3 801 25 424 +3 26 28 147 +3 815 416 150 +3 527 347 567 +3 300 427 423 +3 428 385 178 +3 429 220 579 +3 108 348 347 +3 567 526 566 +3 114 383 568 +3 534 578 525 +3 710 436 430 +3 707 431 751 +3 180 432 270 +3 430 51 750 +3 433 412 140 +3 709 434 710 +3 132 65 52 +3 760 287 435 +3 718 717 719 +3 270 436 434 +3 284 437 274 +3 719 276 721 +3 474 464 145 +3 716 438 718 +3 271 439 447 +3 794 796 440 +3 756 411 791 +3 722 441 182 +3 442 381 181 +3 443 297 799 +3 140 412 411 +3 791 755 790 +3 146 471 792 +3 763 798 754 +3 432 444 446 +3 764 445 441 +3 192 61 66 +3 446 64 708 +3 133 448 447 +3 706 64 446 +3 63 65 132 +3 713 439 134 +3 636 245 638 +3 274 717 438 +3 232 449 233 +3 634 745 450 +3 239 451 458 +3 638 461 452 +3 488 481 137 +3 450 635 244 +3 604 601 727 +3 734 282 749 +3 603 67 277 +3 730 278 453 +3 118 454 358 +3 727 357 603 +3 73 74 135 +3 453 613 184 +3 612 455 457 +3 453 279 732 +3 189 456 365 +3 457 597 611 +3 121 459 458 +3 599 597 457 +3 460 454 118 +3 630 451 122 +3 729 78 741 +3 749 461 731 +3 75 77 185 +3 462 283 748 +3 135 74 78 +3 741 76 740 +3 138 485 742 +3 733 747 728 +3 642 240 463 +3 450 714 743 +3 594 240 595 +3 463 459 633 +3 296 464 474 +3 641 465 642 +3 458 451 121 +3 795 299 466 +3 225 583 591 +3 595 240 465 +3 582 225 467 +3 591 228 593 +3 142 468 370 +3 582 469 225 +3 470 325 116 +3 772 774 467 +3 780 471 473 +3 596 472 188 +3 181 381 380 +3 473 765 779 +3 145 475 474 +3 767 765 473 +3 476 468 142 +3 792 464 146 +3 587 324 629 +3 291 477 472 +3 478 456 189 +3 479 241 640 +3 116 325 324 +3 629 586 628 +3 122 455 630 +3 594 639 585 +3 726 272 480 +3 242 637 243 +3 703 272 704 +3 480 448 437 +3 281 481 488 +3 725 482 726 +3 447 439 133 +3 744 285 483 +3 267 55 700 +3 704 272 482 +3 697 267 484 +3 700 269 702 +3 136 82 72 +3 697 53 267 +3 57 58 131 +3 736 71 484 +3 739 485 487 +3 705 486 191 +3 185 77 81 +3 487 79 738 +3 137 489 488 +3 735 79 487 +3 80 82 136 +3 742 481 138 +3 699 62 712 +3 280 490 486 +3 59 61 192 +3 491 273 724 +3 131 58 62 +3 712 60 711 +3 134 444 713 +3 703 723 698 +3 9 23 492 +3 7 8 493 +3 497 326 493 +3 493 326 103 +3 106 200 494 +3 5 3 494 +3 332 331 106 +3 494 200 160 +3 193 335 154 +3 495 3 4 +3 154 496 193 +3 496 332 495 +3 247 93 651 +3 653 497 330 +3 496 326 193 +3 495 4 103 +3 508 13 11 +3 508 498 499 +3 517 197 499 +3 499 197 104 +3 195 1 15 +3 341 420 500 +3 195 196 341 +3 500 0 1 +3 197 502 503 +3 501 15 14 +3 502 562 343 +3 159 503 506 +3 504 498 350 +3 505 562 502 +3 503 502 506 +3 501 14 104 +3 518 199 504 +3 507 11 10 +3 333 334 198 +3 350 508 507 +3 154 204 509 +3 509 204 105 +3 350 498 508 +3 507 10 160 +3 201 352 215 +3 511 510 337 +3 215 511 201 +3 511 334 515 +3 157 251 512 +3 660 513 327 +3 511 515 201 +3 337 199 198 +3 204 335 516 +3 514 515 334 +3 654 251 655 +3 157 516 329 +3 331 496 154 +3 193 652 335 +3 513 515 514 +3 514 334 105 +3 505 517 504 +3 518 200 328 +3 340 528 519 +3 504 350 518 +3 520 510 340 +3 519 520 340 +3 505 502 517 +3 518 328 198 +3 420 0 500 +3 419 2 521 +3 421 522 523 +3 205 420 522 +3 159 349 523 +3 523 349 107 +3 205 207 419 +3 521 0 420 +3 112 213 524 +3 567 525 527 +3 428 526 524 +3 567 347 526 +3 344 342 112 +3 524 213 152 +3 578 208 527 +3 527 208 108 +3 206 528 158 +3 529 526 347 +3 158 530 206 +3 530 344 529 +3 196 503 159 +3 506 502 343 +3 530 349 206 +3 529 347 107 +3 208 532 533 +3 531 522 421 +3 532 820 423 +3 177 533 536 +3 534 525 429 +3 535 820 532 +3 533 532 536 +3 531 421 108 +3 555 389 537 +3 317 537 539 +3 555 538 540 +3 114 220 539 +3 563 210 540 +3 540 210 109 +3 386 383 114 +3 539 220 178 +3 309 541 546 +3 311 546 367 +3 224 469 544 +3 541 771 542 +3 153 313 543 +3 544 771 541 +3 770 541 542 +3 367 374 110 +3 210 320 548 +3 545 546 311 +3 151 547 226 +3 153 548 312 +3 549 538 318 +3 550 622 320 +3 309 546 545 +3 545 311 109 +3 211 575 166 +3 551 537 389 +3 373 290 552 +3 369 386 551 +3 553 165 373 +3 552 553 373 +3 369 374 211 +3 551 389 110 +3 564 310 549 +3 554 537 317 +3 345 346 212 +3 318 555 554 +3 158 216 556 +3 556 216 111 +3 318 538 555 +3 554 317 152 +3 561 352 558 +3 346 561 559 +3 253 557 237 +3 162 558 315 +3 510 511 215 +3 201 659 352 +3 565 310 559 +3 559 310 212 +3 216 528 340 +3 560 561 346 +3 562 339 528 +3 528 339 519 +3 342 530 158 +3 206 562 528 +3 215 561 560 +3 560 346 111 +3 550 563 549 +3 564 213 338 +3 549 310 550 +3 549 318 564 +3 162 620 621 +3 623 565 314 +3 550 320 563 +3 564 338 212 +3 579 219 534 +3 566 526 428 +3 387 388 218 +3 429 567 566 +3 166 223 568 +3 568 223 113 +3 429 525 567 +3 566 428 178 +3 221 569 307 +3 375 570 415 +3 378 685 571 +3 375 388 572 +3 573 222 378 +3 571 573 378 +3 375 572 221 +3 415 219 218 +3 223 575 576 +3 574 572 388 +3 575 775 379 +3 168 576 577 +3 383 369 166 +3 211 775 575 +3 576 575 577 +3 574 388 113 +3 535 578 534 +3 579 220 377 +3 418 802 580 +3 534 429 579 +3 581 570 418 +3 580 581 418 +3 535 532 578 +3 579 377 218 +3 469 771 544 +3 467 368 582 +3 470 583 543 +3 225 469 583 +3 544 541 309 +3 543 313 115 +3 225 227 467 +3 582 771 469 +3 120 236 584 +3 629 585 587 +3 478 586 584 +3 629 324 586 +3 321 319 120 +3 584 236 164 +3 639 228 587 +3 587 228 116 +3 226 588 151 +3 589 586 324 +3 312 590 153 +3 547 321 589 +3 153 209 548 +3 312 320 590 +3 547 313 226 +3 589 324 115 +3 228 592 593 +3 591 583 470 +3 592 797 472 +3 188 593 596 +3 594 585 479 +3 595 797 592 +3 593 592 596 +3 591 470 116 +3 615 460 597 +3 365 597 599 +3 615 598 600 +3 122 241 599 +3 624 231 600 +3 600 231 117 +3 457 455 122 +3 599 241 189 +3 229 357 601 +3 358 601 604 +3 356 70 602 +3 357 68 603 +3 229 230 356 +3 602 68 357 +3 613 449 604 +3 604 449 118 +3 231 606 607 +3 605 601 358 +3 606 663 360 +3 163 607 610 +3 608 598 366 +3 609 663 606 +3 607 606 610 +3 605 358 117 +3 232 461 183 +3 611 597 460 +3 183 612 232 +3 612 457 611 +3 277 69 730 +3 732 613 453 +3 612 449 232 +3 611 460 118 +3 625 235 608 +3 614 597 365 +3 322 323 234 +3 366 615 614 +3 151 238 616 +3 616 238 119 +3 366 598 615 +3 614 365 164 +3 237 617 253 +3 557 618 351 +3 315 619 162 +3 557 323 620 +3 162 214 558 +3 315 352 619 +3 557 620 237 +3 351 235 234 +3 238 588 314 +3 621 620 323 +3 588 622 217 +3 588 217 623 +3 319 547 151 +3 226 622 588 +3 623 217 565 +3 621 323 119 +3 609 624 608 +3 625 236 316 +3 355 645 626 +3 608 366 625 +3 627 618 355 +3 626 627 355 +3 609 606 624 +3 625 316 234 +3 640 240 594 +3 628 586 478 +3 458 459 239 +3 479 629 628 +3 183 245 630 +3 630 245 121 +3 479 585 629 +3 628 478 189 +3 242 631 298 +3 633 632 463 +3 298 633 242 +3 633 459 637 +3 186 282 634 +3 743 635 450 +3 633 637 242 +3 463 240 239 +3 245 461 638 +3 636 637 459 +3 733 282 734 +3 186 638 452 +3 455 612 183 +3 232 731 461 +3 635 637 636 +3 636 459 121 +3 595 639 594 +3 640 241 451 +3 466 778 641 +3 594 479 640 +3 642 632 466 +3 641 642 466 +3 595 592 639 +3 640 451 239 +3 70 68 602 +3 84 83 643 +3 163 364 643 +3 643 364 123 +3 126 252 644 +3 87 85 644 +3 361 359 126 +3 644 252 156 +3 246 645 161 +3 646 85 86 +3 161 647 246 +3 647 361 646 +3 230 607 163 +3 610 606 360 +3 647 364 246 +3 646 86 123 +3 657 91 89 +3 657 648 649 +3 664 248 649 +3 649 248 124 +3 247 24 93 +3 247 650 492 +3 247 155 650 +3 492 23 24 +3 248 249 330 +3 651 93 94 +3 249 652 194 +3 249 194 653 +3 654 648 336 +3 655 652 249 +3 653 194 497 +3 651 94 124 +3 665 251 654 +3 656 89 90 +3 362 363 250 +3 336 657 656 +3 161 254 658 +3 658 254 125 +3 336 648 657 +3 656 90 156 +3 662 617 327 +3 363 662 512 +3 617 659 202 +3 617 202 660 +3 618 557 253 +3 237 659 617 +3 660 202 513 +3 512 251 250 +3 254 645 355 +3 661 662 363 +3 663 354 645 +3 645 354 626 +3 359 647 161 +3 246 663 645 +3 253 662 661 +3 661 363 125 +3 655 664 654 +3 665 252 353 +3 329 666 157 +3 654 336 665 +3 157 203 516 +3 329 335 666 +3 655 249 664 +3 665 353 250 +3 405 431 667 +3 255 35 37 +3 255 256 405 +3 667 36 35 +3 683 668 669 +3 683 44 42 +3 693 257 669 +3 669 257 127 +3 257 671 672 +3 670 37 39 +3 671 787 407 +3 174 672 675 +3 673 668 414 +3 674 787 671 +3 672 671 675 +3 670 39 127 +3 48 46 676 +3 130 262 676 +3 396 395 130 +3 676 262 175 +3 50 49 678 +3 22 20 677 +3 681 390 678 +3 678 390 128 +3 258 399 169 +3 679 46 45 +3 169 680 258 +3 680 396 679 +3 301 21 808 +3 810 681 394 +3 680 390 258 +3 679 45 128 +3 694 261 673 +3 682 42 41 +3 397 398 260 +3 414 683 682 +3 169 266 684 +3 684 266 129 +3 414 668 683 +3 682 41 175 +3 263 685 294 +3 687 686 401 +3 294 687 263 +3 687 398 691 +3 172 305 688 +3 817 689 391 +3 687 691 263 +3 401 261 260 +3 266 399 692 +3 690 691 398 +3 811 305 812 +3 172 692 393 +3 395 680 169 +3 258 809 399 +3 689 691 690 +3 690 398 129 +3 674 693 673 +3 694 262 392 +3 404 757 695 +3 673 414 694 +3 696 686 404 +3 695 696 404 +3 674 671 693 +3 694 392 260 +3 484 56 697 +3 267 53 55 +3 267 268 484 +3 697 54 53 +3 712 698 699 +3 712 62 60 +3 723 269 699 +3 699 269 131 +3 269 701 702 +3 700 55 57 +3 701 746 486 +3 191 702 705 +3 703 698 491 +3 704 746 701 +3 702 701 705 +3 700 57 131 +3 66 64 706 +3 134 273 706 +3 446 444 134 +3 706 273 192 +3 52 51 430 +3 38 36 707 +3 750 38 707 +3 430 436 132 +3 270 720 180 +3 708 64 63 +3 435 288 709 +3 432 446 708 +3 710 179 435 +3 709 710 435 +3 432 436 270 +3 708 63 132 +3 724 272 703 +3 711 60 59 +3 447 448 271 +3 491 712 711 +3 180 276 713 +3 713 276 133 +3 491 698 712 +3 711 59 192 +3 274 714 284 +3 437 715 480 +3 440 631 716 +3 437 448 717 +3 718 275 440 +3 716 718 440 +3 437 717 274 +3 480 272 271 +3 276 720 721 +3 719 717 448 +3 720 762 441 +3 182 721 722 +3 444 432 180 +3 270 762 720 +3 721 720 722 +3 719 448 133 +3 704 723 703 +3 724 273 439 +3 483 737 725 +3 703 491 724 +3 726 715 483 +3 725 726 483 +3 704 701 723 +3 724 439 271 +3 277 727 603 +3 277 67 69 +3 277 184 727 +3 603 68 67 +3 741 728 729 +3 741 78 76 +3 747 278 729 +3 729 278 135 +3 278 279 453 +3 730 69 73 +3 279 731 233 +3 279 233 732 +3 733 728 462 +3 734 731 279 +3 732 233 613 +3 730 73 135 +3 81 79 735 +3 138 283 735 +3 487 485 138 +3 735 283 185 +3 72 71 736 +3 56 54 697 +3 191 490 736 +3 736 490 136 +3 280 737 190 +3 738 79 80 +3 190 739 280 +3 739 487 738 +3 268 702 191 +3 705 701 486 +3 739 490 280 +3 738 80 136 +3 748 282 733 +3 740 76 75 +3 488 489 281 +3 462 741 740 +3 190 285 742 +3 742 285 137 +3 462 728 741 +3 740 75 185 +3 745 714 450 +3 489 745 634 +3 714 793 243 +3 714 243 743 +3 715 437 284 +3 274 793 714 +3 743 243 635 +3 634 282 281 +3 285 737 483 +3 744 745 489 +3 746 482 737 +3 737 482 725 +3 485 739 190 +3 280 746 737 +3 284 745 744 +3 744 489 137 +3 734 747 733 +3 748 283 481 +3 452 749 186 +3 733 462 748 +3 186 244 638 +3 452 461 749 +3 734 279 747 +3 748 481 281 +3 431 36 667 +3 751 750 707 +3 433 761 752 +3 751 431 761 +3 174 413 752 +3 752 413 139 +3 179 750 751 +3 707 36 431 +3 144 293 753 +3 791 754 756 +3 442 755 753 +3 791 411 755 +3 408 406 144 +3 753 293 167 +3 798 287 756 +3 756 287 140 +3 286 757 173 +3 758 755 411 +3 173 759 286 +3 759 408 758 +3 256 672 174 +3 675 671 407 +3 759 413 286 +3 758 411 139 +3 287 288 435 +3 760 761 433 +3 762 434 288 +3 288 434 709 +3 763 754 443 +3 764 762 288 +3 751 761 760 +3 760 433 140 +3 782 476 765 +3 380 765 767 +3 782 766 768 +3 146 297 767 +3 788 289 768 +3 768 289 141 +3 473 471 146 +3 767 297 181 +3 769 368 774 +3 370 774 772 +3 769 770 542 +3 368 771 582 +3 165 770 769 +3 542 771 368 +3 188 477 772 +3 772 477 142 +3 289 290 373 +3 773 774 370 +3 775 371 290 +3 290 371 552 +3 776 766 382 +3 777 775 290 +3 769 774 773 +3 773 370 141 +3 291 778 187 +3 779 765 476 +3 187 780 291 +3 780 473 779 +3 227 593 188 +3 596 592 472 +3 780 477 291 +3 779 476 142 +3 789 384 776 +3 781 765 380 +3 409 410 292 +3 382 782 781 +3 173 295 783 +3 783 295 143 +3 382 766 782 +3 781 380 167 +3 786 685 378 +3 410 786 784 +3 816 376 685 +3 685 376 571 +3 686 687 294 +3 263 816 685 +3 168 384 784 +3 784 384 292 +3 295 757 404 +3 785 786 410 +3 787 403 757 +3 757 403 695 +3 406 759 173 +3 286 787 757 +3 294 786 785 +3 785 410 143 +3 777 788 776 +3 789 293 402 +3 776 384 777 +3 776 382 789 +3 222 576 168 +3 577 575 379 +3 777 290 788 +3 789 402 292 +3 799 445 763 +3 790 755 442 +3 474 475 296 +3 443 791 790 +3 187 299 792 +3 792 299 145 +3 443 754 791 +3 790 442 181 +3 796 631 440 +3 475 796 794 +3 793 438 631 +3 631 438 716 +3 632 633 298 +3 242 793 631 +3 182 445 794 +3 794 445 296 +3 299 778 466 +3 795 796 475 +3 797 465 778 +3 778 465 641 +3 471 780 187 +3 291 797 778 +3 298 796 795 +3 795 475 145 +3 764 798 763 +3 799 297 464 +3 763 445 764 +3 763 443 799 +3 275 721 182 +3 722 720 441 +3 764 288 798 +3 799 464 296 +3 2 0 521 +3 18 17 800 +3 177 427 800 +3 800 427 147 +3 150 306 801 +3 27 25 801 +3 424 422 150 +3 801 306 171 +3 300 802 176 +3 803 25 26 +3 176 804 300 +3 804 424 803 +3 207 533 177 +3 536 532 423 +3 804 427 300 +3 803 26 147 +3 814 31 29 +3 814 805 806 +3 821 302 806 +3 806 302 148 +3 301 19 21 +3 301 807 677 +3 301 170 807 +3 677 20 19 +3 302 303 394 +3 808 21 33 +3 303 809 259 +3 303 259 810 +3 811 805 400 +3 812 809 303 +3 810 259 681 +3 808 33 148 +3 822 305 811 +3 813 29 30 +3 425 426 304 +3 400 814 813 +3 176 308 815 +3 815 308 149 +3 400 805 814 +3 813 30 171 +3 819 569 391 +3 426 819 688 +3 569 816 264 +3 569 264 817 +3 570 375 307 +3 221 816 569 +3 817 264 689 +3 688 305 304 +3 308 802 418 +3 818 819 426 +3 820 417 802 +3 802 417 580 +3 422 804 176 +3 300 820 802 +3 307 819 818 +3 818 426 149 +3 812 821 811 +3 822 306 416 +3 393 823 172 +3 811 400 822 +3 172 265 692 +3 393 399 823 +3 812 303 821 +3 822 416 304 +3 1838 2835 2842 +3 2030 2787 2794 +3 1918 3091 3098 +3 2222 3043 3050 +3 2110 3347 3354 +3 2366 3299 3306 +3 1822 2915 2922 +3 1810 3283 3290 +3 1886 2771 2778 +3 1874 3171 3178 +3 1950 2851 2858 +3 1936 2721 2732 +3 2014 2979 2986 +3 2002 2572 2579 +3 2078 3027 3034 +3 2066 3427 3434 +3 2142 3107 3114 +3 2128 2499 2517 +3 2206 3235 3242 +3 2194 2665 2672 +3 2270 3363 3370 +3 2256 2692 2703 +3 2334 2405 2412 +3 2322 3491 3498 +3 2354 2389 2396 +3 1954 2376 2384 +3 2318 3529 2445 +3 2018 3519 2467 +3 2178 955 2503 +3 2146 2540 2547 +3 2050 2527 2535 +3 2210 3523 2589 +3 2274 2633 2640 +3 2242 2620 2628 +3 2306 968 2683 +3 1986 971 2712 +3 1906 2755 2762 +3 1998 2742 2750 +3 1806 2819 2826 +3 1970 2806 2814 +3 1870 2883 2890 +3 1842 2870 2878 +3 1934 2947 2954 +3 2034 2934 2942 +3 2098 3011 3018 +3 2190 2998 3006 +3 1890 3075 3082 +3 2162 3062 3070 +3 2062 3139 3146 +3 1922 3126 3134 +3 2126 3203 3210 +3 2226 3190 3198 +3 1858 3267 3274 +3 2338 3254 3262 +3 2082 3331 3338 +3 2290 3318 3326 +3 1826 3395 3402 +3 2114 3382 3390 +3 2254 3459 3466 +3 2370 3446 3454 +3 2177 2500 2510 +3 2257 1347 3509 +3 1937 1357 3510 +3 3585 1588 864 +3 860 1601 3581 +3 861 1602 3583 +3 3609 1646 1604 +3 1635 3625 1048 +3 3613 1648 1606 +3 1637 3633 1052 +3 3546 1582 3588 +3 3619 1651 1609 +3 1587 3596 3609 +3 1591 3598 3613 +3 1597 3601 3619 +3 1610 1694 3644 +3 1618 1696 3646 +3 1630 1699 3649 +3 1659 1058 3621 +3 1663 1060 3629 +3 1669 1063 3641 +3 1660 864 870 +3 1684 1071 1703 +3 1666 867 873 +3 869 1700 875 +3 3569 1029 1641 +3 871 1702 877 +3 1713 1079 1721 +3 3577 1032 1644 +3 874 1705 880 +3 1719 1077 1675 +3 882 888 1719 +3 878 1624 1643 +3 1643 1053 1683 +3 1764 1090 1714 +3 885 891 1722 +3 894 900 1750 +3 888 894 1761 +3 896 902 1754 +3 890 896 1763 +3 885 1054 1688 +3 891 897 1764 +3 1748 893 1760 +3 888 882 1676 +3 894 888 1676 +3 1752 895 1762 +3 890 1643 1683 +3 896 890 1683 +3 1757 1098 1764 +3 897 903 1757 +3 1110 1793 1779 +3 1106 1785 1767 +3 1109 1790 1769 +3 1108 1789 1773 +3 1111 1794 1775 +3 905 1785 1782 +3 1759 898 1765 +3 900 894 1728 +3 902 896 1734 +3 1782 1105 1757 +3 1726 1670 1083 +3 1783 1098 1105 +3 1732 1678 1087 +3 1771 1095 1101 +3 1741 1690 1093 +3 1777 1097 1103 +3 1802 2838 2846 +3 1799 3251 3258 +3 1818 2886 2894 +3 1815 3414 3422 +3 1834 2803 2810 +3 1831 2918 2926 +3 1850 3379 3386 +3 1847 3286 3294 +3 1866 2902 2910 +3 1863 3142 3150 +3 1882 2739 2746 +3 1879 3094 3102 +3 1898 2867 2874 +3 1895 2774 2782 +3 1914 3059 3066 +3 1911 3174 3182 +3 1930 2966 2974 +3 1927 3547 2718 +3 1946 2822 2830 +3 1943 2424 2432 +3 1962 2931 2938 +3 1959 2854 2862 +3 1978 2392 2400 +3 1975 2726 2734 +3 1994 2790 2798 +3 1991 2543 2551 +3 2010 2950 2958 +3 2007 2482 2490 +3 2026 2758 2766 +3 2023 2982 2990 +3 1287 2475 2476 +3 2039 2575 2583 +3 2058 3158 3166 +3 2055 3398 3406 +3 2074 2995 3002 +3 2071 3350 3358 +3 2090 3123 3130 +3 2087 3030 3038 +3 2106 3315 3322 +3 2103 3430 3438 +3 2122 3222 3230 +3 2119 3539 2496 +3 2138 3078 3086 +3 2135 2559 2567 +3 2154 3187 3194 +3 2151 3110 3118 +3 2170 2524 2531 +3 2167 2511 2519 +3 2186 3046 3054 +3 2183 2636 2644 +3 2202 3206 3214 +3 2199 2604 2612 +3 2218 3014 3022 +3 2215 3238 3246 +3 1323 2597 2598 +3 2231 2668 2676 +3 2250 3478 3486 +3 2247 3542 2689 +3 2266 3334 3342 +3 2263 2652 2660 +3 2282 3443 3450 +3 2279 3366 3374 +3 2298 2617 2624 +3 2295 2697 2705 +3 2314 2453 2461 +3 2311 3462 3470 +3 2330 2373 2380 +3 2327 3302 3310 +3 1274 2440 2441 +3 2343 2408 2416 +3 2362 3270 3278 +3 2359 3494 3502 +3 2335 1258 2380 +3 2380 1258 2330 +3 2345 1272 2437 +3 2407 1264 2353 +3 2326 1266 2412 +3 2412 1266 2334 +3 1972 1361 2729 +3 2422 2391 1981 +3 3528 1573 1273 +3 2310 1277 2445 +3 2340 2411 2455 +3 2457 1280 2350 +3 2011 1284 2467 +3 2047 952 3518 +3 2036 1315 2578 +3 2486 1290 2046 +3 2131 1294 2496 +3 2169 1302 2525 +3 955 3550 2503 +3 2123 1300 2515 +3 2517 1195 2130 +3 2175 1304 2531 +3 2525 2502 2169 +3 2139 1308 2547 +3 2547 1308 2146 +3 2164 2514 2561 +3 2557 2529 2173 +3 1995 1316 2579 +3 2579 1316 2002 +3 2203 1320 2589 +3 2239 962 3522 +3 2228 1341 2671 +3 2608 1326 2238 +3 2303 1330 2624 +3 2681 1344 2297 +3 2267 1334 2640 +3 2640 1334 2274 +3 2292 1351 2700 +3 2650 2622 2301 +3 2187 1342 2672 +3 2672 1342 2194 +3 3557 1563 3552 +3 3552 968 3557 +3 3525 969 3572 +3 2251 1352 2701 +3 2703 1227 2258 +3 3558 1565 3553 +3 3553 1565 1354 +3 3526 1564 1357 +3 1931 1362 2730 +3 2732 1147 1938 +3 1887 1366 2746 +3 2746 1366 1882 +3 1897 1396 2868 +3 2773 1372 1905 +3 1878 1374 2778 +3 2778 1374 1886 +3 2020 1425 2985 +3 2788 2757 2029 +3 1839 1382 2810 +3 2869 1396 1833 +3 1798 1386 2826 +3 2826 1386 1806 +3 1828 1409 2921 +3 2836 2808 1837 +3 1942 1394 2858 +3 2858 1394 1950 +3 1903 1398 2874 +3 2868 2760 1897 +3 1862 1402 2890 +3 2890 1402 1870 +3 1892 2777 2904 +3 2900 2872 1901 +3 1814 1410 2922 +3 2922 1410 1822 +3 1967 1414 2938 +3 2932 2805 1961 +3 1926 1418 2954 +3 2954 1418 1934 +3 1956 2857 2968 +3 2964 2936 1965 +3 2006 1426 2986 +3 2986 1426 2014 +3 2079 1430 3002 +3 3002 1430 2074 +3 2089 1460 3124 +3 3029 1436 2097 +3 2070 1438 3034 +3 3034 1438 2078 +3 2212 1489 3241 +3 3044 3013 2221 +3 1919 1446 3066 +3 3125 1460 1913 +3 1883 1450 3082 +3 3082 1450 1890 +3 1908 1473 3177 +3 3092 3064 1917 +3 2134 1458 3114 +3 3114 1458 2142 +3 2095 1462 3130 +3 3124 3016 2089 +3 2054 1466 3146 +3 3146 1466 2062 +3 2084 3033 3160 +3 3156 3128 2093 +3 1867 1474 3178 +3 3178 1474 1874 +3 2159 1478 3194 +3 3188 3061 2153 +3 2118 1482 3210 +3 3210 1482 2126 +3 2148 3113 3224 +3 3220 3192 2157 +3 2198 1490 3242 +3 3242 1490 2206 +3 1811 1494 3258 +3 3258 1494 1799 +3 1849 1524 3380 +3 3285 1500 1857 +3 1803 1502 3290 +3 3290 1502 1810 +3 2356 1553 3497 +3 3300 3269 2365 +3 2111 1510 3322 +3 3381 1524 2105 +3 2075 1514 3338 +3 3338 1514 2082 +3 2100 1537 3433 +3 3348 3320 2109 +3 2262 1522 3370 +3 3370 1522 2270 +3 1855 1526 3386 +3 3380 3272 1849 +3 1819 1530 3402 +3 3402 1530 1826 +3 1844 3289 3416 +3 3412 3384 1853 +3 2059 1538 3434 +3 3434 1538 2066 +3 2287 1542 3450 +3 3444 3317 2281 +3 2246 1546 3466 +3 3466 1546 2254 +3 2276 3369 3480 +3 3476 3448 2285 +3 2315 1554 3498 +3 3498 1554 2322 +3 3520 1569 3568 +3 2119 1292 3539 +3 2306 1345 3524 +3 3614 1053 1031 +3 1738 1787 1107 +3 1986 1355 3527 +3 1023 1035 3591 +3 2683 1346 2306 +3 2712 1356 1986 +3 1677 1067 3611 +3 969 3525 2689 +3 972 3526 2718 +3 1574 3554 3560 +3 1023 955 3520 +3 1578 3556 3562 +3 1025 968 3524 +3 1585 3559 3565 +3 1027 971 3527 +3 1041 1647 1605 +3 1037 1043 1607 +3 3576 1044 1038 +3 87 3609 3596 +3 1677 3627 1727 +3 3645 1614 1041 +3 66 3613 3598 +3 1683 1070 1734 +3 3647 1622 1043 +3 1689 1073 3617 +3 3648 1629 1044 +3 27 3619 3601 +3 92 1646 3609 +3 1641 1616 3569 +3 61 1648 3613 +3 3572 1562 3525 +3 1032 3617 1054 +3 32 1651 3619 +3 875 1612 869 +3 3620 1610 1646 +3 3584 1575 3537 +3 877 1620 871 +3 3628 1618 1648 +3 3586 1579 3541 +3 880 1632 874 +3 3640 1630 1651 +3 3589 1584 3545 +3 3650 1659 1694 +3 3652 1663 1696 +3 3655 1669 1699 +3 1048 3625 1695 +3 1052 3633 1697 +3 1698 1629 3648 +3 863 1586 3584 +3 1067 1728 1676 +3 865 1590 3586 +3 1053 1070 1683 +3 1073 1737 1688 +3 868 1596 3589 +3 1046 1598 3602 +3 1048 3645 3603 +3 1050 1600 3604 +3 3647 3605 1601 +3 3648 3606 1602 +3 1056 1603 3607 +3 1706 1065 1673 +3 1065 1700 1658 +3 1049 3611 1067 +3 1674 80 1661 +3 1710 1069 1681 +3 1069 1702 1662 +3 1071 1079 1712 +3 1070 1088 1734 +3 1054 3617 1073 +3 1686 4 1667 +3 1716 1075 1693 +3 1075 1705 1668 +3 1724 1076 1706 +3 1658 1058 1065 +3 1708 82 1674 +3 1730 1078 1710 +3 1662 1060 1069 +3 872 878 1703 +3 1080 1090 1736 +3 1739 1081 1716 +3 1668 1063 1075 +3 1066 1077 1708 +3 1061 1655 1664 +3 1072 1080 1715 +3 1700 1065 1672 +3 1749 1082 1724 +3 905 1786 1768 +3 1095 1771 1751 +3 1769 900 1728 +3 1702 1069 1680 +3 1753 1086 1730 +3 906 1790 1774 +3 1097 1777 1755 +3 1625 1348 3635 +3 1737 897 1688 +3 1080 1072 1687 +3 1705 1075 1692 +3 1758 1092 1739 +3 907 1794 1778 +3 1672 1065 1076 +3 1077 1085 1729 +3 1680 1069 1078 +3 1079 1089 1735 +3 1704 879 1687 +3 1692 1075 1081 +3 3656 24 1766 +3 1670 1064 1083 +3 1725 893 899 +3 3611 1617 1677 +3 1085 1077 1709 +3 3658 53 1772 +3 1678 1068 1087 +3 1731 895 901 +3 1682 1625 3635 +3 1089 1079 1713 +3 1782 1785 1106 +3 1781 903 1737 +3 3661 19 1780 +3 1690 1074 1093 +3 1740 898 904 +3 1707 1076 1082 +3 1719 888 1709 +3 1711 1078 1086 +3 1721 884 1713 +3 1098 1783 1756 +3 1717 1081 1092 +3 1766 1094 1749 +3 1707 1082 1760 +3 1751 71 1729 +3 1772 1096 1753 +3 1711 1086 1762 +3 1755 49 1735 +3 3660 9 8 +3 1717 1092 1765 +3 1780 1099 1758 +3 1742 1100 1766 +3 1767 899 1748 +3 1084 1067 1677 +3 1744 1102 1772 +3 1773 901 1752 +3 1088 1070 1682 +3 1104 1099 1780 +3 1779 904 1759 +3 1781 1737 1091 +3 1748 1094 1100 +3 1752 1096 1102 +3 1759 1099 1104 +3 1767 1100 1106 +3 1747 1105 1106 +3 1726 1083 1107 +3 1781 1091 1107 +3 1773 1102 1108 +3 1743 1101 1108 +3 1732 1087 1109 +3 1769 1084 1109 +3 1779 1104 1110 +3 1745 1103 1110 +3 1741 1093 1111 +3 1775 1088 1111 +3 2847 1391 1804 +3 1799 1494 3260 +3 2919 1409 1828 +3 3291 3259 1808 +3 1805 1388 2834 +3 2848 2841 1802 +3 1809 3255 3282 +3 3260 3252 1799 +3 2923 2895 1820 +3 3415 3287 1844 +3 2893 1402 1862 +3 3423 1535 1824 +3 1821 2882 2914 +3 2896 2889 1818 +3 1825 1532 3410 +3 3424 3417 1815 +3 2844 1122 1838 +3 2925 1410 1814 +3 1833 1396 2866 +3 2880 1123 1842 +3 1837 2807 2834 +3 2812 1121 1834 +3 2898 1404 1901 +3 2928 1120 1831 +3 3420 1126 1854 +3 3293 1502 1803 +3 1849 3271 3378 +3 3276 1127 1858 +3 1853 3383 3410 +3 3388 1125 1850 +3 1857 1500 3282 +3 3296 1124 1847 +3 2911 1407 1868 +3 3149 1466 2054 +3 2903 2775 1892 +3 3179 3151 1872 +3 1869 1404 2898 +3 2912 2905 1866 +3 1873 3138 3170 +3 3152 3145 1863 +3 2779 2747 1884 +3 3175 1473 1908 +3 1882 1366 2748 +3 3103 1455 1888 +3 1885 2743 2770 +3 2748 2740 1882 +3 1889 1452 3090 +3 3104 3097 1879 +3 2908 1138 1902 +3 2781 1374 1878 +3 1897 2759 2866 +3 2764 1139 1906 +3 1901 2871 2898 +3 2876 1137 1898 +3 1905 1372 2770 +3 2784 1136 1895 +3 3100 1142 1918 +3 3181 1474 1867 +3 1913 1460 3122 +3 3136 1143 1922 +3 1917 3063 3090 +3 3068 1141 1914 +3 3154 1468 2093 +3 3184 1140 1911 +3 2975 1423 1932 +3 3636 1626 1358 +3 2967 2855 1956 +3 2731 2719 1936 +3 1933 1420 2962 +3 2976 2969 1930 +3 1938 1147 2724 +3 2720 2717 1927 +3 2859 2831 1948 +3 2727 1361 1972 +3 2829 1386 1798 +3 2433 1271 1952 +3 1949 2818 2850 +3 2832 2825 1946 +3 2404 1264 2333 +3 2434 2427 1943 +3 2972 1154 1966 +3 2861 1394 1942 +3 1961 2802 2930 +3 2816 1155 1970 +3 1965 2935 2962 +3 2940 1153 1962 +3 2834 1388 1837 +3 2864 1152 1959 +3 2430 1158 1982 +3 2733 1362 1931 +3 2436 1272 2345 +3 2714 1159 1986 +3 1981 2388 2420 +3 2402 1157 1978 +3 3534 1572 1355 +3 2736 1156 1975 +3 2799 1379 1996 +3 2550 1308 2139 +3 2983 1425 2020 +3 2580 2552 2000 +3 2770 1372 1885 +3 2800 2793 1994 +3 2001 2539 2571 +3 2553 2546 1991 +3 2987 2959 2012 +3 2576 1315 2036 +3 2957 1418 1926 +3 2491 1291 2016 +3 2013 2946 2978 +3 2960 2953 2010 +3 2017 838 3506 +3 2492 2485 2007 +3 2796 1170 2030 +3 2989 1426 2006 +3 2866 1396 1897 +3 2944 1171 2034 +3 2029 2754 2786 +3 2768 1169 2026 +3 2962 1420 1965 +3 2992 1168 2023 +3 2488 1174 2046 +3 2582 1316 1995 +3 3512 88 1557 +3 2537 1175 2050 +3 2046 1174 2480 +3 2476 2474 1287 +3 2555 1310 2173 +3 2585 1172 2039 +3 3167 1471 2060 +3 3405 1530 1819 +3 3159 3031 2084 +3 3435 3407 2064 +3 2061 1468 3154 +3 3168 3161 2058 +3 2065 3394 3426 +3 3408 3401 2055 +3 3035 3003 2076 +3 3431 1537 2100 +3 2074 1430 3004 +3 3359 1519 2080 +3 2077 2999 3026 +3 3004 2996 2074 +3 2081 1516 3346 +3 3360 3353 2071 +3 3164 1186 2094 +3 3037 1438 2070 +3 2089 3015 3122 +3 3020 1187 2098 +3 2093 3127 3154 +3 3132 1185 2090 +3 2097 1436 3026 +3 3040 1184 2087 +3 3356 1190 2110 +3 3437 1538 2059 +3 2105 1524 3378 +3 3392 1191 2114 +3 2109 3319 3346 +3 3324 1189 2106 +3 3410 1532 1853 +3 3440 1188 2103 +3 3231 1487 2124 +3 2116 100 3627 +3 3223 3111 2148 +3 2516 2497 2128 +3 2125 1484 3218 +3 3232 3225 2122 +3 2130 1195 2509 +3 2498 2494 2119 +3 3115 3087 2140 +3 2560 2512 2164 +3 3085 1450 1883 +3 2568 1313 2144 +3 2141 3074 3106 +3 3088 3081 2138 +3 2145 1310 2555 +3 2569 2562 2135 +3 3228 1202 2158 +3 3117 1458 2134 +3 2153 3058 3186 +3 3072 1203 2162 +3 2157 3191 3218 +3 3196 1201 2154 +3 3090 1452 1917 +3 3120 1200 2151 +3 2565 1206 2174 +3 2518 1300 2123 +3 2169 2501 2523 +3 2505 1207 2178 +3 2173 2528 2555 +3 2533 1205 2170 +3 2177 839 3531 +3 2521 1204 2167 +3 3055 1443 2188 +3 2643 1334 2267 +3 3239 1489 2212 +3 2673 2645 2192 +3 3026 1436 2077 +3 3056 3049 2186 +3 2193 2632 2664 +3 2646 2639 2183 +3 3243 3215 2204 +3 2669 1341 2228 +3 3213 1482 2118 +3 2613 1327 2208 +3 2205 3202 3234 +3 3216 3209 2202 +3 2209 841 3508 +3 2614 2607 2199 +3 3052 1218 2222 +3 3245 1490 2198 +3 3122 1460 2089 +3 3200 1219 2226 +3 2221 3010 3042 +3 3024 1217 2218 +3 3218 1484 2157 +3 3248 1216 2215 +3 2610 1222 2238 +3 2675 1342 2187 +3 3514 65 1561 +3 2630 1223 2242 +3 2238 1222 2602 +3 2598 2596 1323 +3 2648 1336 2301 +3 2678 1220 2231 +3 3487 1551 2252 +3 3635 1733 1682 +3 3479 3367 2276 +3 2702 2690 2256 +3 2253 1548 3474 +3 3488 3481 2250 +3 2258 1227 2695 +3 2691 2688 2247 +3 3371 3343 2268 +3 2698 1351 2292 +3 3341 1514 2075 +3 2661 1339 2272 +3 2269 3330 3362 +3 3344 3337 2266 +3 2273 1336 2648 +3 2662 2655 2263 +3 3484 1234 2286 +3 3373 1522 2262 +3 2281 3314 3442 +3 3328 1235 2290 +3 2285 3447 3474 +3 3452 1233 2282 +3 3346 1516 2109 +3 3376 1232 2279 +3 2658 1238 2302 +3 2704 1352 2251 +3 2297 1344 2680 +3 2685 1239 2306 +3 2301 2621 2648 +3 2626 1237 2298 +3 3533 1571 1345 +3 2707 1236 2295 +3 2462 1281 2316 +3 3469 1546 2246 +3 2454 2409 2340 +3 3499 3471 2320 +3 3535 3607 3582 +3 2463 2456 2314 +3 2321 3458 3490 +3 3472 3465 2311 +3 2413 2381 2332 +3 3495 1553 2356 +3 2330 1258 2382 +3 3311 1507 2336 +3 2333 2377 2404 +3 2382 2374 2330 +3 3282 1500 1809 +3 3312 3305 2327 +3 2459 1250 2350 +3 2415 1266 2326 +3 2345 2393 2436 +3 2398 1251 2354 +3 2350 1250 2451 +3 2441 2439 1274 +3 2353 1264 2404 +3 2418 1248 2343 +3 3308 1254 2366 +3 3501 1554 2315 +3 3378 1524 1849 +3 3456 1255 2370 +3 2365 3266 3298 +3 3280 1253 2362 +3 3474 1548 2285 +3 3504 1252 2359 +3 2374 2372 1256 +3 2329 99 2372 +3 2383 1258 2335 +3 2333 1264 2406 +3 2332 1266 2413 +3 1258 2381 2382 +3 2386 2379 1954 +3 1952 1271 2435 +3 1983 1263 2400 +3 1260 2389 2390 +3 2394 2392 1261 +3 2347 1262 2396 +3 2347 1249 2399 +3 1262 2397 2398 +3 1980 919 2401 +3 1263 2401 2402 +3 2406 2378 2333 +3 2334 1266 2414 +3 2340 1279 2454 +3 1265 2409 2410 +3 2414 2406 2334 +3 2332 2383 2414 +3 2352 942 2417 +3 1267 2417 2418 +3 1955 1271 2432 +3 1268 2421 2422 +3 2426 2424 1269 +3 1974 1270 2428 +3 1974 1156 2431 +3 1270 2429 2430 +3 1952 2385 2433 +3 1271 2433 2434 +3 2437 2394 2345 +3 2 17 3517 +3 2442 1274 2351 +3 2348 942 2440 +3 2346 3548 2439 +3 2452 2449 2317 +3 2448 1277 2310 +3 2447 2443 2318 +3 2316 1281 2464 +3 2451 2449 1278 +3 2349 837 2449 +3 2455 2453 1279 +3 2342 1280 2457 +3 2342 1248 2460 +3 1280 2458 2459 +3 2316 2446 2462 +3 1281 2462 2463 +3 2470 1284 2011 +3 3537 1575 1556 +3 2469 2466 2018 +3 2016 1291 2493 +3 3644 3602 1040 +3 70 83 3512 +3 2472 70 3512 +3 2044 923 2475 +3 2042 3549 2474 +3 2480 2478 1288 +3 2045 838 2478 +3 2484 2482 1289 +3 2038 1290 2486 +3 2038 1172 2489 +3 1290 2487 2488 +3 2016 2468 2491 +3 1291 2491 2492 +3 2494 1192 2116 +3 2499 1294 2131 +3 2129 2507 2509 +3 2128 1300 2516 +3 1294 2497 2498 +3 2510 2507 2177 +3 2178 1207 2500 +3 2502 3550 1296 +3 2171 1297 2503 +3 2171 1205 2506 +3 1297 2504 2505 +3 2509 2507 1298 +3 2129 839 2507 +3 2164 1311 2560 +3 1299 2512 2513 +3 2517 2515 1300 +3 2130 2508 2515 +3 2176 931 2520 +3 1301 2520 2521 +3 2041 2473 2526 +3 1302 2524 2525 +3 2534 1304 2175 +3 2173 1310 2557 +3 2172 931 2532 +3 1304 2532 2533 +3 2043 1173 2538 +3 1305 2536 2537 +3 2558 1310 2145 +3 2146 1308 2549 +3 1991 1309 2553 +3 1307 2544 2545 +3 2549 2541 2146 +3 2144 1313 2570 +3 2000 1316 2580 +3 1309 2552 2553 +3 2147 1313 2567 +3 1310 2556 2557 +3 2561 2559 1311 +3 2166 1312 2563 +3 2166 1204 2566 +3 1312 2564 2565 +3 2144 2548 2568 +3 1313 2568 2569 +3 2573 2542 2001 +3 2002 1316 2581 +3 2036 2483 2576 +3 1315 2576 2577 +3 2581 2573 2002 +3 2000 2554 2581 +3 2048 923 2584 +3 1317 2584 2585 +3 2592 1320 2203 +3 3541 1579 1560 +3 2591 2588 2210 +3 2208 1327 2615 +3 3646 3604 1042 +3 38 51 3514 +3 2594 38 3514 +3 2236 935 2597 +3 2234 3551 2596 +3 2602 2600 1324 +3 2237 841 2600 +3 2606 2604 1325 +3 2230 1326 2608 +3 2230 1220 2611 +3 1326 2609 2610 +3 2208 2590 2613 +3 1327 2613 2614 +3 2233 2595 2619 +3 1328 2617 2618 +3 2627 1330 2303 +3 2301 1336 2650 +3 2300 939 2625 +3 1330 2625 2626 +3 2235 1221 2631 +3 1331 2629 2630 +3 2651 1336 2273 +3 2274 1334 2642 +3 2183 1335 2646 +3 1333 2637 2638 +3 2642 2634 2274 +3 2272 1339 2663 +3 2192 1342 2673 +3 1335 2645 2646 +3 2275 1339 2660 +3 1336 2649 2650 +3 2654 2652 1337 +3 2294 1338 2656 +3 2294 1236 2659 +3 1338 2657 2658 +3 2272 2641 2661 +3 1339 2661 2662 +3 2666 2635 2193 +3 2194 1342 2674 +3 2228 2605 2669 +3 1341 2669 2670 +3 2674 2666 2194 +3 2192 2647 2674 +3 2240 935 2677 +3 1343 2677 2678 +3 3515 35 2680 +3 1344 1563 3515 +3 3573 1025 3524 +3 3605 1043 3573 +3 2299 1237 2686 +3 1346 2684 2685 +3 1562 3509 1347 +3 3587 860 3543 +3 2244 102 3635 +3 2256 1352 2702 +3 1349 2690 2691 +3 2695 2693 1350 +3 2257 843 2693 +3 2292 2653 2698 +3 1351 2698 2699 +3 2703 2701 1352 +3 2258 2694 2701 +3 2304 939 2706 +3 1353 2706 2707 +3 1583 1595 3600 +3 1354 1565 3516 +3 3576 1027 3527 +3 1985 844 3534 +3 1979 1157 2715 +3 1356 2713 2714 +3 3546 3583 3510 +3 1939 1359 2718 +3 1738 1091 1689 +3 1936 1362 2731 +3 1359 2719 2720 +3 2724 2722 1360 +3 1937 844 2722 +3 1972 2425 2727 +3 1361 2727 2728 +3 2732 2730 1362 +3 1938 2723 2730 +3 1984 919 2735 +3 1363 2735 2736 +3 2740 2738 1364 +3 1881 96 2738 +3 2749 1366 1887 +3 1885 1372 2772 +3 1884 1374 2779 +3 1366 2747 2748 +3 2752 2745 1998 +3 1996 1379 2801 +3 2031 1371 2766 +3 1368 2755 2756 +3 2760 2758 1369 +3 1899 1370 2762 +3 1899 1137 2765 +3 1370 2763 2764 +3 2028 922 2767 +3 1371 2767 2768 +3 2772 2744 1885 +3 1886 1374 2780 +3 1892 1405 2903 +3 1373 2775 2776 +3 2780 2772 1886 +3 1884 2749 2780 +3 1904 914 2783 +3 1375 2783 2784 +3 1999 1379 2798 +3 1376 2787 2788 +3 2792 2790 1377 +3 2022 1378 2794 +3 2022 1168 2797 +3 1378 2795 2796 +3 1996 2751 2799 +3 1379 2799 2800 +3 1961 1412 2932 +3 1380 2803 2804 +3 2813 1382 1839 +3 1837 1388 2836 +3 1836 910 2811 +3 1382 2811 2812 +3 1963 1153 2817 +3 1383 2815 2816 +3 2837 1388 1805 +3 1806 1386 2828 +3 1946 1387 2832 +3 1385 2823 2824 +3 2828 2820 1806 +3 1804 1391 2849 +3 1948 1394 2859 +3 1387 2831 2832 +3 1807 1391 2846 +3 1388 2835 2836 +3 2840 2838 1389 +3 1830 1390 2842 +3 1830 1120 2845 +3 1390 2843 2844 +3 1804 2827 2847 +3 1391 2847 2848 +3 2852 2821 1949 +3 1950 1394 2860 +3 1956 1421 2967 +3 1393 2855 2856 +3 2860 2852 1950 +3 1948 2833 2860 +3 1968 918 2863 +3 1395 2863 2864 +3 1833 2804 2869 +3 1396 2867 2868 +3 2877 1398 1903 +3 1901 1404 2900 +3 1900 914 2875 +3 1398 2875 2876 +3 1835 1121 2881 +3 1399 2879 2880 +3 2901 1404 1869 +3 1870 1402 2892 +3 1818 1403 2896 +3 1401 2887 2888 +3 2892 2884 1870 +3 1868 1407 2913 +3 1820 1410 2923 +3 1403 2895 2896 +3 1871 1407 2910 +3 1404 2899 2900 +3 2904 2902 1405 +3 1894 1406 2906 +3 1894 1136 2909 +3 1406 2907 2908 +3 1868 2891 2911 +3 1407 2911 2912 +3 2916 2885 1821 +3 1822 1410 2924 +3 1828 2839 2919 +3 1409 2919 2920 +3 2924 2916 1822 +3 1820 2897 2924 +3 1840 910 2927 +3 1411 2927 2928 +3 2025 2761 2933 +3 1412 2931 2932 +3 2941 1414 1967 +3 1965 1420 2964 +3 1964 918 2939 +3 1414 2939 2940 +3 2027 1169 2945 +3 1415 2943 2944 +3 2965 1420 1933 +3 1934 1418 2956 +3 2010 1419 2960 +3 1417 2951 2952 +3 2956 2948 1934 +3 1932 1423 2977 +3 2012 1426 2987 +3 1419 2959 2960 +3 1935 1423 2974 +3 1420 2963 2964 +3 2968 2966 1421 +3 1958 1422 2970 +3 1958 1152 2973 +3 1422 2971 2972 +3 1932 2955 2975 +3 1423 2975 2976 +3 2980 2949 2013 +3 2014 1426 2988 +3 2020 2791 2983 +3 1425 2983 2984 +3 2988 2980 2014 +3 2012 2961 2988 +3 2032 922 2991 +3 1427 2991 2992 +3 2996 2994 1428 +3 2073 98 2994 +3 3005 1430 2079 +3 2077 1436 3028 +3 2076 1438 3035 +3 1430 3003 3004 +3 3008 3001 2190 +3 2188 1443 3057 +3 2223 1435 3022 +3 1432 3011 3012 +3 3016 3014 1433 +3 2091 1434 3018 +3 2091 1185 3021 +3 1434 3019 3020 +3 2220 934 3023 +3 1435 3023 3024 +3 3028 3000 2077 +3 2078 1438 3036 +3 2084 1469 3159 +3 1437 3031 3032 +3 3036 3028 2078 +3 2076 3005 3036 +3 2096 926 3039 +3 1439 3039 3040 +3 2191 1443 3054 +3 1440 3043 3044 +3 3048 3046 1441 +3 2214 1442 3050 +3 2214 1216 3053 +3 1442 3051 3052 +3 2188 3007 3055 +3 1443 3055 3056 +3 2153 1476 3188 +3 1444 3059 3060 +3 3069 1446 1919 +3 1917 1452 3092 +3 1916 915 3067 +3 1446 3067 3068 +3 2155 1201 3073 +3 1447 3071 3072 +3 3093 1452 1889 +3 1890 1450 3084 +3 2138 1451 3088 +3 1449 3079 3080 +3 3084 3076 1890 +3 1888 1455 3105 +3 2140 1458 3115 +3 1451 3087 3088 +3 1891 1455 3102 +3 1452 3091 3092 +3 3096 3094 1453 +3 1910 1454 3098 +3 1910 1140 3101 +3 1454 3099 3100 +3 1888 3083 3103 +3 1455 3103 3104 +3 3108 3077 2141 +3 2142 1458 3116 +3 2148 1485 3223 +3 1457 3111 3112 +3 3116 3108 2142 +3 2140 3089 3116 +3 2160 930 3119 +3 1459 3119 3120 +3 1913 3060 3125 +3 1460 3123 3124 +3 3133 1462 2095 +3 2093 1468 3156 +3 2092 926 3131 +3 1462 3131 3132 +3 1915 1141 3137 +3 1463 3135 3136 +3 3157 1468 2061 +3 2062 1466 3148 +3 1863 1467 3152 +3 1465 3143 3144 +3 3148 3140 2062 +3 2060 1471 3169 +3 1872 1474 3179 +3 1467 3151 3152 +3 2063 1471 3166 +3 1468 3155 3156 +3 3160 3158 1469 +3 2086 1470 3162 +3 2086 1184 3165 +3 1470 3163 3164 +3 2060 3147 3167 +3 1471 3167 3168 +3 3172 3141 1873 +3 1874 1474 3180 +3 1908 3095 3175 +3 1473 3175 3176 +3 3180 3172 1874 +3 1872 3153 3180 +3 1920 915 3183 +3 1475 3183 3184 +3 2217 3017 3189 +3 1476 3187 3188 +3 3197 1478 2159 +3 2157 1484 3220 +3 2156 930 3195 +3 1478 3195 3196 +3 2219 1217 3201 +3 1479 3199 3200 +3 3221 1484 2125 +3 2126 1482 3212 +3 2202 1483 3216 +3 1481 3207 3208 +3 3212 3204 2126 +3 2124 1487 3233 +3 2204 1490 3243 +3 1483 3215 3216 +3 2127 1487 3230 +3 1484 3219 3220 +3 3224 3222 1485 +3 2150 1486 3226 +3 2150 1200 3229 +3 1486 3227 3228 +3 2124 3211 3231 +3 1487 3231 3232 +3 3236 3205 2205 +3 2206 1490 3244 +3 2212 3047 3239 +3 1489 3239 3240 +3 3244 3236 2206 +3 2204 3217 3244 +3 2224 934 3247 +3 1491 3247 3248 +3 3252 3250 1492 +3 1796 99 3250 +3 3261 1494 1811 +3 1809 1500 3284 +3 1808 1502 3291 +3 1494 3259 3260 +3 3264 3257 2338 +3 2336 1507 3313 +3 2367 1499 3278 +3 1496 3267 3268 +3 3272 3270 1497 +3 1851 1498 3274 +3 1851 1125 3277 +3 1498 3275 3276 +3 2364 943 3279 +3 1499 3279 3280 +3 3284 3256 1809 +3 1810 1502 3292 +3 1844 1533 3415 +3 1501 3287 3288 +3 3292 3284 1810 +3 1808 3261 3292 +3 1856 911 3295 +3 1503 3295 3296 +3 2339 1507 3310 +3 1504 3299 3300 +3 3304 3302 1505 +3 2358 1506 3306 +3 2358 1252 3309 +3 1506 3307 3308 +3 2336 3263 3311 +3 1507 3311 3312 +3 2281 1540 3444 +3 1508 3315 3316 +3 3325 1510 2111 +3 2109 1516 3348 +3 2108 927 3323 +3 1510 3323 3324 +3 2283 1233 3329 +3 1511 3327 3328 +3 3349 1516 2081 +3 2082 1514 3340 +3 2266 1515 3344 +3 1513 3335 3336 +3 3340 3332 2082 +3 2080 1519 3361 +3 2268 1522 3371 +3 1515 3343 3344 +3 2083 1519 3358 +3 1516 3347 3348 +3 3352 3350 1517 +3 2102 1518 3354 +3 2102 1188 3357 +3 1518 3355 3356 +3 2080 3339 3359 +3 1519 3359 3360 +3 3364 3333 2269 +3 2270 1522 3372 +3 2276 1549 3479 +3 1521 3367 3368 +3 3372 3364 2270 +3 2268 3345 3372 +3 2288 938 3375 +3 1523 3375 3376 +3 2105 3316 3381 +3 1524 3379 3380 +3 3389 1526 1855 +3 1853 1532 3412 +3 1852 911 3387 +3 1526 3387 3388 +3 2107 1189 3393 +3 1527 3391 3392 +3 3413 1532 1825 +3 1826 1530 3404 +3 2055 1531 3408 +3 1529 3399 3400 +3 3404 3396 1826 +3 1824 1535 3425 +3 2064 1538 3435 +3 1531 3407 3408 +3 1827 1535 3422 +3 1532 3411 3412 +3 3416 3414 1533 +3 1846 1534 3418 +3 1846 1124 3421 +3 1534 3419 3420 +3 1824 3403 3423 +3 1535 3423 3424 +3 3428 3397 2065 +3 2066 1538 3436 +3 2100 3351 3431 +3 1537 3431 3432 +3 3436 3428 2066 +3 2064 3409 3436 +3 2112 927 3439 +3 1539 3439 3440 +3 2361 3273 3445 +3 1540 3443 3444 +3 3453 1542 2287 +3 2285 1548 3476 +3 2284 938 3451 +3 1542 3451 3452 +3 2363 1253 3457 +3 1543 3455 3456 +3 3477 1548 2253 +3 2254 1546 3468 +3 2311 1547 3472 +3 1545 3463 3464 +3 3468 3460 2254 +3 2252 1551 3489 +3 2320 1554 3499 +3 1547 3471 3472 +3 2255 1551 3486 +3 1548 3475 3476 +3 3480 3478 1549 +3 2278 1550 3482 +3 2278 1232 3485 +3 1550 3483 3484 +3 2252 3467 3487 +3 1551 3487 3488 +3 3492 3461 2321 +3 2322 1554 3500 +3 2356 3303 3495 +3 1553 3495 3496 +3 3500 3492 2322 +3 2320 3473 3500 +3 2368 943 3503 +3 1555 3503 3504 +3 3518 952 1022 +3 3622 1611 1652 +3 2119 1294 2498 +3 3522 962 1024 +3 3630 1619 1654 +3 3614 1031 3542 +3 3617 1032 3547 +3 3595 3575 1026 +3 3642 1631 1657 +3 1577 1559 3569 +3 2692 1349 2259 +3 2721 1359 1939 +3 3603 1041 3568 +3 2696 2693 2305 +3 2725 2722 1985 +3 951 2467 3519 +3 838 2045 3530 +3 1599 3603 1569 +3 1577 3538 1559 +3 3611 1029 3539 +3 961 2589 3523 +3 841 2237 3532 +3 2688 1224 2244 +3 1562 1347 3525 +3 3533 843 3581 +3 2717 1144 1924 +3 3526 972 3577 +3 3534 844 3583 +3 837 2349 3535 +3 949 2445 3529 +3 3536 951 1028 +3 1634 3622 857 +3 3590 1587 1034 +3 3560 3554 1557 +3 3561 74 1558 +3 3540 961 1030 +3 1636 3630 859 +3 3592 1591 1036 +3 3562 3556 1561 +3 1563 1344 3552 +3 3544 949 1033 +3 1639 3642 862 +3 3595 1597 1039 +3 3565 3559 1566 +3 3553 971 3558 +3 3561 78 74 +3 3563 44 40 +3 1977 2395 2710 +3 3520 955 2178 +3 3538 3579 3507 +3 1562 3572 1581 +3 1571 3524 1345 +3 1594 1627 873 +3 3606 1044 3576 +3 3596 1587 1574 +3 1028 951 3566 +3 876 870 1616 +3 3598 1591 1578 +3 1030 961 3570 +3 878 872 1624 +3 3588 861 3546 +3 1033 949 3574 +3 3601 1597 1585 +3 952 2474 3549 +3 962 2596 3551 +3 948 2439 3548 +3 1034 1604 1040 +3 3584 857 3622 +3 3591 1035 1589 +3 3586 859 3630 +3 1036 1606 1042 +3 3593 1037 1593 +3 1583 1565 3558 +3 1039 1609 1045 +3 3589 862 3642 +3 1599 1635 1048 +3 3585 858 3538 +3 3605 1571 3533 +3 3543 1562 1581 +3 1582 1564 3577 +3 3606 1572 3534 +3 1574 86 3596 +3 1599 858 1635 +3 1589 1605 3610 +3 1578 63 3598 +3 1601 860 1637 +3 1593 1607 3615 +3 1602 861 1638 +3 1595 1608 3616 +3 1585 26 3601 +3 3560 86 1574 +3 3597 76 3561 +3 3562 63 1578 +3 3599 42 3563 +3 3565 26 1585 +3 3558 1027 3594 +3 1646 1610 1040 +3 3624 77 1647 +3 870 864 1588 +3 1648 1618 1042 +3 872 866 1592 +3 1607 1649 3615 +3 5 12 3639 +3 1627 1644 879 +3 1651 1630 1045 +3 3531 839 3579 +3 1601 3605 3581 +3 3583 3546 861 +3 1694 1046 3644 +3 1695 81 1614 +3 1695 1614 3645 +3 1696 1050 3646 +3 1697 48 1622 +3 1697 1622 3647 +3 1602 1055 3648 +3 1650 3616 1608 +3 1699 1056 3649 +3 3555 1023 3591 +3 3557 1025 3593 +3 1583 3594 1595 +3 1616 1641 876 +3 1643 890 884 +3 1594 3577 1627 +3 3620 92 90 +3 1041 3603 3645 +3 3628 61 59 +3 1043 3605 3647 +3 1650 1044 1629 +3 3640 32 30 +3 91 1673 1659 +3 881 887 1640 +3 1727 1084 1677 +3 1615 1635 3626 +3 883 889 1642 +3 62 1681 1663 +3 3614 3542 1625 +3 1623 1637 3634 +3 1924 101 3636 +3 3637 867 1656 +3 31 1693 1669 +3 886 892 1645 +3 77 75 3610 +3 1593 1037 1607 +3 12 10 3616 +3 1615 3625 1635 +3 1637 860 3634 +3 1062 3638 1628 +3 1059 3625 1615 +3 1695 3625 1661 +3 1061 3633 1623 +3 46 48 3653 +3 1628 3638 1638 +3 1698 3638 1667 +3 3623 1613 1670 +3 1725 1064 1671 +3 1672 875 1700 +3 1617 1292 3627 +3 1661 3625 1059 +3 3631 1621 1678 +3 1731 1068 1679 +3 1680 877 1702 +3 1061 1071 1685 +3 1070 1053 3614 +3 1626 3636 1689 +3 1667 3638 1062 +3 3643 1633 1690 +3 1740 1074 1691 +3 1692 880 1705 +3 90 1610 3620 +3 3624 1614 81 +3 3645 1048 1695 +3 59 1618 3628 +3 3632 1622 48 +3 3647 1052 1697 +3 1650 1629 3639 +3 1044 3606 3648 +3 30 1630 3640 +3 1658 869 863 +3 1653 1615 3626 +3 1662 871 865 +3 1655 1623 3634 +3 1656 1628 3637 +3 1668 874 868 +3 3537 857 3584 +3 3541 859 3586 +3 3545 862 3589 +3 101 2009 3623 +3 1718 1076 1707 +3 1700 869 1658 +3 1640 1047 1612 +3 1673 1065 1058 +3 1059 1653 1660 +3 1641 1049 882 +3 1660 870 1701 +3 100 2201 3631 +3 1720 1078 1711 +3 1702 871 1662 +3 1642 1051 1620 +3 1681 1069 1060 +3 1712 47 1685 +3 1703 1664 872 +3 1685 45 1665 +3 1062 1656 1666 +3 1644 1054 885 +3 1666 873 1704 +3 1741 1795 102 +3 1723 1081 1717 +3 1705 874 1668 +3 1645 1057 1632 +3 1693 1075 1063 +3 89 1659 3650 +3 3650 90 89 +3 1695 1661 3651 +3 1661 80 3651 +3 1696 59 3652 +3 3652 60 1663 +3 1697 3633 3653 +3 3653 48 1697 +3 1698 1667 3654 +3 1667 4 3654 +3 29 1669 3655 +3 3655 30 29 +3 1675 1066 1701 +3 1664 866 872 +3 1687 1072 1704 +3 1672 881 875 +3 1611 3621 1058 +3 1680 883 877 +3 1619 3629 1060 +3 1692 886 880 +3 1631 3641 1063 +3 1673 91 95 +3 1760 893 887 +3 1749 1094 1082 +3 1748 899 893 +3 1671 893 1725 +3 1701 876 1675 +3 882 1049 1676 +3 1077 1066 1675 +3 1067 1084 1728 +3 100 1791 1727 +3 1681 62 58 +3 1762 895 889 +3 1753 1096 1086 +3 1752 901 895 +3 1679 895 1731 +3 1684 884 1721 +3 884 878 1643 +3 1079 1071 1684 +3 3614 1682 1070 +3 102 1795 1733 +3 101 1787 1738 +3 1073 1091 1737 +3 1736 7 1715 +3 1722 1080 1687 +3 1715 6 1686 +3 1693 31 34 +3 1765 898 892 +3 1758 1099 1092 +3 1759 904 898 +3 1691 898 1740 +3 1652 863 3622 +3 1663 60 62 +3 1657 868 3642 +3 1724 1082 1076 +3 876 882 1675 +3 1730 1086 1078 +3 878 884 1684 +3 879 885 1687 +3 1739 1092 1081 +3 1707 887 881 +3 1707 881 1718 +3 1709 888 1761 +3 1711 889 883 +3 1711 883 1720 +3 1713 890 1763 +3 1722 891 1714 +3 1717 892 886 +3 1717 886 1723 +3 1706 95 94 +3 1671 1047 1640 +3 1766 24 1742 +3 1725 899 1768 +3 1767 905 899 +3 1726 1787 101 +3 1769 1728 1084 +3 1728 894 1676 +3 1729 72 1708 +3 1710 58 57 +3 1679 1051 1642 +3 1772 53 1744 +3 1731 901 1774 +3 1773 906 901 +3 1732 1791 100 +3 1775 1734 1088 +3 1734 896 1683 +3 1735 50 1712 +3 1764 1098 1090 +3 3617 1626 1689 +3 1091 1073 1689 +3 1716 34 33 +3 1691 1057 1645 +3 1780 1746 1104 +3 1740 904 1778 +3 1765 1099 1759 +3 1111 1795 1741 +3 1742 1784 1106 +3 1771 1101 1743 +3 1744 1788 1108 +3 1777 1103 1745 +3 1746 1792 1110 +3 1783 1105 1747 +3 3651 81 1695 +3 1712 1079 1735 +3 3654 5 1698 +3 1082 1094 1760 +3 1064 1047 1671 +3 1709 1077 1719 +3 906 1789 1770 +3 1086 1096 1762 +3 1068 1051 1679 +3 884 890 1713 +3 907 1793 1776 +3 897 891 1688 +3 1714 1080 1722 +3 1092 1099 1765 +3 1074 1057 1691 +3 1640 875 881 +3 1718 881 1672 +3 1761 894 1750 +3 1642 877 883 +3 1720 883 1680 +3 1763 896 1754 +3 1090 1080 1714 +3 1645 880 886 +3 1723 886 1692 +3 1760 887 1707 +3 1671 887 893 +3 1766 1749 3656 +3 1724 93 1749 +3 3657 56 71 +3 1750 1095 1761 +3 1743 56 1771 +3 1743 54 56 +3 1770 1789 1108 +3 1762 889 1711 +3 1679 889 895 +3 1772 1753 3658 +3 1730 55 1753 +3 3659 22 49 +3 1754 1097 1763 +3 1745 22 1777 +3 1745 20 22 +3 1776 1793 1110 +3 1747 9 1783 +3 1688 1054 1073 +3 1756 8 1736 +3 1747 23 9 +3 1764 897 1757 +3 1780 1758 3661 +3 1779 907 904 +3 21 19 3661 +3 1739 21 1758 +3 1058 1659 1673 +3 82 80 1674 +3 1060 1663 1681 +3 47 45 1685 +3 1783 9 3660 +3 1063 1669 1693 +3 1706 94 1724 +3 3608 1047 1064 +3 1770 1101 1750 +3 1771 56 3657 +3 1085 1761 1095 +3 1710 57 1730 +3 3612 1051 1068 +3 1776 1103 1754 +3 1777 22 3659 +3 1089 1763 1097 +3 8 7 1736 +3 1714 891 1764 +3 903 897 1737 +3 1716 33 1739 +3 3618 1057 1074 +3 3656 1749 93 +3 1767 1785 905 +3 1083 1725 1768 +3 1768 899 905 +3 1742 23 1784 +3 1100 1094 1766 +3 3627 1292 2116 +3 1727 1791 1109 +3 1108 1788 1743 +3 1769 1790 906 +3 1750 900 1770 +3 1770 900 906 +3 3658 1753 55 +3 1773 1789 906 +3 1087 1731 1774 +3 1774 901 906 +3 1744 54 1788 +3 1102 1096 1772 +3 1733 3635 102 +3 1733 1795 1111 +3 1110 1792 1745 +3 1775 1794 907 +3 1754 902 1776 +3 1776 902 907 +3 1093 1740 1778 +3 1779 1793 907 +3 1778 904 907 +3 3661 1758 21 +3 1746 20 1792 +3 1780 19 1746 +3 3636 1358 1924 +3 1689 3636 1738 +3 1106 1784 1747 +3 1781 1786 905 +3 1757 903 1782 +3 1782 903 905 +3 1673 95 1706 +3 1729 1085 1751 +3 1681 58 1710 +3 1735 1089 1755 +3 7 6 1715 +3 1693 34 1716 +3 93 24 3656 +3 1761 1085 1709 +3 55 53 3658 +3 1763 1089 1713 +3 1781 905 903 +3 1765 892 1717 +3 1760 1094 1748 +3 1101 1095 1750 +3 1762 1096 1752 +3 1103 1097 1754 +3 1105 1098 1757 +3 1691 892 898 +3 1106 1100 1742 +3 1784 23 1747 +3 1748 1100 1767 +3 1106 1105 1782 +3 1107 1083 1768 +3 1107 1786 1781 +3 1107 1787 1726 +3 1107 1091 1738 +3 1108 1102 1744 +3 1788 54 1743 +3 1752 1102 1773 +3 1108 1101 1770 +3 1109 1087 1774 +3 906 900 1769 +3 1109 1791 1732 +3 1109 1084 1727 +3 1110 1104 1746 +3 1792 20 1745 +3 1759 1104 1779 +3 1110 1103 1776 +3 1111 1093 1778 +3 907 902 1775 +3 102 2308 3643 +3 1111 1088 1733 +3 1798 1385 2824 +3 3252 1112 1796 +3 1804 1386 2827 +3 3252 1492 1799 +3 979 2819 2830 +3 1797 2827 2829 +3 1006 3254 3258 +3 1796 3250 3252 +3 2841 1389 1802 +3 3259 1494 1808 +3 1828 1389 2839 +3 1803 1501 3288 +3 2842 2835 980 +3 1801 2839 2841 +3 1008 3283 3294 +3 1800 3291 3293 +3 2820 1384 1806 +3 1800 1113 2848 +3 846 2807 2850 +3 1807 1388 2837 +3 979 2822 2826 +3 1805 1384 2820 +3 1838 1122 2836 +3 1114 2828 2849 +3 3256 1115 3261 +3 1797 1112 3260 +3 853 3266 3282 +3 1811 1493 3256 +3 1008 3286 3290 +3 3256 1493 1809 +3 1006 3251 3262 +3 3284 1500 1810 +3 1814 1409 2920 +3 3287 1501 1844 +3 2895 1403 1820 +3 3417 1533 1815 +3 985 2915 2926 +3 1813 2923 2925 +3 3418 3411 1016 +3 1812 3415 3417 +3 2889 1401 1818 +3 1824 1530 3403 +3 2889 1117 1817 +3 1819 1529 3400 +3 2890 2883 983 +3 1817 2887 2889 +3 1015 3395 3406 +3 1816 3403 3405 +3 2885 1118 2897 +3 1816 1117 2896 +3 2898 2871 847 +3 1823 1400 2885 +3 985 2918 2922 +3 2885 1400 1821 +3 1870 1400 2883 +3 2916 1408 1822 +3 3396 1528 1826 +3 1813 1116 3424 +3 855 3383 3426 +3 1827 1532 3413 +3 1015 3398 3402 +3 1825 1528 3396 +3 1854 1126 3412 +3 1119 3404 3425 +3 2845 1390 1830 +3 1812 1116 2920 +3 2811 1382 1836 +3 2921 2918 1831 +3 980 2835 2846 +3 1829 2843 2845 +3 2922 2915 985 +3 1120 2840 2921 +3 2804 2803 1834 +3 2927 1411 1840 +3 824 2759 2930 +3 2881 1399 1835 +3 978 2806 2810 +3 1833 1380 2804 +3 1898 1137 2868 +3 1121 2812 2881 +3 2808 1122 2813 +3 1832 2879 2881 +3 846 2818 2834 +3 1839 1381 2808 +3 980 2838 2842 +3 2808 1381 1837 +3 978 2803 2814 +3 2836 2835 1838 +3 2873 2870 1842 +3 910 2843 2927 +3 1901 1397 2871 +3 1843 1408 2917 +3 2874 2867 982 +3 1841 1397 2873 +3 1822 1408 2915 +3 1123 2880 2929 +3 1847 1503 3296 +3 1801 1113 3288 +3 1856 1503 3297 +3 3289 3286 1847 +3 1016 3411 3422 +3 3296 3295 1845 +3 3290 3283 1008 +3 3421 1534 1846 +3 1851 3270 3272 +3 3295 1503 1856 +3 826 3314 3378 +3 3277 1498 1851 +3 1014 3382 3386 +3 3272 1497 1849 +3 1007 3267 3278 +3 3380 3379 1850 +3 3384 1126 3389 +3 3388 3387 1848 +3 855 3394 3410 +3 1855 1525 3384 +3 1016 3414 3418 +3 3384 1525 1853 +3 1014 3379 3390 +3 3412 3411 1854 +3 3268 3267 1858 +3 3387 1526 1852 +3 853 3255 3298 +3 1859 1500 3285 +3 1007 3270 3274 +3 1857 1496 3268 +3 1810 1500 3283 +3 1127 3276 3297 +3 1862 1401 2888 +3 3145 1128 1860 +3 1868 1402 2891 +3 3145 1465 1863 +3 983 2883 2894 +3 1861 2891 2893 +3 3146 3139 999 +3 1860 3143 3145 +3 2905 1405 1866 +3 3151 1467 1872 +3 2775 1373 1892 +3 1867 1473 3176 +3 2906 2899 984 +3 1865 2903 2905 +3 1001 3171 3182 +3 1864 3179 3181 +3 2884 1400 1870 +3 1864 1129 2912 +3 847 2871 2914 +3 1871 1404 2901 +3 983 2886 2890 +3 1869 1400 2884 +3 1902 1138 2900 +3 1130 2892 2913 +3 3141 1131 3153 +3 1861 1128 3152 +3 3154 3127 851 +3 1875 1464 3141 +3 1001 3174 3178 +3 3141 1464 1873 +3 2062 1464 3139 +3 3172 1472 1874 +3 1878 1373 2776 +3 1908 1453 3095 +3 2747 1366 1884 +3 3097 1453 1879 +3 976 2771 2782 +3 1877 2779 2781 +3 3098 3091 996 +3 1876 3095 3097 +3 2740 1364 1882 +3 1888 1450 3083 +3 2740 1133 1881 +3 1883 1449 3080 +3 974 2742 2746 +3 1881 2738 2740 +3 995 3075 3086 +3 1880 3083 3085 +3 2744 1134 2749 +3 1880 1133 2748 +3 845 2754 2770 +3 1887 1365 2744 +3 976 2774 2778 +3 2744 1365 1885 +3 974 2739 2750 +3 2772 1372 1886 +3 3076 1448 1890 +3 1877 1132 3104 +3 850 3063 3106 +3 1891 1452 3093 +3 995 3078 3082 +3 1889 1448 3076 +3 1918 1142 3092 +3 1135 3084 3105 +3 1895 1375 2784 +3 1876 1132 2776 +3 1904 1375 2785 +3 2777 2774 1895 +3 984 2899 2910 +3 2784 2783 1893 +3 2778 2771 976 +3 2909 1406 1894 +3 1899 2758 2760 +3 2783 1375 1904 +3 824 2802 2866 +3 2765 1370 1899 +3 982 2870 2874 +3 2760 1369 1897 +3 975 2755 2766 +3 2868 2867 1898 +3 2872 1138 2877 +3 2876 2875 1896 +3 847 2882 2898 +3 1903 1397 2872 +3 984 2902 2906 +3 2872 1397 1901 +3 982 2867 2878 +3 2900 2899 1902 +3 2756 2755 1906 +3 2875 1398 1900 +3 845 2743 2786 +3 1907 1372 2773 +3 975 2758 2762 +3 1905 1368 2756 +3 1886 1372 2771 +3 1139 2764 2785 +3 3101 1454 1910 +3 1865 1129 3176 +3 3067 1446 1916 +3 3177 3174 1911 +3 996 3091 3102 +3 1909 3099 3101 +3 3178 3171 1001 +3 1140 3096 3177 +3 3060 3059 1914 +3 3183 1475 1920 +3 825 3015 3186 +3 3137 1463 1915 +3 994 3062 3066 +3 1913 1444 3060 +3 2090 1185 3124 +3 1141 3068 3137 +3 3064 1142 3069 +3 1912 3135 3137 +3 850 3074 3090 +3 1919 1445 3064 +3 996 3094 3098 +3 3064 1445 1917 +3 994 3059 3070 +3 3092 3091 1918 +3 3129 3126 1922 +3 915 3099 3183 +3 2093 1461 3127 +3 1923 1472 3173 +3 3130 3123 998 +3 1921 1461 3129 +3 1874 1472 3171 +3 1143 3136 3185 +3 1926 1417 2952 +3 101 1738 3636 +3 1932 1418 2955 +3 2717 1358 1927 +3 987 2947 2958 +3 1925 2955 2957 +3 3547 1032 972 +3 1924 1358 2717 +3 2969 1421 1930 +3 2719 1359 1936 +3 2855 1393 1956 +3 1931 1361 2728 +3 2970 2963 988 +3 1929 2967 2969 +3 973 2723 2734 +3 1928 2731 2733 +3 2948 1416 1934 +3 1928 1145 2976 +3 848 2935 2978 +3 1935 1420 2965 +3 987 2950 2954 +3 1933 1416 2948 +3 1966 1154 2964 +3 1146 2956 2977 +3 2716 1147 2721 +3 1925 1144 2720 +3 3583 3606 3534 +3 1939 1357 2716 +3 973 2726 2730 +3 2716 1357 1937 +3 972 1032 3577 +3 2724 1360 1938 +3 1942 1393 2856 +3 1972 1269 2425 +3 2831 1387 1948 +3 2427 1269 1943 +3 981 2851 2862 +3 1941 2859 2861 +3 2428 2421 947 +3 1940 2425 2427 +3 2825 1385 1946 +3 1952 1259 2385 +3 2825 1149 1945 +3 1947 1256 2375 +3 2826 2819 979 +3 1945 2823 2825 +3 2330 1256 2373 +3 1944 2385 2387 +3 2821 1150 2833 +3 1944 1149 2832 +3 2834 2807 846 +3 1951 1384 2821 +3 981 2854 2858 +3 2821 1384 1949 +3 1806 1384 2819 +3 2852 1392 1950 +3 2379 1257 1954 +3 1941 1148 2434 +3 2333 1257 2377 +3 1955 1268 2423 +3 2380 2373 944 +3 1953 1257 2379 +3 1982 1158 2422 +3 1151 2386 2435 +3 1959 1395 2864 +3 1940 1148 2856 +3 1968 1395 2865 +3 2857 2854 1959 +3 988 2963 2974 +3 2864 2863 1957 +3 2858 2851 981 +3 2973 1422 1958 +3 1963 2803 2805 +3 2863 1395 1968 +3 2866 2759 824 +3 2817 1383 1963 +3 986 2934 2938 +3 2805 1380 1961 +3 1834 1121 2804 +3 2932 2931 1962 +3 2936 1154 2941 +3 2940 2939 1960 +3 848 2946 2962 +3 1967 1413 2936 +3 988 2966 2970 +3 2936 1413 1965 +3 986 2931 2942 +3 2964 2963 1966 +3 2809 2806 1970 +3 2939 1414 1964 +3 1837 1381 2807 +3 1971 1392 2853 +3 2810 2803 978 +3 1969 1381 2809 +3 1950 1392 2851 +3 1155 2816 2865 +3 2431 1270 1974 +3 1929 1145 2728 +3 2401 1263 1980 +3 2729 2726 1975 +3 947 2421 2432 +3 1973 2429 2431 +3 2730 2723 973 +3 1156 2426 2729 +3 2395 2392 1978 +3 2735 1363 1984 +3 2345 1261 2393 +3 2715 1356 1979 +3 2396 2389 945 +3 1977 1261 2395 +3 1027 1038 3594 +3 1157 2402 2715 +3 2391 1158 2403 +3 1976 2713 2715 +3 2404 2377 836 +3 1983 1260 2391 +3 947 2424 2428 +3 2391 1260 1981 +3 2354 1251 2390 +3 2422 2421 1982 +3 2711 1355 1986 +3 919 2429 2735 +3 844 3510 3583 +3 2737 2734 1987 +3 3527 1572 3576 +3 1985 1355 2711 +3 1938 1360 2723 +3 1159 2714 2737 +3 1990 1364 2741 +3 2546 1160 1988 +3 1996 1367 2751 +3 2546 1307 1991 +3 1882 1364 2739 +3 1989 2751 2753 +3 2547 2540 958 +3 1988 2544 2546 +3 2793 1377 1994 +3 2552 1309 2000 +3 2020 1377 2791 +3 1995 1315 2577 +3 2794 2787 977 +3 1993 2791 2793 +3 960 2572 2583 +3 1992 2580 2582 +3 2745 1365 1998 +3 1992 1161 2800 +3 1885 1365 2743 +3 1999 1376 2789 +3 2746 2739 974 +3 1997 1365 2745 +3 2030 1170 2788 +3 1162 2752 2801 +3 2542 1163 2554 +3 1989 1160 2553 +3 2555 2528 840 +3 2003 1306 2542 +3 960 2575 2579 +3 2542 1306 2001 +3 2146 1306 2540 +3 2573 1314 2002 +3 2006 1425 2984 +3 2036 1289 2483 +3 2959 1419 2012 +3 2485 1289 2007 +3 989 2979 2990 +3 2005 2987 2989 +3 2486 2479 953 +3 2004 2483 2485 +3 2953 1417 2010 +3 2016 1284 2468 +3 2953 1165 2009 +3 2011 1282 2465 +3 2954 2947 987 +3 2009 2951 2953 +3 1670 1613 3608 +3 2008 2468 2470 +3 2949 1166 2961 +3 2008 1165 2960 +3 2962 2935 848 +3 2015 1416 2949 +3 989 2982 2986 +3 2949 1416 2013 +3 1934 1416 2947 +3 2980 1424 2014 +3 2466 1283 2018 +3 2005 1164 2492 +3 2480 2471 2045 +3 2493 2490 2019 +3 951 3536 2467 +3 2017 1283 2466 +3 2046 1288 2479 +3 1167 2469 2493 +3 2797 1378 2022 +3 2004 1164 2984 +3 2767 1371 2028 +3 2985 2982 2023 +3 977 2787 2798 +3 2021 2795 2797 +3 2986 2979 989 +3 1168 2792 2985 +3 2761 2758 2026 +3 2991 1427 2032 +3 1897 1369 2759 +3 2945 1415 2027 +3 2762 2755 975 +3 2025 1369 2761 +3 1962 1153 2932 +3 1169 2768 2945 +3 2757 1170 2769 +3 2024 2943 2945 +3 2770 2743 845 +3 2031 1368 2757 +3 977 2790 2794 +3 2757 1368 2029 +3 1906 1139 2756 +3 2788 2787 2030 +3 2937 2934 2034 +3 922 2795 2991 +3 1965 1413 2935 +3 2035 1424 2981 +3 2938 2931 986 +3 2033 1413 2937 +3 2014 1424 2979 +3 1171 2944 2993 +3 2489 1290 2038 +3 1993 1161 2577 +3 2475 1287 2044 +3 2578 2575 2039 +3 953 2479 2490 +3 2037 2487 2489 +3 2579 2572 960 +3 1172 2484 2578 +3 2473 1286 2042 +3 2584 1317 2048 +3 3512 1286 2472 +3 2538 1305 2043 +3 2047 1287 2474 +3 2041 1286 2473 +3 2170 1205 2525 +3 1173 2476 2538 +3 2471 1174 2477 +3 2040 2536 2538 +3 2045 1285 3530 +3 2047 1285 2471 +3 953 2482 2486 +3 2471 1285 2045 +3 3549 1286 1557 +3 2480 1288 2046 +3 2530 2527 2050 +3 923 2487 2584 +3 2173 1303 2528 +3 2051 1314 2574 +3 2531 2524 957 +3 2049 1303 2530 +3 2002 1314 2572 +3 1175 2537 2586 +3 2054 1465 3144 +3 3401 1176 2052 +3 2060 1466 3147 +3 3401 1529 2055 +3 999 3139 3150 +3 2053 3147 3149 +3 3402 3395 1015 +3 2052 3399 3401 +3 3161 1469 2058 +3 3407 1531 2064 +3 3031 1437 2084 +3 2059 1537 3432 +3 3162 3155 1000 +3 2057 3159 3161 +3 1017 3427 3438 +3 2056 3435 3437 +3 3140 1464 2062 +3 2056 1177 3168 +3 851 3127 3170 +3 2063 1468 3157 +3 999 3142 3146 +3 2061 1464 3140 +3 2094 1186 3156 +3 1178 3148 3169 +3 3397 1179 3409 +3 2053 1176 3408 +3 3410 3383 855 +3 2067 1528 3397 +3 1017 3430 3434 +3 3397 1528 2065 +3 1826 1528 3395 +3 3428 1536 2066 +3 2070 1437 3032 +3 2100 1517 3351 +3 3003 1430 2076 +3 3353 1517 2071 +3 992 3027 3038 +3 2069 3035 3037 +3 3354 3347 1012 +3 2068 3351 3353 +3 2996 1428 2074 +3 2080 1514 3339 +3 2996 1181 2073 +3 2075 1513 3336 +3 990 2998 3002 +3 2073 2994 2996 +3 1011 3331 3342 +3 2072 3339 3341 +3 3000 1182 3005 +3 2072 1181 3004 +3 849 3010 3026 +3 2079 1429 3000 +3 992 3030 3034 +3 3000 1429 2077 +3 990 2995 3006 +3 3028 1436 2078 +3 3332 1512 2082 +3 2069 1180 3360 +3 854 3319 3362 +3 2083 1516 3349 +3 1011 3334 3338 +3 2081 1512 3332 +3 2110 1190 3348 +3 1183 3340 3361 +3 2087 1439 3040 +3 2068 1180 3032 +3 2096 1439 3041 +3 3033 3030 2087 +3 1000 3155 3166 +3 3040 3039 2085 +3 3034 3027 992 +3 3165 1470 2086 +3 2091 3014 3016 +3 3039 1439 2096 +3 825 3058 3122 +3 3021 1434 2091 +3 998 3126 3130 +3 3016 1433 2089 +3 991 3011 3022 +3 3124 3123 2090 +3 3128 1186 3133 +3 3132 3131 2088 +3 851 3138 3154 +3 2095 1461 3128 +3 1000 3158 3162 +3 3128 1461 2093 +3 998 3123 3134 +3 3156 3155 2094 +3 3012 3011 2098 +3 3131 1462 2092 +3 849 2999 3042 +3 2099 1436 3029 +3 991 3014 3018 +3 2097 1432 3012 +3 2078 1436 3027 +3 1187 3020 3041 +3 3357 1518 2102 +3 2057 1177 3432 +3 3323 1510 2108 +3 3433 3430 2103 +3 1012 3347 3358 +3 2101 3355 3357 +3 3434 3427 1017 +3 1188 3352 3433 +3 3316 3315 2106 +3 3439 1539 2112 +3 826 3271 3442 +3 3393 1527 2107 +3 1010 3318 3322 +3 2105 1508 3316 +3 1850 1125 3380 +3 1189 3324 3393 +3 3320 1190 3325 +3 2104 3391 3393 +3 854 3330 3346 +3 2111 1509 3320 +3 1012 3350 3354 +3 3320 1509 2109 +3 1010 3315 3326 +3 3348 3347 2110 +3 3385 3382 2114 +3 927 3355 3439 +3 1853 1525 3383 +3 2115 1536 3429 +3 3386 3379 1014 +3 2113 1525 3385 +3 2066 1536 3427 +3 1191 3392 3441 +3 2118 1481 3208 +3 100 1727 3627 +3 2124 1482 3211 +3 2494 1292 2119 +3 1003 3203 3214 +3 2117 3211 3213 +3 954 3521 2496 +3 2116 1292 2494 +3 3225 1485 2122 +3 2497 1294 2128 +3 3111 1457 2148 +3 2123 1299 2513 +3 3226 3219 1004 +3 2121 3223 3225 +3 956 2508 2519 +3 2120 2516 2518 +3 3204 1480 2126 +3 2120 1193 3232 +3 852 3191 3234 +3 2127 1484 3221 +3 1003 3206 3210 +3 2125 1480 3204 +3 2158 1202 3220 +3 1194 3212 3233 +3 2495 1195 2499 +3 2117 1192 2498 +3 2129 1293 3507 +3 2131 1293 2495 +3 956 2511 2515 +3 2495 1293 2129 +3 954 1029 3569 +3 2509 1298 2130 +3 2134 1457 3112 +3 2512 1299 2164 +3 3087 1451 2140 +3 2562 1311 2135 +3 997 3107 3118 +3 2133 3115 3117 +3 2563 2556 959 +3 2132 2560 2562 +3 3081 1449 2138 +3 2144 1308 2548 +3 3081 1197 2137 +3 2139 1307 2545 +3 3082 3075 995 +3 2137 3079 3081 +3 958 2540 2551 +3 2136 2548 2550 +3 3077 1198 3089 +3 2136 1197 3088 +3 3090 3063 850 +3 2143 1448 3077 +3 997 3110 3114 +3 3077 1448 2141 +3 1890 1448 3075 +3 3108 1456 2142 +3 2541 1306 2146 +3 2133 1196 2569 +3 840 2528 2571 +3 2147 1310 2558 +3 958 2543 2547 +3 2145 1306 2541 +3 2174 1206 2557 +3 1199 2549 2570 +3 2151 1459 3120 +3 2132 1196 3112 +3 2160 1459 3121 +3 3113 3110 2151 +3 1004 3219 3230 +3 3120 3119 2149 +3 3114 3107 997 +3 3229 1486 2150 +3 2155 3059 3061 +3 3119 1459 2160 +3 3122 3015 825 +3 3073 1447 2155 +3 1002 3190 3194 +3 3061 1444 2153 +3 1914 1141 3060 +3 3188 3187 2154 +3 3192 1202 3197 +3 3196 3195 2152 +3 852 3202 3218 +3 2159 1477 3192 +3 1004 3222 3226 +3 3192 1477 2157 +3 1002 3187 3198 +3 3220 3219 2158 +3 3065 3062 2162 +3 3195 1478 2156 +3 1917 1445 3063 +3 2163 1456 3109 +3 3066 3059 994 +3 2161 1445 3065 +3 2142 1456 3107 +3 1203 3072 3121 +3 2167 1301 2521 +3 2121 1193 2513 +3 2176 1301 2522 +3 2514 2511 2167 +3 959 2556 2567 +3 2521 2520 2165 +3 2515 2508 956 +3 2566 1312 2166 +3 2171 3550 2502 +3 2520 1301 2176 +3 68 2472 2523 +3 2506 1297 2171 +3 957 2527 2531 +3 2502 1296 2169 +3 3555 1558 3550 +3 2525 2524 2170 +3 2529 1206 2534 +3 2533 2532 2168 +3 840 2539 2555 +3 2175 1303 2529 +3 959 2559 2563 +3 2529 1303 2173 +3 957 2524 2535 +3 2557 2556 2174 +3 2500 1295 2178 +3 2532 1304 2172 +3 2509 2495 2129 +3 2522 2519 2179 +3 2178 1295 3520 +3 2177 1295 2500 +3 2130 1298 2508 +3 1207 2505 2522 +3 2182 1428 2997 +3 2639 1208 2180 +3 2188 1431 3007 +3 2639 1333 2183 +3 2074 1428 2995 +3 2181 3007 3009 +3 2640 2633 965 +3 2180 2637 2639 +3 3049 1441 2186 +3 2645 1335 2192 +3 2212 1441 3047 +3 2187 1341 2670 +3 3050 3043 993 +3 2185 3047 3049 +3 967 2665 2676 +3 2184 2673 2675 +3 3001 1429 2190 +3 2184 1209 3056 +3 2077 1429 2999 +3 2191 1440 3045 +3 3002 2995 990 +3 2189 1429 3001 +3 2222 1218 3044 +3 1210 3008 3057 +3 2635 1211 2647 +3 2181 1208 2646 +3 2648 2621 842 +3 2195 1332 2635 +3 967 2668 2672 +3 2635 1332 2193 +3 2274 1332 2633 +3 2666 1340 2194 +3 2198 1489 3240 +3 2228 1325 2605 +3 3215 1483 2204 +3 2607 1325 2199 +3 1005 3235 3246 +3 2197 3243 3245 +3 2608 2601 963 +3 2196 2605 2607 +3 3209 1481 2202 +3 2208 1320 2590 +3 3209 1213 2201 +3 2203 1318 2587 +3 3210 3203 1003 +3 2201 3207 3209 +3 1678 1621 3612 +3 2200 2590 2592 +3 3205 1214 3217 +3 2200 1213 3216 +3 3218 3191 852 +3 2207 1480 3205 +3 1005 3238 3242 +3 3205 1480 2205 +3 2126 1480 3203 +3 3236 1488 2206 +3 2588 1319 2210 +3 2197 1212 2614 +3 2602 2593 2237 +3 2615 2612 2211 +3 961 3540 2589 +3 2209 1319 2588 +3 2238 1324 2601 +3 1215 2591 2615 +3 3053 1442 2214 +3 2196 1212 3240 +3 3023 1435 2220 +3 3241 3238 2215 +3 993 3043 3054 +3 2213 3051 3053 +3 3242 3235 1005 +3 1216 3048 3241 +3 3017 3014 2218 +3 3247 1491 2224 +3 2089 1433 3015 +3 3201 1479 2219 +3 3018 3011 991 +3 2217 1433 3017 +3 2154 1201 3188 +3 1217 3024 3201 +3 3013 1218 3025 +3 2216 3199 3201 +3 3026 2999 849 +3 2223 1432 3013 +3 993 3046 3050 +3 3013 1432 2221 +3 2098 1187 3012 +3 3044 3043 2222 +3 3193 3190 2226 +3 934 3051 3247 +3 2157 1477 3191 +3 2227 1488 3237 +3 3194 3187 1002 +3 2225 1477 3193 +3 2206 1488 3235 +3 1219 3200 3249 +3 2611 1326 2230 +3 2185 1209 2670 +3 2597 1323 2236 +3 2671 2668 2231 +3 963 2601 2612 +3 2229 2609 2611 +3 2672 2665 967 +3 1220 2606 2671 +3 2595 1322 2234 +3 2677 1343 2240 +3 3514 1322 2594 +3 2631 1331 2235 +3 2239 1323 2596 +3 2233 1322 2595 +3 2298 1237 2618 +3 1221 2598 2631 +3 2593 1222 2599 +3 2232 2629 2631 +3 2237 1321 3532 +3 2239 1321 2593 +3 963 2604 2608 +3 2593 1321 2237 +3 3551 1322 1561 +3 2602 1324 2238 +3 2623 2620 2242 +3 935 2609 2677 +3 2301 1329 2621 +3 2243 1340 2667 +3 2624 2617 964 +3 2241 1329 2623 +3 2194 1340 2665 +3 1223 2630 2679 +3 2246 1545 3464 +3 1733 1088 1682 +3 2252 1546 3467 +3 2688 1348 2247 +3 1019 3459 3470 +3 2245 3467 3469 +3 3542 1031 969 +3 2244 1348 2688 +3 3481 1549 2250 +3 2690 1349 2256 +3 3367 1521 2276 +3 2251 1351 2699 +3 3482 3475 1020 +3 2249 3479 3481 +3 970 2694 2705 +3 2248 2702 2704 +3 3460 1544 2254 +3 2248 1225 3488 +3 856 3447 3490 +3 2255 1548 3477 +3 1019 3462 3466 +3 2253 1544 3460 +3 2286 1234 3476 +3 1226 3468 3489 +3 2687 1227 2692 +3 2245 1224 2691 +3 3581 3605 3533 +3 2259 1347 2687 +3 970 2697 2701 +3 2687 1347 2257 +3 969 1031 3572 +3 2695 1350 2258 +3 2262 1521 3368 +3 2292 1337 2653 +3 3343 1515 2268 +3 2655 1337 2263 +3 1013 3363 3374 +3 2261 3371 3373 +3 2656 2649 966 +3 2260 2653 2655 +3 3337 1513 2266 +3 2272 1334 2641 +3 3337 1229 2265 +3 2267 1333 2638 +3 3338 3331 1011 +3 2265 3335 3337 +3 965 2633 2644 +3 2264 2641 2643 +3 3333 1230 3345 +3 2264 1229 3344 +3 3346 3319 854 +3 2271 1512 3333 +3 1013 3366 3370 +3 3333 1512 2269 +3 2082 1512 3331 +3 3364 1520 2270 +3 2634 1332 2274 +3 2261 1228 2662 +3 842 2621 2664 +3 2275 1336 2651 +3 965 2636 2640 +3 2273 1332 2634 +3 2302 1238 2650 +3 1231 2642 2663 +3 2279 1523 3376 +3 2260 1228 3368 +3 2288 1523 3377 +3 3369 3366 2279 +3 1020 3475 3486 +3 3376 3375 2277 +3 3370 3363 1013 +3 3485 1550 2278 +3 2283 3315 3317 +3 3375 1523 2288 +3 3378 3271 826 +3 3329 1511 2283 +3 1018 3446 3450 +3 3317 1508 2281 +3 2106 1189 3316 +3 3444 3443 2282 +3 3448 1234 3453 +3 3452 3451 2280 +3 856 3458 3474 +3 2287 1541 3448 +3 1020 3478 3482 +3 3448 1541 2285 +3 1018 3443 3454 +3 3476 3475 2286 +3 3321 3318 2290 +3 3451 1542 2284 +3 2109 1509 3319 +3 2291 1520 3365 +3 3322 3315 1010 +3 2289 1509 3321 +3 2270 1520 3363 +3 1235 3328 3377 +3 2659 1338 2294 +3 2249 1225 2699 +3 2625 1330 2300 +3 2700 2697 2295 +3 966 2649 2660 +3 2293 2657 2659 +3 2701 2694 970 +3 1236 2654 2700 +3 2618 2617 2298 +3 2706 1353 2304 +3 36 2594 2616 +3 2686 1346 2299 +3 964 2620 2624 +3 2297 1328 2618 +3 1025 1037 3593 +3 1237 2626 2686 +3 2622 1238 2627 +3 2296 2684 2686 +3 842 2632 2648 +3 2303 1329 2622 +3 966 2652 2656 +3 2622 1329 2301 +3 964 2617 2628 +3 2650 2649 2302 +3 2682 1345 2306 +3 939 2657 2706 +3 843 3509 3581 +3 2708 2705 2307 +3 3524 1571 3573 +3 2305 1345 2682 +3 2258 1350 2694 +3 1239 2685 2708 +3 2310 1276 2444 +3 3465 1240 2308 +3 2316 1277 2446 +3 3465 1545 2311 +3 1690 1633 3618 +3 2309 2446 2448 +3 3466 3459 1019 +3 2308 3463 3465 +3 2456 1279 2314 +3 3471 1547 2320 +3 2409 1265 2340 +3 2315 1553 3496 +3 2457 2450 950 +3 2313 2454 2456 +3 1021 3491 3502 +3 2312 3499 3501 +3 2443 1275 2318 +3 2312 1241 2463 +3 2451 2438 2349 +3 2464 2461 2319 +3 949 3544 2445 +3 2317 1275 2443 +3 2350 1278 2450 +3 1242 2447 2464 +3 3461 1243 3473 +3 2309 1240 3472 +3 3474 3447 856 +3 2323 1544 3461 +3 1021 3494 3498 +3 3461 1544 2321 +3 2254 1544 3459 +3 3492 1552 2322 +3 2326 1265 2410 +3 2356 1505 3303 +3 2381 1258 2332 +3 3305 1505 2327 +3 946 2405 2416 +3 2325 2413 2415 +3 3306 3299 1009 +3 2324 3303 3305 +3 2374 1256 2330 +3 2336 1495 3263 +3 2374 1245 2329 +3 2331 1492 3253 +3 944 2376 2380 +3 2329 2372 2374 +3 1799 1492 3251 +3 2328 3263 3265 +3 2378 1246 2383 +3 2328 1245 2382 +3 836 2388 2404 +3 2335 1257 2378 +3 946 2408 2412 +3 2378 1257 2333 +3 944 2373 2384 +3 2406 1264 2334 +3 3257 1493 2338 +3 2325 1244 3312 +3 1809 1493 3255 +3 2339 1504 3301 +3 3258 3251 1006 +3 2337 1493 3257 +3 2366 1254 3300 +3 1247 3264 3313 +3 2343 1267 2418 +3 2324 1244 2410 +3 2352 1267 2419 +3 2411 2408 2343 +3 950 2450 2461 +3 2418 2417 2341 +3 2412 2405 946 +3 2460 1280 2342 +3 2347 2392 2394 +3 2417 1267 2352 +3 3517 1272 2436 +3 2399 1262 2347 +3 2351 1274 2439 +3 2394 1261 2345 +3 945 2389 2400 +3 2437 1272 2346 +3 2438 1250 2442 +3 2441 2440 2344 +3 2349 1273 3535 +3 2351 1273 2438 +3 950 2453 2457 +3 2438 1273 2349 +3 3548 3559 948 +3 2451 1278 2350 +3 2390 2389 2354 +3 2440 1274 2348 +3 836 2377 2420 +3 2355 1264 2407 +3 945 2392 2396 +3 2353 1260 2390 +3 2334 1264 2405 +3 1251 2398 2419 +3 3309 1506 2358 +3 2313 1241 3496 +3 3279 1499 2364 +3 3497 3494 2359 +3 1009 3299 3310 +3 2357 3307 3309 +3 3498 3491 1021 +3 1252 3304 3497 +3 3273 3270 2362 +3 3503 1555 2368 +3 1849 1497 3271 +3 3457 1543 2363 +3 3274 3267 1007 +3 2361 1497 3273 +3 2282 1233 3444 +3 1253 3280 3457 +3 3269 1254 3281 +3 2360 3455 3457 +3 3282 3255 853 +3 2367 1496 3269 +3 1009 3302 3306 +3 3269 1496 2365 +3 1858 1127 3268 +3 3300 3299 2366 +3 3449 3446 2370 +3 943 3307 3503 +3 2285 1541 3447 +3 2371 1552 3493 +3 3450 3443 1018 +3 2369 1541 3449 +3 2322 1552 3491 +3 1255 3456 3505 +3 2387 1259 1947 +3 1945 1149 2375 +3 2384 2376 944 +3 1256 2372 2375 +3 2382 1245 2374 +3 1947 1259 2384 +3 2375 2372 1945 +3 2372 99 1945 +3 2423 1268 1953 +3 1954 1257 2376 +3 2420 2388 836 +3 1954 1259 2386 +3 2406 1246 2378 +3 1953 1268 2420 +3 2386 1151 2379 +3 2384 1259 1954 +3 2414 1266 2332 +3 2376 1257 2335 +3 2413 941 2381 +3 2335 2378 2383 +3 2382 2381 2328 +3 2381 941 2328 +3 2332 1258 2383 +3 2380 2376 2335 +3 2387 2385 1259 +3 2373 1256 1947 +3 2387 1149 1944 +3 1944 917 2385 +3 2423 1151 2435 +3 1947 2375 2387 +3 2375 1149 2387 +3 2384 2373 1947 +3 2403 1263 1983 +3 1981 1260 2388 +3 2400 2392 945 +3 1981 1268 2422 +3 2354 1262 2398 +3 2396 1262 2354 +3 2422 1158 2391 +3 2420 1268 1981 +3 2710 1354 1977 +3 1978 1157 2395 +3 1 0 2393 +3 1261 2392 2395 +3 2437 1249 2394 +3 1977 1354 2709 +3 1978 1263 2402 +3 2400 1263 1978 +3 2399 2397 1262 +3 2394 1249 2347 +3 2440 942 2397 +3 2344 2399 2441 +3 2407 1251 2419 +3 2397 942 2352 +3 2344 2397 2399 +3 2396 2392 2347 +3 2430 2429 1980 +3 2389 1260 1983 +3 1980 2403 2430 +3 1983 2391 2403 +3 1979 3553 2710 +3 2715 2402 1976 +3 1980 1263 2403 +3 2400 2389 1983 +3 2419 1267 2355 +3 2388 1260 2353 +3 2416 2408 946 +3 2353 2390 2407 +3 2414 1246 2406 +3 2355 1267 2416 +3 2390 1251 2407 +3 2404 2388 2353 +3 2455 1279 2340 +3 2343 1248 2411 +3 2454 835 2409 +3 1265 2408 2411 +3 2410 2409 2324 +3 2409 835 2324 +3 2340 1265 2411 +3 2416 1267 2343 +3 2415 2413 1266 +3 2408 1265 2326 +3 2415 1244 2325 +3 2325 941 2413 +3 2414 2383 1246 +3 2326 2410 2415 +3 2410 1244 2415 +3 2412 2408 2326 +3 2419 2398 2352 +3 2405 1264 2355 +3 2341 2458 2460 +3 2355 2407 2419 +3 2460 1248 2418 +3 2460 2418 2341 +3 2398 2397 2352 +3 2416 2405 2355 +3 2435 1271 1955 +3 2377 1257 1953 +3 2432 2424 947 +3 1953 2379 2423 +3 1982 1270 2430 +3 2428 1270 1982 +3 2379 1151 2423 +3 2420 2377 1953 +3 2427 2425 1269 +3 1943 1269 2424 +3 2427 1148 1940 +3 1940 829 2425 +3 1975 1363 2736 +3 1943 1271 2434 +3 2434 1148 2427 +3 2432 1271 1943 +3 2431 2429 1270 +3 2426 1156 1974 +3 1984 1363 2737 +3 1973 2431 2736 +3 2430 2403 1158 +3 2429 919 1980 +3 1974 2424 2426 +3 2428 2424 1974 +3 2435 2386 1952 +3 2421 1268 1955 +3 2385 917 2433 +3 1955 2423 2435 +3 2434 2433 1941 +3 2433 917 1941 +3 2386 1259 1952 +3 2432 2421 1955 +3 3517 28 1566 +3 2436 2393 0 +3 2346 1272 3548 +3 2436 2 3517 +3 2346 2439 2441 +3 1566 28 3565 +3 2349 2449 2451 +3 3548 1272 1566 +3 2317 2443 2452 +3 3649 3607 1045 +3 2451 1250 2438 +3 1056 1669 3641 +3 2459 2458 2348 +3 3559 1585 3595 +3 2348 2442 2459 +3 2351 2438 2442 +3 2441 2399 1249 +3 2440 2397 2344 +3 2348 1274 2442 +3 2439 948 2351 +3 2318 1277 2447 +3 2318 1275 3529 +3 3545 1584 1567 +3 2447 1242 2443 +3 1584 1596 3574 +3 2308 1240 2444 +3 1690 1741 3643 +3 2444 1276 2308 +3 3643 1741 102 +3 2448 2446 1277 +3 3544 1033 3618 +3 2448 1240 2309 +3 2309 940 2446 +3 2319 1278 2452 +3 2310 2444 2448 +3 2444 1240 2448 +3 2445 3544 2310 +3 2452 1242 2319 +3 3511 1567 1275 +3 2461 2453 950 +3 1278 2449 2452 +3 2350 1280 2459 +3 2319 1242 2464 +3 2443 1242 2452 +3 2449 837 2317 +3 2456 2454 1279 +3 2314 1279 2453 +3 2456 1241 2313 +3 2313 835 2454 +3 2455 2411 1248 +3 2314 1281 2463 +3 2463 1241 2456 +3 2461 1281 2314 +3 2460 2458 1280 +3 2455 1248 2342 +3 2458 2417 942 +3 2341 2417 2458 +3 2459 2442 1250 +3 2458 942 2348 +3 2342 2453 2455 +3 2457 2453 2342 +3 2464 2447 2316 +3 2450 1278 2319 +3 2446 940 2462 +3 1281 2461 2464 +3 2463 2462 2312 +3 2462 940 2312 +3 2447 1277 2316 +3 2461 2450 2319 +3 2009 1282 3623 +3 2009 1165 2465 +3 2465 1282 2009 +3 1670 1726 3623 +3 2481 2478 2017 +3 2018 1283 3519 +3 2018 1284 2469 +3 2469 1167 2466 +3 2467 1284 2018 +3 2470 2468 1284 +3 3536 1028 3608 +3 2470 1165 2008 +3 2008 921 2468 +3 2019 1288 2481 +3 2011 2465 2470 +3 2465 1165 2470 +3 2467 3536 2011 +3 2477 1287 2047 +3 2017 2466 2481 +3 3549 3554 952 +3 2045 2478 2480 +3 2480 1174 2471 +3 3578 3506 838 +3 2526 1302 2041 +3 2042 1286 3549 +3 2523 2501 68 +3 2042 1173 2473 +3 2042 2474 2476 +3 2476 1173 2042 +3 2488 2487 2044 +3 3518 1568 1285 +3 2044 2477 2488 +3 2047 2471 2477 +3 2043 2524 2526 +3 2538 2476 2040 +3 2044 1287 2477 +3 2474 952 2047 +3 2481 1167 2019 +3 3530 3602 3578 +3 2490 2482 953 +3 1288 2478 2481 +3 2046 1290 2488 +3 2019 1167 2493 +3 2466 1167 2481 +3 2478 838 2017 +3 2485 2483 1289 +3 2007 1289 2482 +3 2485 1164 2004 +3 2004 830 2483 +3 2039 1317 2585 +3 2007 1291 2492 +3 2492 1164 2485 +3 2490 1291 2007 +3 2489 2487 1290 +3 2484 1172 2038 +3 2048 1317 2586 +3 2037 2489 2585 +3 2488 2477 1174 +3 2487 923 2044 +3 2038 2482 2484 +3 2486 2482 2038 +3 2493 2469 2016 +3 2479 1288 2019 +3 2468 921 2491 +3 1291 2490 2493 +3 2492 2491 2005 +3 2491 921 2005 +3 2469 1284 2016 +3 2490 2479 2019 +3 2496 1294 2119 +3 3569 1559 3521 +3 2498 1192 2494 +3 1292 1617 3539 +3 3507 839 2129 +3 3579 1599 3531 +3 2509 1195 2495 +3 1293 1559 3507 +3 2517 1300 2128 +3 3521 1293 2131 +3 2516 928 2497 +3 2131 2495 2499 +3 2498 2497 2117 +3 2497 928 2117 +3 2128 1294 2499 +3 2496 3521 2131 +3 3568 1023 3520 +3 2503 1297 2178 +3 2178 1297 2505 +3 1295 1569 3520 +3 3513 67 2501 +3 3513 69 67 +3 2523 1302 2169 +3 2525 1205 2502 +3 1296 1558 3513 +3 2506 2504 1297 +3 2502 1205 2171 +3 2532 931 2504 +3 2168 2506 2533 +3 2179 1298 2510 +3 2504 931 2176 +3 2168 2504 2506 +3 2503 3550 2171 +3 2510 1207 2179 +3 839 3507 3579 +3 2519 2511 956 +3 1298 2507 2510 +3 2130 2515 2517 +3 2179 1207 2522 +3 2500 1207 2510 +3 2507 839 2177 +3 2561 1311 2164 +3 2167 1204 2514 +3 2560 832 2512 +3 1299 2511 2514 +3 2513 2512 2121 +3 2512 832 2121 +3 2164 1299 2514 +3 2519 1301 2167 +3 2518 2516 1300 +3 2511 1299 2123 +3 2518 1193 2120 +3 2120 928 2516 +3 2517 2499 1195 +3 2123 2513 2518 +3 2513 1193 2518 +3 2515 2511 2123 +3 2522 2505 2176 +3 2508 1298 2179 +3 2165 2564 2566 +3 1301 2519 2522 +3 2566 1204 2521 +3 2566 2521 2165 +3 2505 2504 2176 +3 2519 2508 2179 +3 2526 2524 1302 +3 2472 1286 2041 +3 2535 2527 957 +3 2043 1305 2535 +3 2170 1304 2533 +3 2531 1304 2170 +3 2473 1173 2526 +3 2523 2472 2041 +3 2574 1314 2049 +3 2050 1175 2530 +3 2571 2539 840 +3 1303 2527 2530 +3 2557 1206 2529 +3 2049 1314 2571 +3 2050 1305 2537 +3 2535 1305 2050 +3 2565 2564 2172 +3 2527 1303 2175 +3 2172 2534 2565 +3 2175 2529 2534 +3 2533 2506 1205 +3 2532 2504 2168 +3 2172 1304 2534 +3 2531 2527 2175 +3 2538 2536 1305 +3 2526 1173 2043 +3 2475 923 2536 +3 2040 2475 2536 +3 2574 1175 2586 +3 2536 923 2048 +3 2476 2475 2040 +3 2535 2524 2043 +3 2554 1309 2003 +3 2001 1306 2539 +3 2551 2543 958 +3 2001 1314 2573 +3 2549 1199 2541 +3 2003 1309 2551 +3 2573 1163 2542 +3 2571 1314 2001 +3 2546 2544 1307 +3 1991 1307 2543 +3 2137 1197 2545 +3 1988 96 2544 +3 2545 2544 2137 +3 2544 96 2137 +3 2553 1160 2546 +3 2551 1309 1991 +3 2550 2548 1308 +3 2543 1307 2139 +3 2550 1197 2136 +3 2136 929 2548 +3 2558 1199 2570 +3 2139 2545 2550 +3 2545 1197 2550 +3 2547 2543 2139 +3 2581 1316 2000 +3 2540 1306 2003 +3 2580 920 2552 +3 2003 2542 2554 +3 2553 2552 1989 +3 2552 920 1989 +3 2000 1309 2554 +3 2551 2540 2003 +3 2570 1313 2147 +3 2539 1306 2145 +3 2567 2559 959 +3 2145 2541 2558 +3 2174 1312 2565 +3 2563 1312 2174 +3 2541 1199 2558 +3 2555 2539 2145 +3 2562 2560 1311 +3 2135 1311 2559 +3 2562 1196 2132 +3 2132 832 2560 +3 2561 2514 1204 +3 2135 1313 2569 +3 2569 1196 2562 +3 2567 1313 2135 +3 2566 2564 1312 +3 2561 1204 2166 +3 2564 2520 931 +3 2165 2520 2564 +3 2565 2534 1206 +3 2564 931 2172 +3 2166 2559 2561 +3 2563 2559 2166 +3 2570 2549 2144 +3 2556 1310 2147 +3 2548 929 2568 +3 2147 2558 2570 +3 2569 2568 2133 +3 2568 929 2133 +3 2549 1308 2144 +3 2567 2556 2147 +3 2586 1317 2051 +3 2528 1303 2049 +3 2583 2575 960 +3 2049 2530 2574 +3 2581 1163 2573 +3 2051 1317 2583 +3 2530 1175 2574 +3 2571 2528 2049 +3 2578 2484 2036 +3 2039 1172 2578 +3 2483 830 2576 +3 1315 2575 2578 +3 2577 2576 1993 +3 2576 830 1993 +3 2484 1289 2036 +3 2583 1317 2039 +3 2582 2580 1316 +3 2575 1315 1995 +3 2582 1161 1992 +3 1992 920 2580 +3 2581 2554 1163 +3 1995 2577 2582 +3 2577 1161 2582 +3 2579 2575 1995 +3 2586 2537 2048 +3 2572 1314 2051 +3 2585 2584 2037 +3 2051 2574 2586 +3 2489 1172 2585 +3 2584 2487 2037 +3 2537 2536 2048 +3 2583 2572 2051 +3 2201 1318 3631 +3 2201 1213 2587 +3 2587 1318 2201 +3 1678 1732 3631 +3 2603 2600 2209 +3 2210 1319 3523 +3 2210 1320 2591 +3 2591 1215 2588 +3 2589 1320 2210 +3 2592 2590 1320 +3 3540 1030 3612 +3 2592 1213 2200 +3 2200 933 2590 +3 2211 1324 2603 +3 2203 2587 2592 +3 2587 1213 2592 +3 2589 3540 2203 +3 2599 1323 2239 +3 2209 2588 2603 +3 3551 3556 962 +3 2237 2600 2602 +3 2602 1222 2593 +3 3580 3508 841 +3 2619 1328 2233 +3 2234 1322 3551 +3 3515 37 35 +3 2234 1221 2595 +3 2234 2596 2598 +3 2598 1221 2234 +3 2610 2609 2236 +3 3522 1570 1321 +3 2236 2599 2610 +3 2239 2593 2599 +3 2235 2617 2619 +3 2631 2598 2232 +3 2236 1323 2599 +3 2596 962 2239 +3 2603 1215 2211 +3 3532 3604 3580 +3 2612 2604 963 +3 1324 2600 2603 +3 2238 1326 2610 +3 2211 1215 2615 +3 2588 1215 2603 +3 2600 841 2209 +3 2607 2605 1325 +3 2199 1325 2604 +3 2607 1212 2196 +3 2196 833 2605 +3 2231 1343 2678 +3 2199 1327 2614 +3 2614 1212 2607 +3 2612 1327 2199 +3 2611 2609 1326 +3 2606 1220 2230 +3 2240 1343 2679 +3 2229 2611 2678 +3 2610 2599 1222 +3 2609 935 2236 +3 2230 2604 2606 +3 2608 2604 2230 +3 2615 2591 2208 +3 2601 1324 2211 +3 2590 933 2613 +3 1327 2612 2615 +3 2614 2613 2197 +3 2613 933 2197 +3 2591 1320 2208 +3 2612 2601 2211 +3 2619 2617 1328 +3 2594 1322 2233 +3 2628 2620 964 +3 2235 1331 2628 +3 2298 1330 2626 +3 2624 1330 2298 +3 2595 1221 2619 +3 2616 2594 2233 +3 2667 1340 2241 +3 2242 1223 2623 +3 2664 2632 842 +3 1329 2620 2623 +3 2650 1238 2622 +3 2241 1340 2664 +3 2242 1331 2630 +3 2628 1331 2242 +3 2658 2657 2300 +3 2620 1329 2303 +3 2300 2627 2658 +3 2303 2622 2627 +3 2299 3552 2681 +3 2686 2626 2296 +3 2300 1330 2627 +3 2624 2620 2303 +3 2631 2629 1331 +3 2619 1221 2235 +3 2597 935 2629 +3 2232 2597 2629 +3 2667 1223 2679 +3 2629 935 2240 +3 2598 2597 2232 +3 2628 2617 2235 +3 2647 1335 2195 +3 2193 1332 2632 +3 2644 2636 965 +3 2193 1340 2666 +3 2642 1231 2634 +3 2195 1335 2644 +3 2666 1211 2635 +3 2664 1340 2193 +3 2639 2637 1333 +3 2183 1333 2636 +3 2265 1229 2638 +3 2180 98 2637 +3 2638 2637 2265 +3 2637 98 2265 +3 2646 1208 2639 +3 2644 1335 2183 +3 2643 2641 1334 +3 2636 1333 2267 +3 2643 1229 2264 +3 2264 937 2641 +3 2651 1231 2663 +3 2267 2638 2643 +3 2638 1229 2643 +3 2640 2636 2267 +3 2674 1342 2192 +3 2633 1332 2195 +3 2673 932 2645 +3 2195 2635 2647 +3 2646 2645 2181 +3 2645 932 2181 +3 2192 1335 2647 +3 2644 2633 2195 +3 2663 1339 2275 +3 2632 1332 2273 +3 2660 2652 966 +3 2273 2634 2651 +3 2302 1338 2658 +3 2656 1338 2302 +3 2634 1231 2651 +3 2648 2632 2273 +3 2655 2653 1337 +3 2263 1337 2652 +3 2655 1228 2260 +3 2260 834 2653 +3 2295 1353 2707 +3 2263 1339 2662 +3 2662 1228 2655 +3 2660 1339 2263 +3 2659 2657 1338 +3 2654 1236 2294 +3 2304 1353 2708 +3 2293 2659 2707 +3 2658 2627 1238 +3 2657 939 2300 +3 2294 2652 2654 +3 2656 2652 2294 +3 2663 2642 2272 +3 2649 1336 2275 +3 2641 937 2661 +3 2275 2651 2663 +3 2662 2661 2261 +3 2661 937 2261 +3 2642 1334 2272 +3 2660 2649 2275 +3 2679 1343 2243 +3 2621 1329 2241 +3 2676 2668 967 +3 2241 2623 2667 +3 2674 1211 2666 +3 2243 1343 2676 +3 2623 1223 2667 +3 2664 2621 2241 +3 2671 2606 2228 +3 2231 1220 2671 +3 2605 833 2669 +3 1341 2668 2671 +3 2670 2669 2185 +3 2669 833 2185 +3 2606 1325 2228 +3 2676 1343 2231 +3 2675 2673 1342 +3 2668 1341 2187 +3 2675 1209 2184 +3 2184 932 2673 +3 2674 2647 1211 +3 2187 2670 2675 +3 2670 1209 2675 +3 2672 2668 2187 +3 2679 2630 2240 +3 2665 1340 2243 +3 2678 2677 2229 +3 2243 2667 2679 +3 2611 1220 2678 +3 2677 2609 2229 +3 2630 2629 2240 +3 2676 2665 2243 +3 2681 3552 1344 +3 2616 1328 2297 +3 2299 1346 2683 +3 2618 1237 2681 +3 2680 2616 2297 +3 968 3552 2683 +3 2306 1239 2682 +3 2306 1346 2685 +3 3524 968 2306 +3 2686 2684 1346 +3 2681 1237 2299 +3 2625 939 2684 +3 2296 2625 2684 +3 2307 1350 2696 +3 2684 939 2304 +3 2626 2625 2296 +3 2683 3552 2299 +3 2305 2682 2696 +3 2257 2693 2695 +3 2695 1227 2687 +3 3509 843 2257 +3 2247 1348 3542 +3 2247 1349 2691 +3 2691 1224 2688 +3 2689 1349 2247 +3 2703 1352 2256 +3 3525 1347 2259 +3 2702 936 2690 +3 2259 2687 2692 +3 2691 2690 2245 +3 2690 936 2245 +3 2256 1349 2692 +3 2689 3525 2259 +3 2696 1239 2307 +3 3533 1345 2305 +3 2705 2697 970 +3 1350 2693 2696 +3 2258 2701 2703 +3 2307 1239 2708 +3 2682 1239 2696 +3 2693 843 2305 +3 2700 2654 2292 +3 2295 1236 2700 +3 2653 834 2698 +3 1351 2697 2700 +3 2699 2698 2249 +3 2698 834 2249 +3 2654 1337 2292 +3 2705 1353 2295 +3 2704 2702 1352 +3 2697 1351 2251 +3 2704 1225 2248 +3 2248 936 2702 +3 2703 2692 1227 +3 2251 2699 2704 +3 2699 1225 2704 +3 2701 2697 2251 +3 2708 2685 2304 +3 2694 1350 2307 +3 2707 2706 2293 +3 1353 2705 2708 +3 2659 1236 2707 +3 2706 2657 2293 +3 2685 2684 2304 +3 2705 2694 2307 +3 2710 3553 1354 +3 2393 1261 1977 +3 1979 1356 2712 +3 2395 1157 2710 +3 2709 2393 1977 +3 971 3553 2712 +3 1986 1159 2711 +3 1986 1356 2714 +3 3527 971 1986 +3 2715 2713 1356 +3 2710 1157 1979 +3 2401 919 2713 +3 1976 2401 2713 +3 1987 1360 2725 +3 2713 919 1984 +3 2402 2401 1976 +3 2712 3553 1979 +3 1985 2711 2725 +3 1937 2722 2724 +3 2724 1147 2716 +3 3510 844 1937 +3 1927 1358 3547 +3 1927 1359 2720 +3 2720 1144 2717 +3 2718 1359 1927 +3 2732 1362 1936 +3 3526 1357 1939 +3 2731 916 2719 +3 1939 2716 2721 +3 2720 2719 1925 +3 2719 916 1925 +3 1936 1359 2721 +3 2718 3526 1939 +3 2725 1159 1987 +3 3534 1355 1985 +3 2734 2726 973 +3 1360 2722 2725 +3 1938 2730 2732 +3 1987 1159 2737 +3 2711 1159 2725 +3 2722 844 1985 +3 2729 2426 1972 +3 1975 1156 2729 +3 2425 829 2727 +3 1361 2726 2729 +3 2728 2727 1929 +3 2727 829 1929 +3 2426 1269 1972 +3 2734 1363 1975 +3 2733 2731 1362 +3 2726 1361 1931 +3 2733 1145 1928 +3 1928 916 2731 +3 2732 2721 1147 +3 1931 2728 2733 +3 2728 1145 2733 +3 2730 2726 1931 +3 2737 2714 1984 +3 2723 1360 1987 +3 2736 2735 1973 +3 1363 2734 2737 +3 2431 1156 2736 +3 2735 2429 1973 +3 2714 2713 1984 +3 2734 2723 1987 +3 2753 1367 1990 +3 1988 1160 2741 +3 2750 2742 974 +3 1364 2738 2741 +3 2748 1133 2740 +3 1990 1367 2750 +3 2741 2738 1988 +3 2738 96 1988 +3 2789 1376 1997 +3 1998 1365 2742 +3 2786 2754 845 +3 1998 1367 2752 +3 2772 1134 2744 +3 1997 1376 2786 +3 2752 1162 2745 +3 2750 1367 1998 +3 2780 1374 1884 +3 2742 1365 1887 +3 2779 913 2747 +3 1887 2744 2749 +3 2748 2747 1880 +3 2747 913 1880 +3 1884 1366 2749 +3 2746 2742 1887 +3 2753 2751 1367 +3 2739 1364 1990 +3 2753 1160 1989 +3 1989 920 2751 +3 2789 1162 2801 +3 1990 2741 2753 +3 2741 1160 2753 +3 2750 2739 1990 +3 2769 1371 2031 +3 2029 1368 2754 +3 2766 2758 975 +3 2029 1376 2788 +3 1906 1370 2764 +3 2762 1370 1906 +3 2788 1170 2757 +3 2786 1376 2029 +3 2933 1412 2025 +3 2026 1169 2761 +3 2930 2802 824 +3 1369 2758 2761 +3 2868 1137 2760 +3 2025 1412 2930 +3 2026 1371 2768 +3 2766 1371 2026 +3 2765 2763 1370 +3 2760 1137 1899 +3 2875 914 2763 +3 1896 2765 2876 +3 2773 1139 2785 +3 2763 914 1904 +3 1896 2763 2765 +3 2762 2758 1899 +3 2796 2795 2028 +3 2755 1368 2031 +3 2028 2769 2796 +3 2031 2757 2769 +3 2027 2931 2933 +3 2945 2768 2024 +3 2028 1371 2769 +3 2766 2755 2031 +3 2785 1375 1907 +3 2754 1368 1905 +3 2782 2774 976 +3 1905 2756 2773 +3 2780 1134 2772 +3 1907 1375 2782 +3 2756 1139 2773 +3 2770 2754 1905 +3 2904 1405 1892 +3 1895 1136 2777 +3 2903 828 2775 +3 1373 2774 2777 +3 2776 2775 1876 +3 2775 828 1876 +3 1892 1373 2777 +3 2782 1375 1895 +3 2781 2779 1374 +3 2774 1373 1878 +3 2781 1132 1877 +3 1877 913 2779 +3 2780 2749 1134 +3 1878 2776 2781 +3 2776 1132 2781 +3 2778 2774 1878 +3 2785 2764 1904 +3 2771 1372 1907 +3 1893 2907 2909 +3 1907 2773 2785 +3 2909 1136 2784 +3 2909 2784 1893 +3 2764 2763 1904 +3 2782 2771 1907 +3 2801 1379 1999 +3 2743 1365 1997 +3 2798 2790 977 +3 1997 2745 2789 +3 2030 1378 2796 +3 2794 1378 2030 +3 2745 1162 2789 +3 2786 2743 1997 +3 2793 2791 1377 +3 1994 1377 2790 +3 2793 1161 1993 +3 1993 830 2791 +3 2023 1427 2992 +3 1994 1379 2800 +3 2800 1161 2793 +3 2798 1379 1994 +3 2797 2795 1378 +3 2792 1168 2022 +3 2032 1427 2993 +3 2021 2797 2992 +3 2796 2769 1170 +3 2795 922 2028 +3 2022 2790 2792 +3 2794 2790 2022 +3 2801 2752 1996 +3 2787 1376 1999 +3 2751 920 2799 +3 1999 2789 2801 +3 2800 2799 1992 +3 2799 920 1992 +3 2752 1367 1996 +3 2798 2787 1999 +3 2805 2803 1380 +3 1961 1380 2802 +3 2814 2806 978 +3 1963 1383 2814 +3 1834 1382 2812 +3 2810 1382 1834 +3 2932 1153 2805 +3 2930 1412 1961 +3 2853 1392 1969 +3 1970 1155 2809 +3 2850 2818 846 +3 1381 2806 2809 +3 2836 1122 2808 +3 1969 1392 2850 +3 1970 1383 2816 +3 2814 1383 1970 +3 2844 2843 1836 +3 2806 1381 1839 +3 1836 2813 2844 +3 1839 2808 2813 +3 1835 2867 2869 +3 2881 2812 1832 +3 1836 1382 2813 +3 2810 2806 1839 +3 2817 2815 1383 +3 2805 1153 1963 +3 2939 918 2815 +3 1960 2817 2940 +3 2853 1155 2865 +3 2815 918 1968 +3 1960 2815 2817 +3 2814 2803 1963 +3 2833 1387 1951 +3 1949 1384 2818 +3 2830 2822 979 +3 1949 1392 2852 +3 2828 1114 2820 +3 1951 1387 2830 +3 2852 1150 2821 +3 2850 1392 1949 +3 2825 2823 1385 +3 1946 1385 2822 +3 1796 1112 2824 +3 1945 99 2823 +3 2824 2823 1796 +3 2823 99 1796 +3 2832 1149 2825 +3 2830 1387 1946 +3 2829 2827 1386 +3 2822 1385 1798 +3 2829 1112 1797 +3 1797 908 2827 +3 2837 1114 2849 +3 1798 2824 2829 +3 2824 1112 2829 +3 2826 2822 1798 +3 2860 1394 1948 +3 2819 1384 1951 +3 2859 917 2831 +3 1951 2821 2833 +3 2832 2831 1944 +3 2831 917 1944 +3 1948 1387 2833 +3 2830 2819 1951 +3 2849 1391 1807 +3 2818 1384 1805 +3 2846 2838 980 +3 1805 2820 2837 +3 1838 1390 2844 +3 2842 1390 1838 +3 2820 1114 2837 +3 2834 2818 1805 +3 2841 2839 1389 +3 1802 1389 2838 +3 2841 1113 1801 +3 1801 827 2839 +3 1831 1411 2928 +3 1802 1391 2848 +3 2848 1113 2841 +3 2846 1391 1802 +3 2845 2843 1390 +3 2840 1120 1830 +3 1840 1411 2929 +3 1829 2845 2928 +3 2844 2813 1122 +3 2843 910 1836 +3 1830 2838 2840 +3 2842 2838 1830 +3 2849 2828 1804 +3 2835 1388 1807 +3 2827 908 2847 +3 1807 2837 2849 +3 2848 2847 1800 +3 2847 908 1800 +3 2828 1386 1804 +3 2846 2835 1807 +3 2865 1395 1971 +3 2807 1381 1969 +3 2862 2854 981 +3 1969 2809 2853 +3 2860 1150 2852 +3 1971 1395 2862 +3 2809 1155 2853 +3 2850 2807 1969 +3 2968 1421 1956 +3 1959 1152 2857 +3 2967 829 2855 +3 1393 2854 2857 +3 2856 2855 1940 +3 2855 829 1940 +3 1956 1393 2857 +3 2862 1395 1959 +3 2861 2859 1394 +3 2854 1393 1942 +3 2861 1148 1941 +3 1941 917 2859 +3 2860 2833 1150 +3 1942 2856 2861 +3 2856 1148 2861 +3 2858 2854 1942 +3 2865 2816 1968 +3 2851 1392 1971 +3 1957 2971 2973 +3 1971 2853 2865 +3 2973 1152 2864 +3 2973 2864 1957 +3 2816 2815 1968 +3 2862 2851 1971 +3 2869 2867 1396 +3 2802 1380 1833 +3 2878 2870 982 +3 1835 1399 2878 +3 1898 1398 2876 +3 2874 1398 1898 +3 2804 1121 2869 +3 2866 2802 1833 +3 2917 1408 1841 +3 1842 1123 2873 +3 2914 2882 847 +3 1397 2870 2873 +3 2900 1138 2872 +3 1841 1408 2914 +3 1842 1399 2880 +3 2878 1399 1842 +3 2908 2907 1900 +3 2870 1397 1903 +3 1900 2877 2908 +3 1903 2872 2877 +3 2876 2765 1137 +3 2875 2763 1896 +3 1900 1398 2877 +3 2874 2870 1903 +3 2881 2879 1399 +3 2869 1121 1835 +3 2811 910 2879 +3 1832 2811 2879 +3 2917 1123 2929 +3 2879 910 1840 +3 2812 2811 1832 +3 2878 2867 1835 +3 2897 1403 1823 +3 1821 1400 2882 +3 2894 2886 983 +3 1821 1408 2916 +3 2892 1130 2884 +3 1823 1403 2894 +3 2916 1118 2885 +3 2914 1408 1821 +3 2889 2887 1401 +3 1818 1401 2886 +3 1860 1128 2888 +3 1817 97 2887 +3 2888 2887 1860 +3 2887 97 1860 +3 2896 1117 2889 +3 2894 1403 1818 +3 2893 2891 1402 +3 2886 1401 1862 +3 2893 1128 1861 +3 1861 912 2891 +3 2901 1130 2913 +3 1862 2888 2893 +3 2888 1128 2893 +3 2890 2886 1862 +3 2924 1410 1820 +3 2883 1400 1823 +3 2923 909 2895 +3 1823 2885 2897 +3 2896 2895 1816 +3 2895 909 1816 +3 1820 1403 2897 +3 2894 2883 1823 +3 2913 1407 1871 +3 2882 1400 1869 +3 2910 2902 984 +3 1869 2884 2901 +3 1902 1406 2908 +3 2906 1406 1902 +3 2884 1130 2901 +3 2898 2882 1869 +3 2905 2903 1405 +3 1866 1405 2902 +3 2905 1129 1865 +3 1865 828 2903 +3 2904 2777 1136 +3 1866 1407 2912 +3 2912 1129 2905 +3 2910 1407 1866 +3 2909 2907 1406 +3 2904 1136 1894 +3 2907 2783 914 +3 1893 2783 2907 +3 2908 2877 1138 +3 2907 914 1900 +3 1894 2902 2904 +3 2906 2902 1894 +3 2913 2892 1868 +3 2899 1404 1871 +3 2891 912 2911 +3 1871 2901 2913 +3 2912 2911 1864 +3 2911 912 1864 +3 2892 1402 1868 +3 2910 2899 1871 +3 2929 1411 1843 +3 2871 1397 1841 +3 2926 2918 985 +3 1841 2873 2917 +3 2924 1118 2916 +3 1843 1411 2926 +3 2873 1123 2917 +3 2914 2871 1841 +3 2921 2840 1828 +3 1831 1120 2921 +3 2839 827 2919 +3 1409 2918 2921 +3 2920 2919 1812 +3 2919 827 1812 +3 2840 1389 1828 +3 2926 1411 1831 +3 2925 2923 1410 +3 2918 1409 1814 +3 2925 1116 1813 +3 1813 909 2923 +3 2924 2897 1118 +3 1814 2920 2925 +3 2920 1116 2925 +3 2922 2918 1814 +3 2929 2880 1840 +3 2915 1408 1843 +3 2928 2927 1829 +3 1843 2917 2929 +3 2845 1120 2928 +3 2927 2843 1829 +3 2880 2879 1840 +3 2926 2915 1843 +3 2933 2931 1412 +3 2759 1369 2025 +3 2942 2934 986 +3 2027 1415 2942 +3 1962 1414 2940 +3 2938 1414 1962 +3 2761 1169 2933 +3 2930 2759 2025 +3 2981 1424 2033 +3 2034 1171 2937 +3 2978 2946 848 +3 1413 2934 2937 +3 2964 1154 2936 +3 2033 1424 2978 +3 2034 1415 2944 +3 2942 1415 2034 +3 2972 2971 1964 +3 2934 1413 1967 +3 1964 2941 2972 +3 1967 2936 2941 +3 2940 2817 1153 +3 2939 2815 1960 +3 1964 1414 2941 +3 2938 2934 1967 +3 2945 2943 1415 +3 2933 1169 2027 +3 2767 922 2943 +3 2024 2767 2943 +3 2981 1171 2993 +3 2943 922 2032 +3 2768 2767 2024 +3 2942 2931 2027 +3 2961 1419 2015 +3 2013 1416 2946 +3 2958 2950 987 +3 2013 1424 2980 +3 2956 1146 2948 +3 2015 1419 2958 +3 2980 1166 2949 +3 2978 1424 2013 +3 2953 2951 1417 +3 2010 1417 2950 +3 1924 1144 2952 +3 2009 101 2951 +3 2952 2951 1924 +3 2951 101 1924 +3 2960 1165 2953 +3 2958 1419 2010 +3 2957 2955 1418 +3 2950 1417 1926 +3 2957 1144 1925 +3 1925 916 2955 +3 2965 1146 2977 +3 1926 2952 2957 +3 2952 1144 2957 +3 2954 2950 1926 +3 2988 1426 2012 +3 2947 1416 2015 +3 2987 921 2959 +3 2015 2949 2961 +3 2960 2959 2008 +3 2959 921 2008 +3 2012 1419 2961 +3 2958 2947 2015 +3 2977 1423 1935 +3 2946 1416 1933 +3 2974 2966 988 +3 1933 2948 2965 +3 1966 1422 2972 +3 2970 1422 1966 +3 2948 1146 2965 +3 2962 2946 1933 +3 2969 2967 1421 +3 1930 1421 2966 +3 2969 1145 1929 +3 1929 829 2967 +3 2968 2857 1152 +3 1930 1423 2976 +3 2976 1145 2969 +3 2974 1423 1930 +3 2973 2971 1422 +3 2968 1152 1958 +3 2971 2863 918 +3 1957 2863 2971 +3 2972 2941 1154 +3 2971 918 1964 +3 1958 2966 2968 +3 2970 2966 1958 +3 2977 2956 1932 +3 2963 1420 1935 +3 2955 916 2975 +3 1935 2965 2977 +3 2976 2975 1928 +3 2975 916 1928 +3 2956 1418 1932 +3 2974 2963 1935 +3 2993 1427 2035 +3 2935 1413 2033 +3 2990 2982 989 +3 2033 2937 2981 +3 2988 1166 2980 +3 2035 1427 2990 +3 2937 1171 2981 +3 2978 2935 2033 +3 2985 2792 2020 +3 2023 1168 2985 +3 2791 830 2983 +3 1425 2982 2985 +3 2984 2983 2004 +3 2983 830 2004 +3 2792 1377 2020 +3 2990 1427 2023 +3 2989 2987 1426 +3 2982 1425 2006 +3 2989 1164 2005 +3 2005 921 2987 +3 2988 2961 1166 +3 2006 2984 2989 +3 2984 1164 2989 +3 2986 2982 2006 +3 2993 2944 2032 +3 2979 1424 2035 +3 2992 2991 2021 +3 2035 2981 2993 +3 2797 1168 2992 +3 2991 2795 2021 +3 2944 2943 2032 +3 2990 2979 2035 +3 3009 1431 2182 +3 2180 1208 2997 +3 3006 2998 990 +3 1428 2994 2997 +3 3004 1181 2996 +3 2182 1431 3006 +3 2997 2994 2180 +3 2994 98 2180 +3 3045 1440 2189 +3 2190 1429 2998 +3 3042 3010 849 +3 2190 1431 3008 +3 3028 1182 3000 +3 2189 1440 3042 +3 3008 1210 3001 +3 3006 1431 2190 +3 3036 1438 2076 +3 2998 1429 2079 +3 3035 925 3003 +3 2079 3000 3005 +3 3004 3003 2072 +3 3003 925 2072 +3 2076 1430 3005 +3 3002 2998 2079 +3 3009 3007 1431 +3 2995 1428 2182 +3 3009 1208 2181 +3 2181 932 3007 +3 3045 1210 3057 +3 2182 2997 3009 +3 2997 1208 3009 +3 3006 2995 2182 +3 3025 1435 2223 +3 2221 1432 3010 +3 3022 3014 991 +3 2221 1440 3044 +3 2098 1434 3020 +3 3018 1434 2098 +3 3044 1218 3013 +3 3042 1440 2221 +3 3189 1476 2217 +3 2218 1217 3017 +3 3186 3058 825 +3 1433 3014 3017 +3 3124 1185 3016 +3 2217 1476 3186 +3 2218 1435 3024 +3 3022 1435 2218 +3 3021 3019 1434 +3 3016 1185 2091 +3 3131 926 3019 +3 2088 3021 3132 +3 3029 1187 3041 +3 3019 926 2096 +3 2088 3019 3021 +3 3018 3014 2091 +3 3052 3051 2220 +3 3011 1432 2223 +3 2220 3025 3052 +3 2223 3013 3025 +3 2219 3187 3189 +3 3201 3024 2216 +3 2220 1435 3025 +3 3022 3011 2223 +3 3041 1439 2099 +3 3010 1432 2097 +3 3038 3030 992 +3 2097 3012 3029 +3 3036 1182 3028 +3 2099 1439 3038 +3 3012 1187 3029 +3 3026 3010 2097 +3 3160 1469 2084 +3 2087 1184 3033 +3 3159 831 3031 +3 1437 3030 3033 +3 3032 3031 2068 +3 3031 831 2068 +3 2084 1437 3033 +3 3038 1439 2087 +3 3037 3035 1438 +3 3030 1437 2070 +3 3037 1180 2069 +3 2069 925 3035 +3 3036 3005 1182 +3 2070 3032 3037 +3 3032 1180 3037 +3 3034 3030 2070 +3 3041 3020 2096 +3 3027 1436 2099 +3 2085 3163 3165 +3 2099 3029 3041 +3 3165 1184 3040 +3 3165 3040 2085 +3 3020 3019 2096 +3 3038 3027 2099 +3 3057 1443 2191 +3 2999 1429 2189 +3 3054 3046 993 +3 2189 3001 3045 +3 2222 1442 3052 +3 3050 1442 2222 +3 3001 1210 3045 +3 3042 2999 2189 +3 3049 3047 1441 +3 2186 1441 3046 +3 3049 1209 2185 +3 2185 833 3047 +3 2215 1491 3248 +3 2186 1443 3056 +3 3056 1209 3049 +3 3054 1443 2186 +3 3053 3051 1442 +3 3048 1216 2214 +3 2224 1491 3249 +3 2213 3053 3248 +3 3052 3025 1218 +3 3051 934 2220 +3 2214 3046 3048 +3 3050 3046 2214 +3 3057 3008 2188 +3 3043 1440 2191 +3 3007 932 3055 +3 2191 3045 3057 +3 3056 3055 2184 +3 3055 932 2184 +3 3008 1431 2188 +3 3054 3043 2191 +3 3061 3059 1444 +3 2153 1444 3058 +3 3070 3062 994 +3 2155 1447 3070 +3 1914 1446 3068 +3 3066 1446 1914 +3 3188 1201 3061 +3 3186 1476 2153 +3 3109 1456 2161 +3 2162 1203 3065 +3 3106 3074 850 +3 1445 3062 3065 +3 3092 1142 3064 +3 2161 1456 3106 +3 2162 1447 3072 +3 3070 1447 2162 +3 3100 3099 1916 +3 3062 1445 1919 +3 1916 3069 3100 +3 1919 3064 3069 +3 1915 3123 3125 +3 3137 3068 1912 +3 1916 1446 3069 +3 3066 3062 1919 +3 3073 3071 1447 +3 3061 1201 2155 +3 3195 930 3071 +3 2152 3073 3196 +3 3109 1203 3121 +3 3071 930 2160 +3 2152 3071 3073 +3 3070 3059 2155 +3 3089 1451 2143 +3 2141 1448 3074 +3 3086 3078 995 +3 2141 1456 3108 +3 3084 1135 3076 +3 2143 1451 3086 +3 3108 1198 3077 +3 3106 1456 2141 +3 3081 3079 1449 +3 2138 1449 3078 +3 1881 1133 3080 +3 2137 96 3079 +3 3080 3079 1881 +3 3079 96 1881 +3 3088 1197 3081 +3 3086 1451 2138 +3 3085 3083 1450 +3 3078 1449 1883 +3 3085 1133 1880 +3 1880 913 3083 +3 3093 1135 3105 +3 1883 3080 3085 +3 3080 1133 3085 +3 3082 3078 1883 +3 3116 1458 2140 +3 3075 1448 2143 +3 3115 929 3087 +3 2143 3077 3089 +3 3088 3087 2136 +3 3087 929 2136 +3 2140 1451 3089 +3 3086 3075 2143 +3 3105 1455 1891 +3 3074 1448 1889 +3 3102 3094 996 +3 1889 3076 3093 +3 1918 1454 3100 +3 3098 1454 1918 +3 3076 1135 3093 +3 3090 3074 1889 +3 3097 3095 1453 +3 1879 1453 3094 +3 3097 1132 1876 +3 1876 828 3095 +3 1911 1475 3184 +3 1879 1455 3104 +3 3104 1132 3097 +3 3102 1455 1879 +3 3101 3099 1454 +3 3096 1140 1910 +3 1920 1475 3185 +3 1909 3101 3184 +3 3100 3069 1142 +3 3099 915 1916 +3 1910 3094 3096 +3 3098 3094 1910 +3 3105 3084 1888 +3 3091 1452 1891 +3 3083 913 3103 +3 1891 3093 3105 +3 3104 3103 1877 +3 3103 913 1877 +3 3084 1450 1888 +3 3102 3091 1891 +3 3121 1459 2163 +3 3063 1445 2161 +3 3118 3110 997 +3 2161 3065 3109 +3 3116 1198 3108 +3 2163 1459 3118 +3 3065 1203 3109 +3 3106 3063 2161 +3 3224 1485 2148 +3 2151 1200 3113 +3 3223 832 3111 +3 1457 3110 3113 +3 3112 3111 2132 +3 3111 832 2132 +3 2148 1457 3113 +3 3118 1459 2151 +3 3117 3115 1458 +3 3110 1457 2134 +3 3117 1196 2133 +3 2133 929 3115 +3 3116 3089 1198 +3 2134 3112 3117 +3 3112 1196 3117 +3 3114 3110 2134 +3 3121 3072 2160 +3 3107 1456 2163 +3 2149 3227 3229 +3 2163 3109 3121 +3 3229 1200 3120 +3 3229 3120 2149 +3 3072 3071 2160 +3 3118 3107 2163 +3 3125 3123 1460 +3 3058 1444 1913 +3 3134 3126 998 +3 1915 1463 3134 +3 2090 1462 3132 +3 3130 1462 2090 +3 3060 1141 3125 +3 3122 3058 1913 +3 3173 1472 1921 +3 1922 1143 3129 +3 3170 3138 851 +3 1461 3126 3129 +3 3156 1186 3128 +3 1921 1472 3170 +3 1922 1463 3136 +3 3134 1463 1922 +3 3164 3163 2092 +3 3126 1461 2095 +3 2092 3133 3164 +3 2095 3128 3133 +3 3132 3021 1185 +3 3131 3019 2088 +3 2092 1462 3133 +3 3130 3126 2095 +3 3137 3135 1463 +3 3125 1141 1915 +3 3067 915 3135 +3 1912 3067 3135 +3 3173 1143 3185 +3 3135 915 1920 +3 3068 3067 1912 +3 3134 3123 1915 +3 3153 1467 1875 +3 1873 1464 3138 +3 3150 3142 999 +3 1873 1472 3172 +3 3148 1178 3140 +3 1875 1467 3150 +3 3172 1131 3141 +3 3170 1472 1873 +3 3145 3143 1465 +3 1863 1465 3142 +3 2052 1176 3144 +3 1860 97 3143 +3 3144 3143 2052 +3 3143 97 2052 +3 3152 1128 3145 +3 3150 1467 1863 +3 3149 3147 1466 +3 3142 1465 2054 +3 3149 1176 2053 +3 2053 924 3147 +3 3157 1178 3169 +3 2054 3144 3149 +3 3144 1176 3149 +3 3146 3142 2054 +3 3180 1474 1872 +3 3139 1464 1875 +3 3179 912 3151 +3 1875 3141 3153 +3 3152 3151 1861 +3 3151 912 1861 +3 1872 1467 3153 +3 3150 3139 1875 +3 3169 1471 2063 +3 3138 1464 2061 +3 3166 3158 1000 +3 2061 3140 3157 +3 2094 1470 3164 +3 3162 1470 2094 +3 3140 1178 3157 +3 3154 3138 2061 +3 3161 3159 1469 +3 2058 1469 3158 +3 3161 1177 2057 +3 2057 831 3159 +3 3160 3033 1184 +3 2058 1471 3168 +3 3168 1177 3161 +3 3166 1471 2058 +3 3165 3163 1470 +3 3160 1184 2086 +3 3163 3039 926 +3 2085 3039 3163 +3 3164 3133 1186 +3 3163 926 2092 +3 2086 3158 3160 +3 3162 3158 2086 +3 3169 3148 2060 +3 3155 1468 2063 +3 3147 924 3167 +3 2063 3157 3169 +3 3168 3167 2056 +3 3167 924 2056 +3 3148 1466 2060 +3 3166 3155 2063 +3 3185 1475 1923 +3 3127 1461 1921 +3 3182 3174 1001 +3 1921 3129 3173 +3 3180 1131 3172 +3 1923 1475 3182 +3 3129 1143 3173 +3 3170 3127 1921 +3 3177 3096 1908 +3 1911 1140 3177 +3 3095 828 3175 +3 1473 3174 3177 +3 3176 3175 1865 +3 3175 828 1865 +3 3096 1453 1908 +3 3182 1475 1911 +3 3181 3179 1474 +3 3174 1473 1867 +3 3181 1129 1864 +3 1864 912 3179 +3 3180 3153 1131 +3 1867 3176 3181 +3 3176 1129 3181 +3 3178 3174 1867 +3 3185 3136 1920 +3 3171 1472 1923 +3 3184 3183 1909 +3 1923 3173 3185 +3 3101 1140 3184 +3 3183 3099 1909 +3 3136 3135 1920 +3 3182 3171 1923 +3 3189 3187 1476 +3 3015 1433 2217 +3 3198 3190 1002 +3 2219 1479 3198 +3 2154 1478 3196 +3 3194 1478 2154 +3 3017 1217 3189 +3 3186 3015 2217 +3 3237 1488 2225 +3 2226 1219 3193 +3 3234 3202 852 +3 1477 3190 3193 +3 3220 1202 3192 +3 2225 1488 3234 +3 2226 1479 3200 +3 3198 1479 2226 +3 3228 3227 2156 +3 3190 1477 2159 +3 2156 3197 3228 +3 2159 3192 3197 +3 3196 3073 1201 +3 3195 3071 2152 +3 2156 1478 3197 +3 3194 3190 2159 +3 3201 3199 1479 +3 3189 1217 2219 +3 3023 934 3199 +3 2216 3023 3199 +3 3237 1219 3249 +3 3199 934 2224 +3 3024 3023 2216 +3 3198 3187 2219 +3 3217 1483 2207 +3 2205 1480 3202 +3 3214 3206 1003 +3 2205 1488 3236 +3 3212 1194 3204 +3 2207 1483 3214 +3 3236 1214 3205 +3 3234 1488 2205 +3 3209 3207 1481 +3 2202 1481 3206 +3 2116 1192 3208 +3 2201 100 3207 +3 3208 3207 2116 +3 3207 100 2116 +3 3216 1213 3209 +3 3214 1483 2202 +3 3213 3211 1482 +3 3206 1481 2118 +3 3213 1192 2117 +3 2117 928 3211 +3 3221 1194 3233 +3 2118 3208 3213 +3 3208 1192 3213 +3 3210 3206 2118 +3 3244 1490 2204 +3 3203 1480 2207 +3 3243 933 3215 +3 2207 3205 3217 +3 3216 3215 2200 +3 3215 933 2200 +3 2204 1483 3217 +3 3214 3203 2207 +3 3233 1487 2127 +3 3202 1480 2125 +3 3230 3222 1004 +3 2125 3204 3221 +3 2158 1486 3228 +3 3226 1486 2158 +3 3204 1194 3221 +3 3218 3202 2125 +3 3225 3223 1485 +3 2122 1485 3222 +3 3225 1193 2121 +3 2121 832 3223 +3 3224 3113 1200 +3 2122 1487 3232 +3 3232 1193 3225 +3 3230 1487 2122 +3 3229 3227 1486 +3 3224 1200 2150 +3 3227 3119 930 +3 2149 3119 3227 +3 3228 3197 1202 +3 3227 930 2156 +3 2150 3222 3224 +3 3226 3222 2150 +3 3233 3212 2124 +3 3219 1484 2127 +3 3211 928 3231 +3 2127 3221 3233 +3 3232 3231 2120 +3 3231 928 2120 +3 3212 1482 2124 +3 3230 3219 2127 +3 3249 1491 2227 +3 3191 1477 2225 +3 3246 3238 1005 +3 2225 3193 3237 +3 3244 1214 3236 +3 2227 1491 3246 +3 3193 1219 3237 +3 3234 3191 2225 +3 3241 3048 2212 +3 2215 1216 3241 +3 3047 833 3239 +3 1489 3238 3241 +3 3240 3239 2196 +3 3239 833 2196 +3 3048 1441 2212 +3 3246 1491 2215 +3 3245 3243 1490 +3 3238 1489 2198 +3 3245 1212 2197 +3 2197 933 3243 +3 3244 3217 1214 +3 2198 3240 3245 +3 3240 1212 3245 +3 3242 3238 2198 +3 3249 3200 2224 +3 3235 1488 2227 +3 3248 3247 2213 +3 2227 3237 3249 +3 3053 1216 3248 +3 3247 3051 2213 +3 3200 3199 2224 +3 3246 3235 2227 +3 3265 1495 2331 +3 2329 1245 3253 +3 3262 3254 1006 +3 1492 3250 3253 +3 3260 1112 3252 +3 2331 1495 3262 +3 3253 3250 2329 +3 3250 99 2329 +3 3301 1504 2337 +3 2338 1493 3254 +3 3298 3266 853 +3 2338 1495 3264 +3 3284 1115 3256 +3 2337 1504 3298 +3 3264 1247 3257 +3 3262 1495 2338 +3 3292 1502 1808 +3 3254 1493 1811 +3 3291 908 3259 +3 1811 3256 3261 +3 3260 3259 1797 +3 3259 908 1797 +3 1808 1494 3261 +3 3258 3254 1811 +3 3265 3263 1495 +3 3251 1492 2331 +3 3265 1245 2328 +3 2328 941 3263 +3 3301 1247 3313 +3 2331 3253 3265 +3 3253 1245 3265 +3 3262 3251 2331 +3 3281 1499 2367 +3 2365 1496 3266 +3 3278 3270 1007 +3 2365 1504 3300 +3 1858 1498 3276 +3 3274 1498 1858 +3 3300 1254 3269 +3 3298 1504 2365 +3 3445 1540 2361 +3 2362 1253 3273 +3 3442 3314 826 +3 1497 3270 3273 +3 3380 1125 3272 +3 2361 1540 3442 +3 2362 1499 3280 +3 3278 1499 2362 +3 3277 3275 1498 +3 3272 1125 1851 +3 3387 911 3275 +3 1848 3277 3388 +3 3285 1127 3297 +3 3275 911 1856 +3 1848 3275 3277 +3 3274 3270 1851 +3 3308 3307 2364 +3 3267 1496 2367 +3 2364 3281 3308 +3 2367 3269 3281 +3 2363 3443 3445 +3 3457 3280 2360 +3 2364 1499 3281 +3 3278 3267 2367 +3 3297 1503 1859 +3 3266 1496 1857 +3 3294 3286 1008 +3 1857 3268 3285 +3 3292 1115 3284 +3 1859 1503 3294 +3 3268 1127 3285 +3 3282 3266 1857 +3 3416 1533 1844 +3 1847 1124 3289 +3 3415 827 3287 +3 1501 3286 3289 +3 3288 3287 1801 +3 3287 827 1801 +3 1844 1501 3289 +3 3294 1503 1847 +3 3293 3291 1502 +3 3286 1501 1803 +3 3293 1113 1800 +3 1800 908 3291 +3 3292 3261 1115 +3 1803 3288 3293 +3 3288 1113 3293 +3 3290 3286 1803 +3 3297 3276 1856 +3 3283 1500 1859 +3 1845 3419 3421 +3 1859 3285 3297 +3 3421 1124 3296 +3 3421 3296 1845 +3 3276 3275 1856 +3 3294 3283 1859 +3 3313 1507 2339 +3 3255 1493 2337 +3 3310 3302 1009 +3 2337 3257 3301 +3 2366 1506 3308 +3 3306 1506 2366 +3 3257 1247 3301 +3 3298 3255 2337 +3 3305 3303 1505 +3 2327 1505 3302 +3 3305 1244 2324 +3 2324 835 3303 +3 2359 1555 3504 +3 2327 1507 3312 +3 3312 1244 3305 +3 3310 1507 2327 +3 3309 3307 1506 +3 3304 1252 2358 +3 2368 1555 3505 +3 2357 3309 3504 +3 3308 3281 1254 +3 3307 943 2364 +3 2358 3302 3304 +3 3306 3302 2358 +3 3313 3264 2336 +3 3299 1504 2339 +3 3263 941 3311 +3 2339 3301 3313 +3 3312 3311 2325 +3 3311 941 2325 +3 3264 1495 2336 +3 3310 3299 2339 +3 3317 3315 1508 +3 2281 1508 3314 +3 3326 3318 1010 +3 2283 1511 3326 +3 2106 1510 3324 +3 3322 1510 2106 +3 3444 1233 3317 +3 3442 1540 2281 +3 3365 1520 2289 +3 2290 1235 3321 +3 3362 3330 854 +3 1509 3318 3321 +3 3348 1190 3320 +3 2289 1520 3362 +3 2290 1511 3328 +3 3326 1511 2290 +3 3356 3355 2108 +3 3318 1509 2111 +3 2108 3325 3356 +3 2111 3320 3325 +3 2107 3379 3381 +3 3393 3324 2104 +3 2108 1510 3325 +3 3322 3318 2111 +3 3329 3327 1511 +3 3317 1233 2283 +3 3451 938 3327 +3 2280 3329 3452 +3 3365 1235 3377 +3 3327 938 2288 +3 2280 3327 3329 +3 3326 3315 2283 +3 3345 1515 2271 +3 2269 1512 3330 +3 3342 3334 1011 +3 2269 1520 3364 +3 3340 1183 3332 +3 2271 1515 3342 +3 3364 1230 3333 +3 3362 1520 2269 +3 3337 3335 1513 +3 2266 1513 3334 +3 2073 1181 3336 +3 2265 98 3335 +3 3336 3335 2073 +3 3335 98 2073 +3 3344 1229 3337 +3 3342 1515 2266 +3 3341 3339 1514 +3 3334 1513 2075 +3 3341 1181 2072 +3 2072 925 3339 +3 3349 1183 3361 +3 2075 3336 3341 +3 3336 1181 3341 +3 3338 3334 2075 +3 3372 1522 2268 +3 3331 1512 2271 +3 3371 937 3343 +3 2271 3333 3345 +3 3344 3343 2264 +3 3343 937 2264 +3 2268 1515 3345 +3 3342 3331 2271 +3 3361 1519 2083 +3 3330 1512 2081 +3 3358 3350 1012 +3 2081 3332 3349 +3 2110 1518 3356 +3 3354 1518 2110 +3 3332 1183 3349 +3 3346 3330 2081 +3 3353 3351 1517 +3 2071 1517 3350 +3 3353 1180 2068 +3 2068 831 3351 +3 2103 1539 3440 +3 2071 1519 3360 +3 3360 1180 3353 +3 3358 1519 2071 +3 3357 3355 1518 +3 3352 1188 2102 +3 2112 1539 3441 +3 2101 3357 3440 +3 3356 3325 1190 +3 3355 927 2108 +3 2102 3350 3352 +3 3354 3350 2102 +3 3361 3340 2080 +3 3347 1516 2083 +3 3339 925 3359 +3 2083 3349 3361 +3 3360 3359 2069 +3 3359 925 2069 +3 3340 1514 2080 +3 3358 3347 2083 +3 3377 1523 2291 +3 3319 1509 2289 +3 3374 3366 1013 +3 2289 3321 3365 +3 3372 1230 3364 +3 2291 1523 3374 +3 3321 1235 3365 +3 3362 3319 2289 +3 3480 1549 2276 +3 2279 1232 3369 +3 3479 834 3367 +3 1521 3366 3369 +3 3368 3367 2260 +3 3367 834 2260 +3 2276 1521 3369 +3 3374 1523 2279 +3 3373 3371 1522 +3 3366 1521 2262 +3 3373 1228 2261 +3 2261 937 3371 +3 3372 3345 1230 +3 2262 3368 3373 +3 3368 1228 3373 +3 3370 3366 2262 +3 3377 3328 2288 +3 3363 1520 2291 +3 2277 3483 3485 +3 2291 3365 3377 +3 3485 1232 3376 +3 3485 3376 2277 +3 3328 3327 2288 +3 3374 3363 2291 +3 3381 3379 1524 +3 3314 1508 2105 +3 3390 3382 1014 +3 2107 1527 3390 +3 1850 1526 3388 +3 3386 1526 1850 +3 3316 1189 3381 +3 3378 3314 2105 +3 3429 1536 2113 +3 2114 1191 3385 +3 3426 3394 855 +3 1525 3382 3385 +3 3412 1126 3384 +3 2113 1536 3426 +3 2114 1527 3392 +3 3390 1527 2114 +3 3420 3419 1852 +3 3382 1525 1855 +3 1852 3389 3420 +3 1855 3384 3389 +3 3388 3277 1125 +3 3387 3275 1848 +3 1852 1526 3389 +3 3386 3382 1855 +3 3393 3391 1527 +3 3381 1189 2107 +3 3323 927 3391 +3 2104 3323 3391 +3 3429 1191 3441 +3 3391 927 2112 +3 3324 3323 2104 +3 3390 3379 2107 +3 3409 1531 2067 +3 2065 1528 3394 +3 3406 3398 1015 +3 2065 1536 3428 +3 3404 1119 3396 +3 2067 1531 3406 +3 3428 1179 3397 +3 3426 1536 2065 +3 3401 3399 1529 +3 2055 1529 3398 +3 1817 1117 3400 +3 2052 97 3399 +3 3400 3399 1817 +3 3399 97 1817 +3 3408 1176 3401 +3 3406 1531 2055 +3 3405 3403 1530 +3 3398 1529 1819 +3 3405 1117 1816 +3 1816 909 3403 +3 3413 1119 3425 +3 1819 3400 3405 +3 3400 1117 3405 +3 3402 3398 1819 +3 3436 1538 2064 +3 3395 1528 2067 +3 3435 924 3407 +3 2067 3397 3409 +3 3408 3407 2053 +3 3407 924 2053 +3 2064 1531 3409 +3 3406 3395 2067 +3 3425 1535 1827 +3 3394 1528 1825 +3 3422 3414 1016 +3 1825 3396 3413 +3 1854 1534 3420 +3 3418 1534 1854 +3 3396 1119 3413 +3 3410 3394 1825 +3 3417 3415 1533 +3 1815 1533 3414 +3 3417 1116 1812 +3 1812 827 3415 +3 3416 3289 1124 +3 1815 1535 3424 +3 3424 1116 3417 +3 3422 1535 1815 +3 3421 3419 1534 +3 3416 1124 1846 +3 3419 3295 911 +3 1845 3295 3419 +3 3420 3389 1126 +3 3419 911 1852 +3 1846 3414 3416 +3 3418 3414 1846 +3 3425 3404 1824 +3 3411 1532 1827 +3 3403 909 3423 +3 1827 3413 3425 +3 3424 3423 1813 +3 3423 909 1813 +3 3404 1530 1824 +3 3422 3411 1827 +3 3441 1539 2115 +3 3383 1525 2113 +3 3438 3430 1017 +3 2113 3385 3429 +3 3436 1179 3428 +3 2115 1539 3438 +3 3385 1191 3429 +3 3426 3383 2113 +3 3433 3352 2100 +3 2103 1188 3433 +3 3351 831 3431 +3 1537 3430 3433 +3 3432 3431 2057 +3 3431 831 2057 +3 3352 1517 2100 +3 3438 1539 2103 +3 3437 3435 1538 +3 3430 1537 2059 +3 3437 1177 2056 +3 2056 924 3435 +3 3436 3409 1179 +3 2059 3432 3437 +3 3432 1177 3437 +3 3434 3430 2059 +3 3441 3392 2112 +3 3427 1536 2115 +3 3440 3439 2101 +3 2115 3429 3441 +3 3357 1188 3440 +3 3439 3355 2101 +3 3392 3391 2112 +3 3438 3427 2115 +3 3445 3443 1540 +3 3271 1497 2361 +3 3454 3446 1018 +3 2363 1543 3454 +3 2282 1542 3452 +3 3450 1542 2282 +3 3273 1253 3445 +3 3442 3271 2361 +3 3493 1552 2369 +3 2370 1255 3449 +3 3490 3458 856 +3 1541 3446 3449 +3 3476 1234 3448 +3 2369 1552 3490 +3 2370 1543 3456 +3 3454 1543 2370 +3 3484 3483 2284 +3 3446 1541 2287 +3 2284 3453 3484 +3 2287 3448 3453 +3 3452 3329 1233 +3 3451 3327 2280 +3 2284 1542 3453 +3 3450 3446 2287 +3 3457 3455 1543 +3 3445 1253 2363 +3 3279 943 3455 +3 2360 3279 3455 +3 3493 1255 3505 +3 3455 943 2368 +3 3280 3279 2360 +3 3454 3443 2363 +3 3473 1547 2323 +3 2321 1544 3458 +3 3470 3462 1019 +3 2321 1552 3492 +3 3468 1226 3460 +3 2323 1547 3470 +3 3492 1243 3461 +3 3490 1552 2321 +3 3465 3463 1545 +3 2311 1545 3462 +3 2244 1224 3464 +3 2308 102 3463 +3 3464 3463 2244 +3 3463 102 2244 +3 3472 1240 3465 +3 3470 1547 2311 +3 3469 3467 1546 +3 3462 1545 2246 +3 3469 1224 2245 +3 2245 936 3467 +3 3477 1226 3489 +3 2246 3464 3469 +3 3464 1224 3469 +3 3466 3462 2246 +3 3500 1554 2320 +3 3459 1544 2323 +3 3499 940 3471 +3 2323 3461 3473 +3 3472 3471 2309 +3 3471 940 2309 +3 2320 1547 3473 +3 3470 3459 2323 +3 3489 1551 2255 +3 3458 1544 2253 +3 3486 3478 1020 +3 2253 3460 3477 +3 2286 1550 3484 +3 3482 1550 2286 +3 3460 1226 3477 +3 3474 3458 2253 +3 3481 3479 1549 +3 2250 1549 3478 +3 3481 1225 2249 +3 2249 834 3479 +3 3480 3369 1232 +3 2250 1551 3488 +3 3488 1225 3481 +3 3486 1551 2250 +3 3485 3483 1550 +3 3480 1232 2278 +3 3483 3375 938 +3 2277 3375 3483 +3 3484 3453 1234 +3 3483 938 2284 +3 2278 3478 3480 +3 3482 3478 2278 +3 3489 3468 2252 +3 3475 1548 2255 +3 3467 936 3487 +3 2255 3477 3489 +3 3488 3487 2248 +3 3487 936 2248 +3 3468 1546 2252 +3 3486 3475 2255 +3 3505 1555 2371 +3 3447 1541 2369 +3 3502 3494 1021 +3 2369 3449 3493 +3 3500 1243 3492 +3 2371 1555 3502 +3 3449 1255 3493 +3 3490 3447 2369 +3 3497 3304 2356 +3 2359 1252 3497 +3 3303 835 3495 +3 1553 3494 3497 +3 3496 3495 2313 +3 3495 835 2313 +3 3304 1505 2356 +3 3502 1555 2359 +3 3501 3499 1554 +3 3494 1553 2315 +3 3501 1241 2312 +3 2312 940 3499 +3 3500 3473 1243 +3 2315 3496 3501 +3 3496 1241 3501 +3 3498 3494 2315 +3 3505 3456 2368 +3 3491 1552 2371 +3 3504 3503 2357 +3 2371 3493 3505 +3 3309 1252 3504 +3 3503 3307 2357 +3 3456 3455 2368 +3 3502 3491 2371 +3 2472 68 70 +3 3590 3567 1022 +3 3537 1556 3506 +3 3519 1556 3566 +3 1282 2011 3536 +3 1295 3531 1569 +3 3569 1616 1588 +3 2594 36 38 +3 3592 3571 1024 +3 3541 1560 3508 +3 3523 1560 3570 +3 1318 2203 3540 +3 2305 843 3533 +3 2259 1349 2689 +3 3510 1357 1564 +3 3527 1355 1572 +3 2436 0 2 +3 3528 948 3559 +3 3545 1567 3511 +3 3529 1567 3574 +3 1276 2310 3544 +3 2445 1277 2318 +3 3566 951 3519 +3 3570 961 3523 +3 3582 3511 837 +3 1273 2351 948 +3 1046 1659 3621 +3 3554 1574 3590 +3 1050 1663 3629 +3 3556 1578 3592 +3 3623 1726 101 +3 3519 1283 1556 +3 1047 1028 1612 +3 3506 1556 1283 +3 3530 1285 1568 +3 3512 83 84 +3 1569 3531 1599 +3 1559 1293 3521 +3 3631 1732 100 +3 3523 1319 1560 +3 1051 1030 1620 +3 3508 1560 1319 +3 3532 1321 1570 +3 3514 51 52 +3 1592 1624 872 +3 1601 1637 1052 +3 1564 1582 3546 +3 3637 1628 1638 +3 3517 17 18 +3 3535 1273 1573 +3 3511 2317 837 +3 1057 1033 1632 +3 3589 1596 1584 +3 3643 2308 1276 +3 3602 1568 3567 +3 1034 3567 3590 +3 1557 1286 3512 +3 3591 1589 1576 +3 3555 955 1023 +3 3521 954 3569 +3 3627 1677 1617 +3 3604 1570 3571 +3 1036 3571 3592 +3 1561 1322 3514 +3 3542 1348 1625 +3 3572 1624 1592 +3 3557 968 1025 +3 2297 2618 2681 +3 3607 1573 3575 +3 1039 3575 3595 +3 1566 1272 3517 +3 1565 1583 3564 +3 3558 971 1027 +3 3577 1594 1582 +3 3547 1358 1626 +3 3584 1586 1575 +3 2496 3539 954 +3 3586 1590 1579 +3 2689 3542 969 +3 2718 3547 972 +3 3529 1275 1567 +3 2441 1249 2346 +3 1557 88 3560 +3 1561 65 3562 +3 1028 3566 1612 +3 3518 1022 3567 +3 1030 3570 1620 +3 3522 1024 3571 +3 3528 1026 3575 +3 3574 949 3529 +3 3512 84 88 +3 3584 3622 863 +3 76 78 3561 +3 1588 1616 870 +3 3514 52 65 +3 3586 3630 865 +3 42 44 3563 +3 3543 3581 3509 +3 879 873 1627 +3 11 13 3564 +3 1596 868 874 +3 3517 18 28 +3 1285 2047 3518 +3 1283 2017 3506 +3 3591 1576 3555 +3 3507 1559 3538 +3 1321 2239 3522 +3 1319 2209 3508 +3 3593 1580 3557 +3 3587 1592 866 +3 1638 3638 1055 +3 1038 1595 3594 +3 1273 948 3528 +3 1275 2317 3511 +3 1613 1282 3536 +3 1029 954 3539 +3 1621 1318 3540 +3 1624 3572 1031 +3 1633 1276 3544 +3 1032 1054 1644 +3 1558 1296 3550 +3 3563 40 1563 +3 16 14 3516 +3 3567 1568 3518 +3 3571 1570 3522 +3 3575 1573 3528 +3 3560 88 86 +3 3609 1604 1587 +3 3602 3567 1034 +3 1634 1598 3621 +3 1725 1083 1064 +3 3585 1577 1588 +3 3626 864 1653 +3 3579 3538 858 +3 1731 1087 1068 +3 1636 1600 3629 +3 3604 3571 1036 +3 3613 1606 1591 +3 3562 65 63 +3 3587 1581 1592 +3 1623 3633 1637 +3 3581 3543 860 +3 3588 1582 1594 +3 1602 1638 1055 +3 3606 3583 1602 +3 3565 28 26 +3 3619 1609 1597 +3 3607 3575 1039 +3 1639 1603 3641 +3 1740 1093 1074 +3 3530 1568 3602 +3 3531 1295 2177 +3 3532 1570 3604 +3 2695 2687 2257 +3 2724 2716 1937 +3 3535 1573 3607 +3 3566 1586 1612 +3 3611 1049 1029 +3 3570 1590 1620 +3 1625 1682 3614 +3 3577 1564 3526 +3 3574 1596 1632 +3 3578 838 3530 +3 3566 1556 1575 +3 3580 841 3532 +3 3570 1560 1579 +3 3574 1567 1584 +3 3582 837 3535 +3 3608 1064 1670 +3 3578 3602 1598 +3 3590 1574 1587 +3 86 85 3596 +3 75 76 3597 +3 3612 1068 1678 +3 3580 3604 1600 +3 3592 1578 1591 +3 63 64 3598 +3 41 42 3599 +3 10 11 3600 +3 3618 1074 1690 +3 3582 3607 1603 +3 3595 1585 1597 +3 26 25 3601 +3 3506 3578 3537 +3 3610 3597 1589 +3 858 1599 3579 +3 3508 3580 3541 +3 3509 1562 3543 +3 3632 43 1649 +3 3511 3582 3545 +3 3616 3600 1595 +3 3510 1564 3546 +3 1022 952 3554 +3 3554 3549 1557 +3 1576 1558 3555 +3 74 73 3513 +3 1024 962 3556 +3 3556 3551 1561 +3 1580 1563 3557 +3 40 39 3515 +3 1026 3528 3559 +3 3559 3548 1566 +3 3594 1583 3558 +3 3564 13 16 +3 1586 863 869 +3 1034 1587 1604 +3 3596 85 87 +3 1589 1035 1605 +3 1590 865 871 +3 1036 1591 1606 +3 3598 64 66 +3 43 41 3615 +3 1595 1038 1608 +3 3589 3642 868 +3 1039 1597 1609 +3 3601 25 27 +3 2346 1249 2437 +3 2041 1302 2523 +3 67 68 2501 +3 2233 1328 2616 +3 35 36 2680 +3 1 2393 2709 +3 3621 1611 1634 +3 3629 1619 1636 +3 3641 1631 1639 +3 3609 87 92 +3 1610 90 1694 +3 1058 1652 1611 +3 1647 1041 1614 +3 3603 1599 1048 +3 3613 66 61 +3 1618 59 1696 +3 3629 1600 1050 +3 1649 1043 1622 +3 1601 1052 3647 +3 1055 3638 1698 +3 3648 1055 1698 +3 3619 27 32 +3 1630 30 1699 +3 1063 1657 1631 +3 857 3537 3578 +3 1598 857 3578 +3 869 1612 1586 +3 1066 1059 1660 +3 3568 1569 3603 +3 871 1620 1590 +3 1600 859 3580 +3 859 3541 3580 +3 1071 1061 1664 +3 3573 1571 3605 +3 1072 1062 1666 +3 3576 1572 3606 +3 862 3545 3582 +3 1603 862 3582 +3 874 1632 1596 +3 3590 1022 3554 +3 3568 1041 1035 +3 3610 1647 77 +3 3592 1024 3556 +3 3573 1043 1037 +3 3599 3615 41 +3 1044 1650 1608 +3 3616 1650 12 +3 3595 1026 3559 +3 875 1640 1612 +3 3538 1577 3585 +3 1660 1701 1066 +3 877 1642 1620 +3 1664 1703 1071 +3 3543 1581 3587 +3 3588 1594 867 +3 1666 1704 1072 +3 880 1645 1632 +3 1040 1610 3644 +3 1040 1604 1646 +3 1647 3610 1605 +3 1605 1035 1041 +3 1042 1618 3646 +3 1042 1606 1648 +3 3615 3599 1593 +3 1607 1043 1649 +3 1698 5 1629 +3 3639 1629 5 +3 1045 1630 3649 +3 1045 1609 1651 +3 1646 92 3620 +3 1658 863 1652 +3 3566 1575 1586 +3 1640 887 1671 +3 1613 3536 3608 +3 1641 1029 1049 +3 1701 870 876 +3 864 3626 3585 +3 1615 1653 1059 +3 80 79 3651 +3 1621 3540 3612 +3 1642 889 1679 +3 3570 1579 1590 +3 1662 865 1654 +3 1648 61 3628 +3 1643 1031 1053 +3 1031 1643 1624 +3 866 3634 3587 +3 1623 1655 1061 +3 3653 3633 1665 +3 1644 1627 3577 +3 1704 873 879 +3 867 3637 3588 +3 1628 1656 1062 +3 4 3 3654 +3 1651 32 3640 +3 1668 868 1657 +3 1033 3574 1632 +3 1645 892 1691 +3 1633 3544 3618 +3 1040 3602 1034 +3 1035 1023 3568 +3 3597 3561 1576 +3 1042 3604 1036 +3 1037 1025 3573 +3 3615 1649 43 +3 1038 1027 3576 +3 3600 3564 1583 +3 1045 3607 1039 +3 857 1598 1634 +3 1059 1066 1674 +3 859 1600 1636 +3 1061 1685 1665 +3 1062 1072 1686 +3 862 1603 1639 +3 1058 1658 1652 +3 1659 89 91 +3 1659 1046 1694 +3 3626 858 3585 +3 1653 864 1660 +3 1635 858 3626 +3 3651 79 81 +3 1060 1662 1654 +3 1654 865 3630 +3 1663 1050 1696 +3 3634 860 3587 +3 1655 866 1664 +3 3634 866 1655 +3 1665 45 46 +3 3637 861 3588 +3 1656 867 1666 +3 1638 861 3637 +3 3654 3 5 +3 1063 1668 1657 +3 1669 29 31 +3 1669 1056 1699 +3 3623 1282 1613 +3 3608 1028 1047 +3 1672 1076 1718 +3 1706 1076 1065 +3 3621 1598 1046 +3 1694 90 3650 +3 3611 3539 1617 +3 882 876 1641 +3 1676 1049 1067 +3 1588 1577 3569 +3 1675 882 1719 +3 3631 1318 1621 +3 3612 1030 1051 +3 1680 1078 1720 +3 1710 1078 1069 +3 1060 1654 1619 +3 3652 59 60 +3 1703 878 1684 +3 1592 1581 3572 +3 1721 1079 1684 +3 1775 902 1734 +3 3635 1348 2244 +3 3617 3547 1626 +3 885 879 1644 +3 1688 891 885 +3 873 867 1594 +3 1687 885 1722 +3 3643 1276 1633 +3 3618 1033 1057 +3 1692 1081 1723 +3 1716 1081 1075 +3 3641 1603 1056 +3 1699 30 3655 +3 24 23 1742 +3 1724 94 93 +3 3657 1751 1771 +3 1751 1085 1095 +3 53 54 1744 +3 1730 57 55 +3 3659 1755 1777 +3 1755 1089 1097 +3 3660 1756 1783 +3 1756 1090 1098 +3 19 20 1746 +3 1739 33 21 + diff --git a/Data/data/meshes/polygon_mesh.off b/Data/data/meshes/building.off similarity index 100% rename from Data/data/meshes/polygon_mesh.off rename to Data/data/meshes/building.off diff --git a/Shape_detection/test/Shape_detection/data/cube.off b/Data/data/meshes/cube-sd.off similarity index 100% rename from Shape_detection/test/Shape_detection/data/cube.off rename to Data/data/meshes/cube-sd.off diff --git a/Shape_detection/test/Shape_detection/data/degenerated.off b/Data/data/meshes/degenerated-sd.off similarity index 100% rename from Shape_detection/test/Shape_detection/data/degenerated.off rename to Data/data/meshes/degenerated-sd.off diff --git a/Data/data/points_3/point_set_3.xyz b/Data/data/points_3/building.xyz similarity index 100% rename from Data/data/points_3/point_set_3.xyz rename to Data/data/points_3/building.xyz diff --git a/Data/data/points_3/point_set_2.xyz b/Data/data/points_3/buildings_outline.xyz similarity index 100% rename from Data/data/points_3/point_set_2.xyz rename to Data/data/points_3/buildings_outline.xyz diff --git a/Data/data/points_3/circles.ply b/Data/data/points_3/circles.ply index e8767879066..a9a9c15aa3c 100644 Binary files a/Data/data/points_3/circles.ply and b/Data/data/points_3/circles.ply differ diff --git a/Data/data/points_3/cylinder_no_noise.ply b/Data/data/points_3/cylinder_no_noise.ply new file mode 100644 index 00000000000..0c8dd21979a --- /dev/null +++ b/Data/data/points_3/cylinder_no_noise.ply @@ -0,0 +1,1534 @@ +ply +format ascii 1.0 +comment Generated by the CGAL library +element vertex 1523 +property float x +property float y +property float z +property float nx +property float ny +property float nz +end_header +-2.789348 6.831461 4.088815 -0.5698205 0.001063832 0.8217685 +3.702977 6.510671 3.29321 0.7547343 0.002947173 0.656024 +-4.946004 3.408813 0.1982709 -0.9992087 -0.001755388 0.03973447 +-0.1930067 4.054871 -4.949368 -0.05619995 0.001634939 -0.9984182 +-3.728779 5.502726 -3.261212 -0.7411341 -0.002045728 -0.6713539 +-4.518443 5.945129 -2.041711 -0.9043739 6.003487e-08 -0.426741 +0.306564 0.9387207 4.940382 0.04774346 -0.003110636 0.9988548 +-1.165824 6.877798 4.818326 -0.2455307 0.001791163 0.9693872 +4.951246 3.862305 0.2000181 0.9985321 -0.00292465 0.05408512 +-2.37145 8.756129 -4.342109 -0.4826252 0.0007224891 -0.8758267 +-1.913188 1.144613 4.567244 -0.3797141 -0.003390394 0.9250977 +4.570036 8.56486 -1.905899 0.9235603 0.00247063 -0.3834454 +4.947673 0.6274414 -0.1487358 0.99933 -0.003403726 -0.03644082 +-1.937825 2.783203 4.562202 -0.3982124 -0.002435239 0.91729 +-3.158226 7.149353 3.819127 -0.6280614 0.002916248 0.7781583 +-1.096485 7.97821 -4.827023 -0.2472802 0.00299166 -0.9689394 +2.656978 3.949127 -4.186551 0.535043 -0.001794101 -0.8448229 +4.554005 7.039083 1.939257 0.9187821 0.0001695462 0.3947651 +3.489154 6.20402 3.523175 0.6960989 0.0009855314 0.7179452 +-4.929826 2.487742 0.4668962 -0.99785 -0.003236746 0.06545901 +3.065099 8.109741 -3.89042 0.6221627 0.002211969 -0.7828848 +-3.807339 5.340169 3.170589 -0.7492754 0.00238947 0.6622542 +4.711614 0.5411784 -1.516615 0.9541201 -0.003472535 -0.299404 +-4.121095 2.253418 -2.751607 -0.8265915 -0.00289334 -0.562795 +-1.967445 2.487742 -4.544264 -0.3706078 -0.003236746 -0.9287838 +1.676557 2.487742 -4.659434 0.3656348 -0.003236746 -0.9307528 +1.794647 6.137695 4.616967 0.3891426 0.002809046 0.9211732 +-3.70927 3.83728 3.283896 -0.7362139 0.001494657 0.6767473 +2.83797 0.5745443 4.055442 0.5795895 -0.003472535 0.8149012 +4.860172 10 0.9271317 0.9828913 -0.0002133005 0.1841864 +-0.3202945 3.122203 4.941297 -0.0458363 0.000384689 0.9989489 +3.817938 2.021077 -3.147821 0.7771143 -0.001351713 -0.6293581 +1.445218 8.577474 -4.734127 0.2731749 0.002953209 -0.9619598 +-0.8695415 5.273438 4.882317 -0.1756451 0.0009759053 0.9844531 +-3.403397 4.659831 3.600743 -0.7079948 -0.00238947 0.7062136 +-4.742507 7.589365 -1.41439 -0.958007 0.0005599383 -0.2867442 +-3.272058 10 3.711426 -0.6600835 0.003285111 0.7511851 +0.1383948 7.97821 -4.948058 0.001453996 0.00299166 -0.9999945 +-4.052003 2.02179 2.846531 -0.8291203 -0.003236522 0.5590609 +-4.80092 0.485026 1.201355 -0.9711485 -0.002585106 0.2384615 +3.413433 3.862305 3.589654 0.6678136 -0.002809046 0.7443233 +-4.131586 0.5745443 -2.725928 -0.8388738 -0.003472535 -0.5443149 +-1.943114 4.775696 -4.561154 -0.3841598 -0.001804223 -0.9232649 +-0.1876539 4.982401 4.948152 -0.06002153 -0.001342162 0.9981962 +-1.967445 7.512258 4.544264 -0.3706078 0.003236746 0.9287838 +-0.135994 4.497274 -4.951849 -0.0448704 0.002045728 -0.9989907 +3.309324 8.294271 -3.678988 0.6751275 0.0004454757 -0.7377009 +4.528887 9.48405 1.993186 0.9164211 0.0008321743 0.4002147 +-3.670336 1.43514 3.3236 -0.7401846 -0.00247063 0.6723992 +3.614002 3.408813 -3.393253 0.7416844 -0.00245612 -0.6707445 +2.461125 9.425456 4.294596 0.4905675 0.003472535 0.8713963 +4.514955 5.074819 -2.039474 0.9230187 -0.002045728 -0.3847496 +3.251608 7.039083 -3.731853 0.6593632 0.0001695462 -0.7518245 +4.755512 2.487742 1.380681 0.9518746 -0.003236746 0.3064708 +-2.307311 9.425456 4.379156 -0.472885 0.003472535 0.8811173 +-0.5091249 2.347819 4.928372 -0.09958554 -0.002152001 0.9950266 +-3.213042 7.404378 -3.770631 -0.6621595 0.003198527 -0.7493561 +4.856135 6.877798 -0.9966748 0.9816696 0.001791163 -0.1905822 +3.741089 4.316406 -3.251633 0.7622631 -0.002455002 -0.6472628 +1.394638 2.98289 4.753412 0.2691322 -0.003231747 0.9630978 +4.704283 3.148397 1.542029 0.9472407 -0.00272128 0.3205115 +4.000453 3.122203 2.918113 0.8188801 0.000384689 0.5739645 +-4.002889 0 2.908269 -0.8142219 -0.001397562 0.580552 +-0.7878806 2.98289 -4.890725 -0.1463019 -0.003231747 -0.9892347 +-4.91939 3.949127 -0.6215591 -0.9922289 -0.001794101 -0.1244133 +4.949302 3.83728 -0.2890387 0.9970755 -6.320061e-08 -0.07642277 +-4.089797 7.01711 -2.795265 -0.832794 0.003231747 -0.5535735 +-4.674877 7.216797 1.647539 -0.9404839 0.002435239 0.3398295 +-3.708316 8.391113 3.277279 -0.7564917 0.0004912087 0.6540031 +-4.366658 9.034932 -2.331735 -0.8827091 0.002585704 -0.4699127 +-4.545476 9.372559 -1.959651 -0.9157388 0.003403726 -0.4017597 +0.5012403 5.683594 4.93129 0.112584 0.002455002 0.9936392 +-1.943463 6.703186 -4.561006 -0.3843662 0.001805824 -0.923179 +-4.945848 5.340169 -0.2950431 -0.9995425 0.00238947 -0.03015174 +-4.654243 7.589365 1.701658 -0.9348775 0.00288986 0.3549587 +-0.04268034 2.850647 4.949309 -0.0110809 -0.002086067 0.9999364 +0.3116524 3.408813 -4.947529 0.08150843 -0.00245612 -0.9966697 +-0.1929858 8.109741 4.949036 -0.043172 0.002211969 0.9990652 +4.489921 5.340169 2.095012 0.9182515 0.00238947 0.3959905 +-4.396144 4.054871 2.281976 -0.879467 0.001634939 0.475957 +4.581129 5.482534 -1.878693 0.9287508 -0.001342162 -0.3707021 +2.532949 7.01711 -4.257243 0.5001896 0.003231747 -0.8659099 +-1.808954 5.340169 4.612608 -0.3375516 0.00238947 0.941304 +-4.342235 1.952616 2.379206 -0.8723664 -0.001221879 0.4888511 +-1.899065 9.372559 4.56828 -0.3841836 -0.0002031177 0.9232567 +1.043852 8.109741 4.841546 0.2066417 0.002211969 0.9784142 +-3.302918 2.783203 -3.695888 -0.6604382 -0.002435239 -0.7508764 +4.953391 7.404378 -0.07220062 0.9994652 0.003198527 -0.03254514 +-4.947142 2.253418 0.1449413 -0.9991852 -0.000372711 0.04035883 +3.272038 10 3.711395 0.662166 0.003117237 0.7493507 +-2.001424 5.017599 4.537056 -0.4013768 0.0009768698 0.9159125 +-4.886346 7.97821 0.79123 -0.9825543 0.00299166 0.185952 +-3.567832 4.517466 -3.433191 -0.7270661 0.001342162 -0.6865661 +4.431522 2.783203 2.220465 0.890476 -0.002435239 0.4550237 +-0.371097 5.482534 -4.93746 -0.06555891 -0.001342162 -0.9978478 +-4.574577 7.97821 1.895972 -0.9162956 0.003236522 0.4004896 +1.96879 8.553874 -4.543878 0.3968954 0.00282823 -0.9178595 +-2.220107 5.017599 -4.434152 -0.4498755 0.0009768698 -0.8930908 +2.843341 2.98289 -4.054243 0.5969765 -0.003022951 -0.8022531 +4.927152 1.890259 -0.5033575 0.994383 -0.002211969 -0.1058186 +-1.979402 2.98289 -4.541135 -0.3877182 -0.003231747 -0.9217723 +0.663662 1.028239 4.906597 0.1283777 -0.003353116 0.9917197 +4.374927 3.148397 -2.327912 0.8864843 -0.002931993 -0.4627493 +4.844631 7.746582 -1.041304 0.975724 0.00289334 -0.2189849 +0.5332083 9.425456 -4.921013 0.1153165 0.003472535 -0.9933227 +3.298893 4.485728 3.693061 0.6482606 -0.001834222 0.7614163 +-4.881955 5.074819 -0.8613908 -0.982874 -0.001788816 -0.1842699 +1.646137 5.482534 -4.677976 0.3304341 2.44119e-08 -0.9438291 +4.544295 8.391113 1.959987 0.9138582 0.0004912087 0.4060332 +-4.792346 0 -1.230465 -0.9682458 -0.002286414 -0.2499897 +-4.817496 8.56486 -1.144295 -0.9725595 0.00247063 -0.2326413 +-4.049816 7.404378 -2.853119 -0.8277138 0.003198527 -0.5611413 +3.086579 8.56486 -3.871783 0.6245958 0.00247063 -0.7809443 +4.801685 3.408813 -1.232471 0.9730766 -0.00245612 -0.2304687 +-1.834033 8.756129 4.594998 -0.3671992 0.0007224891 0.930142 +-4.121095 7.746582 2.751607 -0.8265915 0.00289334 0.562795 +-4.114572 5.242106 2.767174 -0.8324043 -0.0009800183 0.554168 +-4.908828 10 0.6201292 -0.9909575 0.001397562 0.134169 +3.696523 5.989481 -3.305495 0.7512103 0.0009782498 -0.6600623 +0.5705192 7.871908 -4.921954 0.1088611 0.002902156 -0.9940527 +0.6649964 8.855388 4.902837 0.1287895 0.0002355205 0.9916719 +0.867379 8.093669 -4.875529 0.1824835 0.001730127 -0.9832074 +-4.918293 3.408813 0.6209424 -0.994289 -0.00245612 0.1066926 +-1.2148 0.5745443 4.796019 -0.2430945 0.0002515278 0.9700026 +3.462578 3.411458 3.542473 0.6777433 -0.00305335 0.7352923 +2.189093 1.43514 -4.441346 0.4406796 -0.00247063 -0.8976611 +-0.5091249 7.652181 -4.928372 -0.09958554 0.002152001 -0.9950266 +-4.947732 8.521118 0.2180103 -0.9988954 0.003058123 0.0468899 +-3.567832 5.482534 3.433191 -0.7270661 -0.001342162 0.6865661 +-2.110387 3.408813 -4.485693 -0.4087229 -0.00245612 -0.9126552 +4.309724 3.148397 2.446515 0.8657143 -0.002931993 0.50053 +1.069376 2.253418 4.832355 0.2268726 -0.000372711 0.9739244 +-2.4123 3.636627 -4.330545 -0.504477 -5.604549e-08 -0.8634252 +-4.600388 10 -1.821423 -0.9330191 0.001397562 -0.3598242 +1.315781 0.5745443 -4.77173 0.2584479 -0.003472535 -0.9660189 +4.911686 4.010519 -0.6223993 0.9911022 0.0008507433 -0.1331007 +0.5531505 5.074819 -4.926409 0.1221911 -0.001788816 -0.992505 +1.946012 9.501546 -4.550746 0.3877296 0.003262528 -0.9217674 +3.268322 1.608887 3.716212 0.6685582 -0.0004912087 0.7436596 +-3.323874 9.425456 3.667772 -0.6771534 0.003472535 0.7358336 +4.748649 7.97821 -1.397413 0.9515005 0.00299166 -0.3076324 +-0.5084419 3.408813 -4.923795 -0.1023969 -0.001755388 -0.9947421 +3.668222 8.577474 3.323365 0.7540951 0.002953209 0.6567586 +-0.3108498 5 -4.940817 -0.06810356 -0.0002468965 -0.9976782 +3.547137 1.422526 3.452308 0.7028127 -0.002953209 0.7113689 +-4.002889 0 -2.908269 -0.8037462 -0.001397562 -0.5949706 +3.715566 0.711263 -3.266488 0.7542503 -0.0003749103 -0.6565869 +-0.4552889 7.746582 4.928278 -0.1030186 0.000372711 0.9946794 +-3.743038 8.921306 3.236433 -0.7614419 0.0003684321 0.6482331 +3.460151 8.855388 3.542225 0.6936004 0.003390394 0.720352 +-3.741629 0.9927877 3.242273 -0.7585452 -0.003215156 0.6516125 +4.529832 7.652181 -2.007157 0.915553 0.002152001 -0.4021916 +4.548202 8.971761 1.950309 0.9183155 0.0009747406 0.395848 +-4.886346 2.02179 -0.79123 -0.9825543 -0.00299166 -0.185952 +-1.558123 0.485026 4.697268 -0.3190277 -0.002585106 0.9477419 +2.796432 7.97821 4.084409 0.5866057 0.00299166 0.8098671 +-4.903571 5.482534 -0.7404142 -0.9890285 2.44119e-08 -0.1477253 +4.844827 5.683594 1.047145 0.9797974 0.002455002 0.1999776 +4.9491 3.411458 0.212054 0.9973958 -0.00305335 0.07205781 +3.914099 8.391113 3.02853 0.7841713 0.0004912087 0.6205442 +-0.400399 1.43514 4.935318 -0.0792824 -0.00247063 0.9968491 +-4.58237 6.851603 1.887072 -0.9216208 0.002931993 0.3880804 +-1.472203 9.034932 4.726236 -0.2961861 0.002585704 0.9551268 +4.855477 2.268677 -0.9574464 0.9843011 -0.002086067 -0.1764848 +-4.945354 0 0.1554168 -0.999566 -0.001053068 0.02944104 +-2.979974 9.425456 -3.952271 -0.5959141 0.003472535 -0.8030407 +0.5332083 0.5745443 4.921013 0.1153165 -0.003472535 0.9933227 +4.843213 0.6274414 -1.009417 0.9788921 0.0002031177 -0.2043776 +2.162142 0.9650676 -4.453071 0.4379189 -0.002585704 -0.8990108 +2.002755 9.501546 4.524992 0.4075509 0.001448062 0.9131814 +0.8975324 0.485026 4.866879 0.177012 -0.002585106 0.9842053 +-0.371097 4.517466 4.93746 -0.06555891 0.001342162 0.9978478 +-0.1189263 3.45988 -4.954065 -0.04429824 0.0004763359 -0.9990183 +-4.531452 2.253418 2.00517 -0.9180934 -0.00289334 0.3963536 +1.646854 5.989481 -4.677441 0.3403031 0.0009782498 -0.9403153 +4.087516 7.746582 -2.790597 0.8320801 0.000372711 -0.5546553 +-4.818195 3.710429 -1.135454 -0.9754742 -0.0006437161 -0.2201127 +2.215101 8.109741 4.429844 0.4434714 0.002211969 0.8962858 +-4.948854 9.514974 0.03032765 -0.9999411 0.002585106 0.01054502 +4.002846 10 -2.908238 0.8082248 0.002286414 -0.5888696 +-1.615183 1.43514 4.68069 -0.3246979 -0.00247063 0.9458145 +-3.869242 9.425456 -3.087014 -0.7769005 0.003472535 -0.6296139 +-1.44453 1.43514 -4.736139 -0.2932497 -0.00247063 -0.9560327 +-4.656462 7.01711 -1.690355 -0.9442984 0.003231747 -0.3290746 +-3.153874 0 -3.812379 -0.6305319 -0.001397562 -0.7761621 +0.7320298 3.408813 -4.895549 0.1482024 -0.001755388 -0.9889555 +3.822659 3.148397 -3.145697 0.7781737 -0.00272128 -0.6280432 +3.531868 4.517466 -3.481254 0.7133101 -2.44119e-08 -0.7008486 +4.248547 5.683594 -2.553177 0.8511357 0.002455002 -0.52494 +-4.521147 1.144613 2.01971 -0.9100726 -0.003390394 0.414435 +-4.949854 0.9650676 -0.06033899 -0.9999061 -0.002585704 -0.0134607 +-3.463934 1.705729 3.533799 -0.6938537 -0.0004454757 0.7201159 +0.1150661 7.746582 4.95394 0.03227365 0.00289334 0.9994749 +-3.608822 5 3.388909 -0.7253134 -0.0002468965 0.6884187 +2.001437 4.054871 4.530756 0.4197956 0.001634939 0.9076172 +2.001437 5.945129 -4.530756 0.4197956 -0.001634939 -0.9076172 +3.697525 6.50706 -3.303274 0.7498546 0.001795748 -0.6616002 +4.908774 0 0.6201224 0.9919429 -0.002286414 0.1266651 +-3.086478 8.577474 3.86966 -0.6081126 0.002953209 0.7938453 +0.8395438 1.43514 4.879841 0.1711147 -0.00247063 0.985248 +4.087516 2.253418 2.790597 0.8320801 -0.000372711 0.5546553 +4.554005 2.960917 -1.939257 0.9187821 -0.0001695462 -0.3947651 +-4.946004 6.591187 -0.1982709 -0.9992087 0.001755388 -0.03973447 +2.314758 7.392782 -4.374267 0.4623324 0.001063832 -0.8867061 +4.793315 0.9387207 1.235102 0.9647209 -0.003110636 0.2632564 +3.221253 2.783203 3.75864 0.6574205 0.0001037997 0.7535239 +-4.719361 8.855388 -1.48582 -0.9521275 0.0002355205 -0.3057011 +4.941553 7.590128 0.3677795 0.9972315 0.002332162 0.07432233 +1.82921 7.978922 4.597762 0.3777949 0.001351713 0.9258884 +-3.690284 1.890259 3.303332 -0.7422741 -0.002211969 0.6700927 +-4.52323 1.639252 -2.006799 -0.9057813 -0.002295095 -0.4237392 +-2.247319 7.512258 -4.412565 -0.4794059 0.003236746 -0.8775873 +-1.485965 2.409871 -4.724179 -0.3125226 -0.000853183 -0.9499099 +-1.642428 1.890259 4.67254 -0.3276401 -0.002211969 0.9448 +4.489921 4.659831 -2.095012 0.9182515 -0.00238947 -0.3959905 +-3.216799 2.02179 3.764794 -0.6640391 -0.003236522 0.7476908 +-4.010791 3.408813 2.913541 -0.8199026 -0.00245612 0.5724978 +-4.766771 4.054871 -1.345878 -0.9669189 0.001634939 -0.2550789 +1.86339 1.144613 -4.583427 0.3713621 -0.0002355205 -0.9284881 +-0.740869 5.683594 4.901018 -0.138061 0.002455002 0.9904207 +3.936311 1.890259 3.005936 0.7973118 -0.002211969 0.6035635 +-4.722021 9.458821 -1.477536 -0.9551969 0.0002546844 -0.2959709 +2.831114 8.855388 -4.062609 0.5776248 0.003390394 -0.8162953 +4.943828 5.340169 -0.3271626 0.9954398 0.00238947 -0.09536191 +3.708515 9.372559 -3.278491 0.7534257 0.003403726 -0.6575243 +-3.744839 2.347819 3.244109 -0.7537374 -0.002152001 0.6571723 +-1.936427 4.316406 -4.562797 -0.3800312 -0.002455002 -0.9249704 +4.187198 3.489329 2.64374 0.8310354 -0.002720124 0.5562128 +-3.920887 1.243871 3.024611 -0.7992613 -0.00321367 0.600975 +0.306564 9.061279 -4.940382 0.04774346 0.003110636 -0.9988548 +4.406182 8.756129 -2.259908 0.8840874 0.00321367 -0.4673106 +-3.416337 6.743876 3.591528 -0.7017208 0.0008925151 0.7124515 +1.216577 4.659831 4.802958 0.2169133 -0.00238947 0.9761879 +-3.324921 9.372559 -3.663405 -0.6718102 -0.0002031177 -0.7407233 +-3.606783 0 3.386995 -0.7298853 -0.002286414 0.6835657 +-4.785835 0.485026 -1.260105 -0.9659036 -0.002585106 -0.258889 +-2.37145 1.243871 4.342109 -0.4826252 -0.0007224891 0.8758267 +4.089826 1.608887 2.786661 0.8324949 -0.0004912087 0.5540325 +4.345213 6.050873 2.388693 0.8758583 0.001794101 0.482565 +-2.230629 6.510671 -4.425106 -0.4602357 0.002947173 -0.8877919 +-4.947732 1.478882 -0.2180103 -0.9988954 -0.003058123 -0.0468899 +3.569985 6.831461 3.439407 0.7187694 0.00243005 0.6952444 +4.453089 7.404378 2.162252 0.909914 0.00272128 0.4147881 +-4.903652 1.394348 0.6904266 -0.9913522 -0.003150284 0.1311904 +0.1317047 3.79598 -4.956774 0.01596692 -0.0009855314 -0.999872 +3.8517 3.989156 -3.112323 0.7934124 -0.002306673 -0.60868 +4.695329 8.971761 1.571311 0.950098 0.003353116 0.3119335 +-3.306334 8.360748 -3.681712 -0.6829017 0.002295095 -0.7305067 +-4.541101 3.79598 1.991322 -0.9115096 -0.0009855314 0.4112775 +3.741704 1.639252 -3.238287 0.7690736 -0.002295095 -0.6391561 +0.7394823 2.410634 -4.893366 0.1484456 -0.0005599383 -0.9889204 +-4.936679 0.5745443 0.3267077 -0.9976476 0.0002515278 0.06855062 +4.309724 6.851603 -2.446515 0.8657143 0.002931993 -0.50053 +3.615139 5.522461 -3.394842 0.7317447 0.0009741628 -0.6815781 +4.470771 1.243871 -2.118937 0.90525 -0.0007224891 -0.4248787 +4.418211 7.97821 2.232004 0.9042029 0.00299166 0.4270926 +-4.295127 1.43514 -2.463648 -0.8682193 -0.00247063 -0.4961746 +2.555629 9.061279 -4.236936 0.5044925 0.002099014 -0.8634135 +-1.060071 3.489329 4.840818 -0.2249917 -0.002947173 0.9743562 +0.6626568 2.850647 -4.904933 0.1363188 -0.002086067 -0.9906628 +2.886457 6.137695 4.025606 0.6060035 0.002809046 0.7954571 +-4.903652 8.605652 -0.6904266 -0.9913522 0.003150284 -0.1311904 +-4.482445 1.243871 -2.094127 -0.9044027 -0.0007224891 -0.4266792 +0.0975223 1.144613 -4.950807 0.01249807 -0.003390394 -0.9999161 +3.277954 5.791117 -3.710396 0.6574369 0.001926908 -0.7535071 +3.822659 6.851603 3.145697 0.7781737 0.00272128 0.6280432 +4.946649 2.98289 0.2283402 0.9972407 -0.003022951 0.07417524 +1.731032 6.588542 4.641346 0.3767433 0.00305335 0.9263127 +3.260326 8.971761 -3.722918 0.6602489 0.0009747406 -0.7510462 +-1.615183 8.56486 -4.68069 -0.3246979 0.00247063 -0.9458145 +4.856698 7.36735 -0.9885537 0.978829 0.00244426 -0.204665 +2.781092 10 4.092258 0.5673731 -0.0008264586 0.8234605 +-4.862409 8.756129 0.9135976 -0.9821001 0.0007224891 0.1883585 +2.19429 7.652181 4.440607 0.4335636 0.001367922 0.9011219 +-4.011568 3.949127 2.914457 -0.8084705 -0.001794101 0.588534 +4.346064 5 -2.389269 0.880093 8.685775e-09 -0.4748014 +-4.634039 8.577474 -1.739624 -0.9429089 0.002953209 -0.3330378 +-4.86384 5.340169 0.9442087 -0.9756384 0.00238947 0.2193716 +-4.640765 0.9387207 1.716439 -0.9426525 -0.002099014 0.333769 +4.340946 8.360748 2.382969 0.8832224 0.003224701 0.4689433 +4.002846 10 2.908238 0.8098035 0.002286414 0.5866967 +-4.860174 10 -0.9271236 -0.9824753 0.003460539 -0.1863609 +2.83797 9.425456 -4.055442 0.5795895 0.003472535 -0.8149012 +1.954291 2.726746 4.553157 0.4028374 -0.001338179 0.9152706 +-1.834033 1.243871 -4.594998 -0.3671992 -0.0007224891 -0.930142 +1.121281 9.007213 4.822329 0.2306678 0.003215156 0.9730273 +3.735308 3.79598 3.261047 0.7602369 -0.0009855314 0.6496451 +4.946737 0.9387207 0.1124751 0.9993247 -0.002099014 0.03668296 +4.801497 6.591187 -1.233207 0.9637427 0.00245612 -0.266822 +4.831603 7.01711 1.093417 0.9780963 0.003231747 0.2081277 +3.247167 1.890259 -3.739799 0.6524361 -0.002211969 -0.7578405 +1.96879 1.446126 4.543878 0.3968954 -0.00282823 0.9178595 +0.6369426 5.340169 4.913529 0.1576779 0.00238947 0.9874877 +2.290428 8.294271 -4.386401 0.4704583 0.0004454757 -0.8824221 +-4.933762 9.425456 0.3983423 -0.9973364 0.003472535 0.07285623 +4.545684 1.446126 1.964616 0.9176424 -0.00282823 0.3973972 +4.955257 6.851603 -0.06767227 0.9997633 0.002931993 -0.02155676 +-4.578968 2.595622 -1.890595 -0.9172986 -0.003198527 -0.3981874 +-4.948302 1.952616 -0.2370275 -0.9987796 -0.002766267 -0.0493119 +-1.115342 5.683594 -4.829583 -0.2362323 0.002455002 -0.9716935 +-4.654455 6.010844 -1.705284 -0.9420305 0.002464777 -0.335518 +-1.165824 3.122203 -4.818326 -0.2455307 -0.001791163 -0.9693872 +-3.741208 6.591187 3.24124 -0.7555919 0.001755388 0.6550403 +-4.116261 4.775696 2.763371 -0.834927 -0.001804223 0.5503578 +-2.39621 3.148397 4.33201 -0.4923295 -0.00272128 0.8704047 +4.755512 7.512258 -1.380681 0.9518746 0.003236746 -0.3064708 +1.157331 5.074819 4.817142 0.2049782 -0.002045728 0.9787644 +-4.948608 3.949127 0.1308191 -0.9996083 -0.001303923 0.02795377 +4.269054 8.756129 2.509343 0.8682811 0.00321367 0.4960621 +-3.717142 4.208883 -3.270302 -0.7466923 -0.001926908 -0.6651668 +4.345826 4.477539 -2.389138 0.8743408 -0.0009741628 -0.4853114 +-3.261029 6.510671 -3.731348 -0.6665614 0.002947173 -0.7454443 +-4.09511 2.487742 2.784106 -0.8428875 -0.003236746 0.5380801 +1.245962 9.425456 -4.788018 0.2542769 -0.0002515278 -0.9671314 +-4.929604 7.97821 -0.4488129 -0.9979299 0.00299166 -0.0642413 +3.845805 5.691885 -3.126334 0.785455 -0.001641768 -0.6189166 +-4.600388 0 1.821423 -0.9330191 -0.001397562 0.3598242 +1.946012 0.4984538 4.550746 0.3877296 -0.003262528 0.9217674 +-2.601318 0.9650676 -4.211631 -0.5244112 -0.002585704 -0.8514612 +3.531078 4.982401 3.481675 0.7103606 -0.0009768698 0.7038372 +4.95309 2.783203 -0.1890943 0.9995394 -0.002435239 -0.03024976 +4.092227 0 -2.781071 0.8277188 -0.003117237 -0.5611345 +3.606822 0 -3.387032 0.7350391 -0.001397562 -0.6780233 +-2.781076 10 4.092224 -0.5604521 0.001053068 0.8281862 +-4.482445 8.756129 2.094127 -0.9044027 0.0007224891 0.4266792 +2.719579 2.02179 -4.138279 0.5650925 -0.003236522 -0.8250212 +-1.987746 6.510671 4.539398 -0.3906901 0.002947173 0.9205176 +-1.588714 8.093669 -4.690322 -0.3137523 0.001730127 -0.9495033 +1.990698 0.9718831 4.532747 0.3995106 -0.002963313 0.9167238 +4.621553 7.590128 1.779666 0.928412 0.000853183 0.3715512 +-1.666598 7.746582 4.660222 -0.3471487 0.000372711 0.93781 +-4.784976 7.590128 1.2767 -0.9694934 0.000853183 0.2451156 +-1.64706 4.982401 -4.669755 -0.3116539 -0.001342162 -0.9501947 +4.856805 9.425456 0.9428614 0.9811892 -0.0002515278 0.1930485 +-4.009898 2.850647 2.912189 -0.8160591 -0.002916248 0.5779611 +-4.893655 4.757894 0.799435 -0.9861507 0.0009800183 0.1658488 +4.310877 2.607219 -2.444551 0.8694137 -0.00288986 -0.4940763 +-0.1203499 7.589365 -4.947462 -0.02333047 0.0005599383 -0.9997277 +0.1317047 6.20402 4.956774 0.01596692 0.0009855314 0.999872 +3.334852 4.925181 -3.663745 0.6511471 0.002045728 -0.7589488 +-1.965024 10 4.540895 -0.391257 -0.0008264586 0.9202811 +1.996012 4.982401 -4.531596 0.4232671 -0.001342162 -0.906004 +2.786492 0.711263 -4.087889 0.5672677 -0.0003749103 -0.8235334 +-2.262469 7.97821 -4.402688 -0.4804769 0.00299166 -0.8770023 +-4.929604 2.02179 0.4488129 -0.9979299 -0.00299166 0.0642413 +2.372803 4.659831 4.349514 0.4528666 -0.00238947 0.8915751 +-4.517382 5.502726 -2.043437 -0.9082375 -0.0009807457 -0.418454 +4.763355 9.061279 -1.339145 0.9588065 0.002099014 -0.2840525 +-1.037409 0.9387207 4.838041 -0.223288 -0.002099014 0.9747503 +4.703547 2.021077 1.536905 0.9477832 -0.001351713 0.3189124 +4.091495 2.325439 -2.793029 0.8221155 -0.00183703 -0.5693178 +-4.937733 7.216797 0.4331836 -0.9954491 0.002435239 0.09526428 +3.271266 5.242106 3.718571 0.6491112 -0.00204843 0.7606907 +-4.946698 8.391113 -0.1494831 -0.9991546 0.0004912087 -0.0411065 +1.528968 10 -4.705678 0.3005294 0.001397562 -0.9537715 +-1.14577 0.5745443 -4.815381 -0.2389035 -0.003472535 -0.9710371 +2.053445 5.482534 -4.505507 0.4232671 -0.001342162 -0.906004 +-0.1203499 2.410634 4.947462 -0.02333047 -0.0005599383 0.9997277 +-4.948682 7.590128 0.2544613 -0.9986832 0.002332162 0.05124998 +-3.161146 4.477539 3.82117 -0.6342865 -0.0009741628 0.7730975 +4.187198 6.510671 -2.64374 0.8310354 0.002720124 -0.5562128 +-4.827764 2.253418 -1.089916 -0.9778308 -0.000372711 -0.2093964 +-1.771234 2.409871 4.627843 -0.3573517 -0.002332162 0.933967 +-0.1578211 1.446126 -4.949551 -0.03113738 -0.00282823 -0.9995111 +-3.433243 7.590128 3.5731 -0.6929256 0.002332162 0.7210053 +-1.067317 8.756129 4.835541 -0.2034695 0.00321367 0.979076 +-4.395852 8.109741 -2.281816 -0.8855995 0.002211969 -0.4644445 +-4.741308 6.591187 -1.422063 -0.9579352 0.001755388 -0.2869793 +0.7026659 6.315511 4.900702 0.1496035 0.002381188 0.9887432 +-4.946698 1.608887 0.1494831 -0.9991546 -0.0004912087 0.0411065 +1.528968 10 4.705678 0.3174795 0.001397562 0.9482641 +-4.397323 5.017599 2.276615 -0.877639 0.001342162 0.4793204 +1.127617 1.705729 4.818201 0.2362286 -0.0004454757 0.9716974 +4.949302 6.16272 0.2890387 0.9970755 6.320061e-08 0.07642277 +-4.00446 1.639252 -2.913186 -0.8003703 -0.003224701 -0.5994972 +4.600338 0 1.821403 0.9292789 -0.002286414 0.3693719 +3.451826 0.5745443 -3.547616 0.6918628 -0.003472535 -0.7220206 +-3.651781 8.093669 -3.344791 -0.73237 0.001730127 -0.6809047 +-4.810479 5.482534 -1.172825 -0.9692684 -0.001342162 -0.2460017 +4.787885 4.726562 1.292005 0.9655458 -0.0009759053 0.2602313 +2.656593 6.591187 4.185413 0.5515757 0.00245612 0.8341213 +-1.591488 4.477539 -4.687748 -0.3246238 -0.0007823346 -0.9458429 +2.331353 0.5159505 -4.36609 0.4768645 -0.00342113 -0.8789701 +2.162638 5.482534 4.454125 0.4282874 -0.001342162 0.9036416 +-1.769754 3.989156 -4.624946 -0.3337111 -0.002306673 -0.9426726 +-4.891058 2.487742 -0.77377 -0.9827797 -0.003236746 -0.1847527 +-4.91796 10 -0.5429495 -0.9950474 -0.0002787848 -0.09940135 +-3.735371 7.589365 3.246362 -0.755432 0.0005599383 0.6552268 +-0.9271334 10 -4.860203 -0.196127 0.001397562 -0.9805775 +0.4828525 7.97821 4.926386 0.12389 0.00299166 0.9922915 +-3.286293 7.97821 -3.701716 -0.6834834 0.00299166 -0.7299599 +-0.6799961 4.659831 -4.909446 -0.1098873 -0.002296097 -0.9939414 +-4.947789 10 4.996004e-16 -0.9999965 0.002286414 0.001342912 +1.593473 2.607219 4.692583 0.322413 -0.00288986 0.9465947 +-3.967719 7.978922 -2.966333 -0.8004026 0.003153452 -0.5994545 +-4.282016 1.890259 -2.488883 -0.8666714 -0.002211969 -0.4988746 +-1.52121 6.877798 4.71221 -0.3251201 -0.000384689 0.9456726 +3.985244 1.478882 -2.936459 0.8016986 -0.001445814 -0.5977268 +-2.39621 6.851603 -4.33201 -0.4923295 0.00272128 -0.8704047 +2.818763 7.746582 -4.075456 0.5613667 0.00289334 -0.8275622 +-1.947166 3.79598 4.560208 -0.3829231 -0.0009855314 0.9237797 +4.550688 3.83728 1.958032 0.9258039 0.001494657 0.3780012 +-0.2636764 2.969259 -4.945463 -0.07366282 0.0002111923 -0.9972832 +-4.511562 9.372559 2.030133 -0.9120705 -0.0002031177 0.4100333 +-3.606783 10 -3.386995 -0.7298853 0.002286414 -0.6835657 +-1.78516 7.154058 -4.623545 -0.3583786 0.001742956 -0.9335747 +-3.791757 7.154058 -3.191636 -0.7638026 0.001742956 -0.6454476 +4.947928 4.256185 0.2645205 0.9965936 -0.002659542 0.08242676 +2.925268 5.340169 3.998909 0.6139001 0.00238947 0.7893801 +4.938572 8.756129 -0.2969721 0.9979635 0.0007224891 -0.06378341 +4.831482 3.989156 -1.10848 0.9766539 -0.002464777 -0.2148046 +0.1383948 2.02179 4.948058 0.001453996 -0.00299166 0.9999945 +-4.58237 3.148397 -1.887072 -0.9216208 -0.002931993 -0.3880804 +-2.040513 0.711263 4.509806 -0.416201 -0.002865907 0.9092681 +-1.417698 1.890259 -4.745559 -0.2902731 -0.002211969 -0.9569413 +4.264025 9.372559 2.513898 0.8581641 0.003403726 0.5133643 +1.466385 2.021077 -4.731981 0.2951888 -0.003153452 -0.9554337 +0.3112522 6.050873 -4.948723 0.06371555 0.001794101 -0.9979665 +-4.817496 1.43514 1.144295 -0.9725595 -0.00247063 0.2326413 +-4.825212 8.109741 -1.116924 -0.9732794 0.002211969 -0.2296135 +-4.862409 1.243871 -0.9135976 -0.9821001 -0.0007224891 -0.1883585 +2.993717 1.705729 -3.94008 0.598128 -0.0004454757 -0.8014005 +4.951962 1.838277 -0.1364328 0.9998899 -0.003153452 -0.01450405 +0.7846279 7.746582 4.886673 0.1475847 0.000372711 0.9890494 +2.710409 7.392782 -4.148876 0.5476923 0.00288986 -0.8366749 +3.757358 0.5745443 3.222258 0.7640383 -0.003472535 0.6451616 +1.780568 5.743815 4.624019 0.3863569 0.002659542 0.9223455 +-3.343179 5.074819 3.660415 -0.6822345 -0.001788816 0.7311313 +1.327681 3.411458 4.772403 0.2396812 -0.00305335 0.9708468 +-2.28137 5.683594 -4.400478 -0.470461 0.002455002 -0.8824174 +4.406182 1.243871 2.259908 0.8840874 -0.00321367 0.4673106 +0.4228614 0.9387207 -4.929914 0.09935869 -0.002099014 -0.9950495 +4.945391 0 0.1554121 0.9992843 0.0008264586 0.03781676 +0.3139876 8.360748 4.942041 0.07731233 0.003224701 0.9970017 +2.543635 7.589365 4.252944 0.52385 0.00288986 0.8518056 +-4.795054 5 -1.231161 -0.9672453 0.0002468965 -0.2538435 +3.827853 4.659831 -3.145792 0.7909241 -0.00238947 -0.6119096 +-1.984995 1.838277 4.53876 -0.4126087 -0.003153452 0.9109029 +-2.103712 9.061279 4.480597 -0.4120937 0.003110636 0.9111362 +-1.108967 4.775696 4.832185 -0.2318897 -0.001804223 0.9727404 +-4.406838 8.391113 2.252097 -0.8953691 0.0004912087 0.4453245 +2.162142 9.034932 4.453071 0.4379189 0.002585704 0.8990108 +-3.433243 2.409871 -3.5731 -0.6929256 -0.002332162 -0.7210053 +1.525556 9.061279 -4.708931 0.2946486 0.003110636 -0.9556006 +3.29904 2.410634 3.68893 0.6673535 -0.0005599383 0.7447409 +-4.918197 3.408813 -0.6216953 -0.989585 -0.00245612 -0.143929 +-1.247749 5.340169 -4.794955 -0.2801996 0.00238947 -0.9599388 +2.189093 8.56486 4.441346 0.4406796 0.00247063 0.8976611 +-1.965024 10 -4.540895 -0.3986427 0.003285111 -0.9171004 +0.8343037 4.726562 -4.880155 0.1730759 -0.001413888 -0.9849074 +3.308337 4.238688 -3.688374 0.6541205 0.001854058 -0.7563881 +-4.381571 1.43514 2.306407 -0.8841492 -0.00247063 0.4671981 +1.646137 4.517466 4.677976 0.3304341 -2.44119e-08 0.9438291 +2.022853 2.347819 4.521279 0.4179626 -0.001367922 0.9084632 +-1.201836 6.137695 -4.80549 -0.2706205 0.002809046 -0.962682 +-0.3106743 10 4.938026 -0.06145004 0.002286414 0.9981076 +-4.443265 10 -2.176729 -0.8984956 0.003346128 -0.4389697 +2.001295 8.109741 -4.530454 0.4079207 0.002211969 -0.9130147 +4.83146 6.510671 1.101939 0.9774207 0.002947173 0.2112821 +1.261885 6.137695 -4.790071 0.226629 0.002809046 -0.9739771 +-3.690526 5.945129 -3.30356 -0.7334712 -0.001634939 -0.6797185 +-4.874147 0 -0.8506709 -0.9843296 0.0006732809 -0.1763369 +4.956626 6.50706 0.1231469 0.999517 0.001795748 0.03102499 +-0.7810001 0.6274414 4.887906 -0.1514604 -0.003403726 0.9884574 +-3.086478 1.422526 -3.86966 -0.6081126 -0.002953209 -0.7938453 +-2.735041 6.289571 4.125992 -0.5604126 0.0006437161 0.8282133 +-3.708316 1.608887 -3.277279 -0.7564917 -0.0004912087 -0.6540031 +-3.469756 3.408813 3.530306 -0.7011917 -0.001755388 0.7129706 +-3.160217 3.408813 3.81945 -0.6517694 -0.00245612 0.7584132 +-4.663116 2.02179 1.660655 -0.9506019 -0.00299166 0.3103981 +-0.9285392 6.591187 4.869598 -0.168914 0.00245612 0.9856277 +4.829222 9.372559 -1.086373 0.9769967 0.003403726 -0.2132273 +-0.400399 8.56486 -4.935318 -0.0792824 0.00247063 -0.9968491 +4.925302 6.586507 0.5261123 0.9917103 -0.0007466546 0.1284918 +3.696523 4.982401 -3.305495 0.7470523 -0.0009768698 -0.6647646 +4.880305 4.925181 0.8525762 0.9897037 0.002045728 0.1431166 +4.091495 7.674561 2.793029 0.8221155 0.00183703 0.5693178 +4.815531 1.422526 -1.145108 0.9772145 -0.002953209 -0.2122338 +3.30576 0.9927877 -3.685658 0.6708952 -0.003215156 -0.7415453 +-3.951856 8.577474 2.980512 -0.7864289 0.002953209 0.6176738 +-2.001424 5.989481 -4.537056 -0.3956198 0.0009782498 -0.9184139 +-2.29961 1.144613 -4.385407 -0.4707612 -0.003390394 -0.8822542 +-4.338232 5 -2.384963 -0.8788593 -0.0002468965 -0.477081 +1.230475 0 -4.792367 0.2496932 -0.003460539 -0.9683188 +-4.810479 4.517466 1.172825 -0.9692684 0.001342162 0.2460017 +4.792397 0 -1.230479 0.9707599 -0.001397562 -0.2400486 +-0.08290439 3.684489 4.950126 -0.02450144 -0.002381188 0.999697 +-2.280021 2.783203 -4.401177 -0.452954 -0.002435239 -0.8915306 +4.174697 5.340169 -2.668402 0.8263696 0.00238947 -0.563123 +1.928112 7.652181 -4.564038 0.3920903 0.002152001 -0.9199242 +-4.008051 8.360748 -2.908244 -0.8174838 0.003224701 -0.5759426 +0.7656388 6.831461 4.890058 0.147158 0.001063832 0.9891124 +-4.94168 6.137695 -0.341964 -0.9991913 0.002809046 -0.0401097 +4.184636 8.756129 -2.639414 0.8437942 0.0007224891 -0.5366664 +-1.539083 6.877798 -4.706403 -0.2928247 -0.000384689 -0.956166 +3.289067 9.501546 3.698418 0.6689528 0.003262528 0.7432977 +0.1906747 4.982401 4.955222 0.03602086 -0.0009768698 0.9993505 +0.2389679 7.404378 -4.94815 0.03027602 0.003198527 -0.9995365 +1.659996 8.161723 -4.667436 0.3227771 0.003153452 -0.9464697 +1.095224 7.273254 4.832285 0.2120803 0.001338179 0.9772514 +3.132689 3.79598 3.834692 0.6425375 0.001107731 0.7662534 +-3.297137 3.79598 -3.703491 -0.6728202 -0.0009855314 -0.7398055 +4.844505 2.783203 1.04863 0.9756598 -0.002435239 0.2192759 +1.382383 7.512258 -4.755017 0.251278 0.003236746 -0.9679096 +1.186557 8.855388 -4.803344 0.2453133 0.0002355205 -0.9694438 +4.90866 3.79598 0.6508971 0.9929262 0.001107731 0.1187275 +-3.493207 6.363373 3.514018 -0.7210532 -0.0009602766 0.692879 +-1.528951 0 4.705627 -0.3102931 -0.002286414 0.9506382 +1.125854 1.078695 4.818431 0.2349976 -0.0003684321 0.9719959 +2.106666 0 -4.476893 0.4269929 -0.002286414 -0.9042521 +4.221544 9.372559 -2.579574 0.8534877 -0.0002031177 -0.5211129 +1.083446 3.133138 -4.834961 0.203382 -0.0003081221 -0.9790994 +-4.890086 5.683594 0.8098894 -0.9846092 0.002455002 0.174753 +4.435682 1.705729 2.205216 0.8911497 -0.003189304 0.4536981 +-4.701385 3.862305 1.560166 -0.957825 -0.002809046 0.2873383 +-1.2148 9.425456 -4.796019 -0.2430945 -0.0002515278 -0.9700026 +-1.333048 1.705729 4.765455 -0.2611101 -0.0004454757 0.9653089 +-4.945452 7.972819 0.2988279 -0.9979295 0.002875061 0.0642524 +-3.151899 9.061279 3.816659 -0.6257374 0.003110636 0.7800276 +3.699048 7.039083 -3.299869 0.7493402 0.002435239 -0.6621807 +2.860599 2.595622 -4.040088 0.597538 -0.00272128 -0.801836 +-4.653774 4.010519 -1.71259 -0.9414427 -0.0009782498 -0.3371714 +4.733936 9.425456 1.44587 0.9541201 0.003472535 0.299404 +1.349287 4.316406 4.769516 0.261105 -0.002455002 0.9653073 +4.906108 7.36735 0.6636516 0.9886434 5.98393e-05 0.1502804 +-1.115342 4.316406 4.829583 -0.2362323 -0.002455002 0.9716935 +-4.440758 8.521118 -2.192544 -0.8979281 0.003058123 -0.4401316 +-0.7574596 7.97821 4.891695 -0.1267751 0.00299166 0.991927 +-2.457391 3.684489 4.297889 -0.5030785 -0.002381188 0.8642375 +3.950539 6.586507 -2.988082 0.8108844 -0.0007466546 -0.5852059 +-1.602677 10 4.681032 -0.3224398 0.001698443 0.9465885 +-0.09309055 8.521118 4.951658 -0.01592378 0.003058123 0.9998685 +-4.165685 6.137695 -2.680338 -0.856275 0.002809046 -0.5165125 +4.735498 4.925181 -1.46647 0.9520287 0.001788816 -0.3060036 +4.091602 3.83728 -2.793107 0.8152275 0.001494657 -0.5791389 +-1.417698 8.109741 4.745559 -0.2902731 0.002211969 0.9569413 +3.15384 10 -3.812337 0.636387 0.002286414 -0.7713665 +-1.079355 7.512258 -4.832822 -0.2460974 0.003236746 -0.9692397 +3.15384 0 3.812337 0.636387 -0.002286414 0.7713665 +3.370568 8.466797 3.629177 0.6840801 0.003178239 0.7293999 +1.315781 9.425456 4.77173 0.2584479 0.003472535 0.9660189 +-2.871461 1.144613 -4.029235 -0.5849626 -0.0002355205 -0.8110602 +4.904416 4.517466 0.6803904 0.9917623 0.001342162 0.1280849 +-0.9301529 2.268677 4.865907 -0.2006334 -0.003160393 0.9796613 +-2.776786 8.391113 4.096538 -0.5700812 0.0004912087 0.8215882 +-4.803568 3.79598 1.201809 -0.966906 0.001107731 0.2551305 +-4.162048 7.731323 -2.677631 -0.8502117 0.002086067 -0.5264368 +2.521478 2.487742 4.261845 0.484093 -0.003236746 0.8750106 +-4.536062 2.02179 -1.981557 -0.9054411 -0.00299166 -0.4244613 +-4.938049 0 -0.3106798 -0.9979551 -0.003460539 -0.06382562 +0.01370937 1.243871 4.947474 -0.000994908 -0.0007224891 0.9999992 +0.8975324 9.514974 -4.866879 0.177012 0.002585106 -0.9842053 +3.735308 4.757894 3.261047 0.7563848 0.0009800183 0.6541262 +-3.86495 0.6274414 -3.088333 -0.781445 0.0002031177 -0.6239741 +-4.334644 3.122203 -2.393713 -0.8843598 0.000384689 -0.4668057 +-4.785835 9.514974 1.260105 -0.9659036 0.002585106 0.258889 +1.975244 2.253418 -4.538021 0.3889146 -0.000372711 -0.9212737 +-2.391039 2.021077 4.332246 -0.4908604 -0.001351713 0.8712372 +3.150717 1.952616 3.819503 0.6436573 -0.001221879 0.7653129 +-4.779339 0.9650676 -1.289422 -0.9651446 -0.002585704 -0.2617043 +-4.910318 9.061279 0.6246013 -0.9901085 0.003110636 0.1402689 +4.888599 3.080241 0.8114794 0.9884373 -0.0006784085 0.1516286 +0.437574 7.039083 -4.937674 0.09295167 0.002435239 -0.9956676 +-4.443265 0 2.176729 -0.8984956 -0.003346128 0.4389697 +4.953032 5.683594 -0.1906129 0.9987476 0.002455002 -0.04997073 +2.036086 10 -4.509433 0.4103878 0.002765833 -0.9119069 +-1.923544 1.639252 -4.559258 -0.3702168 -0.002295095 -0.9289426 +-0.7878806 7.01711 4.890725 -0.1463019 0.003231747 0.9892347 +4.52784 2.410634 -1.997631 0.9145142 -0.0005599383 -0.4045533 +4.407332 0.6274414 2.253221 0.8932751 -0.003403726 0.4494976 +-4.891058 7.512258 0.77377 -0.9827797 0.003236746 0.1847527 +-1.243602 3.148397 4.791825 -0.2604012 -0.00272128 0.9654967 +-4.894824 2.98289 -0.7619981 -0.9860279 -0.003231747 -0.166549 +-3.741629 9.007213 -3.242273 -0.7585452 0.003215156 -0.6516125 +-3.86495 9.372559 3.088333 -0.781445 -0.0002031177 0.6239741 +2.555155 4.517466 -4.250224 0.5166062 -2.44119e-08 -0.8562231 +-4.540897 10 1.965018 -0.9151898 -0.0008264586 0.4030222 +-3.940335 4.517466 3.011143 -0.795525 -2.44119e-08 0.6059207 +4.815531 8.577474 1.145108 0.9772145 0.002953209 0.2122338 +-4.948833 4.62087 -0.2533259 -0.9997591 0.001854058 -0.02186857 +-4.873295 4.238688 0.9097745 -0.9812051 0.0009639648 0.1929653 +-0.6893758 4.925181 4.9092 -0.1284737 0.001788816 0.9917113 +-4.887753 2.253418 0.8152478 -0.9878189 -0.00289334 0.1555809 +0.4828525 2.02179 -4.926386 0.12389 -0.00299166 -0.9922915 +-2.31523 10 4.372717 -0.4668753 0.003451844 0.8843164 +-4.918293 6.591187 -0.6209424 -0.994289 0.00245612 -0.1066926 +4.120701e-06 0 4.947813 -0.003251563 0.0002133005 0.9999947 +-4.609353 3.408813 1.824564 -0.9365183 -0.00245612 0.3506103 +-2.423296 8.971761 4.317728 -0.4844389 0.003353116 0.8748187 +2.843341 7.01711 4.054243 0.5969765 0.003022951 0.8022531 +-1.642531 4.054871 4.672856 -0.3152888 0.001634939 0.9489943 +3.741089 5.683594 3.251633 0.7622631 0.002455002 0.6472628 +-0.9249124 1.639252 -4.864863 -0.1730608 -0.003224701 -0.9849058 +4.145994 3.45988 -2.716009 0.8237545 -2.479629e-08 -0.5669466 +-0.7533138 4.28243 4.901232 -0.1513494 -3.86242e-08 0.9884803 +1.417892 5.482534 4.752137 0.287442 2.44119e-08 0.9577981 +-3.675207 3.710429 -3.31619 -0.7487745 -0.0006437161 -0.6628246 +-2.436788 7.590128 4.314658 -0.4918494 0.002332162 0.8706772 +0.4997282 2.783203 4.931443 0.09295167 -0.002435239 0.9956676 +4.280674 0.9387207 2.481672 0.8580428 -0.002099014 0.5135739 +2.577143 8.577474 -4.225985 0.5038223 0.002953209 -0.8638023 +4.404024 3.989156 -2.275195 0.8925508 -0.002464777 -0.4509401 +-4.951019 5.482534 0.06033899 -0.9999952 -0.001342162 0.002774165 +-4.86879 1.078695 0.9014726 -0.9845468 -0.003390394 0.1750889 +-4.948682 2.409871 -0.2544613 -0.9986832 -0.002332162 -0.05124998 +4.431522 7.216797 -2.220465 0.890476 0.002435239 -0.4550237 +2.383631 10 -4.335799 0.4789017 -0.0002133005 -0.8778685 +1.09523 3.636627 -4.832317 0.1986574 0.0009602766 -0.9800685 +4.345122 3.949127 2.38886 0.8767515 -0.001794101 0.4809404 +0.1915382 5.482534 4.955455 0.0402168 2.44119e-08 0.999191 +4.954408 3.296814 -0.1834835 0.9989725 -0.001805824 -0.04528555 +-2.65126 4.010519 4.181252 -0.5291964 0.0008507433 0.8484989 +1.646854 4.010519 4.677441 0.3403031 -0.0009782498 0.9403153 +-4.926665 6.289571 0.5601009 -0.9940302 0.001789326 0.1090911 +-1.166232 4.925181 -4.818234 -0.2456214 0.001788816 -0.9693642 +0.1880215 4.485728 4.954586 0.03190425 -0.001804865 0.9994893 +4.418211 2.02179 -2.232004 0.9042029 -0.00299166 -0.4270926 +-4.752951 5.791117 -1.386172 -0.9617167 0.001926908 -0.274039 +-3.323874 0.5745443 -3.667772 -0.6771534 -0.003472535 -0.7358336 +4.170531 6.363373 2.679457 0.830045 5.604549e-08 0.5576964 +-4.538794 4.775696 -1.994785 -0.9120587 -0.001804223 -0.4100557 +3.612617 2.268677 -3.389871 0.7381463 -0.003160393 -0.6746333 +4.550688 6.16272 -1.958032 0.9258039 -0.001494657 -0.3780012 +3.743731 2.253418 3.24642 0.7495366 -0.00289334 0.6619565 +3.700983 7.589365 -3.295503 0.7385581 0.00288986 -0.6741836 +4.900437 1.43514 0.7095 0.9899039 -0.00247063 0.1417186 +4.580045 0.9650676 1.878264 0.9247339 -0.002585704 0.3806054 +-4.600719 9.061279 1.826125 -0.924119 0.003110636 0.3820921 +0.3121251 7.149353 4.945978 0.07484898 0.002916248 0.9971906 +2.767653 3.489329 -4.110641 0.5678764 -0.002947173 -0.8231086 +4.47733 4.238688 2.128428 0.9072338 0.0009639648 0.4206257 +2.413483 3.862305 4.325765 0.4617273 -0.002809046 0.8870175 +-1.067843 7.01711 -4.837319 -0.2281336 0.003231747 -0.9736245 +1.894949 7.392782 4.571814 0.388517 0.001063832 0.921441 +0.3112522 3.949127 4.948723 0.06371555 -0.001794101 0.9979665 +2.239909 3.83728 -4.418763 0.435387 0.001494657 -0.9002421 +-4.717091 4.659831 1.515756 -0.9606416 -0.00238947 0.2777806 +4.269054 1.243871 -2.509343 0.8682811 -0.00321367 -0.4960621 +1.463157 8.605652 4.730926 0.3033926 0.003150284 0.9528604 +3.932232 5.017599 3.009481 0.8073825 0.001342162 0.5900268 +4.908774 10 -0.6201224 0.9919429 0.002286414 -0.1266651 +4.633543 2.783203 1.741871 0.9391149 0.0001037997 0.3436034 +4.533208 3.080241 2.001731 0.9196752 -0.0006784085 0.3926792 +-3.239833 0.9387207 3.739832 -0.6652583 -0.002099014 0.7466103 +-4.653729 4.517466 -1.713483 -0.9378594 -2.44119e-08 -0.3470154 +3.510885 1.243871 -3.492178 0.7176368 -0.00321367 -0.6964101 +4.47733 6.586507 -2.128428 0.9094037 0.0009627147 -0.4159133 +3.490316 5.71757 3.522393 0.7034584 3.86242e-08 0.7107365 +2.427891 4.256185 4.319411 0.4644063 -0.002659542 0.8856183 +3.73746 5.224304 3.257485 0.7593652 0.001804223 0.6506622 +4.84426 4.28243 1.059578 0.9770265 -3.86242e-08 0.2131179 +0.8682399 9.034932 -4.873485 0.1741414 0.002585704 -0.9847172 +-1.529815 5 4.708287 -0.3039488 -0.0002468965 0.9526883 +-0.3089834 4.010519 4.941313 -0.0549709 0.0008507433 0.9984876 +0.06865396 4.925181 -4.956891 0.003166302 0.001788816 -0.9999934 +2.472817 6.588542 -4.292288 0.473591 0.00305335 -0.8807396 +-4.693068 4.925181 -1.597057 -0.9500718 0.001788816 -0.3120263 +4.828672 10 -1.079339 0.9755542 0.003285111 -0.2197342 +-4.503091 4.256185 -2.067399 -0.896266 -0.002659542 -0.443509 +3.304597 3.45988 -3.692769 0.651583 0.0004763359 -0.7585772 +-4.840791 9.007213 -1.038682 -0.978635 0.003215156 -0.2055804 +3.969214 3.596395 2.961776 0.8111889 0.001157394 0.5847831 +-3.693002 4.982401 -3.298661 -0.7308642 -0.001342162 -0.6825216 +-3.659541 10 3.329924 -0.7385786 0.001698443 0.6741652 +0.04668447 5.743815 -4.954774 -0.01968749 0.002659542 -0.9998026 +-1.447491 2.783203 4.733773 -0.2839578 0.0001037997 0.9588367 +-4.541101 4.757894 1.991322 -0.913924 0.0009800183 0.405884 +-4.950609 6.540121 0.2396568 -0.9996743 2.479629e-08 0.02552133 +-4.934915 1.144613 -0.4081936 -0.9971583 -0.003390394 -0.07525866 +-4.632125 7.404378 -1.756334 -0.9412599 0.003198527 -0.337668 +1.122799 2.347819 -4.8257 0.2235102 -0.002152001 -0.9746992 +-1.417801 4.054871 -4.745875 -0.3027308 0.001634939 -0.9530747 +-4.535044 5.683594 2.00056 -0.9102166 0.002455002 0.4141251 +-4.942066 5.743815 -0.3577052 -0.9990659 0.002659542 -0.04312949 +-3.261623 1.838277 -3.728587 -0.6485294 -0.003153452 -0.7611831 +4.264025 0.6274414 -2.513898 0.8581641 -0.003403726 -0.5133643 +-3.444782 3.45988 -3.563627 -0.7112606 -2.479629e-08 -0.7029284 +-4.950963 5.989481 -0.001893911 -0.9999689 -0.0008507433 -0.007833129 +0.3830841 2.595622 -4.939083 0.09523785 -0.003198527 -0.9954494 +0.4310554 5.482534 -4.940386 0.08533216 2.44119e-08 -0.9963526 +-1.123685 8.360748 -4.819148 -0.2465071 0.002295095 -0.9691383 +-1.611398 2.783203 -4.680517 -0.3338634 0.0001037997 -0.9426215 +-4.335781 10 2.383616 -0.8756567 0.002286414 0.4829288 +4.404268 2.410634 2.271571 0.8830176 -0.00288986 0.469331 +-3.726666 0.4984538 3.257026 -0.7568378 -0.003262528 0.6535946 +1.079331 10 4.828636 0.2192581 0.003117237 0.9756619 +-2.601943 5.482534 4.212615 -0.533482 -0.001342162 0.8458104 +1.682332 9.288737 4.652433 0.3446415 0.0003749103 0.9387343 +-2.377667 4.62087 -4.349351 -0.4911319 0.001733976 -0.8710835 +-0.3202945 6.877798 -4.941297 -0.0458363 -0.000384689 -0.9989489 +1.954291 7.273254 -4.553157 0.4028374 0.001338179 -0.9152706 +3.711422 10 3.272063 0.7543343 -0.0008264586 0.65649 +3.201648 9.034932 3.775466 0.6477358 0.002585704 0.7618607 +4.946984 7.97821 -0.1725693 0.9981125 0.00299166 -0.06133905 +4.86837 8.855388 0.8826107 0.9829342 0.0002355205 0.1839574 +-4.405039 2.253418 -2.25629 -0.8950357 -0.000372711 -0.4459944 +-2.651158 0 4.177557 -0.5369588 -0.002286414 0.8436054 +-2.111403 9.061279 -4.476978 -0.439364 0.003110636 -0.8983037 +2.068485 2.63265 -4.497966 0.4028557 -5.98393e-05 -0.9152635 +3.230598 6.289571 -3.750666 0.6597962 0.0006437161 -0.7514443 +0.3106776 10 -4.93808 0.05389437 0.001397562 -0.9985456 +3.715566 9.288737 3.266488 0.7542503 0.0003749103 0.6565869 +4.218715 10 -2.585227 0.8502926 -0.0006732809 -0.5263098 +2.457753 2.98289 4.298945 0.47172 -0.003022951 0.8817432 +-4.838694 1.906331 1.059916 -0.9765714 -0.0025533 0.2151784 +4.721929 3.83728 -1.510799 0.946745 -6.320061e-08 -0.3219844 +4.581129 4.517466 1.878693 0.9287508 0.001342162 0.3707021 +-4.9273 0.6274414 -0.4725448 -0.9960172 -0.003403726 -0.08909579 +-1.965024 0 4.540895 -0.3986427 -0.003285111 0.9171004 +-2.036841 2.02179 -4.513618 -0.3937968 -0.003236522 -0.9191918 +0.3078902 1.639252 4.942424 0.04825475 -0.003224701 0.9988298 +4.63671 5.71757 1.739309 0.9311891 -0.00159503 0.3645332 +1.024098 3.710429 4.843086 0.2161728 -0.0006437161 0.9763549 +-0.793889 1.838277 4.889814 -0.1731135 -0.003153452 0.9848968 +3.268354 2.325439 -3.722794 0.6547036 -0.00183703 -0.7558835 +4.37273 0 -2.315243 0.8885796 0.0002787848 -0.4587224 +-0.2506571 5.482534 4.945038 -0.06002153 -0.001342162 0.9981962 +4.590164 0.485026 1.849993 0.9258398 -0.002585106 0.3779074 +0.3150474 9.061279 4.939848 0.07782271 0.003110636 0.9969624 +4.251939 2.02179 2.534451 0.8451024 -0.00299166 0.5345962 +-0.3542849 7.36735 4.938098 -0.08790646 5.98393e-05 0.9961287 +-1.25955 3.636627 -4.794408 -0.2739027 -5.604549e-08 -0.9617574 +-1.943463 3.296814 4.561006 -0.3843662 -0.001805824 0.923179 +4.918943 2.409871 -0.5744214 0.9916453 -0.000853183 -0.1289916 +-4.815321 7.216797 1.147398 -0.9747746 -0.0001037997 0.2231916 +2.448162 5.074819 4.310682 0.4845251 -0.001788816 0.8747755 +3.489154 3.79598 -3.523175 0.6960989 -0.0009855314 -0.7179452 +-0.07771299 10 -4.947193 -0.01825239 0.0004031878 -0.9998333 +4.90326 9.034932 -0.6802444 0.9903345 0.002585704 -0.138676 +4.440022 0.6274414 -2.182163 0.8973117 0.0002031177 -0.4413973 +-2.936614 3.862305 -3.989165 -0.5692592 -0.002809046 -0.8221533 +2.099812 6.877798 -4.484395 0.4410807 -0.000384689 -0.8974674 +-4.93685 1.243871 0.3243368 -0.9980884 -0.0007224891 0.06179753 +-4.118064 1.639252 2.743792 -0.8431167 -0.002295095 0.5377257 +3.241603 9.501546 -3.738795 0.6527445 0.001448062 -0.7575768 +-0.7265839 8.294271 -4.900033 -0.1561121 0.003189304 -0.9877342 +-1.528131 5.989481 -4.709231 -0.3015577 -0.0008507433 -0.9534476 +-2.167884 6.831461 4.458092 -0.4391047 0.00243005 0.8984326 +1.416998 5.989481 4.752125 0.2773924 0.0009782498 0.9607562 +-4.360019 7.972819 2.344859 -0.8876701 0.0006083836 0.4604796 +3.969992 4.517466 2.958951 0.8073825 0.001342162 0.5900268 +4.951246 6.137695 -0.2000181 0.9985321 0.00292465 -0.05408512 +4.432204 5.683594 2.219106 0.8992828 0.002455002 0.4373607 +2.98786 7.239787 -3.953491 0.6071232 0.001616554 -0.794606 +4.735498 5.074819 1.46647 0.9520287 -0.001788816 0.3060036 +-1.060071 6.510671 -4.840818 -0.2249917 0.002947173 -0.9743562 +4.957704 4.517466 -0.1199954 0.9997445 -2.44119e-08 -0.02260228 +0.2224841 8.577474 -4.944807 0.02536287 0.002953209 -0.999674 +-2.975488 9.372559 3.952481 -0.6017184 -0.0002031177 0.7987083 +-1.965024 0 -4.540895 -0.391257 0.0008264586 -0.9202811 +2.106666 0 4.476893 0.4245627 -0.002286414 0.9053956 +-3.310159 3.862305 3.687504 -0.6781616 -0.00292465 0.734907 +3.241603 0.4984538 3.738795 0.6527445 -0.001448062 0.7575768 +4.831603 2.98289 -1.093417 0.9780963 -0.003231747 -0.2081277 +-2.271428 5.71757 4.407967 -0.4585699 3.86242e-08 0.8886583 +1.216577 5.340169 -4.802958 0.2169133 0.00238947 -0.9761879 +-3.90076 7.97821 3.047375 -0.7714358 0.00299166 0.6363001 +1.394638 7.01711 -4.753412 0.2691322 0.003231747 -0.9630978 +1.80854 8.756129 4.605092 0.3690493 0.0007224891 0.9294095 +0.7800248 4.757894 4.89086 0.1723633 0.00204843 0.9850313 +-0.8699906 5.242513 -4.882511 -0.1795993 8.685775e-09 -0.9837399 +-2.383623 10 -4.335803 -0.4846005 -0.0002133005 -0.8747356 +4.955575 5.71757 0.1784288 0.9993317 3.86242e-08 0.03655416 +-4.84403 3.45988 1.045119 -0.9730222 0.0004763359 0.230711 +-0.1930067 5.945129 4.949368 -0.05619995 -0.001634939 0.9984182 +-4.838706 7.273254 -1.066499 -0.9745429 0.001338179 -0.2241974 +-4.91796 0 0.5429495 -0.9950474 0.0002787848 0.09940135 +-4.540897 0 -1.965018 -0.9151898 0.0008264586 -0.4030222 +0.9571133 0.485026 -4.855514 0.1977285 -0.002585106 -0.9802534 +-4.951757 3.45988 -0.1923767 -0.9998284 0.0004763359 -0.01851805 +-3.717142 5.791117 3.270302 -0.7466923 0.001926908 0.6651668 +-4.700336 0.5745443 1.544146 -0.9492568 0.0002515278 0.3145019 +4.142582 8.047383 2.71678 0.8370145 0.002766267 0.5471737 +-4.912573 1.639252 -0.6236814 -0.9901799 -0.003224701 -0.139762 +4.68054 8.521118 1.618681 0.9460108 0.003058123 0.3241208 +4.922927 1.43514 -0.5314795 0.9940482 -0.00247063 -0.1089128 +4.897536 1.890259 0.7377893 0.9894586 -0.002211969 0.1447988 +-4.128549 6.588542 -2.737453 -0.8492647 0.00305335 -0.5279586 +-4.944047 8.921306 -0.2030277 -0.9988133 0.0003684321 -0.04870123 +3.547137 8.577474 -3.452308 0.7028127 0.002953209 -0.7113689 +-4.839754 1.705729 -1.031192 -0.9797993 -0.0004454757 -0.1999826 +2.448162 4.925181 -4.310682 0.4845251 0.001788816 -0.8747755 +0.07772093 10 4.947212 0.01689674 0.003451844 0.9998513 +-3.604584 8.047383 3.394495 -0.734501 0.001221879 0.6786065 +-3.208459 3.168538 -3.778902 -0.6487405 -0.00243005 -0.7610058 +-4.729074 0 1.454857 -0.9565383 -0.0004031878 0.2916064 +-2.654458 4.010519 -4.179222 -0.5424239 0.0008507433 -0.8401045 +-3.457503 1.478882 -3.545878 -0.6960651 -0.003058123 -0.7179722 +-4.309124 3.596395 -2.440947 -0.8780852 0.001157394 -0.478503 +-3.266154 2.98289 3.724538 -0.6689621 -0.003231747 0.7432895 +-4.947019 9.007213 0.1978056 -0.9990151 0.003215156 0.04425487 +-0.1189263 6.919759 4.954065 -0.03627189 0.0006784085 0.9993417 +1.306998 4.054871 -4.782956 0.2476601 -6.003487e-08 -0.968847 +3.747912 8.294271 -3.239044 0.7503225 0.003189304 -0.6610643 +4.899558 2.783203 -0.7058138 0.9884848 0.0001037997 -0.1513201 +2.232045 8.971761 -4.416766 0.4527284 0.0009747406 -0.8916479 +4.625942 3.49294 1.762722 0.9363586 0.0003211451 0.3510448 +4.771617 5.989481 1.349905 0.9598276 0.0009782498 0.2805887 +1.069376 7.746582 -4.832355 0.2268726 0.000372711 -0.9739244 +-2.72477 2.783203 -4.132731 -0.5577949 0.0001037997 -0.8299788 +4.871992 4.316406 -0.8938434 0.9883095 -0.002461132 -0.1524409 +-3.42613 0.5411784 3.569625 -0.6944604 -0.0002546844 0.7195309 +4.428562 5.71757 -2.231008 0.8933311 3.86242e-08 -0.4493991 +-3.159632 6.591187 3.819934 -0.6228502 0.00245612 0.7823372 +-3.470814 9.007213 3.530661 -0.6979561 0.003215156 0.7161333 +3.161464 8.047383 3.810613 0.6311477 0.001221879 0.7756617 +3.443256 10 -3.553159 0.6926911 -0.0006732809 -0.721234 +4.739081 8.360748 -1.424064 0.9517476 0.002295095 -0.3068734 +-2.31523 0 4.372717 -0.471881 0.0006732809 0.881662 +-3.398256 6.851603 -3.599998 -0.6933229 0.00272128 -0.7206219 +2.287139 4.238688 -4.395247 0.445464 0.001854058 -0.8952979 +4.874401 6.363373 -0.9016848 0.9868462 5.604549e-08 -0.1616618 +-3.066865 5.017599 3.896783 -0.616545 0.0009768698 0.7873191 +4.871533 1.028239 0.8850417 0.9828523 -0.003353116 0.1843638 +0.3990189 1.422526 -4.9337 0.1001295 -0.002953209 -0.99497 +3.177886 0.485026 -3.793827 0.6455115 -0.002585106 -0.7637462 +-2.036841 7.97821 4.513618 -0.3937968 0.003236522 0.9191918 +3.488064 7.97821 -3.512241 0.6856033 0.00299166 -0.7279693 +4.912161 5.989481 -0.6186413 0.9930657 -0.0008507433 -0.117558 +-1.288346 5.37913 4.784902 -0.2881443 -0.001854058 0.9575852 +-3.586799 9.514974 3.409832 -0.7217071 0.002585106 0.6921937 +3.711422 10 -3.272063 0.749027 0.003285111 -0.6625314 +-2.810017 4.485728 -4.077401 -0.5477181 -0.001834222 -0.8366609 +-3.156344 2.268677 -3.818341 -0.6269535 -0.003160393 -0.7790503 +-4.911384 9.061279 -0.6161682 -0.9938859 0.003110636 -0.1103679 +-3.670821 4.28243 3.324055 -0.731604 0.00159503 0.6817279 +4.943593 7.154058 0.3533486 0.9973139 0.001742956 0.07322618 +4.760723 7.01711 -1.369474 0.9573786 0.003231747 -0.2888178 +-4.679695 0.5745443 -1.612804 -0.9478846 -0.003472535 -0.3185948 +-3.960731 0.711263 2.968948 -0.802763 -0.002865907 0.5962914 +4.05752 2.845942 -2.841118 0.8072379 -0.0001362761 -0.5902261 +2.413483 6.137695 -4.325765 0.4617273 0.002809046 -0.8870175 +-1.716966 3.408813 -4.642661 -0.3465622 -0.001755388 -0.9380254 +-4.795054 5 1.231161 -0.9698935 0.0002468965 0.2435292 +4.844742 8.294271 -1.032826 0.9759828 0.003189304 -0.2178244 +-4.553994 8.161723 -1.949791 -0.9243348 0.003153452 -0.3815695 +-3.02007 6.20402 -3.9327 -0.6006275 0.0009855314 -0.7995284 +-3.670336 8.56486 -3.3236 -0.7401846 0.00247063 -0.6723992 +-3.939605 5.989481 -3.01166 -0.7891335 0.0009782498 -0.6142209 +2.958343 2.409871 3.975225 0.5970958 -0.002332162 0.8021665 +2.33729 2.409871 -4.369357 0.471591 -0.002332162 -0.8818144 +2.290428 1.705729 4.386401 0.4704583 -0.0004454757 0.8824221 +4.949019 1.422526 0.08844196 0.9992939 -0.002953209 0.03745722 +2.051402 6.403605 -4.507607 0.4291289 -0.001157394 -0.9032425 +4.335828 0 2.383642 0.871978 -0.001397562 0.489543 +-4.946443 5.761312 0.3307468 -0.9983672 -0.0009639648 0.05711283 +-3.299718 5.224304 -3.700227 -0.6718277 0.001804223 -0.7407052 +4.218715 10 2.585227 0.8532561 0.003451844 0.5214807 +4.913632 0.485026 -0.5901675 0.9933779 -0.002585106 -0.114864 +4.389044 9.061279 2.284546 0.8933871 0.002099014 0.4492829 +-1.488429 7.36735 -4.721748 -0.2849661 5.98393e-05 -0.9585376 +4.600476 6.877798 -1.831563 0.9358926 -0.000384689 -0.3522851 +-2.451304 1.952616 -4.304996 -0.4935375 -0.002766267 -0.8697202 +0.9869987 5.482534 4.852016 0.1901055 -0.001342162 0.9817628 +-1.160769 4.497274 -4.820268 -0.2408553 0.0009807457 -0.9705606 +2.262556 7.273254 4.408099 0.4484499 0.001338179 0.893807 +-3.061093 7.039083 -3.898949 -0.6138226 0.002435239 -0.7894403 +4.944345 8.360748 -0.200763 0.998163 0.002295095 -0.06054236 +0.8684582 5.482534 -4.874629 0.1846554 -0.001342162 -0.9828024 +1.919806 1.705729 -4.560803 0.3800365 -0.0004454757 -0.9249714 +4.344328 6.591187 2.387882 0.8851904 0.00245612 0.4652224 +-4.538947 6.703186 -1.994438 -0.9121504 0.001805824 -0.4098517 +-4.26281 8.391113 -2.514083 -0.8557627 0.0004912087 -0.5173683 +4.659989 4.208883 1.672278 0.9391212 -0.001926908 0.3435807 +0.1067175 1.705729 -4.95246 0.03108524 -0.003189304 -0.9995117 +-4.864543 9.458821 -0.9141341 -0.9841219 0.003472535 -0.1774602 +4.514307 6.315511 2.032647 0.9149851 0.002381188 0.4034807 +-4.679695 9.425456 1.612804 -0.9478846 0.003472535 0.3185948 +1.406058 7.589365 4.751906 0.2955568 0.00288986 0.9553208 +4.222028 5.074819 2.598068 0.8460189 -0.001788816 0.5331498 +1.965004 10 4.540864 0.3989554 0.001053068 0.9169697 +-4.585059 3.684489 -1.884518 -0.9227017 -0.00245612 -0.385507 +-4.658834 2.487742 1.678226 -0.9502217 -0.003236746 0.3115577 +-4.425355 7.589365 2.215423 -0.894647 0.0005599383 0.4467734 +-3.37939 4.238688 -3.627177 -0.688682 0.0009639648 -0.7250629 +-1.590485 6.50706 4.687951 -0.3263728 -0.0003211451 0.9452411 +4.938699 0.5745443 0.2945985 0.9983726 0.0002515278 0.05702833 +-3.97466 5.791117 2.964418 -0.7997717 0.0018013 0.6003016 +2.577143 1.422526 4.225985 0.5038223 -0.002953209 0.8638023 +-0.2469538 6.50706 -4.944243 -0.04451272 -0.0003211451 -0.9990088 +-2.435498 6.010844 -4.31167 -0.5136262 0.002306673 -0.8580109 +3.969049 9.034932 -2.958266 0.801029 0.002585704 -0.59862 +3.711422 0 3.272063 0.749027 -0.003285111 0.6625314 +-3.90076 2.02179 -3.047375 -0.7714358 -0.00299166 -0.6363001 +3.30789 1.078695 3.680039 0.6741925 -0.0003684321 0.7385556 +-0.2505839 0.9650676 -4.943875 -0.04935048 -0.002585704 -0.9987782 +-2.598315 6.50706 -4.213702 -0.5202829 -0.0003211451 -0.8539939 +-4.431936 3.45988 2.216946 -0.8850775 0.0004763359 0.4654435 +-1.217108 8.756129 -4.795449 -0.2496534 0.0007224891 -0.968335 +4.879497 1.705729 -0.8228543 0.9846129 -0.0004454757 -0.174749 +-4.87576 4.256185 -0.8825746 -0.9784043 -0.002659542 -0.2066831 +-2.27253 5.242106 4.407104 -0.4624689 -0.0009800183 0.8866349 +3.8517 6.010844 3.112323 0.7934124 0.002306673 0.60868 +3.571779 4.208883 3.4392 0.7182275 -0.0018013 0.695806 +1.676016 0 -4.655322 0.3447617 0.0008264586 -0.9386899 +-4.678361 1.144613 -1.622633 -0.9471146 -0.003390394 -0.3208775 +4.959048 5.242513 0.06031054 0.9999686 8.685775e-09 0.007916379 +-0.1060472 8.294271 -4.947255 -0.0128443 0.0004454757 -0.9999174 +4.40855 10 -2.246272 0.8902597 0.003285111 -0.4554413 +4.911404 8.047383 -0.6274836 0.9930987 0.001221879 -0.1172753 +4.904416 5.482534 -0.6803904 0.9917623 -0.001342162 -0.1280849 +1.936981 4.485728 -4.557356 0.4129341 -0.001834222 -0.910759 +-1.587335 4.517466 4.690053 -0.3116539 0.001342162 0.9501947 +-4.309542 4.517466 -2.438047 -0.874966 0.001342162 -0.4841824 +-3.338058 5.945129 3.666371 -0.6853217 6.003487e-08 0.7282405 +-3.066865 4.982401 -3.896783 -0.616545 -0.0009768698 -0.7873191 +-3.035746 7.512258 3.912214 -0.5899436 0.003236746 0.807438 +4.830317 1.838277 1.099356 0.9720834 -0.003153452 0.2346141 +0.5900716 3.862305 -4.918227 0.1478305 -0.002809046 -0.9890087 +4.657674 6.16272 1.687817 0.9336416 -0.001494657 0.3582053 +4.772107 5.482534 1.349156 0.9627148 2.44119e-08 0.2705185 +0.7800834 1.608887 -4.887088 0.1468445 -0.0004912087 -0.9891595 +-3.304051 5.683594 -3.694875 -0.6751288 0.002455002 -0.7376958 +-4.257333 7.273254 2.534878 -0.8638849 0.001338179 0.5036876 +-2.309411 9.372559 -4.375186 -0.4664936 -0.0002031177 -0.8845245 +1.954305 3.636627 4.553187 0.4153526 0.0009602766 0.90966 +3.304597 6.540121 3.692769 0.651583 -0.0004763359 0.7585772 +-4.952261 7.030741 0.0473721 -0.9999406 -0.0002111923 -0.01089753 +2.8577 6.877798 -4.050798 0.5851439 0.001791163 -0.8109275 +1.748927 0 4.628413 0.3523596 -0.003451844 0.9358583 +-0.9249124 8.360748 4.864863 -0.1730608 0.003224701 0.9849058 +4.475796 3.489329 -2.118781 0.9149171 -0.002720124 -0.4036327 +-2.652657 5 4.179918 -0.5313236 -0.0002468965 0.8471689 +1.532334 7.149353 4.712969 0.3204887 0.002916248 0.9472479 +1.325674 1.144613 -4.771016 0.2607745 -0.003390394 -0.9653938 +-4.805891 2.63265 -1.189011 -0.9745393 -5.98393e-05 -0.2242167 +4.021533 9.514974 2.884328 0.8151675 0.002585106 0.5792195 +-1.558123 9.514974 -4.697268 -0.3190277 0.002585106 -0.9477419 +-3.726424 6.363373 -3.265667 -0.736787 -0.0009602766 -0.6761242 +-3.272058 0 3.711426 -0.6661061 0.0008264586 0.7458565 +0.08776271 9.425456 4.949039 0.01008919 0.003472535 0.9999431 +-0.6971582 10 4.898461 -0.1364682 -0.0006732809 0.9906442 +1.965393 3.133138 4.548399 0.4109607 -0.0003081221 0.911653 +3.952482 8.56486 -2.982543 0.7991859 0.00247063 -0.6010788 +2.106304 5.989481 4.480572 0.4186785 -0.0008507433 0.9081342 +4.005108 5 -2.909881 0.8058759 -0.0002468965 -0.5920845 +-2.845016 10 -4.048042 -0.5758824 0.003346128 -0.8175257 +-4.168653 0.5745443 2.664559 -0.8412207 0.0002515278 0.5406918 +4.602938 5 1.822432 0.9278032 0.0002468965 0.3730699 +-2.953419 7.871908 -3.978498 -0.6011196 0.002902156 -0.7991538 +4.046901 0.9927877 2.849133 0.8185061 -0.00151491 0.5744959 +3.000937 0.9927877 3.937829 0.6026973 -0.003215156 0.7979635 +-4.717091 5.340169 -1.515756 -0.9606416 0.00238947 -0.2777806 +-4.603133 8.360748 1.825795 -0.9243141 0.003224701 0.3816189 +0.7851595 6.16272 -4.891439 0.1769135 -0.001494657 -0.9842253 +2.451445 0 4.297833 0.4915654 0.0006732809 0.8708404 +-1.155043 0 4.811115 -0.2377955 0.0006732809 0.971315 +-3.586799 0.485026 -3.409832 -0.7217071 -0.002585106 -0.6921937 +2.505021 2.02179 4.269344 0.4830252 -0.00299166 0.8756014 +-4.925702 6.831461 0.5583602 -0.9938558 0.00243005 0.1106559 +4.888956 8.391113 0.76829 0.986124 0.0004912087 0.1660096 +-4.948854 0.485026 -0.03032765 -0.9999411 -0.002585106 -0.01054502 +-3.021321 5.71757 -3.932071 -0.6088325 3.86242e-08 -0.7932988 +-1.230467 10 4.792369 -0.2476833 0.003460539 0.9688349 +1.095224 2.726746 -4.832285 0.2120803 -0.001338179 -0.9772514 +2.336183 0.5411784 4.361518 0.4697145 -0.0002546844 0.8828183 +4.537589 8.093669 -1.986623 0.9165416 0.0025533 -0.3999313 +2.285307 3.408813 4.390859 0.4613952 -0.001755388 0.887193 +-0.3882007 0 4.932539 -0.07968899 -0.002765833 0.9968159 +-4.880195 8.360748 0.8188707 -0.9827042 0.002295095 0.185168 +2.372803 5.340169 -4.349514 0.4528666 0.00238947 -0.8915751 +-2.52436 8.391113 -4.256732 -0.5006665 0.0004912087 -0.8656402 +-4.793756 3.122203 -1.240528 -0.9726659 0.000384689 -0.2322088 +-4.5882 5.273438 1.881898 -0.9253166 0.0009759053 0.3791942 +1.599704 0.711263 4.684335 0.3190394 -0.002865907 0.9477371 +0.3732117 4.208883 -4.944332 0.07831234 -0.0018013 -0.9969273 +-3.039162 0.6274414 3.907055 -0.6089188 -0.003403726 0.7932253 +2.215101 1.890259 -4.429844 0.4434714 -0.002211969 -0.8962858 +4.62447 0.9650676 -1.766061 0.9346443 -0.002585704 -0.3555745 +4.95139 2.253418 -0.1962214 0.9995291 -0.00289334 -0.03054758 +-0.04526434 8.855388 -4.947523 -0.003484541 0.0002355205 -0.9999939 +1.838877 5.340169 4.60076 0.3983024 0.00238947 0.9172511 +-1.380388 10 -4.751338 -0.2808828 0.001053068 -0.9597415 +0.4651311 7.512258 4.929993 0.1226789 0.003236746 0.9924411 +4.947673 9.372559 0.1487358 0.99933 0.003403726 0.03644082 +3.737211 3.296814 3.257772 0.7592196 -0.001805824 0.6508319 +-4.766448 8.109741 1.345796 -0.9635084 0.002211969 0.2676691 +-1.468779 3.49294 4.727496 -0.2915576 0.0003211451 0.9565532 +-2.401005 5.340169 -4.33401 -0.5101237 0.00238947 -0.8600977 +-3.62832 9.514974 -3.365616 -0.7361442 0.002585106 -0.6768197 +-2.817758 0.9927877 4.070917 -0.5726647 -0.003215156 0.8197834 +3.213334 0 -3.762329 0.6503835 -0.002765833 -0.759601 +4.729095 0 1.454856 0.954467 0.0006732809 0.2983157 +1.527348 1.639252 4.71058 0.2951376 -0.003224701 0.9554493 +-4.531452 7.746582 -2.00517 -0.9180934 0.00289334 -0.3963536 +2.655996 1.639252 -4.179479 0.5480586 -0.003224701 -0.8364338 +0.1622246 0.6274414 -4.947249 0.02637954 -0.003403726 -0.9996462 +4.934637 1.838277 0.3649458 0.9971682 -0.0008047276 0.07519922 +-1.930653 7.746582 -4.563698 -0.3979385 0.00289334 -0.9174075 +-4.720262 2.850647 1.488829 -0.9544203 -0.002086067 0.2984588 +-4.351325 0.485026 2.357553 -0.8813351 -0.002585106 0.4724846 +0.6971479 10 -4.898443 0.1398346 0.003346128 -0.9901692 +-4.510209 2.63265 2.054939 -0.9121884 -0.00244426 0.4097638 +-4.874697 0.6274414 -0.844373 -0.9853873 0.0002031177 -0.1703287 +-4.537618 0.711263 -1.971141 -0.9152417 -0.0003749103 -0.402905 +-2.286855 1.639252 4.388296 -0.4797775 -0.002295095 0.8773872 +-4.766448 1.890259 -1.345796 -0.9635084 -0.002211969 -0.2676691 +4.735616 6.877798 1.466068 0.9520573 0.001791163 0.3059145 +1.971826 4.757894 4.54322 0.4119155 0.00204843 0.9112198 +-1.067317 1.243871 -4.835541 -0.2034695 -0.00321367 -0.979076 +-3.711398 0 -3.272034 -0.748806 -0.001053068 -0.6627884 +4.880305 5.074819 -0.8525762 0.9897037 -0.002045728 -0.1431166 +2.39755 9.425456 -4.327735 0.4868042 -0.0002515278 -0.8735111 +-0.7740145 0 4.886916 -0.158045 -0.003285111 0.9874265 +-2.624403 1.478882 4.197317 -0.5253626 -0.001445814 0.8508772 +4.407332 9.372559 -2.253221 0.8932751 0.003403726 -0.4494976 +4.911435 6.877798 -0.6299291 0.9940996 -0.000384689 -0.1084704 +-3.272058 10 -3.711426 -0.6661061 -0.0008264586 -0.7458565 +3.037965 8.391113 3.90678 0.605212 0.0004912087 0.7960641 +-4.429734 6.591187 2.20901 -0.8947555 0.001755388 0.4465529 +4.781072 2.021077 -1.297412 0.9648694 -0.003153452 -0.2627109 +4.155971 7.149353 -2.688009 0.8383368 0.002086067 -0.5451487 +4.659989 5.791117 -1.672278 0.9391212 0.001926908 -0.3435807 +-0.2804734 9.514974 4.940993 -0.05226261 0.002585106 0.99863 +-4.772872 8.56486 1.318093 -0.9643362 0.00247063 0.264669 +-4.207313 5.691885 2.619675 -0.8568323 -0.001641768 0.5155926 +3.969821 8.093669 -2.960346 0.8060765 0.001730127 -0.5918088 +-1.459125 0.9927877 4.729262 -0.2934457 -0.00151491 0.9559745 +-2.323053 6.403605 4.380159 -0.4799224 0.0009790179 0.8773104 +4.739081 1.639252 1.424064 0.9517476 -0.002295095 0.3068734 +-2.929695 4.238688 3.999197 -0.5831739 0.0009639648 0.8123468 +-4.946443 4.238688 -0.3307468 -0.9983672 0.0009639648 -0.05711283 +4.816881 3.168538 1.171311 0.9721501 -0.00243005 0.2343465 +0.811805 4.054871 4.88615 0.1808918 0.001634939 0.9835017 +-3.913301 2.487742 -3.034345 -0.7722111 -0.003236746 -0.6353578 +4.802697 3.949127 1.233221 0.9688117 -0.001794101 0.2477915 +4.647177 1.890259 -1.712876 0.9368266 -0.002211969 -0.3497871 +4.340946 1.639252 -2.382969 0.8832224 -0.003224701 -0.4689433 +4.942087 9.372559 -0.2267534 0.998965 -0.0002031177 -0.04548382 +-0.4809416 2.726746 4.931449 -0.08792589 -0.001338179 0.9961261 +-4.521147 8.855388 -2.01971 -0.9100726 0.003390394 -0.414435 +4.84502 0 1.003359 0.9789751 -0.003451844 0.2039509 +4.681046 0 -1.602676 0.9464282 -0.003346128 -0.322897 +2.999931 6.591187 3.937344 0.6063037 0.001755388 0.7952313 +-3.548959 2.783203 3.450903 -0.7107573 0.0001037997 0.7034373 +-2.40999 1.533203 -4.327078 -0.4823082 -0.003178239 -0.8759958 +2.282423 3.45988 -4.398573 0.4424618 0.0004763359 -0.8967872 +0.6201212 0 -4.908798 0.1285585 0.0002133005 -0.9917019 +-2.436788 2.409871 -4.314658 -0.4918494 -0.002332162 -0.8706772 +-0.563977 3.989156 -4.919764 -0.08879386 -0.002306673 -0.9960474 +1.532334 2.850647 -4.712969 0.3204887 -0.002916248 -0.9472479 +4.815727 2.595622 -1.161926 0.9761587 -0.003198527 -0.2170342 +3.605399 0.9387207 3.391526 0.7185667 -0.003110636 0.6954511 +2.973961 4.925181 3.9623 0.623493 0.002045728 0.7818263 +-4.460097 7.149353 2.145932 -0.9000515 0.002086067 0.4357785 +-2.105697 8.360748 4.482008 -0.4125599 0.003224701 0.9109247 +4.919541 5.482534 0.560664 0.9924577 -0.001342162 0.1225803 +1.09523 6.363373 4.832317 0.1986574 -0.0009602766 0.9800685 +4.90603 0.485026 0.6503445 0.9907346 -0.002585106 0.1357877 +4.94233 0 -0.2330705 0.9989393 -0.003451844 -0.04591778 +-0.3710238 9.034932 -4.936297 -0.07621876 0.002585704 -0.9970878 +3.432504 7.404378 -3.566967 0.6756658 0.00272128 -0.737203 +-2.468943 6.016337 4.296743 -0.5130879 -0.001475025 0.8583348 +1.141261 1.478882 -4.819243 0.2332337 -0.003058123 -0.9724159 +-0.6336842 8.756129 4.906743 -0.1243461 0.0007224891 0.9922386 +-4.942799 5.074819 0.3797642 -0.9978213 -0.001788816 0.06595016 +-4.49517 6.137695 2.081007 -0.8949211 0.002809046 0.4462157 +3.740091 2.783203 3.252779 0.7493402 -0.002435239 0.6621807 +-1.782279 7.149353 4.617463 -0.3577984 0.002086067 0.9337965 +4.86987 5.340169 0.9125957 0.9878818 0.00238947 0.1551899 +-4.36768 4.517466 2.332296 -0.877639 0.001342162 0.4793204 +2.343822 1.144613 4.357353 0.4786972 -0.0002355205 0.8779801 +0.7252665 8.294271 4.894953 0.1380659 0.0004454757 0.990423 +-3.297137 4.757894 -3.703491 -0.6684367 0.0009800183 -0.7437684 +-4.632593 6.289571 1.767716 -0.935671 0.001789326 0.352869 +-2.970776 0 3.956696 -0.6013676 -0.003451844 0.798965 +4.762458 8.161723 1.363649 0.9648694 0.003153452 0.2627109 +-3.213042 2.595622 3.770631 -0.6621595 -0.003198527 0.7493561 +3.512105 2.98289 3.493575 0.6998183 -0.003231747 0.7143136 +4.803448 4.477539 -1.233316 0.9675639 -0.0009741628 -0.2526247 +1.155045 10 -4.811094 0.2309695 0.0004031878 -0.9729609 +0.1150661 2.253418 -4.95394 0.03227365 -0.00289334 -0.9994749 +3.308715 7.652181 3.687881 0.6654284 0.002152001 0.7464586 +-3.523284 7.239787 3.482778 -0.7204728 0.0008917711 0.6934826 +-1.958442 0.711263 -4.543114 -0.391375 -0.0003749103 -0.9202312 +4.262747 7.512258 -2.519952 0.8457534 0.003236746 -0.5335641 +-2.275842 4.775696 4.404584 -0.4665152 -0.001804223 0.8845114 +-4.890017 0.6274414 0.7676708 -0.9868827 -0.003403726 0.1614027 +3.273154 1.446126 -3.716103 0.6615143 -0.00282823 -0.7499272 +2.470529 8.855388 4.291444 0.4926654 0.003390394 0.8702122 +-4.263518 6.866862 2.524503 -0.8683304 0.0003081221 0.4959861 +-0.8548638 9.288737 -4.875577 -0.1769995 0.002865907 -0.9842068 +-4.681061 0 -1.60269 -0.9456937 -0.003451844 -0.3250408 +3.078878 3.710429 -3.87618 0.6145007 -0.0006437161 -0.7889161 +3.163545 3.122203 -3.809329 0.6242498 0.000384689 -0.7812247 +2.655952 3.408813 4.18582 0.519886 -0.00245612 0.8542321 +-2.901879 2.021077 -4.008057 -0.5793208 -0.001351713 -0.8150985 +4.185891 0.5745443 2.637395 0.8474069 0.0002515278 0.5309439 +-4.308521 9.034932 2.437486 -0.8697396 0.002585704 0.4935041 +3.906059 7.273254 -3.048475 0.7939441 0.001338179 -0.6079894 +4.908324 3.296814 -0.6481662 0.9898975 0.0005844671 -0.1417833 +-0.4809416 7.273254 -4.931449 -0.08792589 0.001338179 -0.9961261 +3.51643 1.838277 -3.489307 0.7189596 -0.003153452 -0.6950447 +4.949886 8.756129 0.1423219 0.9998603 0.00321367 0.01640495 +3.953487 7.216797 2.978889 0.7933168 -0.0001037997 0.608809 +-3.70553 2.253418 -3.280894 -0.7560022 -0.000372711 -0.654569 +4.580045 9.034932 -1.878264 0.9247339 0.002585704 -0.3806054 +-3.744839 7.652181 -3.244109 -0.7537374 0.002152001 -0.6571723 +3.564652 7.978922 3.44023 0.7189596 0.003153452 0.6950447 +-2.693552 7.030741 -4.155949 -0.5265939 -0.0002111923 -0.850117 +0.1770956 6.510671 -4.952364 0.02438939 0.002947173 -0.9996982 +3.287723 2.726746 -3.706935 0.6566418 -0.001338179 -0.7542014 +-2.453007 2.607219 4.298264 -0.5009406 -0.001063832 0.865481 +-1.86738 5.743815 4.589647 -0.3497469 0.002659542 0.9368404 +4.666883 2.726746 -1.66454 0.9387589 -0.001338179 -0.3445722 +3.7525 8.855388 -3.230906 0.762482 0.003390394 -0.6470005 +4.86837 1.144613 -0.8826107 0.9829342 -0.0002355205 -0.1839574 +-4.755672 2.253418 1.370692 -0.9577571 -0.000372711 0.2875781 +4.674846 6.540121 1.643996 0.9364339 -0.0004763359 0.3508438 +-2.899231 5.340169 4.017826 -0.5610396 0.00238947 0.8277855 +0.9703991 2.63265 4.854756 0.2120613 -5.98393e-05 0.9772564 +2.951721 9.458821 3.970886 0.5988032 0.0002546844 0.8008961 +-0.7877151 8.756129 -4.888878 -0.1712408 0.00321367 -0.9852239 +4.002846 0 2.908238 0.8082248 -0.002286414 0.5888696 +4.702021 1.533203 -1.556489 0.9508551 -0.003178239 -0.3096199 +-4.691451 5.945129 1.604744 -0.9513845 6.003486e-08 0.3080058 +0.6331505 2.027181 4.913849 0.123879 -0.002875061 0.9922932 +4.899117 4.726562 -0.7145808 0.9901861 -0.001413888 -0.1397482 +-4.708619 7.978922 -1.521293 -0.9542248 0.001351713 -0.2990875 +-0.3089834 5.989481 -4.941313 -0.0549709 -0.0008507433 -0.9984876 +4.855477 7.731323 0.9574464 0.9843011 0.002086067 0.1764848 +-4.774887 0.9927877 1.302085 -0.9643921 -0.00151491 0.2644724 +2.655996 8.360748 4.179479 0.5480586 0.003224701 0.8364338 +-4.697844 4.256185 1.575509 -0.9569526 -0.002659542 0.2902321 +2.451445 0 -4.297833 0.4964887 -0.003451844 -0.8680363 +-3.369967 1.078695 -3.627822 -0.675379 -0.003390394 -0.737463 +4.945846 8.391113 0.2717309 0.9988396 0.003206477 0.04805311 +-3.933801 3.989156 -3.016149 -0.7880524 -0.002464777 -0.6156031 +-3.798955 6.743876 -3.184081 -0.7551071 0.0008925151 -0.6556008 +4.541739 4.208883 -1.970944 0.919787 -0.001926908 -0.3924132 +0.184731 2.960917 -4.953581 0.03257153 -0.002435239 -0.9994664 +2.001295 1.890259 4.530454 0.4079207 -0.002211969 0.9130147 +1.043852 1.890259 -4.841546 0.2066417 -0.002211969 -0.9784142 +-2.703835 4.517466 4.147952 -0.5381666 0.001342162 0.8428375 +2.405362 5.761312 4.33485 0.4767613 -0.0009639648 0.8790323 +2.874575 4.256185 -4.035937 0.6035967 -0.002659542 -0.7972853 +-1.173411 2.63265 -4.815378 -0.2315787 -0.00244426 -0.9728131 +4.37451 6.289571 -2.334395 0.8840668 0.001789326 -0.4673572 +-1.014229 1.422526 4.844786 -0.2240427 -0.002953209 0.9745749 +-0.7033177 9.372559 4.897038 -0.1425092 -0.0002031177 0.9897935 +0.3116524 6.591187 4.947529 0.08150843 0.00245612 0.9966697 +-0.7670877 0.711263 -4.887428 -0.1502271 -0.0003749103 -0.9886515 +4.587233 2.409871 1.86635 0.9311276 -0.000853183 0.3646926 +3.24738 5.945129 3.740056 0.6424963 -0.001634939 0.766287 +-3.786303 2.850647 -3.187694 -0.763401 -0.002086067 -0.6459215 +-0.9946457 2.021077 -4.853103 -0.2016078 -0.003153452 -0.9794613 +-4.541893 4.28243 1.990168 -0.9156986 -3.86242e-08 0.4018657 +4.720842 4.238688 -1.513386 0.9492831 0.0009639648 -0.3144213 +2.427891 5.743815 -4.319411 0.4644063 0.002659542 -0.8856183 +-1.409636 7.239787 4.749336 -0.2972674 0.0008917711 0.9547939 +1.532577 5 4.716788 0.3165362 -8.685775e-09 0.9485804 +4.647177 8.109741 1.712876 0.9368266 0.002211969 0.3497871 +-0.3106743 0 -4.938026 -0.06145004 -0.002286414 -0.9981076 +4.544295 1.608887 -1.959987 0.9138582 -0.0004912087 -0.4060332 +3.840984 8.855388 3.118793 0.7727297 0.0002355205 0.6347352 +-4.943531 7.392782 -0.2319831 -0.9991672 0.001063832 -0.04078975 +-2.677336 9.514974 -4.162206 -0.5446987 0.002585106 -0.8386279 +1.871469 0.5411784 -4.580196 0.380816 -0.0002546844 -0.9246508 +4.0307 2.63265 2.874681 0.8235641 -5.98393e-05 0.5672233 +-0.5084419 6.591187 4.923795 -0.1023969 0.001755388 0.9947421 +-4.948346 4.485728 0.1877951 -0.9998982 -0.001834222 0.01414837 +-3.909556 10 3.032559 -0.7862099 -0.0008264586 0.617959 +0.08401024 0.6274414 4.946572 0.01733146 0.0002031177 0.9998498 +-2.280021 7.216797 4.401177 -0.452954 0.002435239 0.8915306 +-4.372688 0 -2.315217 -0.8830329 -0.001698443 -0.4693081 +-4.186777 3.148397 2.641786 -0.8507523 -0.00272128 0.5255598 +0.9186187 3.122203 4.865711 0.2040322 0.000384689 0.9789641 +4.764703 3.489329 1.361937 0.9583062 -0.002947173 0.285728 +-4.545476 0.6274414 1.959651 -0.9157388 -0.003403726 0.4017597 +-0.341009 0.485026 4.937185 -0.07331103 -0.002585106 0.9973058 +4.683293 7.239787 1.619928 0.9433267 0.001616554 0.3318617 +-4.681061 10 1.60269 -0.9456937 0.003451844 0.3250408 +2.503358 6.20402 4.280205 0.4956839 0.0009855314 0.8685024 +4.913632 9.514974 0.5901675 0.9933779 0.002585106 0.114864 +-3.969111 6.851603 2.967375 -0.7961548 0.002931993 0.6050859 +4.930143 7.589365 -0.4307662 0.99629 0.0005599383 -0.08605786 +-2.865607 5.37913 -4.042699 -0.554162 -0.001854058 -0.8324068 +-2.37262 0.5411784 -4.343973 -0.472885 -0.003472535 -0.8811173 +-0.8665457 3.168538 4.880923 -0.1728422 -0.00243005 0.9849465 +3.265106 7.746582 -3.719449 0.6680016 0.000372711 -0.7441597 +-4.047378 7.392782 2.859759 -0.817232 0.00288986 0.5763016 +-3.474502 7.589365 -3.52416 -0.7013679 0.0005599383 -0.7127993 +-1.637624 0.4984538 -4.669557 -0.3280239 -0.001448062 -0.9446684 +4.236044 8.360748 -2.557886 0.8455304 0.002295095 -0.5339224 +4.939009 4.925181 -0.3878917 0.994202 0.002045728 -0.107509 +2.995019 1.078695 -3.938869 0.5991426 -0.0003684321 -0.8006423 +0.6041207 0.5745443 -4.910456 0.1196041 0.0002515278 -0.9928216 +2.315228 10 4.372697 0.4688783 0.003346128 0.8832564 +-1.947166 5.242106 -4.560208 -0.3883752 -0.0009800183 -0.9215008 +4.939009 5.074819 0.3878917 0.994202 -0.002045728 0.107509 +3.874656 1.478882 3.084578 0.7805622 -0.003058123 0.6250707 +3.00814 3.45988 3.93802 0.6230462 0.0004763359 0.7821849 +3.861414 0 -3.09358 0.7820193 -0.0004031878 -0.6232541 +1.992214 7.039083 4.531088 0.3995279 0.0001695462 0.916721 +-4.871471 6.137695 0.8977252 -0.9777748 0.002809046 0.2096392 +-1.44453 8.56486 4.736139 -0.2932497 0.00247063 0.9560327 +-4.803568 6.20402 -1.201809 -0.966906 -0.001107731 -0.2551305 +0.3882014 0 4.932588 0.0752421 -0.00284677 0.9971612 +-0.563977 6.010844 4.919764 -0.08879386 0.002306673 0.9960474 +-3.743038 1.078695 -3.236433 -0.7614419 -0.0003684321 -0.6482331 +-2.002312 4.517466 4.536956 -0.4052194 -2.44119e-08 0.9142195 +4.767874 6.010844 -1.356216 0.9593313 0.002464777 -0.2822719 +-4.088196 1.243871 -2.794329 -0.8185465 -0.00321367 -0.5744312 +1.664955 1.243871 4.663641 0.3245758 -0.00321367 0.9458542 +4.918385 0.9650676 -0.560518 0.9937086 -0.002585704 -0.1119669 +0.6487193 3.636627 4.914466 0.1512028 -5.604549e-08 0.9885027 +0.774003 0 4.88688 0.1553041 -0.003117237 0.9878618 +-4.169944 8.756129 -2.662564 -0.8448604 0.0007224891 -0.5349864 +-4.893655 3.79598 0.799435 -0.9851534 -0.0009855314 0.1716732 +3.228419 5.273438 -3.75357 0.6485615 0.001413888 -0.7611609 +0.3108949 3.408813 4.947577 0.04405012 -0.00245612 0.9990263 +0.6201212 10 4.908798 0.1285585 -0.0002133005 0.9917019 +3.803355 1.243871 -3.164202 0.7711468 -0.0007224891 -0.6366569 +1.957693 3.168538 -4.546021 0.388517 -0.001063832 -0.921441 +3.488064 2.02179 3.512241 0.6856033 -0.00299166 0.7279693 +-4.730356 5.37913 1.476092 -0.9629114 -0.001854058 0.2698115 +1.27742 5.743815 -4.787501 0.2295718 0.002659542 -0.9732881 +-4.289585 3.710429 2.470571 -0.8617676 -0.0006437161 0.5073028 +-3.879264 3.411458 -3.080564 -0.7645556 -0.00305335 -0.6445505 +-4.324346 6.20402 2.412187 -0.879493 -0.001107731 0.4759105 +2.648691 0.9387207 4.181601 0.5230399 -0.003110636 0.8523026 +0.9571133 9.514974 4.855514 0.1977285 0.002585106 0.9802534 +-3.856443 4.659831 -3.113343 -0.7605041 -0.002296097 -0.6493291 +1.417892 4.517466 -4.752137 0.287442 -2.44119e-08 -0.9577981 +-3.158448 9.061279 -3.811241 -0.6489597 0.003110636 -0.7608165 +-4.780468 4.517466 -1.289712 -0.9678887 0.001342162 -0.2513757 +4.40855 10 2.246272 0.8938979 -0.0008264586 0.4482698 +1.364579 2.02179 4.758188 0.2500968 -0.00299166 0.9682162 +-0.4656315 10 -4.925837 -0.09524627 0.003117237 -0.9954489 +4.795429 0.9387207 -1.226869 0.9722161 -0.003110636 -0.2340645 +-0.4597938 8.391113 4.92755 -0.1037628 0.0004912087 0.994602 +2.879547 1.608887 4.030315 0.5757776 -0.003206477 0.8176001 +4.925188 1.028239 0.4820438 0.9954273 -0.0009747406 0.09551767 +4.87798 3.684489 -0.8461252 0.9865807 -0.002381188 -0.1632571 +-4.634039 1.422526 1.739624 -0.9429089 -0.002953209 0.3330378 +-4.3065 5.522461 -2.441695 -0.868261 0.0007823346 -0.4961071 +-2.658938 8.047383 -4.176801 -0.5289547 0.001221879 -0.8486491 +4.540861 0 -1.965009 0.9185349 -0.001053068 -0.3953384 +-4.460097 2.850647 -2.145932 -0.9000515 -0.002086067 -0.4357785 +4.844631 2.253418 1.041304 0.975724 -0.00289334 0.2189849 +-4.893655 6.20402 -0.799435 -0.9851534 0.0009855314 -0.1716732 +1.646854 4.982401 -4.677441 0.3343941 -0.0009768698 -0.9424328 +-1.587335 5.482534 -4.690053 -0.3116539 -0.001342162 -0.9501947 +-2.346071 4.256185 4.364392 -0.4989109 -0.002659542 0.8666492 +-2.111141 3.949127 -4.486627 -0.4266172 -0.001794101 -0.9044305 +-3.060127 6.010844 3.899688 -0.6102 0.002464777 0.7922435 +-4.936262 7.01711 -0.3934399 -0.9986737 0.003022951 -0.05139705 +4.942901 6.510671 -0.299529 0.9961995 0.002720124 -0.08705859 +-3.443237 0 -3.55315 -0.6951354 -0.003346128 -0.718871 +4.818249 5.242513 -1.174849 0.9705215 8.685775e-09 -0.2410144 +-0.3710238 0.9650676 4.936297 -0.07621876 -0.002585704 0.9970878 +3.793633 7.731323 3.17816 0.7775275 0.002086067 0.6288455 +4.571162 10 -1.893439 0.923403 0.002765833 -0.3838218 +4.859854 6.137695 0.9586242 0.9862853 0.002809046 0.1650253 +0.6019826 6.586507 -4.920804 0.1361157 0.0009627147 -0.9906925 +-4.948928 7.871908 -0.09627638 -0.9994493 0.0003733202 -0.03317985 +-4.908051 7.392782 -0.6859462 -0.9902421 0.00288986 -0.139328 +3.00541 7.589365 3.931841 0.6064999 0.0005599383 0.7950833 +-2.490855 6.919759 4.283987 -0.5132219 0.0006784085 0.8582557 +2.874575 5.743815 4.035937 0.6035967 0.002659542 0.7972853 +-0.9285392 3.408813 -4.869598 -0.168914 -0.00245612 -0.9856277 +-2.689409 7.36735 4.15661 -0.5569217 5.98393e-05 0.830565 +-3.83642 6.137695 3.133532 -0.7558361 0.002809046 0.6547548 +2.282423 6.540121 4.398573 0.4424618 -0.0004763359 0.8967872 +1.875898 3.989156 -4.58292 0.4020388 -0.002306673 -0.9156197 +-0.4870353 9.501546 -4.925348 -0.1042948 0.003262528 -0.994541 +-4.874697 9.372559 0.844373 -0.9853873 -0.0002031177 0.1703287 +-4.9506 2.63265 0.04352009 -0.9996828 -5.98393e-05 0.02518556 +-0.1060472 1.705729 4.947255 -0.0128443 -0.0004454757 0.9999174 +1.015926 4.28243 -4.846872 0.1911705 0.00159503 -0.9815555 +-1.799085 6.363373 -4.619102 -0.3437148 5.604549e-08 -0.9390741 +-4.351325 9.514974 -2.357553 -0.8813351 0.002585106 -0.4724846 +3.920777 6.16272 -3.028227 0.802713 -0.001494657 -0.5963637 +-4.845003 10 1.003348 -0.9787034 0.0004031878 0.2052792 +1.043915 5.945129 4.841873 0.1938622 -0.001634939 0.9810274 +1.121548 6.591187 -4.821245 0.2262637 0.001755388 -0.9740645 +4.618972 7.36735 -1.781973 0.9387529 5.98393e-05 -0.3445908 +3.525623 2.960917 -3.484548 0.7079255 -0.002435239 -0.7062829 +4.625942 6.50706 -1.762722 0.9363586 -0.0003211451 -0.3510448 +-0.7755212 7.512258 4.890781 -0.1279854 0.003236746 0.9917708 +4.373391 7.978922 -2.327096 0.8831975 0.003153452 -0.4689906 +-0.4288146 1.890259 4.934198 -0.0823845 -0.002211969 0.9965982 +-3.861434 10 -3.093587 -0.7811691 0.003451844 -0.62431 +1.532262 3.408813 -4.714589 0.3268093 -0.00245612 -0.9450871 +-2.943228 8.391113 -3.984047 -0.5996588 0.003206477 -0.8002494 +-4.860456 6.851603 0.9402668 -0.9799422 0.00272128 0.1992634 +-0.01609154 5.340169 -4.954615 -0.03266955 0.00238947 -0.9994634 +-0.6971582 0 -4.898461 -0.1364682 0.0006732809 -0.9906442 +-3.252617 5.482534 3.743488 -0.6546765 2.44119e-08 0.7559091 +-0.3102761 2.50651 -4.941827 -0.08049281 -0.0002593113 -0.9967552 +-3.368239 6.137695 -3.632094 -0.7009221 0.002809046 -0.7132322 +-4.322104 9.514974 2.410705 -0.8711749 0.002585106 0.490966 +-2.451304 8.047383 4.304996 -0.4935375 0.002766267 0.8697202 +-3.312399 8.294271 3.683241 -0.6615527 0.003189304 0.7498919 +-3.920887 8.756129 -3.024611 -0.7992613 0.00321367 -0.600975 +3.567508 7.392782 3.439822 0.7192277 0.00288986 0.6947684 +3.529022 9.061279 -3.468266 0.7033652 0.002099014 -0.7108256 +4.625553 4.517466 -1.76649 0.9307933 0.001342162 -0.3655435 +3.936581 4.054871 3.006132 0.8051177 0.001634939 0.5931129 +-4.258774 0 2.518635 -0.861743 -0.001053068 0.5073439 +-2.797196 2.726746 4.089766 -0.5569375 -0.001338179 0.8305534 +-1.722606 8.294271 4.63888 -0.3561518 0.0004454757 0.934428 +4.772476 10 1.3056 0.9653998 0.00284677 0.2607588 +4.710278 9.425456 -1.513548 0.9528245 -0.0002515278 -0.3035218 +-2.490855 3.080241 -4.283987 -0.5132219 -0.0006784085 -0.8582557 +1.400485 8.161723 4.751756 0.2951888 0.003153452 0.9554337 +4.196165 4.238688 -2.639866 0.8412662 0.0009639648 -0.5406203 +-4.362059 7.590128 -2.344867 -0.8745235 0.000853183 -0.4849823 +3.287723 7.273254 3.706935 0.6566418 0.001338179 0.7542014 +-4.751336 10 -1.380394 -0.9608411 0.001053068 -0.277098 +-4.788375 6.20402 1.260983 -0.9702163 -0.001107731 0.2422379 +0.1554182 0 -4.945391 0.03304145 -0.003285111 -0.9994486 +1.017892 8.466797 -4.843789 0.2117965 0.0009591123 -0.9773133 +4.455897 4.925181 2.172662 0.9034729 0.001788816 0.4286414 +-4.860174 0 0.9271236 -0.9824753 -0.003460539 0.1863609 +-4.00204 9.061279 2.912906 -0.8000637 0.003110636 0.599907 +4.94104 2.268677 0.2801415 0.9972675 -0.002086067 0.07384556 +-2.626122 9.514974 4.194706 -0.5268918 0.002585106 0.8499284 +4.217092 7.36735 2.604014 0.8536385 0.00244426 0.5208603 +4.911686 5.989481 0.6223993 0.9911022 -0.0008507433 0.1331007 +4.936863 7.149353 -0.3533658 0.9972675 0.002086067 -0.07384556 +1.157331 4.925181 -4.817142 0.2049782 0.002045728 -0.9787644 +1.245962 0.5745443 4.788018 0.2542769 0.0002515278 0.9671314 +-4.882021 6.877798 -0.8609779 -0.9828913 0.001791163 -0.1841779 +2.925268 4.659831 -3.998909 0.6139001 -0.00238947 -0.7893801 +-4.257333 2.726746 -2.534878 -0.8638849 -0.001338179 -0.5036876 +-3.222769 1.422526 3.75691 -0.6658351 -0.002953209 0.746093 +2.852219 5.945129 -4.05583 0.588645 6.003486e-08 -0.8083917 +-4.950586 5 4.979741e-16 -0.9999858 -0.0002468965 0.005324436 +-1.073203 9.372559 4.832165 -0.2230511 0.003403726 0.9748008 +-4.369129 5.522461 2.327773 -0.8841146 0.0007823346 0.4672695 +-0.5148445 1.705729 -4.921535 -0.1125799 -0.0004454757 -0.9936426 +4.905603 7.972819 0.6657242 0.9888033 0.0006083836 0.1492236 +4.917911 10 0.5429409 0.9940918 0.002765833 0.1085072 +4.855585 5.945129 -1.004095 0.9824859 6.003486e-08 -0.1863369 +1.648801 6.50706 -4.675977 0.3383743 0.001795748 -0.9410099 +3.966517 5.522461 2.962189 0.7992358 0.0007823346 0.6010171 +-4.86384 4.659831 -0.9442087 -0.9756384 -0.00238947 -0.2193716 +3.985881 9.514974 -2.933399 0.8027711 0.002585106 -0.5962817 +-0.5938395 3.636627 4.921399 -0.09937817 -5.604549e-08 0.9950497 +-1.346953 2.410634 4.762099 -0.2712197 -0.0005599383 0.9625173 +-4.937733 2.783203 -0.4331836 -0.9954491 -0.002435239 -0.09526428 +-4.082548 5.514272 -2.813551 -0.8268016 0.001804865 -0.5624908 +1.230475 0 4.792367 0.2455392 0.0002133005 0.9693866 +-4.114022 4.28243 -2.768462 -0.8299623 -3.86242e-08 -0.5578195 +-4.46636 7.154058 -2.148393 -0.9003226 0.001742956 -0.4352197 +4.949905 4.659831 0.2519869 0.9969268 -0.002296097 0.07830516 +3.003122 4.238688 3.94087 0.6204205 0.001854058 0.7842672 +2.494341 2.783203 -4.283354 0.5100393 -0.002435239 -0.8601477 +-1.079333 0 -4.828673 -0.2165494 -0.003285111 -0.9762661 +4.90603 9.514974 -0.6503445 0.9907346 0.002585106 -0.1357877 +4.918385 9.034932 0.560518 0.9937086 0.002585704 0.1119669 +-0.9290373 3.949127 -4.87069 -0.1882915 -0.001794101 -0.9821116 +-4.421491 6.363373 -2.236346 -0.8817848 -0.0009602766 -0.471651 +-4.160993 8.391113 2.68726 -0.8363231 0.003206477 0.5482274 +-4.772872 1.43514 -1.318093 -0.9643362 -0.00247063 -0.264669 +-4.295666 2.783203 2.459897 -0.8633653 0.0001037997 0.5045794 +-0.1132106 9.007213 4.949677 -0.01856113 0.003215156 0.9998226 +-0.7533138 5.71757 -4.901232 -0.1513494 3.86242e-08 -0.9884803 +4.730431 0.6274414 1.448676 0.9562694 0.0002031177 0.2924874 +3.967019 6.50706 2.961298 0.7981229 -0.0003211451 0.6024945 +1.201863 6.743876 4.808946 0.2255419 0.0008925151 0.974233 +-4.131514 9.372559 -2.721438 -0.8349144 -0.0002031177 -0.5503798 +-0.4068322 2.128093 -4.933117 -0.09587032 -0.0003733202 -0.9953938 +4.174697 4.659831 2.668402 0.8263696 -0.00238947 0.563123 +-0.2804734 0.485026 -4.940993 -0.05226261 -0.002585106 -0.99863 +2.973961 5.074819 -3.9623 0.623493 -0.002045728 -0.7818263 +4.600338 10 1.821403 0.9302676 0.002286414 0.3668747 +0.8431121 7.154058 -4.881043 0.1903474 0.0001362761 -0.9817168 +-3.863112 4.925181 3.106742 -0.7725264 0.001788816 0.6349801 +-4.838706 2.726746 1.066499 -0.9745429 -0.001338179 0.2241974 +-4.390308 0.4984538 -2.28293 -0.8857891 -0.001448062 -0.4640858 +-2.692853 7.590128 -4.156261 -0.5327088 0.000853183 -0.8462982 +2.532115 1.243871 -4.255587 0.5219008 -0.00321367 -0.8530002 +-0.7755212 2.487742 -4.890781 -0.1279854 -0.003236746 -0.9917708 +-4.366658 0.9650676 2.331735 -0.8827091 -0.002585704 0.4699127 +-2.111225 8.360748 -4.479407 -0.438904 0.003224701 -0.8985282 +4.402851 3.49294 2.279958 0.8908298 -0.001795748 0.4543336 +-4.362059 2.409871 2.344867 -0.8745235 -0.000853183 0.4849823 +4.674846 3.45988 -1.643996 0.9364339 0.0004763359 -0.3508438 +-0.04268034 7.149353 -4.949309 -0.0110809 0.002086067 -0.9999364 +4.286661 5.482534 2.493545 0.8651941 2.44119e-08 0.5014371 +-1.120544 7.746582 4.826919 -0.2172996 0.00289334 0.9761007 +-4.526558 1.705729 2.012094 -0.9176207 -0.003189304 0.3974446 +4.747035 7.746582 1.421417 0.9605302 0.00289334 0.2781607 +3.863045 2.607219 -3.093413 0.7843676 -0.001063832 -0.6202953 +-4.798429 3.122203 1.222327 -0.9642211 0.000384689 0.2650993 +-3.786303 7.149353 3.187694 -0.763401 0.002086067 0.6459215 +-4.773517 5.71757 1.318259 -0.9676149 -0.00159503 0.2524257 +-3.741366 3.080241 3.249474 -0.7468855 -0.0006784085 0.6649523 +-3.026741 0.711263 -3.913338 -0.6079315 -0.0003749103 -0.7939894 +-4.933471 5.017599 -0.5014393 -0.9951168 0.0009768698 -0.09869952 +4.142582 1.952616 -2.71678 0.8370145 -0.002766267 -0.5471737 +-1.586975 9.034932 -4.688945 -0.3217899 0.002585704 -0.9468076 +-4.15844 4.256185 2.694318 -0.8547104 -0.002659542 0.5190983 +-3.020359 7.97821 3.921716 -0.5889583 0.00299166 0.8081579 +-4.177574 10 -2.651174 -0.8460657 -0.0002133005 -0.5330786 +-4.748346 6.919759 1.417785 -0.9616391 0.0006784085 0.274317 +0.9867803 0.9650676 -4.850872 0.200586 -0.002585704 -0.9796727 +-1.472203 0.9650676 -4.726236 -0.2961861 -0.002585704 -0.9551268 +2.505021 7.97821 -4.269344 0.4830252 0.00299166 -0.8756014 +-2.31523 0 -4.372717 -0.4668753 -0.003451844 -0.8843164 +-3.474502 2.410634 3.52416 -0.7013679 -0.0005599383 0.7127993 +-2.369357 0.5745443 4.343235 -0.4766871 0.0002515278 0.879073 +-1.25955 6.363373 4.794408 -0.2739027 5.604549e-08 0.9617574 +-4.33765 5.989481 -2.386805 -0.8725058 -0.0008507433 -0.4886029 +-2.111032 2.268677 4.481716 -0.437962 -0.003160393 0.8989879 +0.4419737 2.410634 4.935815 0.07687524 -0.00288986 0.9970365 +-4.169944 1.243871 2.662564 -0.8448604 -0.0007224891 0.5349864 +-0.05396466 9.458821 -4.947493 -0.01368706 0.0002546844 -0.9999063 +-1.528951 0 -4.705627 -0.3077387 -0.002286414 -0.9514682 +4.945391 10 0.1554121 0.9995511 0.003285111 0.02977965 +0.5366221 9.372559 4.918097 0.1081196 -0.0002031177 0.9941379 +-2.929695 6.586507 -3.999197 -0.5789516 0.0009627147 -0.8153614 +4.021533 0.485026 -2.884328 0.8151675 -0.002585106 -0.5792195 +-3.528529 1.890259 -3.475584 -0.7153782 -0.002211969 -0.6987339 +-2.789348 3.168538 -4.088815 -0.5698205 -0.001063832 -0.8217685 +-4.779339 9.034932 1.289422 -0.9651446 0.002585704 0.2617043 +4.676099 2.347819 -1.637729 0.9427285 -0.002152001 -0.3335541 +-2.932095 3.83728 3.997743 -0.5766751 -6.320061e-08 0.8169736 +-4.081663 5.017599 -2.816133 -0.8244786 0.0009768698 -0.5658922 +-3.465074 8.921306 -3.532434 -0.6947653 0.0003684321 -0.7192364 +-0.6897888 6.877798 -4.909135 -0.1285665 0.001791163 -0.9916993 +3.443256 0 3.553159 0.6926911 0.0006732809 0.721234 +4.795429 9.061279 1.226869 0.9722161 0.003110636 0.2340645 +1.760527 6.877798 -4.634216 0.3650911 0.001791163 -0.9309701 +-4.931536 9.372559 -0.3944423 -0.9967886 -0.0002031177 -0.08007835 +-4.936262 2.98289 0.3934399 -0.9986737 -0.003022951 0.05139705 +-1.444736 5.71757 4.736772 -0.305344 -0.00159503 0.9522408 +4.88688 0 -0.7740086 0.9879941 -0.001053068 -0.1544877 +-2.651158 0 -4.177557 -0.534691 -0.002286414 -0.8450446 +-2.652657 5 -4.179918 -0.5403147 -0.0002468965 -0.841463 +4.915263 8.521118 -0.5875006 0.9935852 0.001445814 -0.1130764 +-2.705237 1.906331 4.14787 -0.5400271 -0.001730127 0.8416459 +2.781092 10 -4.092258 0.56073 0.003285111 -0.8279921 +3.00814 3.080241 3.93802 0.6167429 -0.0006784085 0.7871643 +4.729095 10 -1.454856 0.954467 -0.0006732809 -0.2983157 +2.781092 0 4.092258 0.56073 -0.003285111 0.8279921 +-2.96946 3.122203 3.969599 -0.5904185 -0.001791163 0.8070953 +2.74556 9.061279 4.116401 0.5664374 0.002099014 0.8241021 +4.917017 2.63265 0.5772977 0.9949566 -5.98393e-05 0.1003065 +2.781092 0 -4.092258 0.5673731 0.0008264586 -0.8234605 +2.757786 4.517466 4.121631 0.5547736 -2.44119e-08 0.8320013 +2.448523 6.877798 4.31047 0.484607 0.001791163 0.8747302 +-4.308521 0.9650676 -2.437486 -0.8697396 -0.002585704 -0.4935041 +4.881535 3.45988 0.8582429 0.9885929 -2.479629e-08 0.1506125 +4.94233 10 -0.2330705 0.9986688 -0.0006732809 -0.05157725 +-2.75302 5.945129 -4.117569 -0.5413888 -0.001634939 -0.8407708 +-1.158875 5.945129 4.820988 -0.2497194 6.003487e-08 0.9683182 +-2.776786 1.608887 -4.096538 -0.5700812 -0.0004912087 -0.8215882 +4.152591 4.62087 -2.703906 0.8216761 0.001854058 -0.5699517 +-2.733057 7.871908 4.126931 -0.5635464 0.0003733202 0.8260843 +-4.135425 10 2.716471 -0.8351486 0.003451844 0.5500135 +-3.903212 5.242106 -3.058086 -0.7842722 -0.0009800183 -0.6204161 +-1.65362 6.050873 4.665981 -0.3354816 0.001303923 0.9420459 +-4.399521 3.949127 -2.269372 -0.8894303 -0.001303923 -0.4570689 +3.00814 6.540121 -3.93802 0.6230462 -0.0004763359 -0.7821849 +2.282423 3.080241 -4.398573 0.4496512 -0.0006784085 -0.893204 +-3.603171 3.122203 -3.396492 -0.7404862 0.000384689 -0.6720715 +-4.14822 3.122203 -2.714348 -0.8425754 -0.001791163 -0.5385755 +-4.84403 6.540121 -1.045119 -0.9730222 -0.0004763359 -0.230711 +-4.735476 3.45988 -1.463294 -0.9619208 -2.479629e-08 -0.2733284 +-4.951757 3.080241 -0.1923767 -0.9996473 -0.0006784085 -0.02654887 +-4.748346 6.540121 1.417785 -0.9638117 -0.0004763359 0.2665835 +-4.882021 3.122203 0.8609779 -0.9828913 -0.001791163 0.1841779 +-4.514527 3.122203 2.048038 -0.9062088 -0.001791163 0.4228267 +-1.201836 3.862305 4.80549 -0.2706205 -0.002809046 0.962682 +-3.741366 3.45988 3.249474 -0.74152 0.0004763359 0.6709306 +-0.1189263 6.540121 4.954065 -0.04429824 -0.0004763359 0.9990183 +4.222241 6.877798 2.597709 0.8460688 0.001791163 0.5330707 +4.735616 3.122203 -1.466068 0.9520573 -0.001791163 -0.3059145 +-2.70321 9.034932 -4.146968 -0.5471417 0.002585704 -0.837036 +4.947161 1.144613 -0.2135339 0.9987278 -0.003390394 -0.05031185 +4.150236 6.010844 -2.701424 0.824067 0.002306673 -0.5664876 +2.758347 4.010519 4.120934 0.5634588 -0.0009782498 0.8261436 +-2.371178 4.238688 -4.353643 -0.48673 0.0009639648 -0.873552 +-1.903462 9.425456 -4.569192 -0.3774843 0.003472535 -0.9260095 +-2.78707 5.791117 4.091975 -0.5578133 0.001926908 0.8299642 +-2.111141 6.050873 4.486627 -0.4266172 0.001794101 0.9044305 +-0.6336842 1.243871 -4.906743 -0.1243461 -0.0007224891 -0.9922386 +4.075471 5.945129 2.814965 0.8128789 -0.001634939 0.5824304 +4.58131 1.906331 1.880087 0.927929 -0.001730127 0.372753 +4.150236 3.989156 2.701424 0.824067 -0.002306673 0.5664876 +1.533159 1.639252 -4.708692 0.3228277 -0.003224701 -0.9464523 +-2.943228 1.608887 3.984047 -0.5996588 -0.003206477 0.8002494 +2.708809 6.289571 -4.153082 0.5495626 0.001789326 -0.8354506 +4.844841 8.855388 -1.023484 0.979863 0.003390394 -0.1996423 +4.039982 0.9650676 -2.860636 0.816853 -0.002585704 -0.5768401 +2.757786 5.482534 -4.121631 0.5547736 2.44119e-08 -0.8320013 +-0.5938395 6.363373 -4.921399 -0.09937817 5.604549e-08 -0.9950497 +-4.145865 6.403605 2.719223 -0.8432068 0.0009790179 0.5375885 +-2.768012 8.971761 4.102189 -0.5609116 0.0009747406 0.8278751 +4.039982 9.034932 2.860636 0.816853 0.002585704 0.5768401 +-2.81068 2.410634 -4.073321 -0.5687504 -0.0005599383 -0.8225099 +4.709564 1.243871 1.515815 0.9507483 -0.0007224891 0.309963 +0.5817469 8.391113 -4.919024 0.110676 0.003206477 -0.9938514 +4.707146 5.340169 -1.546364 0.9404507 0.00238947 -0.3399217 +-2.775993 2.325439 4.103072 -0.5548038 -0.00183703 0.8319792 +-4.726512 2.845942 -1.491323 -0.9542353 -0.001742956 -0.2990517 +2.813656 2.783203 4.08071 0.5611207 -0.002435239 0.8277304 +-3.0542 3.489329 -3.902452 -0.6073393 -0.002947173 -0.7944371 +-4.67592 2.253418 -1.640286 -0.940584 -0.00289334 -0.3395488 +-0.717254 1.144613 4.899546 -0.1377222 -0.003390394 0.9904651 +1.863033 8.971761 -4.587401 0.3709751 0.003353116 -0.9286367 +-2.734129 3.413493 4.130367 -0.5331353 0.0007466546 0.8460296 +0.6199397 7.49349 -4.916856 0.1224606 0.00241979 -0.9924704 +-1.390903 7.746582 -4.7498 -0.2703817 0.000372711 -0.9627531 +-1.468779 6.50706 -4.727496 -0.2915576 -0.0003211451 -0.9565532 +-4.343698 6.877798 -2.377246 -0.8680007 -0.000384689 -0.4965627 +-4.887753 7.746582 -0.8152478 -0.9878189 0.00289334 -0.1555809 +4.783378 7.392782 1.295679 0.9649713 0.00288986 0.2623396 +4.345826 4.477539 2.389138 0.8782572 -0.0009741628 0.4781876 +4.590164 9.514974 -1.849993 0.9258398 0.002585106 -0.3779074 +4.58541 0.4882812 -1.861036 0.9279362 -0.00205317 -0.3727334 +-2.747447 0.4984538 -4.115594 -0.5526478 -0.001448062 -0.8334136 +-4.131586 9.425456 2.725928 -0.8388738 0.003472535 0.5443149 +-2.677336 0.485026 4.162206 -0.5446987 -0.002585106 0.8386279 +-1.500437 9.514974 4.716012 -0.2989699 0.002585106 0.954259 +3.985881 0.485026 2.933399 0.8027711 -0.002585106 0.5962817 +4.844933 0.5745443 1.013566 0.9803408 -0.003472535 0.1972811 +-2.467055 8.521118 4.294324 -0.4956445 0.003058123 0.8685201 +1.015801 8.56486 4.846218 0.2035956 0.00247063 0.9790519 +-4.737889 1.705729 1.427929 -0.9549471 -0.0004454757 0.2967758 diff --git a/Data/data/points_3/cylinders.ply b/Data/data/points_3/cylinders.ply new file mode 100644 index 00000000000..42a06b3c26e --- /dev/null +++ b/Data/data/points_3/cylinders.ply @@ -0,0 +1,1824 @@ +ply +format ascii 1.0 +comment Generated by the CGAL library +element vertex 1813 +property double x +property double y +property double z +property double nx +property double ny +property double nz +end_header +0.215729 0.035262399999999999 -0.16386999999999999 -0.41390399999999999 0.91031799999999996 0.0022166600000000001 +-0.27056400000000003 -0.0174098 -0.28064699999999998 0.90856000000000003 0.41755799999999998 -0.012825700000000001 +-0.21754000000000001 -0.041411000000000003 -0.141795 -0.30893999999999999 0.95101100000000005 0.011550899999999999 +-0.25491399999999997 0.0361041 -0.26710899999999999 -0.56586099999999995 0.82448999999999995 -0.0041995699999999997 +-0.27430700000000002 -0.000595314 -0.22750300000000001 0.999135 0.032648299999999998 0.025744 +-0.20269999999999999 -0.033341500000000003 -0.094560199999999997 -0.63541700000000001 0.772011 0.015625199999999999 +0.21898599999999999 -0.036509600000000003 -0.17472099999999999 0.323351 0.94573700000000005 0.032027 +0.24903500000000001 0.033758499999999997 -0.081355700000000003 0.51610699999999998 0.85594099999999995 0.031605300000000003 +-0.18815699999999999 0.0087436000000000007 -0.139289 0.98249399999999998 0.186227 -0.0049578299999999999 +-0.196824 -0.027227399999999999 -0.093579300000000004 0.784169 -0.62049500000000002 -0.00805553 +-0.191942 -0.019484899999999999 -0.26385999999999998 0.879579 -0.475271 0.021427000000000002 +0.19550600000000001 -0.015039800000000001 -0.14136199999999999 0.91270700000000005 0.40857500000000002 0.0057379700000000002 +0.24097299999999999 -0.036932699999999999 -0.31028800000000001 -0.2276 0.97373600000000005 -0.0059862800000000001 +0.19266900000000001 0.0041270200000000003 -0.014967299999999999 0.989595 -0.13889399999999999 0.037542100000000002 +-0.19356799999999999 -0.0225781 -0.16997699999999999 0.83206100000000005 -0.55463600000000002 -0.0073217600000000001 +-0.189718 0.014571499999999999 -0.063986199999999993 0.95312699999999995 0.30224200000000001 -0.014078200000000001 +-0.26519599999999999 0.0265414 -0.123497 0.78465200000000002 -0.61981399999999998 -0.0122912 +0.209536 0.031906799999999999 -0.024394599999999999 -0.53372200000000003 0.84524500000000002 0.026505899999999999 +0.26918500000000001 0.000522048 -0.222883 0.999413 -0.032431700000000001 -0.0110835 +-0.194826 -0.024375399999999998 -0.29685899999999998 0.82469199999999998 -0.56555299999999997 -0.00571201 +-0.24216399999999999 0.041902500000000002 -0.23402899999999999 -0.30517899999999998 0.95225700000000002 -0.0084661200000000006 +0.25668299999999999 -0.028271600000000001 -0.20505999999999999 -0.70454000000000006 0.70965299999999998 0.0040095199999999999 +-0.206318 0.035889999999999998 -0.22211400000000001 0.57452400000000003 0.81827000000000005 -0.018879900000000002 +0.192415 -0.00122532 -0.10002900000000001 0.99943800000000005 0.033518699999999998 0.000168789 +0.26828600000000002 0.0080228999999999995 -0.19395799999999999 0.97719400000000001 0.21223800000000001 -0.0067838000000000004 +-0.27204400000000001 0.013737600000000001 -0.16745699999999999 0.94622799999999996 -0.32344600000000001 0.0058836299999999999 +-0.208616 0.037499299999999999 -0.29947000000000001 0.54534499999999997 0.83819299999999997 0.0056768399999999998 +-0.25875300000000001 -0.033415899999999998 -0.16356599999999999 0.63816600000000001 0.76986299999999996 0.0073826999999999999 +-0.213975 -0.040081400000000003 -0.27180900000000002 -0.42998399999999998 0.90283500000000005 -0.0018786499999999999 +-0.189861 0.015023 -0.135405 0.939666 0.342086 0.0020192399999999998 +0.237787 -0.037786399999999998 -0.32043300000000002 -0.12400799999999999 0.99224500000000004 -0.0084504200000000002 +0.23731099999999999 0.037889199999999998 -0.29972700000000002 0.18552299999999999 0.98259399999999997 -0.0094642200000000006 +0.23760200000000001 -0.037836099999999998 -0.085555400000000004 -0.19920099999999999 0.97989999999999999 0.0107113 +-0.21416199999999999 0.040168799999999998 -0.23314399999999999 0.41275200000000001 0.91078300000000001 0.0104831 +-0.189856 0.015011399999999999 -0.16584499999999999 0.93790799999999996 0.34662599999999999 -0.0133934 +-0.25928699999999999 -0.032892299999999999 -0.31979600000000002 0.60807500000000003 0.79378800000000005 -0.012035000000000001 +-0.26712200000000003 0.023790100000000002 -0.32065199999999999 0.83649600000000002 -0.54795899999999997 0.0039518799999999996 +0.21349000000000001 -0.034218800000000001 -0.26135199999999997 0.47055399999999997 0.88231000000000004 -0.0103841 +-0.23117499999999999 -0.043554200000000001 -0.050445400000000001 0.045710599999999997 0.99894799999999995 -0.00366373 +0.19314899999999999 0.0076395100000000004 -0.31739200000000001 0.97124900000000003 -0.238067 0 +0.20198199999999999 -0.025398199999999999 -0.055935100000000001 0.76385099999999995 0.64526600000000001 0.0128129 +-0.23879700000000001 0.042804500000000002 -0.24081900000000001 -0.157556 0.98750400000000005 -0.0035214000000000001 +-0.18746399999999999 0.0032543400000000001 -0.129636 0.99729100000000004 0.071374300000000002 0.017779400000000001 +0.222304 -0.037398500000000001 -0.225521 0.21262 0.97712299999999996 -0.0048982899999999996 +0.199875 0.0226786 -0.214396 0.80007399999999995 -0.59981799999999996 -0.0099346699999999996 +-0.26863500000000001 -0.021546900000000001 -0.20366400000000001 0.88317999999999997 0.46899299999999999 0.0062185399999999998 +-0.188388 0.0096065300000000003 -0.27556999999999998 0.98393399999999998 0.17851400000000001 -0.0024449699999999999 +-0.27138600000000002 -0.0156472 -0.25930599999999998 0.93491800000000003 0.35467100000000001 -0.0117041 +0.205043 -0.028459600000000002 -0.071491600000000002 0.63892599999999999 0.76912899999999995 0.014625000000000001 +-0.196961 -0.027423900000000001 -0.15101899999999999 0.79251499999999997 -0.60870299999999999 0.037407999999999997 +0.26759500000000003 0.010602800000000001 -0.12520800000000001 0.96217900000000001 0.27241799999999999 0 +0.21182799999999999 0.033443899999999999 -0.183452 -0.50287800000000005 0.86418499999999998 0.017262599999999999 +0.21302299999999999 -0.034001200000000002 -0.086881200000000006 0.48022199999999998 0.87708900000000001 0.010076699999999999 +0.26566099999999998 -0.015835999999999999 -0.160718 0.91590499999999997 -0.40132299999999999 0.0075671799999999997 +-0.271088 0.016284699999999999 -0.093884899999999993 0.92597300000000005 -0.37758399999999998 -0.0019852300000000002 +0.23113800000000001 -0.038429199999999997 -0.247859 0.039049300000000002 0.99920500000000001 -0.0080488299999999999 +-0.26509899999999997 0.026679899999999999 -0.088077000000000003 0.76892700000000003 -0.63931000000000004 -0.0058318800000000002 +-0.26313500000000001 0.0290447 -0.24684800000000001 0.74317599999999995 -0.66909600000000002 0 +0.23741799999999999 0.037879799999999998 -0.17804500000000001 0.207396 0.97821499999999995 0.0090182400000000003 +-0.23666899999999999 0.043073599999999997 -0.239929 -0.154228 0.98802699999999999 0.00398876 +-0.26625700000000002 0.025025100000000002 -0.28448099999999998 0.82777699999999999 -0.56102799999999997 -0.0056724799999999997 +0.21234800000000001 -0.033686399999999998 -0.021867000000000001 0.50520799999999999 0.862479 0.0299233 +-0.19279099999999999 0.021306599999999998 -0.18320900000000001 0.87493600000000005 0.48366900000000002 0.023461200000000001 +-0.26454 -0.027477399999999999 -0.30752099999999999 0.80019300000000004 0.59953199999999995 -0.015901800000000001 +-0.27227400000000002 -0.012879699999999999 -0.26285700000000001 0.95199500000000004 0.304892 -0.0273265 +0.227515 0.038176799999999997 -0.133904 -0.0874505 0.996089 -0.0125848 +-0.214004 0.040094999999999999 -0.179475 0.36178900000000003 0.93225000000000002 -0.00437259 +0.192525 -0.0024862 -0.056148299999999998 0.999247 0.038800800000000003 -0.00035267399999999998 +0.263652 0.019839200000000001 -0.029121399999999999 0.86841699999999999 0.49579200000000001 0.0065564100000000004 +-0.219134 -0.041838199999999999 -0.116905 -0.18618699999999999 0.98217200000000005 -0.025926999999999999 +-0.23935400000000001 0.042655400000000003 -0.18094099999999999 -0.22103 0.97441999999999995 0.040650600000000002 +-0.27415400000000001 -0.0023466400000000001 -0.28939100000000001 0.99917699999999998 0.039235399999999997 0.0103062 +0.264567 0.018181900000000001 -0.155419 0.86951400000000001 0.49362400000000001 0.016734499999999999 +-0.210475 0.0384496 -0.23753199999999999 0.47624300000000003 0.87929900000000005 -0.0051686099999999997 +-0.27104600000000001 -0.0163757 -0.122765 0.92722000000000004 0.37451800000000002 0 +0.21324699999999999 -0.034105400000000001 -0.016920000000000001 0.454733 0.89058300000000001 0.0089449799999999999 +0.26072899999999999 -0.024013400000000001 -0.24784100000000001 0.77258400000000005 -0.63461500000000004 0.019460100000000001 +0.20691200000000001 -0.0300693 -0.25507099999999999 0.62308399999999997 0.78202700000000003 -0.014139000000000001 +-0.27383099999999999 -0.0060381699999999998 -0.255025 0.98935099999999998 0.14537700000000001 -0.00712797 +0.23132 0.038413299999999997 -0.073161100000000007 0.036957999999999998 0.99924999999999997 -0.0115508 +0.25913900000000001 -0.025815500000000002 -0.0117909 0.73485900000000004 -0.67821200000000004 0.00319054 +-0.26004300000000002 -0.032136900000000003 -0.20601 0.66393199999999997 0.74769600000000003 0.012063300000000001 +-0.26445299999999999 0.0276023 -0.0684419 0.73926099999999995 -0.67333299999999996 -0.010721400000000001 +-0.18748600000000001 -0.0035021100000000001 -0.078974199999999994 0.99315699999999996 -0.11604100000000001 0.013159300000000001 +0.197244 0.0187663 -0.049576700000000001 0.87146400000000002 -0.48919000000000001 0.035275599999999997 +-0.19059499999999999 -0.016596400000000001 -0.067556599999999994 0.91292799999999996 -0.40812100000000001 0 +0.22432099999999999 0.037897399999999998 -0.151781 -0.18490799999999999 0.98275599999999996 0 +0.21369199999999999 0.034313000000000003 -0.28894700000000001 -0.38730300000000001 0.92195099999999996 -0.0016194200000000001 +-0.20466400000000001 0.0347318 -0.077268900000000001 0.60303099999999998 0.79750500000000002 -0.018411899999999998 +0.26614399999999999 -0.014800000000000001 -0.26374500000000001 0.94495700000000005 -0.32713999999999999 0.00597447 +0.25979200000000002 -0.025163000000000001 -0.32235200000000003 0.72076099999999999 -0.68756399999999995 0.088088799999999995 +0.26020399999999999 -0.024750600000000001 -0.16919899999999999 0.78261599999999998 -0.62242299999999995 -0.010079299999999999 +-0.27387299999999998 0.0055520300000000003 -0.28357599999999999 0.98622299999999996 -0.16492999999999999 0.012718699999999999 +-0.198076 -0.028716700000000001 -0.242452 0.72266699999999995 -0.69096000000000002 0.018111499999999999 +0.24489 0.035691599999999997 -0.31412899999999999 0.36829400000000001 0.92970799999999998 -0.0018132599999999999 +-0.26491700000000001 0.026938900000000002 -0.17289299999999999 0.80186199999999996 -0.59740599999999999 -0.0111603 +-0.24569099999999999 -0.0409548 -0.21840300000000001 0.34090399999999998 0.94009699999999996 0.00158344 +0.19264200000000001 -0.0038172599999999998 -0.21273 0.99834999999999996 0.057089300000000003 0.0061544199999999999 +0.237376 -0.037883500000000001 -0.019981100000000002 -0.13917099999999999 0.99023700000000003 -0.0078975699999999996 +0.21177199999999999 0.0334179 -0.11311599999999999 -0.49450499999999997 0.868973 -0.0187148 +-0.221999 0.042605799999999999 -0.266795 0.19603699999999999 0.98059499999999999 -0.0014160799999999999 +-0.19985700000000001 -0.0304982 -0.20472399999999999 -0.70052499999999995 0.71351299999999995 -0.0127624 +0.19805300000000001 -0.020076699999999999 -0.106151 0.86145300000000002 0.50773000000000001 -0.010409 +0.19922100000000001 -0.021744300000000001 -0.12192500000000001 0.796871 0.60377800000000004 -0.0211913 +-0.25811200000000001 0.033865100000000002 -0.111508 -0.63690899999999995 0.77018799999999998 0.0340139 +0.22275600000000001 0.0375196 -0.063158300000000001 -0.24815599999999999 0.96871099999999999 -0.0041393699999999999 +-0.218914 0.0417791 -0.069605600000000004 0.28661700000000001 0.95801499999999995 0.0075829900000000004 +-0.18842 0.0097284699999999995 -0.087700899999999998 0.97155400000000003 0.23680100000000001 0.0028009900000000002 +0.23818700000000001 -0.037679299999999999 -0.17144300000000001 -0.17172399999999999 0.98454900000000001 -0.034278000000000003 +-0.202434 0.033075199999999999 -0.067836599999999997 0.64013399999999998 0.76826099999999997 -0.0019104700000000001 +0.26910200000000001 -0.00147108 -0.160663 0.99884099999999998 -0.037447099999999997 -0.0302288 +0.25858199999999998 0.0263731 -0.26745099999999999 0.73229200000000005 0.68099100000000001 0 +0.197327 -0.0189445 -0.097175700000000004 0.84782100000000005 0.53025699999999998 0.0051147299999999996 +0.22334000000000001 0.037676000000000001 -0.237679 -0.22620399999999999 0.97399800000000003 0.0126505 +0.19580400000000001 0.015678500000000001 -0.027469799999999999 0.90071500000000004 -0.43438900000000003 -0.0042932300000000003 +-0.22914200000000001 -0.043447399999999997 -0.070252599999999998 -0.053647500000000001 0.99848800000000004 -0.011989 +-0.26508999999999999 0.026691800000000002 -0.077189199999999999 0.77149800000000002 -0.63569799999999999 0.026047399999999998 +0.222189 0.037367499999999998 -0.049916500000000003 -0.254415 0.96704599999999996 -0.0097772299999999996 +0.26084099999999999 -0.023853200000000001 -0.021935900000000001 0.76675800000000005 -0.64186100000000001 0.0098910999999999999 +-0.19036700000000001 0.0161076 -0.121582 0.90856499999999996 0.41748299999999999 -0.014733599999999999 +0.23893200000000001 -0.037479499999999999 -0.133938 -0.227552 0.97359700000000005 0.0181195 +0.26678600000000002 -0.013422699999999999 -0.184202 0.94273300000000004 -0.33348699999999998 0.0064193399999999999 +0.193163 -0.0076891499999999996 -0.181538 0.97736199999999995 0.211539 -0.0039227799999999998 +0.19259399999999999 -0.0032751799999999999 -0.081474900000000003 0.99635200000000002 0.085044599999999998 -0.0070836600000000003 +0.20094999999999999 -0.024214300000000001 -0.12103800000000001 0.780088 0.62517199999999995 -0.024942700000000002 +0.23394300000000001 -0.038183799999999997 -0.29179899999999998 -0.097175700000000004 0.99506499999999998 -0.020062099999999999 +-0.192328 0.020313700000000001 -0.26599699999999998 0.88386399999999998 0.46770800000000001 0.0058149300000000003 +0.23178199999999999 -0.038372900000000001 -0.099788000000000002 -0.024432800000000001 0.99933700000000003 -0.027006700000000002 +-0.25936300000000001 -0.032816400000000003 -0.112715 0.643926 0.76508799999999999 0 +0.19314999999999999 -0.0076412700000000004 -0.105432 0.97214800000000001 0.23411999999999999 0.010749099999999999 +-0.227801 -0.043330100000000003 -0.291767 -0.071805599999999997 0.99738599999999999 0.0080540400000000002 +-0.26286399999999999 0.029316100000000001 -0.125115 0.74925600000000003 -0.66227100000000005 -0.0033770900000000001 +0.233262 0.038243399999999997 -0.19300600000000001 0.011993999999999999 0.999915 0.0050224800000000002 +0.207844 -0.030721499999999999 -0.17630599999999999 0.56668499999999999 0.822237 -0.052854699999999998 +0.19251499999999999 -0.0023689000000000002 -0.32092500000000002 0.99676200000000004 0.080035899999999993 -0.0077629099999999996 +0.26012299999999999 0.024831900000000001 -0.23297300000000001 0.77851999999999999 0.62761999999999996 0 +0.25898300000000002 0.0259718 -0.11111600000000001 0.74186799999999997 0.670539 0.00306807 +0.22636500000000001 0.038076199999999998 -0.027799399999999998 -0.13674500000000001 0.99059699999999995 -0.0043723399999999997 +-0.21565599999999999 0.0408653 -0.173925 0.334839 0.94227399999999994 0.00156263 +0.26185999999999998 0.022398100000000001 -0.080507499999999996 0.82913999999999999 0.55904100000000001 0 +0.21890000000000001 0.036486200000000003 -0.27215299999999998 -0.28650700000000001 0.95807399999999998 -0.0027226799999999999 +0.19345799999999999 -0.0087908299999999995 -0.033934499999999999 0.97492400000000001 0.22217100000000001 -0.012804599999999999 +-0.21343300000000001 -0.0398289 -0.16880999999999999 -0.39638400000000001 0.91786599999999996 -0.020042399999999998 +0.24627099999999999 -0.035047799999999997 -0.21876000000000001 -0.404889 0.91418200000000005 0.018345299999999998 +-0.27240599999999998 -0.0123845 -0.17421900000000001 0.95704299999999998 0.28983700000000001 -0.0079877100000000003 +-0.187611 -0.0049364999999999999 -0.32000299999999998 0.99502400000000002 -0.0995674 -0.0035818099999999999 +-0.26894899999999999 0.0208722 -0.22068299999999999 0.87560800000000005 -0.48259000000000002 0.0204388 +0.227575 -0.038182000000000001 -0.081487000000000004 0.102342 0.99472000000000005 0.0076647900000000003 +0.22840199999999999 0.038254400000000001 -0.071737999999999996 -0.109782 0.99394300000000002 0.0049681100000000004 +-0.190828 0.0170955 -0.18087400000000001 0.93218500000000004 0.361599 0.0166397 +-0.24890799999999999 0.039454599999999999 -0.31098399999999998 -0.41173700000000002 0.91128500000000001 0.00571932 +-0.220112 0.042099999999999999 -0.31179099999999998 0.26471699999999998 0.96432399999999996 -0.0018920199999999999 +0.265955 0.0152043 -0.162632 0.930566 0.36605300000000002 0.0072540599999999997 +-0.18765799999999999 0.00546665 -0.17254 0.99290800000000001 0.11874700000000001 0.0057776299999999997 +-0.273949 0.0046873399999999999 -0.229181 0.99743400000000004 -0.070475700000000002 0.012586699999999999 +0.25564300000000001 0.029312499999999998 -0.196857 0.66425800000000002 0.74744100000000002 0.00969129 +0.22300500000000001 0.0375862 -0.028308900000000001 -0.17615900000000001 0.98435799999999996 0.00263138 +0.209421 0.031826300000000002 -0.0237442 -0.56722700000000004 0.82354400000000005 0.0053070799999999996 +-0.267036 0.0239136 -0.26278899999999999 0.82741600000000004 -0.56109900000000001 -0.023462 +-0.26232 0.029859500000000001 -0.0668961 0.71382299999999999 -0.69971300000000003 -0.029320100000000002 +-0.191496 -0.018527800000000001 -0.079598600000000005 0.906968 -0.42111100000000001 -0.0086710599999999995 +-0.27413799999999999 -0.0025280799999999998 -0.075559399999999999 0.99532600000000004 0.089834800000000006 0.035430799999999998 +0.26880300000000001 -0.00488259 -0.30324499999999999 0.99514800000000003 -0.097959599999999994 0.0092171500000000003 +-0.25555099999999997 0.0356584 -0.087501499999999996 -0.57713999999999999 0.81663600000000003 0.0038890000000000001 +0.236344 0.037973800000000002 -0.15476400000000001 0.100788 0.99468999999999996 -0.020797099999999999 +-0.24756600000000001 0.040080600000000001 -0.10546 -0.35870299999999999 0.933342 0.014290300000000001 +-0.18945999999999999 0.013609599999999999 -0.289993 0.95679099999999995 0.29074499999999998 -0.0041847100000000003 +0.197743 0.019633600000000001 -0.27915699999999999 0.85529599999999995 -0.51807099999999995 0.00842182 +0.26827200000000001 0.0080760999999999993 -0.25322299999999998 0.97520300000000004 0.22126999999999999 0.0044237399999999998 +-0.24385100000000001 0.041450500000000001 -0.102072 -0.28700399999999998 0.95784100000000005 0.0130104 +-0.26766000000000001 0.023021199999999999 -0.222076 0.84365599999999996 -0.53679900000000003 -0.0095362199999999998 +0.22541600000000001 -0.037993100000000002 -0.24495900000000001 0.15251300000000001 0.98827600000000004 0.0071426099999999998 +0.21710199999999999 -0.0359031 -0.114941 0.36202699999999999 0.93180700000000005 0.025943999999999998 +0.23164899999999999 0.038384500000000002 -0.21274599999999999 -0.0115192 0.99993100000000001 -0.0023276899999999999 +-0.20258899999999999 -0.033230700000000002 -0.13900299999999999 -0.63401200000000002 0.77325100000000002 -0.010612399999999999 +-0.24975900000000001 -0.039058000000000002 -0.156887 0.43584899999999999 0.89993900000000004 -0.0120438 +0.249531 0.033527399999999999 -0.18066399999999999 0.51260099999999997 0.85862700000000003 0 +0.21737799999999999 0.036031599999999997 -0.21148400000000001 -0.35706399999999999 0.93408000000000002 0 +-0.26600400000000002 0.0253875 -0.23214599999999999 0.81198700000000001 -0.58366200000000001 0.0039002099999999999 +0.22547600000000001 -0.037998400000000002 -0.18674099999999999 0.14221300000000001 0.98976900000000001 0.011554699999999999 +-0.230901 -0.043578199999999997 -0.16692599999999999 -0.057160299999999997 0.99807400000000002 -0.024088100000000001 +0.26916099999999998 0.00080040099999999996 -0.131159 0.99989499999999998 -0.0057149899999999997 0.0132944 +-0.26480999999999999 -0.027092100000000001 -0.30898599999999998 0.80740199999999995 0.58999800000000002 -0.00216701 +0.256851 0.028104500000000001 -0.072189299999999998 0.69381300000000001 0.72011400000000003 0.0076643600000000003 +-0.27098299999999997 -0.0165113 -0.17746400000000001 0.92430599999999996 0.38098199999999999 0.022612299999999998 +0.26883699999999999 -0.0044996699999999999 -0.27308500000000002 0.99051199999999995 -0.137155 0.0086725299999999995 +-0.20725399999999999 -0.0365452 -0.19071199999999999 -0.56234600000000001 0.82665500000000003 -0.0202268 +-0.26763999999999999 0.0230496 -0.21518599999999999 0.84423000000000004 -0.53567500000000001 -0.018135100000000001 +0.23990300000000001 -0.037219599999999999 -0.17158000000000001 -0.23452100000000001 0.97155599999999998 -0.032849099999999999 +-0.202294 -0.032935199999999998 -0.046060499999999997 -0.63294899999999998 0.77419400000000005 0 +0.217525 0.036100199999999999 -0.091808699999999993 -0.370838 0.92868600000000001 0.0047009900000000004 +0.19723399999999999 0.018745100000000001 -0.28458699999999998 0.86113799999999996 -0.508328 0.00668076 +0.20560999999999999 -0.029026 -0.046163099999999999 0.65460700000000005 0.75588299999999997 -0.011392599999999999 +0.20296 0.0263766 -0.111563 0.748 -0.66201299999999996 -0.0472659 +-0.27299499999999999 0.010186799999999999 -0.110347 0.97819599999999995 -0.20746600000000001 -0.0095384900000000002 +-0.22764799999999999 0.043316800000000003 -0.29271599999999998 0.045977200000000003 0.99892899999999996 0.0052399999999999999 +-0.212788 0.039528300000000002 -0.168048 0.41097299999999998 0.91160799999999997 -0.0085244199999999996 +-0.22046199999999999 -0.042193799999999997 -0.29982199999999998 -0.25285800000000003 0.96749499999999999 -0.0040663899999999996 +0.263486 0.020076799999999999 -0.113789 0.84075900000000003 0.54137900000000005 0.0058414199999999999 +-0.20984700000000001 0.038157099999999999 -0.15432899999999999 0.52440699999999996 0.85142700000000004 -0.00830118 +-0.216947 0.041251999999999997 -0.11462700000000001 0.28047800000000001 0.95983700000000005 0.0066694600000000003 +0.20177500000000001 -0.0251912 -0.29274600000000001 0.75383500000000003 0.65692200000000001 -0.013654100000000001 +-0.26589499999999999 -0.0255418 -0.235124 0.80816600000000005 0.58877299999999999 0.014630499999999999 +0.21460099999999999 0.034736499999999997 -0.069578299999999996 -0.44663799999999998 0.89444900000000005 -0.021809100000000001 +0.19871 0.0210142 -0.21248400000000001 0.82750999999999997 -0.561392 -0.0081489700000000002 +-0.260855 0.031324600000000001 -0.063795900000000003 -0.69684199999999996 0.71718599999999999 0.0073886899999999998 +-0.190829 0.017097600000000001 -0.110107 0.93496999999999997 0.35472399999999998 0.0012209499999999999 +0.22708400000000001 -0.038138999999999999 -0.061348699999999999 0.12637699999999999 0.99198200000000003 0.00118935 +-0.26997100000000002 -0.0186815 -0.21580099999999999 0.89505599999999996 0.44577600000000001 -0.0125749 +-0.19736699999999999 -0.028003400000000001 -0.19386500000000001 0.76974799999999999 -0.63833200000000001 0.0044259199999999999 +0.203485 0.0269013 -0.206873 0.728302 -0.684809 -0.024768600000000002 +-0.20544100000000001 0.0352757 -0.13272700000000001 0.566415 0.82389900000000005 -0.019074299999999999 +0.21490999999999999 0.034880599999999998 -0.20080300000000001 -0.40667799999999998 0.91351400000000005 0.0102151 +-0.25971499999999997 0.032465000000000001 -0.30360399999999998 -0.67336200000000002 0.739313 0 +-0.20347000000000001 -0.033896000000000003 -0.19583999999999999 -0.63991699999999996 0.76838799999999996 0.0093352499999999998 +0.24018 -0.037145200000000003 -0.18357999999999999 -0.24090500000000001 0.97054600000000002 0.0024118299999999998 +0.26862399999999997 0.0067625599999999999 -0.31830799999999998 0.98659200000000002 0.162935 0.0093984199999999993 +0.26879799999999998 -0.0049386500000000002 -0.021526 0.99437799999999998 -0.102899 0.024983000000000002 +-0.24815599999999999 -0.039805500000000001 -0.257718 0.36668400000000001 0.93034099999999997 0.00280218 +-0.27333000000000002 -0.0089370200000000004 -0.30895899999999998 0.97697999999999996 0.21227499999999999 -0.021185499999999999 +-0.24036399999999999 -0.042384699999999997 -0.061324499999999997 0.17810799999999999 0.98399199999999998 -0.0061202899999999996 +-0.188726 -0.0108697 -0.14088800000000001 0.96559200000000001 -0.25933299999999998 -0.019474399999999999 +0.22656899999999999 0.038094000000000003 -0.28306799999999999 -0.113745 0.99290699999999998 -0.034607100000000002 +0.208647 0.031283699999999998 -0.037703399999999998 -0.55256799999999995 0.83323999999999998 -0.019505000000000002 +0.267125 -0.0123544 -0.079600299999999999 0.95925700000000003 -0.28177999999999997 -0.020622999999999999 +-0.20821500000000001 -0.037218300000000003 -0.29008600000000001 -0.54819200000000001 0.83635199999999998 0.00079950599999999996 +-0.26417499999999999 0.027998499999999999 -0.0733346 0.76544900000000005 -0.642791 0.030115400000000001 +0.23630000000000001 0.037977700000000003 -0.049940600000000002 0.197801 0.97959600000000002 0.035593699999999999 +0.21676300000000001 0.0357448 -0.17780199999999999 -0.41549399999999997 0.90953300000000004 0.0106728 +-0.21007100000000001 0.038261499999999997 -0.18251600000000001 0.41591499999999998 0.90938799999999997 -0.00530775 +0.26694099999999998 0.0130443 -0.22805600000000001 0.94775100000000001 0.318407 -0.019628 +-0.19777900000000001 0.0284201 -0.180537 0.78989500000000001 0.613236 0.0028524000000000002 +-0.249615 -0.039125 -0.132489 0.44108799999999998 0.89735900000000002 -0.013736699999999999 +0.19953099999999999 -0.0221879 -0.2185 0.81787699999999997 0.57537400000000005 0.00479584 +-0.226795 -0.043242099999999999 -0.081508499999999998 -0.123544 0.99224699999999999 0.0135008 +0.200574 0.023677699999999999 -0.23832400000000001 0.73307800000000001 -0.68000799999999995 0.0136224 +-0.188393 -0.0096249000000000005 -0.096674499999999997 0.97663100000000003 -0.214868 0.0048779499999999998 +-0.26601200000000003 -0.025376099999999999 -0.083506499999999997 0.80491400000000002 0.59297 0.022371100000000001 +-0.22790299999999999 0.043339099999999998 -0.20025999999999999 0.078171500000000005 0.99684499999999998 -0.013764200000000001 +-0.190105 -0.0155462 -0.148591 0.93018500000000004 -0.36671599999999999 0.016605700000000001 +-0.198291 0.028931800000000001 -0.249141 0.751058 0.65992300000000004 -0.020331599999999998 +-0.273872 -0.0055638399999999996 -0.260791 0.99140399999999995 0.130331 0.011475300000000001 +0.224409 0.037905000000000001 -0.29674600000000001 -0.15681300000000001 0.98751599999999995 -0.014895500000000001 +-0.22711300000000001 0.0432699 -0.156333 0.12545000000000001 0.99185400000000001 0.0220669 +-0.208563 -0.0374624 -0.086430099999999996 -0.472549 0.88130399999999998 0 +-0.20703299999999999 0.036390699999999998 -0.30335899999999999 0.55970299999999995 0.82859899999999997 -0.012488900000000001 +0.222996 0.037583800000000001 -0.21773899999999999 -0.19325200000000001 0.98113600000000001 0.00502835 +0.209231 -0.031693100000000002 -0.17569299999999999 0.518814 0.85469399999999995 -0.0181733 +-0.26836100000000002 -0.022020600000000001 -0.187859 0.85764899999999999 0.51418799999999998 -0.0069241900000000002 +-0.232935 0.043400300000000003 -0.137071 -0.079490699999999997 0.99669700000000006 0.016626999999999999 +0.26527800000000001 -0.016657499999999999 -0.12934699999999999 0.92144199999999998 -0.38766899999999999 0.025650099999999999 +0.22120699999999999 -0.037104400000000003 -0.077432500000000001 0.23430599999999999 0.97216000000000002 -0.0022007400000000001 +0.20430999999999999 0.027726000000000001 -0.0356174 -0.66796999999999995 0.74418799999999996 0 +-0.22951099999999999 0.043479700000000003 -0.181279 0.040751799999999998 0.99912999999999996 -0.0088952600000000003 +0.19264400000000001 -0.00384702 -0.039241900000000003 0.99586699999999995 0.090823399999999999 -0.000458274 +-0.23542199999999999 0.043182699999999997 -0.111261 -0.094750899999999999 0.99549799999999999 0.0025362200000000001 +-0.24993199999999999 -0.038977499999999998 -0.23536000000000001 0.43615799999999999 0.89943499999999998 0.027972299999999999 +0.26909499999999997 -0.0015494300000000001 -0.23636799999999999 0.996367 -0.085135100000000005 0.0023231800000000002 +0.21687500000000001 -0.035797000000000002 -0.288298 0.34971099999999999 0.93674299999999999 0.0146593 +-0.24612100000000001 -0.0407543 -0.16930999999999999 0.382853 0.92380099999999998 0.0039326999999999999 +-0.227991 -0.043346700000000002 -0.067174800000000007 -0.110095 0.99391700000000005 0.0027679900000000001 +-0.26721099999999998 -0.023663199999999999 -0.059912300000000002 0.83379599999999998 0.55179900000000004 -0.017394699999999999 +0.26644699999999999 0.014150100000000001 -0.193299 0.93581700000000001 0.35229899999999997 0.011460400000000001 +0.22628899999999999 -0.038069499999999999 -0.068357399999999999 0.15795300000000001 0.98682400000000003 -0.035051800000000001 +-0.18804299999999999 -0.0083199099999999998 -0.22006400000000001 0.98191300000000004 -0.189331 0.00064296899999999996 +-0.19112100000000001 0.017723900000000001 -0.080525200000000005 0.90284799999999998 0.42990600000000001 0.0068273500000000003 +0.21219099999999999 0.033612999999999997 -0.28839399999999998 -0.48893900000000001 0.87221499999999996 -0.013436200000000001 +-0.25301000000000001 -0.037437699999999997 -0.22277 0.52857299999999996 0.84879199999999999 0.012801399999999999 +0.26730100000000001 -0.0116977 -0.053724099999999997 0.941303 -0.33745199999999997 0.0086208299999999995 +0.19714000000000001 -0.0185419 -0.26558100000000001 0.88731499999999996 0.46100000000000002 -0.0122962 +-0.26556999999999997 0.026007099999999998 -0.132572 0.79788599999999998 -0.60253299999999999 0.018213400000000001 +-0.22573799999999999 0.043149699999999999 -0.31853300000000001 0.122779 0.99236899999999995 0.0113557 +-0.27213199999999999 0.0134106 -0.123584 0.94728299999999999 -0.32028600000000002 -0.0084561600000000008 +-0.21038499999999999 0.038407999999999998 -0.19200600000000001 0.48709999999999998 0.87321599999999999 -0.0150711 +0.207956 -0.030800399999999999 -0.13699 0.61199000000000003 0.79081500000000005 -0.0090014899999999991 +0.26872400000000002 0.0057874099999999998 -0.25420599999999999 0.98364099999999999 0.18001200000000001 0.0067914400000000002 +-0.19995299999999999 0.0305939 -0.21957699999999999 0.69239399999999995 0.72150300000000001 0.0049054199999999997 +0.22922000000000001 -0.038325999999999999 -0.110522 0.050029200000000003 0.99874600000000002 -0.0018675300000000001 +0.195661 0.015370999999999999 -0.069559599999999999 0.91450100000000001 -0.40403800000000001 -0.0209938 +-0.27184799999999998 0.0144668 -0.29406500000000002 0.94150100000000003 -0.33701100000000001 0 +0.203929 -0.027345399999999999 -0.235649 0.69594199999999995 0.71804000000000001 -0.0091455500000000006 +-0.27307199999999998 0.0099029400000000007 -0.121336 0.97591099999999997 -0.21798200000000001 -0.0090292299999999992 +-0.192111 -0.0198482 -0.082954700000000006 0.89308600000000005 -0.44963700000000001 -0.014974299999999999 +-0.23363900000000001 -0.043338700000000001 -0.078173300000000001 0.106241 0.99430700000000005 0.0081487599999999997 +-0.21454000000000001 0.040344900000000003 -0.25168600000000002 0.370002 0.92899699999999996 0.0079260200000000006 +0.24737700000000001 -0.034532 -0.25992199999999999 -0.473109 0.88091399999999997 -0.0126029 +-0.20319000000000001 0.033699699999999999 -0.11224000000000001 0.60757000000000005 0.79426200000000002 -0.00243495 +-0.233182 -0.043378600000000003 -0.10308299999999999 0.0827933 0.99650799999999995 -0.010862200000000001 +0.197049 0.018346600000000001 -0.27426400000000001 0.88100699999999998 -0.47245100000000001 -0.0248337 +-0.26883899999999999 0.0211077 -0.12189700000000001 0.88356999999999997 -0.46821800000000002 0.0087530300000000002 +-0.27263599999999999 0.011529299999999999 -0.23666400000000001 0.96995200000000004 -0.243172 0.0077731600000000003 +0.25024299999999999 -0.033138800000000003 -0.058216900000000002 -0.50483299999999998 0.86301899999999998 0.018482700000000001 +-0.26916299999999999 0.020413899999999999 -0.155226 0.91143099999999999 -0.41144700000000001 0.0023743599999999998 +-0.21326300000000001 0.039749800000000002 -0.159415 0.36900899999999998 0.92942499999999995 0.0013695000000000001 +-0.24526800000000001 0.041070700000000002 -0.20580399999999999 -0.350885 0.93627899999999997 0.016149199999999999 +-0.24762400000000001 -0.040053600000000002 -0.087481699999999996 0.38841900000000001 0.92148099999999999 -0.0017541099999999999 +0.19725300000000001 -0.018783999999999999 -0.057728000000000002 0.89391100000000001 0.44819799999999999 -0.0064719399999999998 +-0.20536099999999999 -0.0352202 -0.24007000000000001 -0.553755 0.83243800000000001 -0.020072400000000001 +-0.26577899999999999 -0.025708100000000001 -0.18806700000000001 0.79154999999999998 0.61110500000000001 0 +-0.20222999999999999 -0.032871600000000001 -0.18401600000000001 -0.65627000000000002 0.75426300000000002 -0.019906699999999999 +-0.263044 -0.029135999999999999 -0.083733399999999999 0.73627900000000002 0.67666099999999996 -0.0048178300000000004 +-0.20496800000000001 0.034944599999999999 -0.24305499999999999 0.59932700000000005 0.80047599999999997 -0.0067642099999999997 +0.26441500000000001 -0.0185086 -0.014639299999999999 0.85997599999999996 -0.51030900000000001 0.0051066999999999996 +-0.25879000000000002 -0.0333899 -0.23904700000000001 0.64777799999999996 0.761822 0.00320112 +0.20044799999999999 0.023496699999999999 -0.11422300000000001 0.77965300000000004 -0.62392800000000004 -0.053431399999999997 +0.26192100000000001 -0.022311399999999999 -0.16147500000000001 0.84282199999999996 -0.53795300000000001 0.016068800000000001 +0.195961 0.016014400000000002 -0.172565 0.90701399999999999 -0.42047099999999998 -0.023004199999999999 +-0.27374799999999999 0.0069881500000000003 -0.080092800000000006 0.99441299999999999 -0.104717 0.013332 +0.19272800000000001 0.0047985700000000003 -0.27738299999999999 0.99212500000000003 -0.123988 -0.0177304 +-0.268955 -0.020860900000000002 -0.28634199999999999 0.87187400000000004 0.48970799999999998 0.0046823200000000002 +-0.18851299999999999 -0.010073199999999999 -0.17763399999999999 0.98043199999999997 -0.19556100000000001 0.022543000000000001 +0.19231799999999999 -0.00011231900000000001 -0.031865299999999999 0.99860000000000004 0.049207899999999999 0.019424899999999998 +-0.24225099999999999 -0.041879199999999998 -0.153252 0.29343399999999997 0.955928 0.0098727899999999993 +-0.26510800000000001 0.026665999999999999 -0.22694600000000001 0.79955299999999996 -0.60058400000000001 -0.0036613499999999998 +0.266903 -0.013171499999999999 -0.26441199999999998 0.96038999999999997 -0.27862300000000001 0.00442473 +0.255577 -0.029378499999999998 -0.17961199999999999 -0.67247699999999999 0.74005699999999996 0.00953268 +-0.27390599999999998 -0.0051803099999999996 -0.114181 0.98847399999999996 0.15121000000000001 0.0073915300000000003 +0.25070599999999998 0.032814299999999998 -0.11555600000000001 0.53149100000000005 0.84705399999999997 -0.0041145399999999999 +0.246998 -0.0347084 -0.041486099999999998 -0.44337399999999999 0.89612099999999995 0.019668499999999998 +-0.21621000000000001 0.041054500000000001 -0.26574999999999999 0.37143799999999999 0.92844599999999999 0.0046760999999999999 +0.26322200000000001 -0.0204528 -0.0390555 0.84685999999999995 -0.53181500000000004 0.0011508600000000001 +0.19317599999999999 -0.0077405499999999997 -0.162552 0.97596400000000005 0.21784300000000001 -0.00614899 +-0.19736300000000001 0.0279972 -0.19444900000000001 0.77029700000000001 0.637629 -0.0084346000000000004 +0.21954499999999999 -0.036659299999999999 -0.057363699999999997 0.27299800000000002 0.96201400000000004 0 +-0.199043 -0.029683999999999999 -0.203348 0.71903700000000004 -0.69460599999999995 -0.022550199999999999 +-0.272926 -0.0104455 -0.079474199999999995 0.96730300000000002 0.25339499999999998 -0.010781499999999999 +0.20876600000000001 0.031367699999999998 -0.22173200000000001 -0.57298800000000005 0.81928900000000004 0.0212058 +0.26700099999999999 0.0128203 -0.0791602 0.93646600000000002 0.35073599999999999 0.00406662 +-0.24885199999999999 -0.039480700000000001 -0.207931 0.41105000000000003 0.911609 0.0026685099999999998 +-0.27432400000000001 -0.000405153 -0.26928800000000003 0.99971200000000005 -0.0239831 -0.0011323800000000001 +0.20629400000000001 -0.029636200000000001 -0.116678 0.64383999999999997 0.76515999999999995 0 +-0.25415500000000002 0.036635800000000003 -0.27353899999999998 -0.54445699999999997 0.83877100000000004 0.0055467299999999997 +-0.19178300000000001 0.0191448 -0.18277099999999999 0.90180199999999999 0.43161100000000002 0.021571 +-0.25370999999999999 -0.036947300000000002 -0.218115 0.54562600000000006 0.83802900000000002 0 +-0.248839 -0.039487000000000001 -0.20949999999999999 0.42809999999999998 0.90373099999999995 0 +0.19401499999999999 -0.010868600000000001 -0.049965700000000002 0.95064099999999996 0.310276 0.0031972400000000001 +-0.238312 -0.0429299 -0.26896700000000001 0.153451 0.98801600000000001 -0.016627099999999999 +0.24366099999999999 0.036212500000000002 -0.18707099999999999 0.34024199999999999 0.94028699999999998 0.0098422700000000002 +0.225297 0.037982700000000001 -0.12756000000000001 -0.15427399999999999 0.98799599999999999 0.0079696799999999998 +0.22190499999999999 -0.037291499999999998 -0.094663899999999995 0.18196499999999999 0.98326499999999994 0.0088463099999999996 +-0.25508500000000001 0.035984700000000001 -0.29446099999999997 -0.57469499999999996 0.81822099999999998 -0.015498700000000001 +0.239039 -0.037450900000000002 -0.301344 -0.26750299999999999 0.96354499999999998 0.0047497800000000003 +-0.22049299999999999 -0.042202099999999999 -0.29872100000000001 -0.244168 0.96966600000000003 -0.011380400000000001 +-0.187582 0.0046012700000000002 -0.29380800000000001 0.99555199999999999 0.092946100000000004 0.0153995 +0.267513 -0.0109064 -0.21928500000000001 0.95647400000000005 -0.290769 0.024725500000000001 +-0.18981200000000001 -0.0149167 -0.056315200000000003 0.93630400000000003 -0.35108600000000001 0.00857868 +-0.26413900000000001 0.028041199999999999 -0.17952199999999999 0.74895100000000003 -0.66222400000000003 0.023075100000000001 +0.19284000000000001 0.0060884299999999997 -0.066090899999999994 0.98858000000000001 -0.150588 0.0057411199999999997 +0.19441700000000001 -0.0123701 -0.29141800000000001 0.94378200000000001 0.33037499999999997 0.011313200000000001 +-0.20644399999999999 0.035978099999999999 -0.271088 0.526312 0.850132 0.0164872 +-0.227383 0.043293499999999999 -0.213949 0.10453999999999999 0.99450899999999998 -0.0047975600000000002 +-0.272038 -0.013757500000000001 -0.16242200000000001 0.94826200000000005 0.31695200000000001 -0.018481500000000001 +-0.19219800000000001 0.020033599999999999 -0.317637 0.89708600000000005 0.441662 -0.013099100000000001 +0.23178599999999999 0.0383726 -0.079564999999999997 0.0050119500000000003 0.99996700000000005 0.0063521799999999998 +0.219945 0.036766300000000002 -0.072502499999999998 -0.24682399999999999 0.96903799999999995 0.0065252900000000004 +-0.27171299999999998 0.014944199999999999 -0.21865999999999999 0.93736399999999998 -0.34823799999999999 0.0088914200000000006 +-0.19096399999999999 0.017387699999999999 -0.21776599999999999 0.91588700000000001 0.40128599999999998 0.010995 +-0.26649800000000001 0.0246818 -0.057168999999999998 0.82270600000000005 -0.56820700000000002 0.017172699999999999 +-0.21262500000000001 0.0394522 -0.052392500000000002 0.41708299999999998 0.90885899999999997 0.0042156099999999998 +0.19619900000000001 0.0165252 -0.15019199999999999 0.90311300000000005 -0.42886200000000002 -0.0215564 +-0.18782799999999999 -0.0074069899999999996 -0.23577000000000001 0.99049900000000002 -0.13748199999999999 -0.00309932 +-0.26240400000000003 0.029776 -0.097536700000000004 0.74663000000000002 -0.66520100000000004 0.0071301799999999999 +0.19883799999999999 0.021197000000000001 -0.086789699999999997 0.83511999999999997 -0.54987699999999995 0.014493499999999999 +-0.24823000000000001 -0.039770899999999998 -0.155555 0.37894 0.92542000000000002 0.0017756600000000001 +0.19256699999999999 0.0029609300000000001 -0.0685027 0.99712500000000004 -0.075258199999999997 -0.0087986799999999997 +0.26319900000000002 -0.0204855 -0.17719799999999999 0.87067099999999997 -0.491865 0 +-0.23197100000000001 0.043484700000000001 -0.121569 0.0060402099999999999 0.99996700000000005 0.0055108099999999997 +0.25322800000000001 -0.031048800000000001 -0.021004700000000001 -0.58107200000000003 0.81385099999999999 -0.0015619 +0.221665 0.037227200000000002 -0.105416 -0.24116599999999999 0.970356 -0.0157406 +-0.223084 0.042896499999999997 -0.082019400000000006 0.19935700000000001 0.97991899999999998 0.00388858 +0.21157300000000001 0.033325100000000003 -0.32404100000000002 -0.49772499999999997 0.86684799999999995 0.029058899999999999 +-0.18760299999999999 -0.0048422700000000001 -0.16251199999999999 0.99095900000000003 -0.13353499999999999 0.012997699999999999 +0.26481399999999999 0.0176528 -0.099517599999999998 0.86740300000000004 0.49728800000000001 -0.0178146 +0.192744 0.0049889000000000001 -0.247725 0.99425600000000003 -0.107028 0 +-0.229687 -0.043494999999999999 -0.308342 -0.053581499999999997 0.99787800000000004 -0.036989300000000003 +0.243976 0.036117400000000001 -0.26946700000000001 0.31483899999999998 0.94896100000000005 0.018687700000000002 +0.227071 0.038137900000000002 -0.20390900000000001 -0.070301100000000005 0.99751199999999995 0.0052928300000000001 +-0.18858900000000001 -0.0103561 -0.13580500000000001 0.97670199999999996 -0.21412800000000001 0.0142392 +0.19373199999999999 -0.0098143999999999992 -0.177345 0.97821999999999998 0.20746700000000001 0.0065678200000000003 +-0.250917 0.0385181 -0.207672 -0.475049 0.87975300000000001 -0.019036500000000001 +0.21149100000000001 0.033275699999999998 -0.13215199999999999 -0.49094199999999999 0.87107100000000004 -0.014531199999999999 +0.194908 0.0137576 -0.028013799999999998 0.947909 -0.31844299999999998 -0.00795212 +0.219278 0.036587500000000002 -0.25243700000000002 -0.30845899999999998 0.95123199999999997 -0.00336068 +-0.27411999999999997 0.0027352000000000001 -0.085851499999999997 0.99441900000000005 -0.10421 0.0164878 +0.231298 -0.038415199999999997 -0.14258899999999999 -0.038327199999999999 0.999247 0.0059917399999999997 +0.23272000000000001 -0.0382908 -0.0619228 -0.099380999999999997 0.995008 0.0090694399999999998 +0.207256 0.030310199999999999 -0.26631199999999999 -0.605653 0.79562999999999995 0.012563400000000001 +-0.20306299999999999 0.033610899999999999 -0.056142999999999998 0.57849799999999996 0.81559099999999995 -0.0122763 +-0.24126700000000001 -0.042142699999999998 -0.060817000000000003 0.179761 0.98369899999999999 -0.0047349000000000002 +-0.263376 -0.028803800000000001 -0.119801 0.75948800000000005 0.64999600000000002 0.026141600000000001 +-0.20674400000000001 -0.0361883 -0.24582200000000001 -0.52716799999999997 0.84971200000000002 0.0090843999999999994 +-0.217584 0.041422599999999997 -0.23707800000000001 0.30750100000000002 0.95144200000000001 -0.0141666 +0.25221300000000002 0.031758799999999997 -0.27939000000000003 0.541157 0.84092 -0.0014128299999999999 +0.247082 -0.0346693 -0.27362199999999998 -0.40932299999999999 0.91239000000000003 0 +-0.19881599999999999 0.0294576 -0.22670899999999999 0.71417799999999998 0.69994599999999996 0.0050180399999999997 +-0.23455500000000001 0.043258499999999998 -0.17738799999999999 -0.15890499999999999 0.98694099999999996 0.026389099999999999 +0.193802 0.0100754 -0.053705799999999998 0.97656500000000002 -0.21479899999999999 -0.0134746 +-0.26490799999999998 -0.026952799999999999 -0.26236700000000002 0.81053399999999998 0.58558900000000003 0.0109365 +0.192748 -0.00503682 -0.13978299999999999 0.98609199999999997 0.16284799999999999 -0.033208000000000001 +-0.24449100000000001 -0.041279000000000003 -0.092027600000000001 0.318135 0.94804500000000003 0 +0.21820800000000001 -0.036301 -0.14521400000000001 0.30364099999999999 0.95270299999999997 -0.0126248 +0.19733700000000001 0.018965800000000001 -0.14949999999999999 0.87183500000000003 -0.48978699999999997 0.00352885 +0.25026199999999998 0.033125500000000002 -0.094353300000000001 0.52059 0.85356299999999996 -0.020418700000000001 +0.26903700000000003 0.0022118900000000002 -0.245864 0.99999499999999997 0.0014973499999999999 -0.00271733 +0.224133 -0.037880900000000002 -0.15128900000000001 0.145924 0.98883900000000002 -0.0300489 +0.26638899999999999 0.014273299999999999 -0.26688899999999999 0.921852 0.387355 0.0120667 +-0.27408500000000002 0.0031341300000000002 -0.084562100000000001 0.99440700000000004 -0.10534300000000001 0.00762366 +0.201353 -0.024769599999999999 -0.218975 0.74103699999999995 0.67133100000000001 -0.0133718 +0.26902399999999999 0.00236645 -0.301902 0.99888399999999999 0.047227999999999999 -0.000426492 +0.23511399999999999 0.038081400000000001 -0.31809700000000002 0.094256400000000004 0.994919 -0.0353855 +0.19530700000000001 -0.014612 -0.014106799999999999 0.911188 0.41198699999999999 0.0017234699999999999 +-0.19003200000000001 0.0153881 -0.080343700000000004 0.92885300000000004 0.36999500000000002 0.018332399999999999 +-0.19254099999999999 -0.020769800000000001 -0.202097 0.86986200000000002 -0.492502 -0.027979500000000001 +-0.25502000000000002 -0.036029800000000001 -0.315141 0.54414700000000005 0.83887500000000004 0.013902299999999999 +0.26867799999999997 0.0063130399999999998 -0.132299 0.98799599999999999 0.154334 0.0067705999999999999 +-0.195216 0.024931399999999999 -0.256853 0.80781000000000003 0.58838400000000002 -0.0353225 +-0.27215099999999998 -0.013337 -0.26039299999999999 0.94855900000000004 0.31509700000000002 -0.0308282 +0.24085899999999999 0.036963200000000002 -0.053323500000000003 0.27318900000000002 0.96188300000000004 -0.012175099999999999 +-0.20547399999999999 0.035298999999999997 -0.214226 0.56362699999999999 0.82601999999999998 0.0039647199999999997 +-0.24679499999999999 0.040439999999999997 -0.14507999999999999 -0.35766599999999998 0.93367199999999995 -0.0182294 +0.192412 -0.0011869999999999999 -0.139847 0.99944 0.023424799999999999 -0.023895599999999999 +-0.27335100000000001 0.0088600499999999995 -0.25329800000000002 0.96589199999999997 -0.25894200000000001 -0.0016024100000000001 +-0.18779399999999999 0.0070219200000000001 -0.097049200000000002 0.98667000000000005 0.16272500000000001 0.00159953 +0.23999500000000001 0.037194600000000001 -0.11742900000000001 0.22666900000000001 0.97397100000000003 -0.0015215999999999999 +-0.212141 -0.039226400000000002 -0.30666599999999999 -0.43121399999999999 0.90224599999999999 -0.0027568100000000002 +-0.22900899999999999 0.043435799999999997 -0.28608600000000001 0.042276399999999999 0.99910100000000002 0.0031327899999999999 +-0.204511 0.034624599999999998 -0.224467 0.62282099999999996 0.78236300000000003 -0.0014838900000000001 +0.19827800000000001 -0.020398099999999999 -0.085054199999999996 0.85436800000000002 0.51905800000000002 -0.0251994 +-0.19064999999999999 -0.016714400000000001 -0.21082200000000001 0.92777200000000004 -0.37286000000000002 -0.0146576 +0.26880100000000001 -0.0049083599999999996 -0.090800400000000003 0.99140300000000003 -0.13051099999999999 -0.0092922600000000001 +-0.21526100000000001 0.040681299999999997 -0.31422600000000001 0.313363 0.94951300000000005 -0.015143500000000001 +0.26665 0.0137143 -0.16667100000000001 0.93906800000000001 0.34371499999999999 0.00341757 +-0.22551399999999999 0.043130099999999998 -0.26403900000000002 0.12706300000000001 0.99172199999999999 -0.0185314 +0.26497700000000002 0.017303599999999999 -0.16427800000000001 0.89299700000000004 0.45006299999999999 0 +-0.25658900000000001 0.034931700000000003 -0.0724075 -0.62061599999999995 0.78411299999999995 0.0016494299999999999 +-0.221666 -0.042516499999999999 -0.30172300000000002 -0.22167400000000001 0.97502200000000006 0.013916700000000001 +-0.25154500000000002 -0.038224899999999999 -0.14450499999999999 0.50754699999999997 0.86155099999999996 0.0112312 +0.19266800000000001 -0.0041192299999999998 -0.21059800000000001 0.99317999999999995 0.115949 0.012186000000000001 +-0.25827800000000001 -0.033748599999999997 -0.108587 0.61917 0.78523799999999999 0.0054610700000000002 +0.25436999999999999 -0.0302487 -0.068184900000000007 -0.63793800000000001 0.770069 0.0053954399999999996 +0.238565 0.037577800000000001 -0.28171200000000002 0.15302199999999999 0.98812699999999998 0.013778800000000001 +-0.24090700000000001 -0.042239400000000003 -0.069092799999999996 0.16292000000000001 0.98641900000000005 0.020825799999999998 +0.196492 -0.017154099999999999 -0.24592900000000001 0.88915999999999995 0.45687699999999998 0.025663999999999999 +-0.26756999999999997 -0.0231506 -0.13115399999999999 0.85922399999999999 0.51158700000000001 -0.0035974499999999999 +0.26171100000000003 0.0226108 -0.032862000000000002 0.76972799999999997 0.63835600000000003 -0.0045799400000000002 +-0.269706 -0.0192494 -0.059850500000000001 0.89481200000000005 0.44644400000000001 0 +0.226379 0.038077399999999997 -0.29591200000000001 -0.053128500000000002 0.99849299999999996 -0.013721000000000001 +-0.21981899999999999 0.042021599999999999 -0.278445 0.237155 0.97137700000000005 0.0136093 +0.24987400000000001 0.033367599999999997 -0.019657399999999998 0.52081200000000005 0.85366600000000004 0.00303484 +-0.27221099999999998 -0.013114300000000001 -0.23051199999999999 0.95364599999999999 0.30081999999999998 -0.00817646 +0.24263299999999999 0.036487800000000001 -0.097259200000000004 0.30066900000000002 0.95327399999999995 0.0294478 +-0.22495100000000001 -0.043080800000000002 -0.18154899999999999 -0.15676999999999999 0.987568 0.0115012 +-0.21868699999999999 0.041718199999999997 -0.169263 0.32891300000000001 0.944303 0.0103967 +-0.18773999999999999 0.0063993100000000001 -0.28771000000000002 0.99182899999999996 0.12722700000000001 -0.0094126599999999998 +-0.18760099999999999 -0.0048197600000000002 -0.059192399999999999 0.995228 -0.0962369 0.016112600000000001 +-0.22028700000000001 -0.042146999999999997 -0.27484900000000001 -0.22253899999999999 0.97491899999999998 -0.0032133000000000001 +0.26060899999999998 -0.024183699999999999 -0.150307 0.75028300000000003 -0.660524 -0.027985400000000001 +0.19681199999999999 0.017840200000000001 -0.161302 0.88816099999999998 -0.45941700000000002 0.0102402 +-0.21543300000000001 0.040761199999999997 -0.25696799999999997 0.300811 0.95367000000000002 0.0050311599999999998 +0.255743 -0.029211899999999999 -0.144067 -0.66446300000000003 0.747278 0.0080557400000000005 +0.22956399999999999 -0.038356000000000001 -0.32046200000000002 -0.0285831 0.999475 0.015235800000000001 +-0.18823899999999999 -0.0090495599999999999 -0.134494 0.98683100000000001 -0.161329 0.011755099999999999 +-0.26152500000000001 0.030655000000000002 -0.091405700000000006 0.70878399999999997 -0.70530800000000005 -0.0128419 +0.251942 -0.031948900000000002 -0.14888999999999999 -0.52715599999999996 0.84976799999999997 0 +-0.25942100000000001 0.032758799999999998 -0.32132300000000003 -0.65797499999999998 0.75302100000000005 -0.0052650300000000004 +0.19233700000000001 -0.00033135700000000001 -0.058375700000000003 0.99999000000000005 -0.0042486499999999996 0.0012080000000000001 +0.205456 -0.028872499999999999 -0.232269 0.65217899999999995 0.75805599999999995 0.00366965 +-0.27185999999999999 -0.014422900000000001 -0.28593299999999999 0.93921500000000002 0.34331800000000001 0.0029136000000000001 +-0.267739 0.022909499999999999 -0.120751 0.85267300000000001 -0.52241199999999999 -0.0058342300000000001 +0.238819 0.037509899999999999 -0.18562999999999999 0.243648 0.9698 -0.011163599999999999 +0.240282 0.037117900000000002 -0.22106899999999999 0.21557399999999999 0.97615300000000005 -0.025567800000000002 +-0.26404 -0.028139500000000001 -0.23755399999999999 0.77865899999999999 0.62729999999999997 -0.013632999999999999 +0.22315299999999999 0.037625899999999997 -0.209867 -0.18467 0.98267300000000002 0.0158446 +0.19259899999999999 -0.00332782 -0.165745 0.99792599999999998 0.063849000000000003 0.0081278900000000005 +0.237035 0.037913299999999997 -0.19999800000000001 0.11862300000000001 0.99293299999999995 -0.0035726899999999999 +-0.187449 -0.0030795200000000001 -0.14140900000000001 0.99794799999999995 -0.0617575 0.016880800000000001 +-0.187497 -0.0036312200000000001 -0.298568 0.99778999999999995 -0.066438399999999995 -0.00090671399999999998 +0.235093 0.038083199999999998 -0.32192700000000002 0.084250900000000004 0.99568999999999996 -0.038778 +-0.26004500000000003 -0.032134700000000002 -0.15706800000000001 0.67065900000000001 0.74161999999999995 0.014709 +0.19267400000000001 -0.0041853000000000003 -0.28562700000000002 0.995726 0.089927800000000002 0.0210295 +0.19584599999999999 -0.0157681 -0.070014900000000005 0.89825699999999997 0.439083 0.018447100000000001 +0.25521700000000003 0.029655600000000001 -0.145201 0.64374299999999995 0.76503900000000002 -0.017616300000000001 +0.21918399999999999 0.036562400000000002 -0.066546900000000006 -0.31149100000000002 0.95006299999999999 0.018831400000000002 +0.203878 0.0272944 -0.237289 -0.69146200000000002 0.72241299999999997 0 +0.265762 -0.015618099999999999 -0.22085199999999999 0.89277499999999999 -0.45050299999999999 0 +-0.27418799999999999 0.0019601200000000001 -0.19119900000000001 0.99910900000000002 -0.042090200000000001 0.00320623 +0.19986699999999999 -0.0226675 -0.121798 0.79463600000000001 0.60641100000000003 -0.028618299999999999 +-0.19573699999999999 -0.0256762 -0.199076 0.82559400000000005 -0.56421200000000005 -0.0076368299999999998 +0.26559500000000003 0.0159778 -0.299626 0.90696500000000002 0.42060700000000001 -0.022431799999999998 +-0.21753800000000001 -0.041410299999999997 -0.28294599999999998 -0.30859799999999998 0.95107600000000003 0.014919200000000001 +0.218692 0.0364306 -0.264214 -0.28294399999999997 0.95891599999999999 0.0205439 +0.260181 0.024773300000000002 -0.31114000000000003 0.73801700000000003 0.67476800000000003 0.0043080499999999999 +-0.21706300000000001 0.041283 -0.075879500000000003 0.32378299999999999 0.94611699999999999 -0.0051095200000000002 +-0.27265899999999998 -0.0114415 -0.13764399999999999 0.95907399999999998 0.28306399999999998 -0.00711613 +-0.188585 0.010342499999999999 -0.18138499999999999 0.97609400000000002 0.217028 -0.0118058 +0.23349700000000001 0.038222899999999997 -0.119116 0.108477 0.99409800000000004 0.00115267 +0.192661 -0.0040407899999999998 -0.066917500000000005 0.996166 0.087079199999999995 -0.00841159 +0.194602 0.0130622 -0.19140299999999999 0.94527000000000005 -0.32615699999999997 -0.0092679900000000003 +-0.187552 -0.0042579999999999996 -0.159051 0.99313899999999999 -0.115115 0.0205983 +0.26547199999999999 -0.0162419 -0.17332900000000001 0.905026 -0.42528899999999997 0.00749134 +0.202378 -0.025794000000000001 -0.12756300000000001 0.72536900000000004 0.68829899999999999 0.0091760799999999997 +-0.25644400000000001 0.0350327 -0.23824500000000001 -0.59437899999999999 0.80415499999999995 0.0069058799999999997 +-0.26728400000000002 -0.023559 -0.27989999999999998 0.84738500000000005 0.53070899999999999 -0.0169249 +0.26065899999999997 0.024112600000000001 -0.239785 0.77803 0.62611399999999995 -0.051485099999999999 +-0.21277799999999999 0.039523700000000002 -0.14458699999999999 0.39363100000000001 0.91926399999999997 0.0028508299999999999 +-0.25703300000000001 0.034620900000000003 -0.095853099999999997 -0.62173400000000001 0.78322000000000003 0.0036347800000000002 +0.24552199999999999 -0.035396999999999998 -0.066516699999999998 -0.37798300000000001 0.92482900000000001 -0.042656399999999997 +-0.27424799999999999 0.0012716100000000001 -0.27652199999999999 0.99906899999999998 -0.043097200000000002 0.00182321 +0.24679200000000001 -0.0348049 -0.18503600000000001 -0.41481099999999999 0.90988899999999995 -0.0058434100000000003 +0.26045099999999999 -0.024410000000000001 -0.25742799999999999 0.78289900000000001 -0.62080100000000005 -0.0409278 +-0.202905 -0.033500500000000002 -0.082865999999999995 -0.66394900000000001 0.74700200000000005 0.034059300000000001 +-0.258519 0.033579999999999999 -0.14397599999999999 -0.60665599999999997 0.79494500000000001 -0.00554361 +0.21778900000000001 0.036188400000000003 -0.17224100000000001 -0.38564399999999999 0.92264500000000005 0.0021186299999999998 +-0.19675100000000001 0.027123700000000001 -0.127332 0.76867300000000005 0.63945600000000002 -0.015462999999999999 +0.20255999999999999 0.025976599999999999 -0.20454900000000001 0.75121199999999999 -0.65954900000000005 -0.0259735 +0.194632 -0.013165700000000001 -0.22419 0.95061099999999998 0.31018499999999999 -0.011160399999999999 +0.24529500000000001 0.035502499999999999 -0.30512499999999998 0.36063600000000001 0.93262500000000004 -0.012316300000000001 +-0.25395699999999999 -0.036774800000000003 -0.31161 0.51333399999999996 0.85816899999999996 -0.0057605800000000004 +-0.190776 0.0169844 -0.30723800000000001 0.90943499999999999 0.41583399999999998 0.0032222100000000001 +0.26815099999999997 -0.0085261199999999999 -0.176312 0.96322300000000005 -0.26766800000000002 -0.023559199999999999 +-0.20691799999999999 -0.0363104 -0.159997 -0.53641399999999995 0.84393700000000005 -0.0054682799999999998 +0.26744299999999999 -0.0111704 -0.122215 0.95432099999999997 -0.298759 -0.00372478 +0.21235100000000001 -0.033687700000000001 -0.201178 0.48452099999999998 0.87476399999999999 0.00523895 +0.26782699999999998 -0.0097364400000000007 -0.099423800000000007 0.96197699999999997 -0.27311299999999999 -0.0030593500000000002 +-0.18895700000000001 -0.011731200000000001 -0.080279500000000004 0.96234900000000001 -0.27091100000000001 0.022189500000000001 +-0.228542 -0.0433949 -0.30983899999999998 -0.080744800000000005 0.99669399999999997 -0.0089736999999999994 +-0.195211 -0.024925099999999999 -0.32072200000000001 0.80765699999999996 -0.58944300000000005 0.0157057 +-0.195965 -0.0260016 -0.16529199999999999 0.771513 -0.63620500000000002 0.0033556100000000002 +-0.26525300000000002 0.0264601 -0.16659299999999999 0.80090499999999998 -0.59864700000000004 0.013158100000000001 +0.26009500000000002 -0.024859599999999999 -0.30338799999999999 0.76114000000000004 -0.64858800000000005 0 +-0.273287 0.0090973800000000004 -0.13677 0.97659099999999999 -0.21492900000000001 -0.0086452400000000002 +0.26632800000000001 -0.014404399999999999 -0.075470400000000007 0.92994100000000002 -0.367699 0.0026562199999999999 +0.22047 0.036906799999999997 -0.11383699999999999 -0.27152399999999999 0.96240000000000003 -0.0078469000000000004 +0.193332 -0.0083196599999999996 -0.13727900000000001 0.97074899999999997 0.238259 -0.029659100000000001 +0.21859400000000001 -0.036404499999999999 -0.026109 0.317722 0.94809600000000005 0.012883 +-0.19015000000000001 0.015642300000000001 -0.089838299999999996 0.93607799999999997 0.35141800000000001 0.016227200000000001 +-0.197071 -0.0275806 -0.23485200000000001 0.76261299999999999 -0.64632800000000001 0.026096399999999999 +-0.250666 -0.038635099999999999 -0.26006800000000002 0.477551 0.87770700000000001 -0.039683299999999998 +-0.223999 0.042997500000000001 -0.19656299999999999 0.152527 0.98829900000000004 0 +0.193301 0.0082051499999999996 -0.14247899999999999 0.98458800000000002 -0.17458599999999999 0.0102889 +-0.204538 -0.034643800000000002 -0.25234499999999999 -0.53119799999999995 0.847248 0 +0.26236900000000002 0.0216709 -0.229015 0.82959400000000005 0.55796000000000001 0.021306100000000001 +0.260241 0.024710200000000002 -0.32344899999999999 0.75856999999999997 0.65148499999999998 0.011766499999999999 +0.19928999999999999 0.021843399999999999 -0.23286699999999999 0.83476700000000004 -0.550543 0.00810226 +-0.27434799999999998 -0.000120702 -0.14249100000000001 0.99998600000000004 0.00184815 -0.00488873 +-0.18751399999999999 0.0038193300000000001 -0.32186999999999999 0.99604300000000001 0.088811299999999996 -0.00332694 +0.19747000000000001 0.0192435 -0.115786 0.87761699999999998 -0.47897800000000001 -0.019177300000000001 +0.26901900000000001 -0.0024220999999999999 -0.12917300000000001 0.99852799999999997 -0.054200600000000002 -0.0019945100000000001 +0.211284 0.033131099999999997 -0.12441199999999999 -0.48047699999999999 0.87683500000000003 0.017377500000000001 +-0.269812 -0.019021400000000001 -0.25075399999999998 0.88956000000000002 0.45676299999999997 -0.0070907899999999996 +0.19236200000000001 0.00062111399999999998 -0.20718500000000001 0.99988299999999997 -0.010322599999999999 -0.011282 +0.21954000000000001 0.0366579 -0.31469999999999998 -0.30055500000000002 0.95375699999999997 0.0037685800000000001 +-0.26798699999999998 0.022555200000000001 -0.075916200000000003 0.81187399999999998 -0.583812 0.0049057800000000002 +-0.23083300000000001 -0.043584100000000001 -0.30818000000000001 0.0016711899999999999 0.99995900000000004 -0.0088931700000000006 +-0.26996399999999998 0.018696399999999998 -0.17902199999999999 0.89519400000000005 -0.44564199999999998 -0.00559999 +-0.25326500000000002 -0.037259199999999999 -0.050162199999999997 0.53472699999999995 0.84502500000000003 0 +-0.26933099999999999 -0.0200532 -0.077282799999999999 0.89747900000000003 0.44102400000000003 -0.0053791899999999998 +0.22703100000000001 0.038134500000000002 -0.060483799999999997 -0.096144300000000002 0.99530600000000002 0.0110837 +0.26886100000000002 -0.00422698 -0.21854299999999999 0.98868100000000003 -0.147207 0.028991599999999999 +0.19634599999999999 0.016839300000000001 -0.260909 0.89037500000000003 -0.45518599999999998 -0.0061958200000000003 +0.22306400000000001 0.037601900000000001 -0.25479200000000002 -0.22604099999999999 0.97411599999999998 -0.0019563100000000002 +-0.19900300000000001 0.029644400000000001 -0.0606721 0.70541399999999999 0.70879400000000004 -0.0015038199999999999 +-0.27391300000000002 0.0050962500000000001 -0.19433800000000001 0.991649 -0.127968 -0.016034400000000001 +0.199382 0.021975100000000001 -0.081130400000000005 0.84583600000000003 -0.533389 0.0076060299999999997 +0.249414 0.033582099999999997 -0.25854500000000002 0.54638799999999998 0.83752099999999996 -0.0044382600000000003 +0.20436099999999999 0.027777699999999999 -0.095680200000000007 -0.68468499999999999 0.72883900000000001 0 +0.24488199999999999 -0.035695299999999999 -0.23055999999999999 -0.35087299999999999 0.936419 -0.00257705 +0.19231100000000001 3.43339e-05 -0.15640799999999999 0.99978699999999998 -0.019492700000000002 0.0068500000000000002 +0.21218999999999999 0.033612599999999999 -0.15733800000000001 -0.449073 0.892872 -0.033356700000000003 +-0.18787599999999999 0.0076944099999999996 -0.300981 0.97523800000000005 0.21996299999999999 -0.022974700000000001 +-0.20108899999999999 0.031730700000000001 -0.155639 0.68372699999999997 0.72959499999999999 0.0144508 +-0.21127099999999999 0.038821099999999997 -0.160414 0.44480999999999998 0.89562200000000003 0.0020531999999999998 +0.192608 0.0034292200000000002 -0.316473 0.998668 -0.046964199999999998 -0.021377 +-0.26021499999999997 0.031964800000000002 -0.23852000000000001 -0.67270799999999997 0.73979300000000003 0.013041000000000001 +-0.261824 -0.030356000000000001 -0.077515899999999999 0.74477499999999996 0.66715199999999997 0.0147534 +-0.25203100000000001 -0.037998499999999998 -0.27471600000000002 0.460289 0.88775300000000001 0.0054162000000000004 +0.26150899999999999 -0.022899599999999999 -0.18779000000000001 0.80280600000000002 -0.595804 0.022791100000000002 +0.26736799999999999 -0.011450699999999999 -0.189552 0.96019100000000002 -0.27864299999999997 0.019767400000000001 +0.192691 -0.0043836099999999996 -0.173041 0.99451000000000001 0.10446999999999999 0.0060419999999999996 +-0.26496799999999998 0.026867100000000001 -0.052090699999999997 0.786215 -0.617842 0.011731999999999999 +0.25903399999999999 -0.025920700000000001 -0.120064 0.70841299999999996 -0.705291 0.026739700000000002 +-0.19039800000000001 -0.016173 -0.31670500000000001 0.924238 -0.38179000000000002 -0.00454989 +-0.273727 -0.0072215600000000001 -0.180588 0.981568 0.190552 -0.014626500000000001 +-0.20141800000000001 0.032059900000000002 -0.157138 0.70847499999999997 0.70570900000000003 -0.0061571200000000003 +0.26919799999999999 -0.00037520899999999999 -0.30017500000000003 0.99995299999999998 0.0094882300000000003 0.00204083 +0.19509199999999999 -0.014152 -0.140406 0.93496599999999996 0.35463899999999998 -0.0084120600000000007 +0.212835 0.0339133 -0.206509 -0.44846999999999998 0.89350300000000005 -0.022960499999999998 +0.20663200000000001 -0.029872900000000001 -0.175868 0.61630499999999999 0.78674500000000003 -0.034650599999999997 +0.207981 -0.030817399999999998 -0.29114400000000001 0.57833199999999996 0.81579299999999999 0.0037772999999999999 +-0.21134700000000001 -0.038856300000000003 -0.256546 -0.47139700000000001 0.88190999999999997 0.00434629 +-0.272901 0.010540300000000001 -0.27895700000000001 0.96231100000000003 -0.271953 0 +0.26685599999999998 0.013271700000000001 -0.024474800000000001 0.92747599999999997 0.37388300000000002 0 +0.269013 0.0024840399999999999 -0.25943500000000003 0.99275599999999997 0.118672 -0.0187691 +0.26884000000000002 0.0044601800000000002 -0.25061699999999998 0.99309099999999995 0.115728 0.019414399999999998 +-0.272899 -0.0105462 -0.16916300000000001 0.96282199999999996 0.26996900000000001 -0.0095448300000000007 +0.244253 -0.0359885 -0.13914199999999999 -0.31612000000000001 0.94871899999999998 0 +-0.27401999999999999 -0.00387959 -0.11157499999999999 0.99771299999999996 0.065393199999999999 -0.017077599999999998 +-0.25000099999999997 -0.038945 -0.29234599999999999 0.46751100000000001 0.88395000000000001 0.0081171799999999999 +-0.27387899999999998 0.0054862399999999999 -0.058835800000000001 0.98965499999999995 -0.143453 0.0021416299999999998 +-0.20993700000000001 -0.0381991 -0.170484 -0.47376800000000002 0.88062300000000004 -0.0068994099999999999 +-0.193914 -0.023072200000000001 -0.29112100000000002 0.83585299999999996 -0.54895300000000002 0 +-0.20183000000000001 -0.032472099999999997 -0.31633299999999998 -0.67273799999999995 0.73972599999999999 0.0151285 +0.19304099999999999 0.0072361300000000003 -0.241034 0.99556800000000001 -0.093765299999999996 0.0072247600000000002 +-0.20124300000000001 -0.0318844 -0.22142100000000001 -0.67435699999999998 0.73800900000000003 0.0242133 +0.267457 0.0111182 -0.081862900000000002 0.94626399999999999 0.322764 -0.0202028 +-0.18742500000000001 0.00280672 -0.138964 0.99891700000000005 0.044618900000000003 -0.013225000000000001 +0.26876 0.0053750999999999998 -0.29145700000000002 0.99057200000000001 0.13698199999999999 -0.00152842 +-0.19148100000000001 0.018496100000000001 -0.28673599999999999 0.90302700000000002 0.42954999999999999 -0.0052990299999999997 +-0.187254 -0.00085504400000000001 -0.092802800000000005 0.99986900000000001 -0.0149847 0.0060496999999999999 +0.21141299999999999 0.033221399999999998 -0.034522999999999998 -0.50677899999999998 0.86156200000000005 -0.0297638 +-0.20868300000000001 -0.037546400000000001 -0.17858399999999999 -0.476713 0.87875300000000001 0.0231833 +-0.27412799999999998 -0.00263745 -0.060189800000000002 0.99879200000000001 0.0436256 -0.0226026 +-0.27410699999999999 -0.0028797900000000001 -0.21013399999999999 0.99818399999999996 0.060060200000000001 -0.0045934599999999997 +0.265878 -0.0153712 -0.29745899999999997 0.91371100000000005 -0.40631899999999999 -0.0060346999999999996 +0.254274 -0.0303159 -0.23649200000000001 -0.59911400000000004 0.80066400000000004 0 +-0.24860299999999999 -0.039596800000000001 -0.11377 0.40994199999999997 0.91210999999999998 0.0017359599999999999 +0.24370600000000001 0.036200299999999998 -0.065351199999999998 0.37701099999999999 0.926207 0.0019551199999999999 +-0.268063 -0.0224455 -0.055516700000000002 0.85168999999999995 0.52396100000000001 -0.0093923800000000005 +-0.27220899999999998 -0.01312 -0.296601 0.96660000000000001 0.25628200000000001 -0.0022378400000000001 +-0.244368 -0.041312000000000001 -0.182009 0.35203899999999999 0.93596500000000005 -0.0062381900000000002 +-0.220834 0.042293499999999998 -0.054118800000000002 0.30143799999999998 0.95347000000000004 -0.0055491300000000002 +-0.19026000000000001 -0.015878300000000001 -0.266121 0.92181100000000005 -0.38756600000000002 0.0075791000000000001 +-0.25901099999999999 0.033168900000000001 -0.206506 -0.64303999999999994 0.76582700000000004 0.002895 +-0.21681500000000001 0.041216500000000003 -0.10290299999999999 0.33047399999999999 0.94378899999999999 0.0070053499999999996 +0.19246099999999999 0.0017476 -0.029747699999999998 0.99778699999999998 -0.053915499999999998 -0.038908999999999999 +-0.24826999999999999 -0.0397524 -0.056313500000000002 0.408667 0.91212700000000002 0.031880600000000002 +0.26806000000000002 -0.0088670599999999995 -0.0126455 0.96260199999999996 -0.27068199999999998 -0.011312900000000001 +-0.26916899999999999 -0.020401099999999998 -0.288109 0.87491600000000003 0.48415999999999998 0.0105196 +0.20294799999999999 0.026364800000000001 -0.0573812 -0.69029600000000002 0.72316100000000005 0.023010800000000001 +0.20955299999999999 0.031918500000000002 -0.19015899999999999 -0.57463900000000001 0.818407 0 +-0.187276 -0.00110778 -0.241284 0.99963599999999997 -0.0266839 0.0039530700000000004 +-0.271125 0.016206100000000001 -0.29374 0.93099900000000002 -0.36474000000000001 0.014334899999999999 +0.26531100000000002 0.016585599999999999 -0.0824318 0.91789900000000002 0.396096 -0.023886299999999999 +0.26694099999999998 0.013041199999999999 -0.28450900000000001 0.943106 0.33213500000000001 -0.0154217 +-0.20238 -0.033022099999999999 -0.32367400000000002 -0.63846700000000001 0.764961 -0.084815299999999996 +0.26152900000000001 0.022870100000000001 -0.114838 0.79353300000000004 0.60852499999999998 -0.0016209600000000001 +-0.26785199999999998 0.022747699999999999 -0.29231499999999999 0.856271 -0.51650399999999996 -0.0049029900000000003 +-0.22779099999999999 -0.043329199999999998 -0.066878599999999996 -0.112055 0.99365000000000003 0.0101224 +-0.23069500000000001 0.043583400000000001 -0.26116499999999998 0.0109421 0.99987099999999995 0.011736099999999999 +0.19577800000000001 0.0156229 -0.31153799999999998 0.90361800000000003 -0.42787900000000001 0.0198313 +0.26854699999999998 -0.0070474300000000004 -0.225384 0.98339100000000002 -0.17895900000000001 -0.030261400000000001 +0.202181 0.025597999999999999 -0.087060499999999999 0.74779700000000005 -0.66375700000000004 -0.0150575 +-0.26830599999999999 0.022099299999999999 -0.27465699999999998 0.84148299999999998 -0.54025900000000004 0.0051224399999999998 +-0.26919500000000002 -0.020346 -0.25211099999999997 0.86780199999999996 0.496589 -0.017869900000000001 +-0.21651200000000001 -0.041135600000000001 -0.13473399999999999 -0.33688600000000002 0.94152800000000003 -0.0057178000000000003 +-0.27389799999999997 -0.0052688700000000002 -0.115762 0.98883200000000004 0.14896100000000001 -0.0047429300000000002 +-0.27370899999999998 -0.0074355799999999998 -0.13839000000000001 0.98285199999999995 0.18418799999999999 0.0088121999999999992 +0.26072499999999998 -0.024019200000000001 -0.16924400000000001 0.79150799999999999 -0.61111099999999996 0.0076301199999999998 +0.19405900000000001 -0.011033599999999999 -0.024968500000000001 0.92211100000000001 0.386818 0.0090735699999999996 +-0.187391 0.00241764 -0.15936600000000001 0.99864299999999995 0.052072 -0.0012896100000000001 +0.197656 0.019509800000000001 -0.29489500000000002 0.85973100000000002 -0.51074699999999995 0 +-0.27216899999999999 0.0132703 -0.059446300000000001 0.95230800000000004 -0.30503200000000003 0.0080734599999999993 +0.23518 0.038075699999999997 -0.242644 0.129299 0.99148999999999998 0.015111899999999999 +-0.19192999999999999 0.0194586 -0.047931500000000002 0.90987300000000004 0.41044399999999998 0.060550300000000001 +-0.25409799999999999 0.036675800000000001 -0.211145 -0.55951099999999998 0.82881899999999997 0.0023995100000000001 +0.192469 -0.00184593 -0.22381300000000001 0.99770599999999998 0.065720500000000001 0.0162319 +-0.235426 0.043182400000000003 -0.20056299999999999 -0.090334899999999996 0.99586699999999995 -0.0094531100000000007 +-0.274113 -0.0028070999999999999 -0.074745300000000001 0.99384700000000004 0.110598 0.0060521000000000004 +0.26377400000000001 -0.019664999999999998 -0.051128699999999999 0.88734500000000005 -0.46091599999999999 -0.0132233 +-0.19767299999999999 0.028314300000000001 -0.15051999999999999 0.78178199999999998 0.62308600000000003 -0.024097500000000001 +0.209288 0.031732900000000001 -0.185803 -0.55248900000000001 0.83346699999999996 0.0094181999999999998 +-0.23202800000000001 0.0434796 -0.31444899999999998 -0.023128200000000002 0.99968900000000005 -0.0093373499999999995 +0.19448399999999999 -0.0126214 -0.191746 0.95016900000000004 0.311693 -0.0051108300000000002 +-0.26015199999999999 -0.032027699999999999 -0.12984699999999999 0.67794200000000004 0.73456699999999997 0.028411499999999999 +-0.18839600000000001 -0.0096374500000000005 -0.099290299999999998 0.97997100000000004 -0.19869400000000001 -0.013358099999999999 +-0.27196900000000002 0.0140175 -0.056176499999999997 0.94480399999999998 -0.32763500000000001 0 +-0.26793600000000001 0.022627100000000001 -0.16050500000000001 0.88581900000000002 -0.46392600000000001 -0.0099288499999999995 +0.26347300000000001 0.0200941 -0.028947400000000002 0.85883100000000001 0.51223300000000005 -0.0051157900000000003 +-0.191855 0.019297499999999999 -0.114048 0.89805900000000005 0.43970900000000002 -0.012042300000000001 +0.26147199999999998 -0.022952299999999998 -0.140013 0.776119 -0.63013600000000003 0.023845600000000002 +0.21739 -0.036037100000000002 -0.289464 0.33895799999999998 0.94078899999999999 0.00476517 +-0.189583 0.0140704 -0.191939 0.94775500000000001 0.318996 0.00134238 +-0.26368399999999997 0.028495800000000002 -0.25058200000000003 0.76898200000000005 -0.63926400000000005 -0.0028237599999999998 +0.240289 -0.037116000000000003 -0.073601299999999995 -0.27780300000000002 0.96051200000000003 0.015544000000000001 +-0.27398099999999997 0.0043200699999999996 -0.24481 0.99733700000000003 -0.072786500000000004 0.0046162800000000004 +0.20010700000000001 0.0230105 -0.14757500000000001 0.79000400000000004 -0.61304099999999995 -0.0085885300000000005 +0.19789000000000001 -0.019843599999999999 -0.085225999999999996 0.85436800000000002 0.51905800000000002 -0.0251994 +0.221057 0.037064199999999999 -0.20149400000000001 -0.23629 0.97167999999999999 -0.0023269300000000001 +0.20449100000000001 -0.027907700000000001 -0.038703599999999998 0.66046199999999999 0.75078800000000001 0.0103354 +-0.27376499999999998 0.0067869799999999997 -0.26188400000000001 0.985792 -0.16792199999999999 -0.00395751 +0.25233 0.031677200000000003 -0.117072 0.59299000000000002 0.80519799999999997 -0.0043170099999999996 +-0.18814900000000001 0.0087146800000000007 -0.097338300000000003 0.98047499999999999 0.196572 0.0053267000000000002 +-0.20300299999999999 0.033568599999999997 -0.061245300000000003 0.62302100000000005 0.78217300000000001 -0.0071391199999999997 +0.192527 0.0025013499999999998 -0.24937100000000001 0.99700100000000003 -0.076308799999999996 -0.012907999999999999 +-0.22601499999999999 0.043173900000000001 -0.30224800000000002 0.041779999999999998 0.99904400000000004 -0.012858 +0.26643899999999998 -0.014167300000000001 -0.19991 0.93193700000000002 -0.36249999999999999 -0.0093412600000000005 +-0.21712799999999999 -0.041300499999999997 -0.26580799999999999 -0.315104 0.94904500000000003 -0.0047878 +0.24390300000000001 0.036147499999999999 -0.049127299999999999 0.35242200000000001 0.93576499999999996 -0.0119034 +0.26797199999999999 0.0091927199999999997 -0.12406200000000001 0.97450599999999998 0.22420300000000001 0.0084728700000000004 +-0.27427400000000002 0.00097499700000000002 -0.120252 0.99980000000000002 -0.0198652 -0.0025046399999999998 +-0.18765899999999999 -0.0054781200000000004 -0.288101 0.99264399999999997 -0.120958 -0.0052234999999999998 +-0.20195299999999999 -0.032594100000000001 -0.189556 -0.66528100000000001 0.74658400000000003 -0.0037065000000000002 +-0.25232199999999999 0.037862899999999998 -0.29696099999999997 -0.50210999999999995 0.86466500000000002 -0.0154666 +-0.210566 0.038492100000000001 -0.29120600000000002 0.47141499999999997 0.88188999999999995 -0.0062233999999999996 +-0.265567 0.026011200000000002 -0.22517000000000001 0.79955299999999996 -0.60058400000000001 -0.0036613499999999998 +-0.20791999999999999 -0.037011700000000002 -0.32220300000000002 -0.53145799999999999 0.84708499999999998 0 +0.26110699999999998 0.023473000000000001 -0.17144400000000001 0.80684999999999996 0.59034900000000001 -0.021950799999999999 +0.21242900000000001 -0.033723900000000001 -0.25376100000000001 0.50607100000000005 0.862371 -0.014441900000000001 +0.267596 -0.010597000000000001 -0.026043899999999998 0.96749399999999997 -0.25154300000000002 0.026115300000000001 +-0.22827500000000001 0.043371600000000003 -0.12307800000000001 0.048706300000000001 0.99880400000000003 -0.00423633 +0.20599300000000001 -0.029409000000000001 -0.19447200000000001 0.66374599999999995 0.74795800000000001 0 +-0.272982 0.010237 -0.19240699999999999 0.97277400000000003 -0.23156199999999999 -0.0095090499999999998 +0.26545000000000002 0.016288299999999999 -0.16913 0.88122100000000003 0.47258800000000001 0.010458500000000001 +0.26868900000000001 -0.0061868899999999996 -0.27094299999999999 0.99032299999999995 -0.137401 0.019511400000000002 +-0.210753 0.038579500000000003 -0.23330500000000001 0.46978500000000001 0.88277899999999998 0.0016536599999999999 +0.21965699999999999 -0.036689300000000001 -0.037252899999999999 0.29726000000000002 0.95474099999999995 -0.010293999999999999 +-0.21925900000000001 -0.041871699999999998 -0.050621600000000003 -0.262299 0.96498399999999995 -0.00206857 +0.20127900000000001 0.024683900000000002 -0.093668199999999993 0.779088 -0.624888 0.050368700000000002 +0.228324 -0.0382476 -0.16261100000000001 0.096128000000000005 0.995367 0.0017107699999999999 +0.21518999999999999 0.035011399999999998 -0.28739599999999998 -0.382156 0.92408699999999999 -0.0045039399999999997 +-0.25649300000000003 -0.034999000000000002 -0.16270499999999999 0.58486300000000002 0.81104799999999999 -0.0116746 +0.25656400000000001 -0.028391199999999998 -0.21799199999999999 -0.67791100000000004 0.73501000000000005 -0.0140254 +0.20111899999999999 0.0244557 -0.23636799999999999 0.71684099999999995 -0.69718899999999995 0.0081763500000000006 +0.26439699999999999 -0.018547600000000001 -0.100272 0.86358999999999997 -0.50416700000000003 -0.0052695900000000002 +-0.24145900000000001 -0.042091299999999998 -0.20232800000000001 0.29747400000000002 0.95465599999999995 0.011849800000000001 +-0.27179300000000001 0.0146719 -0.10524699999999999 0.94081300000000001 -0.33888600000000002 0.00513205 +-0.27382299999999998 -0.0061291599999999998 -0.069331599999999993 0.990456 0.137793 0.0032360100000000001 +0.25005500000000003 -0.033269899999999998 -0.215169 -0.52493800000000002 0.851128 0.0044984700000000001 +-0.26669999999999999 0.0243932 -0.095283400000000004 0.81111500000000003 -0.58488600000000002 0 +-0.26693600000000001 -0.024055099999999999 -0.29261700000000002 0.82987599999999995 0.55793800000000005 0.00321755 +-0.215279 0.040689500000000003 -0.13177700000000001 0.34501199999999999 0.93837400000000004 0.020501399999999999 +-0.27129500000000001 0.0158406 -0.32166899999999998 0.92779699999999998 -0.37165599999999999 0.032614200000000003 +0.204982 -0.028398199999999998 -0.29894700000000002 0.67837000000000003 0.73429900000000004 0.0248582 +-0.18722900000000001 0.00057171999999999995 -0.067315899999999998 0.99935300000000005 0.035383600000000001 0.0063952100000000001 +0.26683800000000002 -0.013312299999999999 -0.259156 0.91752100000000003 -0.397588 0.0089075200000000004 +0.21904399999999999 0.036524899999999999 -0.30648999999999998 -0.33121099999999998 0.94355500000000003 0.00188178 +0.20402000000000001 0.027436800000000001 -0.28154299999999999 0.70946799999999999 -0.70473799999999998 0 +-0.188253 0.0091034199999999992 -0.051428000000000001 0.97054700000000005 0.24091299999999999 0 +0.25720100000000001 0.0277536 -0.293742 0.66053300000000004 0.75079700000000005 0 +0.19442899999999999 0.0124169 -0.050905199999999998 0.92427999999999999 -0.38165100000000002 -0.0070530999999999996 +-0.188531 0.0101405 -0.25036900000000001 0.96035300000000001 0.27849600000000002 -0.0127546 +0.21600900000000001 -0.035393300000000003 -0.062231799999999997 0.43537300000000001 0.900231 0.0058980400000000002 +0.24390600000000001 0.0361468 -0.075246400000000005 0.328318 0.94449000000000005 -0.012071399999999999 +0.20339099999999999 -0.026806900000000002 -0.28027600000000003 0.72422799999999998 0.68952999999999998 0.0064945200000000002 +0.19921900000000001 0.021742000000000001 -0.057344199999999998 0.85392800000000002 -0.520069 0.018306300000000001 +-0.23882800000000001 -0.042796399999999998 -0.157998 0.213417 0.97530499999999998 0.056865899999999997 +0.26386500000000002 -0.019534699999999999 -0.17260300000000001 0.85634999999999994 -0.51620900000000003 -0.0138719 +0.25162200000000001 -0.032172600000000003 -0.15942400000000001 -0.51444900000000005 0.85747099999999998 0.0093141500000000002 +0.259299 -0.025655500000000001 -0.28824899999999998 -0.68806299999999998 0.72561600000000004 -0.0071064300000000004 +0.19378400000000001 0.010009000000000001 -0.091003899999999999 0.96275500000000003 -0.26740000000000003 0.039997400000000002 +0.19379399999999999 -0.010043699999999999 -0.16927300000000001 0.956677 0.291153 0 +0.195073 0.014111800000000001 -0.0816384 0.90252900000000003 -0.42998199999999998 0.023604799999999999 +-0.21701500000000001 0.0412702 -0.14066500000000001 0.35319600000000001 0.93554899999999996 0 +0.26871400000000001 -0.0058978299999999997 -0.039897099999999998 0.98348500000000005 -0.178588 -0.029397599999999999 +0.20630499999999999 -0.029643800000000001 -0.020545600000000001 0.61624400000000001 0.78700000000000003 -0.029563800000000001 +0.26874300000000001 -0.0055729600000000001 -0.16924 0.98209000000000002 -0.18713199999999999 0.021952800000000001 +-0.18937200000000001 0.013280200000000001 -0.21668899999999999 0.96285799999999999 0.26904400000000001 -0.022815499999999999 +0.19559399999999999 0.015228 -0.052831900000000001 0.90754900000000005 -0.41985099999999997 -0.0088962999999999993 +-0.27418999999999999 -0.0019294 -0.199736 0.99968000000000001 0.0240568 0.0078440200000000002 +0.257525 0.027430300000000001 -0.13816999999999999 0.70533599999999996 0.70887299999999998 0 +0.260129 -0.024825199999999999 -0.28520800000000002 0.75100900000000004 -0.65993400000000002 0.021723300000000001 +-0.26027600000000001 0.031903500000000001 -0.14513000000000001 -0.65846899999999997 0.75250499999999998 -0.0124566 +-0.19003100000000001 0.0153863 -0.26925900000000003 0.94791899999999996 0.31849300000000003 -0.0033432700000000002 +-0.245062 0.041126000000000003 -0.24027699999999999 -0.32347799999999999 0.94609600000000005 -0.0162752 +0.26433099999999998 0.0186886 -0.087940699999999997 0.87672399999999995 0.480993 0.0012250200000000001 +-0.25296299999999999 0.037470499999999997 -0.23780499999999999 -0.47171999999999997 0.88148700000000002 -0.021449099999999999 +0.25682300000000002 0.028132399999999998 -0.039130199999999997 0.67504799999999998 0.73765499999999995 -0.0132357 +0.26835999999999999 -0.0077447000000000002 -0.108461 0.975136 -0.221606 0 +0.26835999999999999 0.0077469799999999997 -0.32008900000000001 0.97407999999999995 0.22498099999999999 0.023499699999999998 +-0.21615300000000001 0.041039199999999998 -0.223362 0.29440499999999997 0.95561799999999997 0.010981100000000001 +-0.21728800000000001 -0.041343499999999998 -0.19689999999999999 -0.34065099999999998 0.94018699999999999 0.0023679999999999999 +-0.19136600000000001 -0.018249100000000001 -0.30119499999999999 0.91686400000000001 -0.39865899999999999 -0.020757999999999999 +0.21438599999999999 0.034636399999999998 -0.22803200000000001 -0.41092400000000001 0.91114899999999999 0.030812699999999998 +0.244363 -0.035937299999999998 -0.025208100000000001 -0.38826100000000002 0.92147000000000001 0.0121181 +0.20644999999999999 0.029745600000000001 -0.13001599999999999 -0.620309 0.78435600000000005 0.0017924200000000001 +-0.22007199999999999 0.042089300000000003 -0.164462 0.27416600000000002 0.96167899999999995 -0.0024253199999999999 +0.22900000000000001 -0.038306800000000002 -0.17999699999999999 0.067965800000000007 0.99753099999999995 -0.017658900000000002 +-0.220556 0.042219 -0.120243 0.19681699999999999 0.97998300000000005 0.029942099999999999 +0.25409300000000001 -0.030443000000000001 -0.206682 -0.65227800000000002 0.757934 -0.0083577600000000005 +0.22592300000000001 0.038037500000000002 -0.220273 -0.14398 0.98852700000000004 0.045644900000000002 +0.26809300000000003 -0.00874342 -0.051143399999999999 0.95625300000000002 -0.29191499999999998 0.019123100000000001 +-0.19600999999999999 -0.0260652 -0.060146999999999999 0.81734499999999999 -0.57606800000000002 0.0096561600000000004 +0.20544899999999999 -0.028865399999999999 -0.055816400000000002 0.68239499999999997 0.73097500000000004 0.0036618100000000002 +-0.22256400000000001 0.042757200000000002 -0.0539006 0.22170100000000001 0.97509599999999996 0.0060261200000000003 +-0.231627 -0.043514700000000003 -0.13370799999999999 -0.0173659 0.99968000000000001 0.0184063 +0.250247 -0.033136100000000002 -0.24406900000000001 -0.50026599999999999 0.86587000000000003 -0.0018722000000000001 +-0.22076699999999999 -0.042275600000000003 -0.26437500000000003 -0.225661 0.97406599999999999 0.016538799999999999 +-0.23812 -0.042946699999999997 -0.32611099999999998 0.114639 0.97500600000000004 -0.19031600000000001 +-0.231681 0.04351 -0.19608800000000001 -0.033582099999999997 0.99942699999999995 -0.0043144000000000004 +-0.27394499999999999 -0.0047376099999999997 -0.084428500000000004 0.992178 0.12482799999999999 0.0010070299999999999 +0.228349 0.038249699999999998 -0.064336599999999994 -0.111318 0.99373900000000004 0.0095546099999999998 +-0.18945200000000001 0.0135785 -0.24390600000000001 0.94989000000000001 0.31257699999999999 0.00206077 +0.248501 0.034007799999999998 -0.30732500000000001 0.40938400000000003 0.91190700000000002 -0.028806399999999999 +-0.188997 -0.011879600000000001 -0.18746599999999999 0.96131900000000003 -0.275204 -0.0113794 +0.201515 0.024931700000000001 -0.271177 0.76413600000000004 -0.64500999999999997 0.0076444499999999997 +-0.19683800000000001 -0.0272477 -0.063794600000000007 0.808064 -0.58909500000000004 0 +-0.27389400000000003 -0.0053179100000000003 -0.208041 0.993421 0.114491 -0.0027476800000000002 +-0.189084 0.0122066 -0.121782 0.96698700000000004 0.25455800000000001 0.0116364 +-0.20808499999999999 -0.0371277 -0.29619000000000001 -0.53026899999999999 0.84773399999999999 0.012719599999999999 +0.24623 0.035066399999999998 -0.13136 0.38564799999999999 0.92227199999999998 0.026255000000000001 +-0.18973999999999999 -0.014655100000000001 -0.058373500000000002 0.93779599999999996 -0.34713100000000002 0.0062519000000000003 +-0.19269 -0.021089 -0.19761799999999999 0.87170000000000003 -0.49002200000000001 0.0041723899999999998 +0.26147399999999998 0.022949600000000001 -0.12056500000000001 0.790686 0.612174 -0.0076248399999999999 +-0.22992899999999999 -0.043516199999999998 -0.082008499999999998 -0.072231600000000007 0.99715399999999998 0.0216084 +0.211974 0.033512 -0.033071499999999997 -0.48835699999999999 0.87253700000000001 -0.0136683 +0.26890999999999998 0.0036619399999999998 -0.075195799999999993 0.99436500000000005 0.105812 -0.0064336999999999997 +0.26324399999999998 0.0204218 -0.242421 0.87338499999999997 0.48686600000000002 0.0126385 +0.243337 -0.0362993 -0.21380299999999999 -0.31401400000000002 0.94940899999999995 -0.0041302200000000004 +0.25505 -0.029773000000000001 -0.21934799999999999 -0.63153400000000004 0.77534400000000003 -0.0024697500000000002 +0.19236600000000001 0.00065830900000000004 -0.277117 0.99900500000000003 0.042217299999999999 0.014353899999999999 +0.251697 -0.032120700000000002 -0.226356 -0.55212300000000003 0.833561 0.018327199999999998 +-0.26275500000000002 -0.029425300000000001 -0.24299999999999999 0.76094600000000001 0.64858400000000005 -0.017336600000000001 +-0.23632500000000001 -0.043103700000000002 -0.25777 0.082050999999999999 0.99655199999999999 -0.0123331 +-0.27389599999999997 -0.0052970200000000004 -0.21201 0.99222999999999995 0.12417499999999999 -0.0077521999999999999 +0.19336200000000001 0.0084326899999999996 -0.197466 0.97799499999999995 -0.207153 -0.024782200000000001 +-0.19602900000000001 0.026092600000000001 -0.23611799999999999 0.80269100000000004 0.59607900000000003 -0.019403199999999999 +0.194045 0.0109835 -0.16950200000000001 0.95404500000000003 -0.29957899999999998 0.0070887199999999997 +0.245006 -0.035637299999999997 -0.13259699999999999 -0.36653400000000003 0.93034600000000001 -0.010421400000000001 +0.19728599999999999 -0.018856299999999999 -0.11815100000000001 0.86354299999999995 0.504247 -0.0053690999999999999 +0.25115500000000002 0.032499599999999997 -0.062291899999999997 0.51105699999999998 0.85954699999999995 0.00084018000000000005 +0.268789 0.00505128 -0.13069600000000001 0.99541800000000003 0.095540700000000006 0.0037879900000000002 +-0.25485799999999997 -0.036143799999999997 -0.085632 0.567994 0.82273799999999997 -0.0220302 +0.26745200000000002 0.0111363 -0.26636300000000002 0.95982800000000001 0.28055999999999998 -0.0040195400000000003 +-0.22156300000000001 -0.042488999999999999 -0.23982000000000001 -0.23886499999999999 0.97104100000000004 -0.0048492600000000002 +0.19247400000000001 0.00190018 -0.15848000000000001 0.99771900000000002 -0.067440100000000003 0.0029234899999999999 +-0.273563 -0.0080685199999999992 -0.107081 0.98510399999999998 0.17191899999999999 -0.0037593499999999998 +-0.19456200000000001 -0.023998100000000001 -0.078856800000000005 0.84331100000000003 -0.537107 0.018496800000000001 +0.22774 0.038196500000000001 -0.160441 -0.066521399999999994 0.99747600000000003 -0.024822199999999999 +-0.198606 0.0292474 -0.196849 0.749421 0.66208699999999998 -0.0029171100000000001 +-0.21179500000000001 0.039065299999999997 -0.221828 0.43311300000000003 0.90132900000000005 -0.0043403499999999998 +-0.192742 0.021200900000000002 -0.14507600000000001 0.86123400000000006 0.50801600000000002 0.014006599999999999 +-0.18721299999999999 0.00038641899999999999 -0.288464 0.99995299999999998 -0.0094097199999999999 -0.0023336099999999999 +-0.25231399999999998 -0.037866299999999999 -0.160966 0.52549000000000001 0.85074000000000005 -0.0100844 +-0.19095899999999999 0.017378000000000001 -0.15731999999999999 0.91014799999999996 0.413941 0.0168185 +-0.262104 0.030076100000000001 -0.090114899999999998 0.71885299999999996 -0.69516199999999995 0 +-0.22761700000000001 0.043313999999999998 -0.13700999999999999 0.080643199999999998 0.99663900000000005 0.014364399999999999 +0.192352 -0.00050818300000000005 -0.145229 0.99961199999999995 0.0035677899999999999 -0.027623200000000001 +0.26455400000000001 0.018210400000000002 -0.243176 0.87549999999999994 0.48319200000000001 0.0049514600000000004 +0.21190200000000001 0.033478599999999997 -0.051107800000000002 -0.45631500000000003 0.88965099999999997 0.017256799999999999 +-0.25877600000000001 0.033400100000000002 -0.185668 -0.65607400000000005 0.754355 0.022692299999999999 +-0.188111 -0.0085722400000000001 -0.228411 0.95933900000000005 -0.28219499999999997 0.0057924500000000002 +-0.18978999999999999 0.0148399 -0.096271899999999994 0.95637899999999998 0.29210000000000003 -0.0041749700000000001 +-0.249059 -0.0393844 -0.19962199999999999 0.45182600000000001 0.89102800000000004 -0.043837899999999999 +0.26842500000000002 -0.0075037200000000002 -0.20347199999999999 0.98516400000000004 -0.17061299999999999 0.018505000000000001 +-0.216724 0.041192100000000002 -0.092321700000000007 0.34160000000000001 0.93981499999999996 -0.0075105399999999996 +-0.19175500000000001 0.019083099999999999 -0.070363099999999998 0.91084299999999996 0.41266700000000001 0.0083981999999999998 +0.25046800000000002 -0.032980700000000002 -0.116076 -0.51318600000000003 0.85517699999999996 0.072893600000000003 +-0.18781900000000001 -0.0073045200000000001 -0.046667300000000002 0.97520399999999996 -0.219586 0.027557499999999999 +-0.19935600000000001 -0.029997699999999999 -0.149477 0.73116800000000004 -0.68213299999999999 0.0093612699999999997 +-0.20049600000000001 0.031137700000000001 -0.22209999999999999 0.67185799999999996 0.74048800000000004 -0.016849699999999999 +-0.19167300000000001 -0.0189076 -0.077681 0.90265099999999998 -0.43032999999999999 -0.0061119199999999999 +0.257498 -0.027457100000000002 -0.13003100000000001 0.73833899999999997 -0.67438399999999998 -0.0078823000000000001 +-0.18731300000000001 0.00152695 -0.25866499999999998 0.99946599999999997 0.027294300000000001 0.017984799999999999 +-0.19051199999999999 0.016419199999999998 -0.092400200000000002 0.93890499999999999 0.34404400000000002 0.0095154200000000001 +-0.21542600000000001 -0.040758299999999997 -0.26707599999999998 -0.34920099999999998 0.93700700000000003 -0.0087400199999999994 +-0.26387100000000002 0.028309399999999998 -0.26011800000000002 0.76177399999999995 -0.64766900000000005 0.014978200000000001 +0.19690099999999999 0.0180296 -0.30899700000000002 0.85632600000000003 -0.51623799999999997 -0.0142845 +-0.23747599999999999 -0.043003 -0.142596 0.209706 0.97773399999999999 -0.0077660100000000003 +-0.2215 0.042472000000000003 -0.24233099999999999 0.224521 0.97407900000000003 -0.027589300000000001 +0.19307099999999999 -0.0073464400000000001 -0.13664899999999999 0.97319500000000003 0.22786400000000001 -0.031129199999999999 +-0.23103599999999999 0.043566399999999998 -0.120333 0.0067600200000000003 0.99997599999999998 0.00115204 +0.223803 -0.037799899999999997 -0.23879300000000001 0.22419 0.97448699999999999 -0.0106476 +-0.249116 0.039357900000000001 -0.28992299999999999 -0.42413200000000001 0.90525800000000001 0.024893599999999998 +0.25938600000000001 -0.025568899999999999 -0.145619 0.755413 -0.65524899999999997 0 +0.25090299999999999 0.032676700000000003 -0.089621099999999995 0.53957500000000003 0.84165699999999999 -0.0217305 +-0.200101 0.030741899999999999 -0.13670099999999999 0.71403799999999995 0.69996000000000003 0.014353899999999999 +0.25757099999999999 -0.027383899999999999 -0.019826300000000002 0.72120099999999998 -0.69272100000000003 0.0025963100000000001 +0.19264000000000001 -0.0037932500000000002 -0.18179300000000001 0.99642200000000003 0.084512799999999999 0.00121645 +-0.193719 0.022793799999999999 -0.300062 0.86140300000000003 0.50790999999999997 0.0036451299999999999 +0.26900200000000002 0.0026182100000000002 -0.184535 0.99946400000000002 0.0318067 -0.0076978400000000001 +-0.19603300000000001 -0.026098799999999998 -0.12879299999999999 0.77828399999999998 -0.62780000000000002 0.011919900000000001 +0.222686 -0.037500800000000001 -0.071258299999999997 0.247834 0.96870599999999996 -0.013650900000000001 +-0.214089 0.040134999999999997 -0.304537 0.37370700000000001 0.92752900000000005 0.0058435900000000001 +-0.19944799999999999 0.030089399999999999 -0.104767 0.72633499999999995 0.68733 -0.0038512799999999999 +0.193222 -0.0079109000000000002 -0.21820700000000001 0.986954 0.16051599999999999 0.012526900000000001 +0.25988600000000001 -0.025068300000000002 -0.120953 0.727549 -0.68605000000000005 0.0028761099999999999 +-0.270175 0.018243499999999999 -0.213091 0.90621499999999999 -0.42250599999999999 0.016220700000000001 +0.193548 0.0091271100000000008 -0.16757 0.958928 -0.28365000000000001 0 +-0.269675 0.019316300000000002 -0.16692299999999999 0.90125699999999997 -0.43318800000000002 -0.0091810099999999999 +-0.21989900000000001 -0.042043200000000003 -0.133326 -0.227441 0.97378399999999998 0.0038515300000000001 +0.25360500000000002 0.0307844 -0.17063600000000001 0.56272999999999995 0.82586400000000004 0.035825599999999999 +0.198273 -0.020390700000000001 -0.16086300000000001 0.868201 0.495502 -0.026537100000000001 +-0.26855200000000001 -0.021724799999999999 -0.13162299999999999 0.89674699999999996 0.44253300000000001 -0.0032210400000000001 +0.205762 -0.0291778 -0.18728 0.63555799999999996 0.77196200000000004 0.0118619 +-0.188171 0.0087960599999999996 -0.24918299999999999 0.98729199999999995 0.15884699999999999 0.0047453 +0.19405500000000001 0.0110207 -0.20615600000000001 0.95794100000000004 -0.28670299999999999 0.012297000000000001 +0.26885300000000001 -0.0043197499999999998 -0.030685 0.99210500000000001 -0.12528800000000001 0.0055962499999999997 +-0.21898000000000001 -0.041796899999999998 -0.054988599999999999 -0.25720100000000001 0.96625300000000003 -0.0142326 +-0.18809000000000001 0.0084951000000000002 -0.28847499999999998 0.97742399999999996 0.21113899999999999 -0.0079563600000000009 +0.22278800000000001 0.037527999999999999 -0.051722600000000001 -0.237424 0.97136900000000004 -0.0084626100000000006 +0.20141200000000001 0.024828599999999999 -0.084842500000000001 0.75520500000000002 -0.65537800000000002 -0.01206 +0.192688 0.0043511499999999998 -0.325465 0.982765 0.15241299999999999 -0.104614 +0.19961400000000001 0.0223053 -0.050854999999999997 0.80847400000000003 -0.58853100000000003 0 +0.26896599999999998 -0.00303053 -0.080768699999999999 0.99273199999999995 -0.106404 0.056233100000000001 +-0.20483100000000001 0.034849100000000001 -0.054004900000000002 0.56184999999999996 0.82720899999999997 -0.0070089899999999997 +0.269038 0.0022055 -0.098134600000000002 0.99992999999999999 0.0034597299999999998 0.0112794 +0.22980200000000001 0.038376899999999999 -0.25851099999999999 -0.019442399999999999 0.99958000000000002 0.021493999999999999 +-0.21470700000000001 0.040422800000000002 -0.15565300000000001 0.32486300000000001 0.94573700000000005 -0.0067296400000000003 +-0.21397099999999999 -0.040079900000000002 -0.096661700000000003 -0.441882 0.89706799999999998 0.0031848800000000002 +0.22667799999999999 -0.038103499999999998 -0.24265400000000001 0.110069 0.99391600000000002 -0.00405901 +-0.24557499999999999 0.040988499999999997 -0.16936399999999999 -0.38692199999999999 0.92210000000000003 0.0047735399999999997 +-0.25520100000000001 -0.035903299999999999 -0.181533 0.58363299999999996 0.81200399999999995 0.0046794200000000001 +-0.247671 0.040031600000000001 -0.184947 -0.38387300000000002 0.92338600000000004 0 +0.22567899999999999 -0.038016099999999997 -0.053772300000000002 0.142791 0.98974499999999999 0.0039096299999999999 +-0.271536 -0.0153248 -0.112925 0.94372500000000004 0.33071400000000001 0.0034378999999999998 +-0.26881699999999997 -0.021155400000000001 -0.113134 0.85998200000000002 0.51031000000000004 -0.0037191500000000001 +-0.191021 -0.017510000000000001 -0.15174799999999999 0.91006200000000004 -0.414433 0.0057462800000000003 +0.21945700000000001 -0.0366357 -0.104591 0.249971 0.96815700000000005 0.0136674 +0.25184000000000001 -0.032020600000000003 -0.113496 -0.56872500000000004 0.82219600000000004 0.023349700000000001 +0.26873900000000001 -0.0056221099999999996 -0.14852399999999999 0.990985 -0.13225700000000001 0.021395600000000001 +0.26865299999999998 -0.0065973899999999999 -0.0913601 0.98731999999999998 -0.158553 -0.0077815499999999999 +0.19886400000000001 -0.021234699999999999 -0.055356299999999997 0.82491599999999998 0.56525499999999995 0.00073734199999999999 +0.19725400000000001 0.0187879 -0.274922 0.880166 -0.47413300000000003 -0.0225075 +0.22036 -0.036877600000000003 -0.052310700000000002 0.26748 0.96356299999999995 -0.000874689 +0.264349 -0.018649800000000001 -0.0531236 0.88871699999999998 -0.45813999999999999 -0.01703 +-0.26718700000000001 -0.0236975 -0.313386 0.845078 0.53464400000000001 0 +0.20263700000000001 0.026053900000000001 -0.22250200000000001 0.730796 -0.68232199999999998 -0.019344199999999999 +-0.198431 0.029072600000000001 -0.17566699999999999 0.76810299999999998 0.64029199999999997 0.0066645000000000003 +-0.187636 -0.0052201499999999998 -0.18926499999999999 0.99101399999999995 -0.13312599999999999 0.0129724 +0.23797599999999999 0.0377358 -0.11495900000000001 0.18956300000000001 0.98183600000000004 0.0079671399999999993 +-0.27354800000000001 0.0081247799999999998 -0.25445800000000002 0.96618999999999999 -0.25774000000000002 -0.0068204900000000002 +0.256631 -0.0283244 -0.25256099999999998 -0.66793599999999997 0.74417599999999995 -0.0080051400000000009 +0.26103599999999999 -0.023575200000000001 -0.052204199999999999 0.77883599999999997 -0.627166 -0.0087448500000000002 +0.24538299999999999 0.0354615 -0.238728 0.36509599999999998 0.93096500000000004 0.0029586500000000002 +0.21180299999999999 0.033432400000000001 -0.230994 -0.49213400000000002 0.87051599999999996 0.0024640399999999998 +-0.24751699999999999 0.040103399999999997 -0.277314 -0.35176800000000003 0.936087 0 +0.23144899999999999 0.038401999999999999 -0.15054000000000001 0.0135085 0.99988100000000002 0.00738735 +-0.20211899999999999 -0.032760200000000003 -0.1118 -0.68554700000000002 0.727599 -0.024992400000000001 +0.23302800000000001 -0.038263800000000001 -0.275723 -0.096711099999999994 0.995282 -0.0077595199999999998 +0.26672099999999999 -0.013563 -0.16126799999999999 0.93382299999999996 -0.35766399999999998 0.0070842800000000001 +-0.22528599999999999 -0.043110099999999998 -0.13688600000000001 -0.109918 0.99245899999999998 0.054256499999999999 +-0.22813800000000001 0.043359700000000001 -0.27806999999999998 0.065045699999999998 0.99788200000000005 -0.00104189 +0.211003 -0.0329343 -0.28415200000000002 0.52198299999999997 0.85264799999999996 0.0229204 +-0.26704099999999997 0.023905699999999998 -0.186167 0.87542200000000003 -0.48333700000000002 -0.0046134000000000001 +0.24563199999999999 -0.035345599999999998 -0.27079500000000001 -0.39401900000000001 0.91910000000000003 0.0020232900000000001 +0.20764199999999999 0.030580199999999998 -0.17018900000000001 -0.60401400000000005 0.79697399999999996 0 +0.25752700000000001 0.027427699999999999 -0.21615000000000001 0.70512200000000003 0.70863100000000001 -0.0254004 +-0.25888699999999998 0.033292599999999999 -0.190665 -0.66824499999999998 0.74394199999999999 0 +0.215889 -0.035337500000000001 -0.27588400000000002 0.39634000000000003 0.91803100000000004 -0.0115595 +0.26891199999999998 -0.0036368899999999998 -0.085289199999999996 0.99340300000000004 -0.114661 -0.00169633 +0.19232199999999999 0.000157973 -0.0989091 0.99976600000000004 -0.021292100000000001 0.0038692800000000001 +-0.24523800000000001 -0.041078799999999999 -0.19375999999999999 0.26672400000000002 0.96360599999999996 0.0179115 +-0.195741 0.025681499999999999 -0.193305 0.80014700000000005 0.59979700000000002 0.00289865 +-0.19082299999999999 -0.0170844 -0.31776599999999999 0.92500300000000002 -0.37995899999999999 0 +-0.220577 0.0422248 -0.27300099999999999 0.249172 0.96843500000000005 -0.00689969 +-0.188966 -0.0117635 -0.099024399999999999 0.95113999999999999 -0.30814999999999998 0.019418899999999999 +-0.18870500000000001 -0.0107914 -0.286269 0.96696899999999997 -0.25465199999999999 -0.011073100000000001 +-0.189974 0.015265000000000001 -0.063543000000000002 0.94291400000000003 0.332897 -0.0095815099999999997 +-0.19595099999999999 0.025981899999999999 -0.25281900000000002 0.774227 0.63263599999999998 -0.018559800000000001 +-0.19705400000000001 -0.027557000000000002 -0.096653900000000001 0.78702300000000003 -0.61684099999999997 -0.010125 +-0.24722 -0.040241899999999997 -0.163379 0.39906000000000003 0.91692399999999996 0.0013493299999999999 +-0.25117299999999998 0.038398399999999999 -0.25687700000000002 -0.49071399999999998 0.87131599999999998 0.00283388 +-0.2276 0.043312499999999997 -0.222715 0.129333 0.99147399999999997 0.015910199999999999 +-0.20360300000000001 -0.033989199999999997 -0.0791076 -0.63795199999999996 0.77000199999999996 0.010689199999999999 +-0.20120399999999999 0.031845600000000002 -0.20116400000000001 0.69791800000000004 0.71612299999999995 -0.0089040100000000004 +-0.25768600000000003 0.034163100000000002 -0.21576100000000001 -0.61331199999999997 0.78968700000000003 -0.015547 +-0.27297700000000003 -0.0102547 -0.31242700000000001 0.96523000000000003 0.26139800000000002 -0.00140942 +-0.19006000000000001 0.01545 -0.16198699999999999 0.93354599999999999 0.35820999999999997 -0.013342100000000001 +-0.20435900000000001 0.034518 -0.150141 0.61927100000000002 0.78509499999999999 0.011376900000000001 +0.23799799999999999 -0.03773 -0.30952600000000002 -0.202651 0.97925099999999998 0 +0.25579800000000003 -0.029156899999999999 -0.13597600000000001 -0.69475500000000001 0.71924600000000005 0 +0.26914199999999999 -0.0010192999999999999 -0.12515599999999999 0.99949399999999999 -0.0297994 0.0111019 +0.192638 0.0037684900000000002 -0.0373292 0.99344100000000002 -0.110039 -0.031077299999999999 +0.20852799999999999 -0.031200800000000001 -0.31941900000000001 0.63380999999999998 0.77333499999999999 0.015401700000000001 +0.26821699999999998 -0.0082792000000000004 -0.11447599999999999 0.98274499999999998 -0.182999 0.0269159 +-0.22792299999999999 0.043340799999999999 -0.13202 0.051557199999999997 0.99847600000000003 -0.01967 +-0.20990300000000001 -0.038183099999999998 -0.203796 -0.49523200000000001 0.86870000000000003 -0.0102687 +-0.216415 -0.0411095 -0.184507 -0.31234299999999998 0.94990300000000005 0.011214399999999999 +-0.20574799999999999 -0.035490899999999999 -0.25627499999999998 -0.53791 0.84299999999999997 0.0019897000000000001 +0.193491 0.0089132599999999992 -0.113554 0.96692699999999998 -0.25414199999999998 -0.0215674 +0.217029 -0.035868700000000003 -0.098252999999999993 0.363873 0.93137800000000004 -0.011427 +-0.26734799999999997 0.023467600000000002 -0.100422 0.85262400000000005 -0.52252399999999999 0 +0.22487199999999999 0.037945600000000003 -0.21773200000000001 -0.15535199999999999 0.98750199999999999 0.026565499999999999 +-0.213223 0.039731000000000002 -0.25316300000000003 0.41685899999999998 0.90895599999999999 -0.0052213399999999997 +-0.20922299999999999 -0.037866200000000003 -0.25096299999999999 -0.50013099999999999 0.86594000000000004 -0.0041024800000000004 +0.20796300000000001 -0.030805200000000001 -0.264123 0.55631200000000003 0.83096400000000004 -0.0039310500000000002 +-0.20721500000000001 -0.036518200000000001 -0.23957300000000001 -0.51148899999999997 0.85928800000000005 -0.0015821699999999999 +0.192357 -0.00055862000000000001 -0.20646500000000001 0.99988699999999997 -0.015011 -0.00113575 +0.25381399999999998 -0.030638200000000001 -0.12878100000000001 -0.59911000000000003 0.80066199999999998 -0.0027388 +0.26511000000000001 -0.017016300000000002 -0.22494600000000001 0.89951300000000001 -0.43686999999999998 -0.0046218300000000004 +0.22203100000000001 0.037325299999999999 -0.29805100000000001 -0.21507699999999999 0.97609800000000002 0.031235200000000001 +-0.27399000000000001 -0.0042196400000000002 -0.31172 0.99735600000000002 0.072668899999999995 -0.00074010000000000005 +-0.259044 -0.033135299999999999 -0.20269699999999999 0.60699899999999996 0.79406600000000005 -0.031810400000000003 +0.197127 -0.018514300000000001 -0.091487200000000005 0.84909599999999996 0.52823200000000003 -0.00280941 +-0.26084400000000002 0.031335700000000001 -0.283891 -0.67560100000000001 0.73724100000000004 -0.0062698500000000004 +-0.26011600000000001 -0.032063800000000003 -0.114671 0.69002200000000002 0.72353500000000004 0.0191202 +0.19261800000000001 -0.0035401299999999998 -0.071912799999999999 0.99504599999999999 0.096024100000000001 -0.025756100000000001 +0.24246999999999999 -0.036531599999999997 -0.27556199999999997 -0.28507500000000002 0.95813499999999996 0.026652200000000001 +0.212871 -0.033930000000000002 -0.31553900000000001 0.47964400000000001 0.87746299999999999 0 +-0.19011500000000001 -0.015566699999999999 -0.158114 0.938801 -0.34443699999999999 -0.0040239899999999999 +-0.24953800000000001 -0.0391612 -0.082103099999999998 0.40489799999999998 0.91435100000000002 0.0044396000000000001 +-0.192103 -0.019830299999999999 -0.118343 0.90904700000000005 -0.41624800000000001 -0.019271799999999999 +0.26784200000000002 -0.0096787000000000002 -0.20418700000000001 0.95422700000000005 -0.29873 -0.0145104 +-0.26110499999999998 0.031074600000000001 -0.14668500000000001 0.71736900000000003 -0.69654300000000002 0.014460600000000001 +0.19725799999999999 0.018794600000000002 -0.29672999999999999 0.88753599999999999 -0.46057399999999998 -0.012343700000000001 +0.2581 0.026855 -0.27330700000000002 0.69893300000000003 0.71514200000000006 -0.0080988599999999994 +-0.18828800000000001 0.0092356299999999999 -0.186806 0.97009100000000004 0.24259500000000001 0.0083765999999999997 +0.264428 0.018480699999999999 -0.188887 0.89267099999999999 0.45070700000000002 0.00121339 +-0.233407 -0.043359000000000002 -0.063571299999999997 0.083613800000000002 0.99646199999999996 -0.0085190600000000002 +0.19265599999999999 -0.0039780800000000002 -0.17810200000000001 0.99315900000000001 0.11604 -0.013002700000000001 +0.25085200000000002 -0.032711900000000002 -0.24665699999999999 -0.55033699999999997 0.83484599999999998 0.0127104 +-0.27379999999999999 -0.0063952100000000001 -0.24838299999999999 0.99405299999999996 0.10839699999999999 -0.0104175 +0.220941 0.037033099999999999 -0.22536500000000001 -0.252967 0.96746600000000005 -0.0042359399999999997 +-0.220078 0.042090799999999998 -0.13161500000000001 0.22515199999999999 0.97426699999999999 -0.0104995 +-0.26906000000000002 -0.0206351 -0.27943699999999999 0.88595199999999996 0.46371099999999998 -0.0078358100000000003 +-0.25274400000000002 -0.037623700000000003 -0.140379 0.50031199999999998 0.86582400000000004 0.0060991200000000004 +-0.27046599999999998 0.017619099999999999 -0.318106 0.91811900000000002 -0.395459 0.025882200000000001 +0.19272900000000001 0.0048157299999999998 -0.16223399999999999 0.99164600000000003 -0.12796099999999999 0.016263699999999999 +0.264098 -0.019188199999999999 -0.170707 0.86581300000000005 -0.50008300000000006 -0.016876499999999999 +0.20094400000000001 0.024205299999999999 -0.27953800000000001 0.78216300000000005 -0.62268199999999996 -0.0220961 +-0.21085400000000001 -0.038626300000000002 -0.24818799999999999 -0.48713800000000002 0.87332200000000004 -0.0021083199999999999 +-0.205707 -0.035462500000000001 -0.31205899999999998 -0.56727499999999997 0.823492 -0.0077951699999999997 +-0.197102 -0.027624800000000001 -0.086969500000000005 0.78676900000000005 -0.61712699999999998 0.0122145 +0.244141 0.036040799999999998 -0.070096199999999997 0.41281899999999999 0.91080099999999997 -0.0046391899999999996 +0.23303699999999999 0.038263100000000001 -0.21690499999999999 0.0623574 0.99783100000000002 -0.021098599999999999 +0.22109000000000001 0.037073099999999998 -0.32181900000000002 -0.26645000000000002 0.96384899999999996 0 +0.26760499999999998 -0.010566000000000001 -0.20024900000000001 0.96674800000000005 -0.25573099999999999 0 +0.20980299999999999 -0.032093299999999998 -0.216947 0.54794399999999999 0.83624100000000001 0.021404900000000001 +0.26367600000000002 -0.019804200000000001 -0.31289800000000001 0.85393399999999997 -0.520262 -0.0111495 +0.194356 0.012142200000000001 -0.17000199999999999 0.94097500000000001 -0.33833400000000002 -0.0098059099999999993 +0.22135099999999999 -0.037143000000000002 -0.30844500000000002 0.21541199999999999 0.97589899999999996 0.034926800000000001 +0.26191799999999998 -0.022314899999999999 -0.23042000000000001 0.81703899999999996 -0.57643999999999995 -0.0127936 +-0.22190699999999999 0.042581000000000001 -0.109208 0.213198 0.97685200000000005 -0.017530199999999999 +-0.190834 -0.017107899999999999 -0.10741299999999999 0.91423900000000002 -0.40517599999999998 0 +0.19340599999999999 0.0085970300000000003 -0.229378 0.98206000000000004 -0.18450900000000001 -0.038906000000000003 +-0.18906600000000001 -0.0121402 -0.208338 0.96188300000000004 -0.27345900000000001 0.00077682499999999998 +0.22220899999999999 0.037373000000000003 -0.32632899999999998 -0.30991200000000002 0.91415599999999997 0.26129000000000002 +0.19734699999999999 -0.018986900000000001 -0.053881199999999997 0.87259500000000001 0.48828899999999997 0.012360599999999999 +0.252112 0.031829900000000001 -0.22988500000000001 0.57000600000000001 0.82149000000000005 -0.015698799999999999 +0.19533200000000001 -0.014666800000000001 -0.091309199999999993 0.91642999999999997 0.400003 0.0124186 +-0.20489399999999999 -0.034892699999999999 -0.069009100000000004 -0.61328000000000005 0.78807099999999997 -0.0532218 +-0.260098 0.032081899999999997 -0.070250300000000002 -0.68568099999999998 0.72786799999999996 0.0070592700000000003 +0.19275300000000001 0.0050876699999999999 -0.13389599999999999 0.98666399999999999 -0.162054 -0.0152391 +0.20782900000000001 0.0307113 -0.109874 -0.573569 0.81894699999999998 -0.018561299999999999 +0.24897900000000001 0.033784700000000001 -0.308471 0.425562 0.90481999999999996 -0.0140743 +0.218254 -0.036313400000000003 -0.077129299999999998 0.308919 0.95108400000000004 -0.00294152 +-0.20356399999999999 0.033961499999999999 -0.318546 0.64083999999999997 0.76746800000000004 0.017796599999999999 +-0.18723400000000001 0.00062956799999999995 -0.149479 0.99956999999999996 0.028535600000000001 -0.0067610700000000001 +0.26447700000000002 -0.0183748 -0.085832000000000006 0.88338000000000005 -0.46782000000000001 0.028019700000000002 +-0.26840599999999998 -0.0219559 -0.061110499999999998 0.86076299999999994 0.50897000000000003 0.0059880300000000001 +0.261243 0.023279000000000001 -0.149174 0.79972500000000002 0.600267 0.0109798 +0.22261800000000001 0.037482399999999999 -0.107181 -0.216892 0.97601400000000005 -0.018803799999999999 +-0.20197100000000001 0.032612200000000001 -0.20122000000000001 0.69791800000000004 0.71612299999999995 -0.0089040000000000005 +-0.189251 -0.0128308 -0.23907300000000001 0.94190099999999999 -0.33588699999999999 0.0013597699999999999 +0.19923399999999999 -0.0217638 -0.014644300000000001 0.816388 0.57711599999999996 -0.0211317 +0.22925200000000001 -0.038328800000000003 -0.29002600000000001 0.067706500000000003 0.99770300000000001 -0.0022983999999999999 +-0.19070400000000001 0.016830999999999999 -0.26527099999999998 0.92414300000000005 0.38142700000000002 0.021747300000000001 +0.20564499999999999 0.029060699999999998 -0.22352900000000001 -0.674701 0.73746299999999998 -0.030435199999999999 +0.26841700000000002 0.00753413 -0.0125652 0.98116199999999998 0.19306999999999999 -0.0067558799999999997 +-0.263544 0.0286357 -0.29522599999999999 0.786825 -0.61716700000000002 0.0033417899999999999 +0.19846900000000001 -0.020670299999999999 -0.204848 0.84960199999999997 0.52741499999999997 -0.0029683800000000001 +0.21305299999999999 -0.034014900000000001 -0.159193 0.42197099999999998 0.90610900000000005 -0.030110499999999998 +-0.22147900000000001 0.042466400000000001 -0.13918800000000001 0.212064 0.97723499999999996 0.0063247800000000003 +-0.20370099999999999 0.034057700000000003 -0.072177199999999997 0.57567699999999999 0.81755900000000004 0.0138662 +0.214196 -0.034547899999999999 -0.156275 0.410551 0.91173599999999999 -0.013615199999999999 +0.19869300000000001 -0.020989799999999999 -0.29066599999999998 0.85384400000000005 0.52046599999999998 -0.0081472899999999997 +-0.20987 0.038167800000000002 -0.16795599999999999 0.433782 0.90100499999999994 -0.0048489800000000001 +0.23465800000000001 0.038121299999999997 -0.30428899999999998 0.14069100000000001 0.98989400000000005 -0.017762500000000001 +0.24419199999999999 -0.036017300000000002 -0.16848199999999999 -0.30803700000000001 0.95134799999999997 -0.0070978500000000002 +0.218559 0.036394900000000001 -0.13881499999999999 -0.321573 0.94675299999999996 0.015801599999999999 +-0.25117200000000001 0.0383989 -0.141737 -0.45891399999999999 0.88834900000000006 -0.015325200000000001 +-0.23650099999999999 0.043088300000000003 -0.10317 -0.17440800000000001 0.98462899999999998 -0.0093969299999999995 +0.20450599999999999 0.027922300000000001 -0.25721300000000002 -0.69161799999999996 0.72225700000000004 0.0031041699999999998 +-0.20296800000000001 -0.033544499999999998 -0.29434300000000002 -0.64397499999999996 0.765046 0 +0.22724900000000001 -0.0381535 -0.072184999999999999 0.092434000000000002 0.99571500000000002 0.00292684 +0.25989200000000001 0.0250627 -0.14596500000000001 0.75320900000000002 0.65771599999999997 0.0093085300000000006 +-0.21614700000000001 -0.041037700000000003 -0.26382800000000001 -0.35979299999999997 0.93285600000000002 -0.018144400000000001 +-0.242313 -0.041862700000000003 -0.115135 0.23786099999999999 0.97129399999999999 0.0032498399999999999 +-0.221359 0.042434100000000002 -0.20608899999999999 0.20754900000000001 0.97798499999999999 -0.0216388 +-0.269986 -0.018649099999999998 -0.073464199999999993 0.90426399999999996 0.42635499999999998 -0.022981100000000001 +0.26874399999999998 0.0055638199999999997 -0.160909 0.98814800000000003 0.15220800000000001 -0.0198931 +-0.25883200000000001 -0.033347799999999997 -0.219281 0.64864699999999997 0.76108900000000002 0 +-0.260158 0.032021300000000003 -0.069357799999999997 -0.68223299999999998 0.73110699999999995 -0.00639537 +0.202848 0.026263999999999999 -0.14460200000000001 0.72316100000000005 -0.69062199999999996 -0.0088330000000000006 +-0.25932500000000003 0.032854800000000003 -0.31730900000000001 -0.64156100000000005 0.76707199999999998 0 +-0.247859 0.039943699999999999 -0.22698099999999999 -0.37322699999999998 0.92773600000000001 0.00293071 +-0.25210300000000002 0.037964699999999997 -0.199764 -0.48930400000000002 0.87139800000000001 0.035319499999999997 +-0.23754 -0.042997399999999998 -0.32245699999999999 0.18989600000000001 0.98175000000000001 0.0103392 +-0.26597700000000002 0.025425400000000001 -0.072008900000000001 0.80859899999999996 -0.58828199999999997 0.0095980100000000006 +-0.23741899999999999 -0.043007999999999998 -0.19480500000000001 0.148704 0.98876900000000001 0.0149611 +-0.27002100000000001 -0.018574 -0.27399000000000001 0.90631799999999996 0.42258600000000002 0.0029029300000000002 +0.19814100000000001 -0.020201299999999998 -0.025344700000000001 0.83953299999999997 0.54328799999999999 0.0047668399999999996 +-0.27375899999999997 -0.0068625200000000004 -0.116676 0.98883200000000004 0.14896100000000001 -0.0047429300000000002 +0.26874799999999999 -0.0055124099999999997 -0.17693 0.98285 -0.18229200000000001 -0.027844500000000001 +-0.18865999999999999 0.0106245 -0.089968000000000006 0.96832300000000004 0.249529 0.0092156400000000006 +-0.22239600000000001 0.042712 -0.15634400000000001 0.189997 0.98170800000000003 -0.0122405 +-0.196294 0.026471700000000001 -0.19073499999999999 0.78991 0.61322299999999996 0 +0.219165 0.036557300000000001 -0.28505999999999998 -0.28559600000000002 0.958256 -0.013451899999999999 +-0.27309800000000001 -0.0098052499999999997 -0.24355599999999999 0.97366399999999997 0.227377 -0.016659 +-0.20957500000000001 0.038030099999999997 -0.089095199999999999 0.49979800000000002 0.86609199999999997 0.0092704699999999994 +-0.27389999999999998 -0.0052526500000000002 -0.063401700000000005 0.99307199999999995 0.11749900000000001 -0.0013421100000000001 +-0.26853300000000002 -0.021764800000000001 -0.26672000000000001 0.88033700000000004 0.47375899999999999 0.023639199999999999 +-0.192687 0.021082799999999999 -0.151287 0.86880199999999996 0.49502699999999999 -0.011429399999999999 +-0.19190599999999999 0.019407400000000002 -0.223437 0.89574699999999996 0.44456299999999999 0 +-0.197155 -0.027700800000000001 -0.27404699999999999 0.76902700000000002 -0.63919800000000004 -0.0049659300000000003 +0.205014 0.028429900000000001 -0.30174499999999999 -0.691527 0.72232799999999997 0.0057151600000000004 +0.26656999999999997 0.013886600000000001 -0.29189100000000001 0.93073600000000001 0.365371 0.015304999999999999 +-0.18829000000000001 -0.0092427499999999992 -0.26973399999999997 0.97741400000000001 -0.209869 0.0248332 +-0.24379100000000001 0.041466500000000003 -0.21301300000000001 -0.30605599999999999 0.95198799999999995 0.0070225299999999999 +0.192693 -0.0044027500000000004 -0.205732 0.99005100000000001 0.13859299999999999 -0.0242951 +0.23352500000000001 0.038220400000000002 -0.31563000000000002 0.0553617 0.99780599999999997 -0.036301699999999999 +0.233764 0.038199499999999997 -0.119088 0.12625600000000001 0.99199800000000005 0 +-0.26820500000000003 0.0222434 -0.099662399999999998 0.86344699999999996 -0.50439000000000001 0.0070524200000000002 +-0.23761199999999999 -0.042991099999999997 -0.23564299999999999 0.124311 0.99223700000000004 -0.0035583799999999999 +0.261716 0.022603700000000001 -0.014357200000000001 0.80583700000000003 0.59187800000000002 0.017533300000000002 +-0.189304 -0.013025200000000001 -0.199383 0.95394900000000005 -0.29826000000000003 0.031962699999999997 +-0.25751499999999999 -0.034283000000000001 -0.230765 0.61910699999999996 0.78530699999999998 0 +0.25619500000000001 0.028759900000000001 -0.21651300000000001 0.66399300000000006 0.74706399999999995 -0.031774999999999998 +-0.27371899999999999 -0.0073162599999999998 -0.188219 0.99230399999999996 0.123655 0.0064841600000000001 +0.22784799999999999 0.038205900000000001 -0.26013799999999998 -0.075783699999999996 0.99700200000000005 -0.0155996 +0.24364 -0.036218100000000003 -0.076058500000000001 -0.37789 0.92584299999999997 0.0036194700000000001 +0.24330099999999999 -0.036309000000000001 -0.281808 -0.361844 0.93223599999999995 0.0021473299999999998 +-0.195718 -0.025648399999999998 -0.14802599999999999 0.80619399999999997 -0.59157800000000005 0.0093499700000000008 +0.19909399999999999 -0.021563499999999999 -0.192383 0.83827499999999999 0.54435699999999998 -0.031141100000000001 +0.24726000000000001 -0.034586600000000002 -0.25880300000000001 -0.47735300000000003 0.87870499999999996 -0.0034090000000000001 +0.220167 0.036825700000000003 -0.0204329 -0.26178800000000002 0.96511499999999995 0.0044842099999999998 +0.196691 0.017579299999999999 -0.20799100000000001 0.88782099999999997 -0.460088 -0.0096496499999999992 +0.194077 -0.0111033 -0.054122499999999997 0.947654 0.31845699999999999 -0.023161899999999999 +-0.212534 -0.039409800000000002 -0.17718800000000001 -0.40392 0.91479100000000002 0.0023532100000000001 +-0.25153999999999999 -0.038227299999999999 -0.15762000000000001 0.503328 0.86407699999999998 -0.0056467399999999999 +0.25719599999999998 0.027758999999999999 -0.25645800000000002 0.67447299999999999 0.73818099999999998 0.0132283 +0.26395400000000002 0.019407899999999999 -0.20712700000000001 0.85858900000000005 0.51256299999999999 -0.010236 +-0.18742700000000001 0.0028291200000000001 -0.073656700000000006 0.99845899999999999 0.053418800000000002 -0.0150315 +-0.21129000000000001 0.038829599999999999 -0.14296200000000001 0.439083 0.89843899999999999 -0.0035704299999999999 +0.19549900000000001 0.0150232 -0.257683 0.91956099999999996 -0.39223799999999998 0.0235917 +0.21279100000000001 0.033892899999999997 -0.047837200000000003 -0.46066200000000002 0.88745099999999999 0.0149033 +0.215168 -0.0350011 -0.26955099999999999 0.42773600000000001 0.90353399999999995 0.025858300000000001 +-0.25818400000000002 0.033814700000000003 -0.25083499999999997 -0.65662699999999996 0.75420900000000002 0.0030213499999999999 +-0.27427400000000002 0.00097627200000000003 -0.30608400000000002 0.99970000000000003 0.018973500000000001 0.0154571 +-0.245255 -0.0410745 -0.220831 0.30383900000000003 0.95271700000000004 -0.0035529699999999999 +0.267955 0.0092581499999999997 -0.18726799999999999 0.96457099999999996 0.26334299999999999 0.015899 +0.26831199999999999 0.0079270399999999998 -0.19072700000000001 0.977155 0.21249699999999999 0.0035354399999999999 +-0.24258299999999999 0.0417902 -0.22627900000000001 -0.33619500000000002 0.94164700000000001 0.016572199999999999 +0.263876 -0.019519499999999999 -0.29921799999999998 0.854047 -0.52012599999999998 -0.0085529899999999999 +0.25714199999999998 -0.027813299999999999 -0.259494 -0.65462900000000002 0.75514999999999999 0.034779499999999998 +-0.214499 0.040325899999999998 -0.18206700000000001 0.350406 0.93655100000000002 -0.00933989 +0.19933799999999999 -0.021912000000000001 -0.172481 0.83042499999999997 0.55432099999999995 0.055872199999999997 +-0.26553399999999999 0.026058000000000001 -0.24398300000000001 0.82886499999999996 -0.55942499999999995 -0.0051376599999999996 +0.26902300000000001 0.0023772899999999998 -0.23969599999999999 0.99994400000000006 -0.0071663100000000004 0.0077548599999999997 +0.197382 -0.019060400000000002 -0.047586200000000002 0.84813000000000005 0.52976000000000001 -0.0054900900000000004 +-0.24473700000000001 -0.041213100000000003 -0.27830700000000003 0.29832999999999998 0.954461 0.00186616 +0.20987600000000001 -0.032144800000000001 -0.059789700000000001 0.52774900000000002 0.84934100000000001 0.0100237 +0.194884 0.0137065 -0.21082200000000001 0.91410899999999995 -0.40539199999999997 0.0078516899999999997 +-0.27353 -0.0081915800000000004 -0.28628599999999998 0.969333 0.24568400000000001 -0.0057917400000000001 +0.23932500000000001 0.037374200000000003 -0.108904 0.198686 0.98005699999999996 0.0034938999999999999 +0.21079400000000001 -0.032787499999999997 -0.052015400000000003 0.53146700000000002 0.84707900000000003 0 +-0.22752600000000001 0.0433061 -0.20547299999999999 0.111356 0.99378 -0.00129093 +-0.22815199999999999 0.043360799999999998 -0.167245 0.095440700000000003 0.99518700000000004 -0.022243800000000001 +0.23963100000000001 -0.037292400000000003 -0.065266599999999994 -0.16689699999999999 0.98587199999999997 0.014176599999999999 +-0.18732799999999999 -0.00170382 -0.168401 0.99951900000000005 0.030788599999999999 0.00360275 +-0.26310499999999998 -0.029074900000000001 -0.064678899999999998 0.73593399999999998 0.67704799999999998 0.0026670399999999999 +-0.21702399999999999 0.041272499999999997 -0.20139899999999999 0.271679 0.96236999999999995 0.0059260700000000003 +0.233651 -0.038209300000000002 -0.15271899999999999 -0.026919100000000001 0.99955700000000003 0.012707100000000001 +0.25545499999999999 0.029489100000000001 -0.19061700000000001 0.66395700000000002 0.74774700000000005 -0.0058615500000000001 +0.26780399999999999 -0.0098227699999999998 -0.17174700000000001 0.956843 -0.290466 -0.0089967099999999998 +-0.27298899999999998 -0.010211599999999999 -0.17760000000000001 0.96160599999999996 0.27443499999999998 0 +-0.24620300000000001 -0.040716200000000001 -0.32524599999999998 0.31241000000000002 0.93164199999999997 -0.18559100000000001 +-0.274233 -0.0014351800000000001 -0.303952 0.99638499999999997 0.084891099999999997 0.0032263000000000001 +0.193159 0.0076768399999999999 -0.088744699999999996 0.98050199999999998 -0.19636600000000001 0.0074998499999999997 +-0.19647600000000001 -0.026731100000000001 -0.095991499999999993 0.78702300000000003 -0.61684099999999997 -0.010125 +-0.21956100000000001 -0.041952499999999997 -0.10777200000000001 -0.19084300000000001 0.98140700000000003 -0.020474200000000001 +0.25031399999999998 0.033088899999999997 -0.17366000000000001 0.498973 0.86655899999999997 0.0100629 +-0.27307599999999999 -0.0098846899999999998 -0.184917 0.98121000000000003 0.19172800000000001 -0.021613500000000001 +0.192667 -0.0041062 -0.239764 0.998556 0.053660899999999997 0.00266643 +-0.19400400000000001 0.0232021 -0.073695800000000006 0.86462099999999997 0.50240099999999999 -0.0048905399999999996 +0.205097 -0.0285131 -0.15504899999999999 0.67865399999999998 0.73420600000000003 0.019239699999999998 +0.26313399999999998 0.020579400000000001 -0.22055900000000001 0.83710300000000004 0.54679299999999997 -0.016592300000000001 +0.24002799999999999 0.037185799999999998 -0.28342899999999999 0.23812700000000001 0.97123400000000004 0 +-0.26438899999999999 0.0276928 -0.24718200000000001 0.78530800000000001 -0.61907599999999996 -0.0060676100000000002 +0.26133699999999999 0.0231448 -0.280165 0.77702000000000004 0.62945499999999999 0.0051433099999999999 +0.268648 0.0066594200000000001 -0.21392700000000001 0.988784 0.14866099999999999 -0.0143426 +-0.212369 -0.039332800000000001 -0.141897 -0.42038199999999998 0.90734300000000001 -0.0028285099999999998 +-0.26202599999999998 -0.030153599999999999 -0.24074899999999999 0.75887899999999997 0.65080000000000005 -0.023723000000000001 +0.19284999999999999 -0.0061989699999999998 -0.25770999999999999 0.99151100000000003 0.122533 0.0434965 +-0.19305800000000001 -0.0218502 -0.20291400000000001 0.86580000000000001 -0.50039100000000003 0 +0.269015 0.00246372 -0.057695700000000003 0.99904800000000005 0.041295199999999997 -0.0140731 +0.25591700000000001 -0.029038100000000001 -0.21227699999999999 -0.67649000000000004 0.73645099999999997 -0.0013854200000000001 +-0.18907399999999999 -0.0121683 -0.085240399999999994 0.95474999999999999 -0.29730099999999998 -0.0079759400000000008 +0.26890700000000001 0.0036980400000000001 -0.18074100000000001 0.99582899999999996 0.085477300000000006 0.031910399999999998 +-0.24246500000000001 0.041821900000000002 -0.19809299999999999 -0.26627899999999999 0.96383300000000005 -0.0110087 +-0.18798100000000001 -0.0080891999999999995 -0.13466900000000001 0.98797000000000001 -0.154277 0.010679900000000001 +-0.214251 -0.040210299999999997 -0.11573 -0.41805399999999998 0.908107 0.023910899999999999 +0.26433600000000002 -0.0186774 -0.082711699999999999 0.88645799999999997 -0.46272999999999997 0.0085879400000000005 +-0.271011 -0.016450900000000001 -0.23057900000000001 0.94098400000000004 0.338426 -0.00399285 +0.24949499999999999 -0.033544200000000003 -0.22198200000000001 -0.52907800000000005 0.84856200000000004 0.0043319700000000001 +-0.18731400000000001 0.0015381800000000001 -0.28611799999999998 0.99963100000000005 0.026563300000000001 0.0056547300000000002 +0.21335499999999999 -0.034156100000000002 -0.16408800000000001 0.41842699999999999 0.90807700000000002 -0.017768099999999998 +-0.27432699999999999 0.00036382999999999999 -0.32421299999999997 0.99367700000000003 -0.0132211 -0.111498 +-0.24603800000000001 0.040792799999999997 -0.167075 -0.39327600000000001 0.91941499999999998 0.0032632 +-0.19226199999999999 -0.020171399999999999 -0.102113 0.90319700000000003 -0.428761 0.020007899999999999 +-0.23507500000000001 0.043213099999999997 -0.088723899999999994 -0.083595900000000001 0.99645899999999998 0.0089901400000000006 +-0.27412700000000001 -0.0026566599999999999 -0.29852400000000001 0.99402199999999996 0.106476 -0.0241269 +-0.251498 -0.038247000000000003 -0.216782 0.476601 0.87903600000000004 -0.012125800000000001 +-0.21551699999999999 0.040800599999999999 -0.27953699999999998 0.32849099999999998 0.94450599999999996 -0.0016288800000000001 +-0.19991300000000001 -0.030554600000000001 -0.218193 -0.69851600000000003 0.71554499999999999 0.0083769399999999994 +-0.20182700000000001 0.032468900000000002 -0.216559 0.66920900000000005 0.74301099999999998 0.0097191900000000008 +0.19232099999999999 -0.000151543 -0.27026600000000001 0.99987499999999996 0.014369099999999999 -0.0065650600000000002 +-0.27333200000000002 -0.0089297999999999999 -0.181445 0.981568 0.190552 -0.014626500000000001 +0.233485 -0.038223899999999998 -0.14347399999999999 -0.070776500000000006 0.99749200000000005 0 +-0.25772400000000001 0.034136600000000003 -0.14144300000000001 -0.58494699999999999 0.810998 -0.010940399999999999 +0.20444100000000001 -0.027857199999999999 -0.253523 0.68161400000000005 0.73167000000000004 0.0078420999999999994 +-0.272756 0.011078899999999999 -0.265488 0.95776899999999998 -0.28743800000000003 0.00764016 +-0.257295 0.034436799999999997 -0.21671299999999999 -0.64246199999999998 0.76599899999999999 -0.022091599999999999 +0.258378 0.0265764 -0.31607099999999999 0.70868100000000001 0.70552899999999996 0 +0.26717600000000002 0.012167000000000001 -0.27228799999999997 0.93857599999999997 0.34488999999999997 -0.011227300000000001 +-0.195823 -0.025799300000000001 -0.074644100000000005 0.81523199999999996 -0.57911500000000005 -0.00479102 +0.25786300000000001 -0.0270923 -0.17252899999999999 0.75339900000000004 -0.65532500000000005 -0.0542196 +0.206343 -0.0296704 -0.089127300000000007 0.664489 0.74729800000000002 0 +-0.25259399999999999 -0.037729199999999997 -0.28476600000000002 0.477242 0.87871500000000002 -0.0100476 +-0.270204 0.018181300000000001 -0.19831799999999999 0.91492099999999998 -0.40362900000000002 -0.0019283200000000001 +-0.26887499999999998 0.021031299999999999 -0.125143 0.88325799999999999 -0.46886100000000003 -0.0049238900000000002 +-0.21584999999999999 -0.040955900000000003 -0.20275699999999999 -0.35060799999999998 0.93649499999999997 0.0071047100000000002 +0.26239800000000002 0.021628999999999999 -0.1918 0.82608099999999995 0.56272699999999998 0.030489499999999999 +-0.19539300000000001 0.0251848 -0.22861000000000001 0.80579999999999996 0.59168399999999999 0.024404800000000001 +0.26459199999999999 0.018128399999999999 -0.23736699999999999 0.871556 0.48995499999999997 0.0182913 +0.19237099999999999 -0.00072541800000000003 -0.27629599999999999 0.99756599999999995 0.069417199999999998 0.0065177300000000002 +-0.26460299999999998 -0.027387499999999999 -0.055731099999999999 0.77516300000000005 0.63174699999999995 0.0042532000000000004 +0.19786400000000001 0.019806299999999999 -0.191164 0.87381799999999998 -0.48625200000000002 -0.0012692599999999999 +-0.27217200000000003 -0.0132611 -0.32388800000000001 0.94395300000000004 0.31526399999999999 -0.097786700000000004 +0.25732699999999997 -0.027627599999999999 -0.24560000000000001 -0.67410899999999996 0.73861900000000003 0.0043896600000000001 +0.229605 -0.038359600000000001 -0.19323899999999999 0.026604599999999999 0.99963800000000003 -0.00403595 +-0.19008800000000001 -0.0155096 -0.266127 0.940056 -0.34099499999999999 -0.0040137300000000001 +0.23166200000000001 0.038383399999999998 -0.233594 0.021989000000000002 0.99963500000000005 0.0157295 +-0.27063999999999999 0.017246600000000001 -0.104171 0.92313299999999998 -0.38383 0.0223725 +0.267571 -0.010692800000000001 -0.043772899999999997 0.945025 -0.32696500000000001 0.00468558 +-0.26162400000000002 0.030556199999999999 -0.203406 -0.70022799999999996 0.71388099999999999 0.0073252200000000003 +0.25828099999999998 -0.026674300000000001 -0.299068 0.73989799999999994 -0.67266000000000004 0.0089282400000000005 +0.192915 -0.0067663200000000001 -0.31180999999999998 0.98920600000000003 0.14530999999999999 0.018879300000000002 +0.19690099999999999 0.018030899999999999 -0.198243 0.90461599999999998 -0.42615500000000001 0.0079112200000000001 +0.22636899999999999 0.038076499999999999 -0.26205200000000001 -0.087257199999999993 0.99586300000000005 -0.025364999999999999 +-0.22367100000000001 -0.042968800000000001 -0.27963100000000002 -0.18579899999999999 0.98257899999999998 -0.0042548799999999999 +-0.27319399999999999 0.0094458200000000006 -0.12604899999999999 0.98283500000000001 -0.18448100000000001 -0.0015283499999999999 +-0.20106299999999999 0.031704099999999999 -0.14185900000000001 0.67699900000000002 0.73595100000000002 -0.0069439599999999999 +-0.26553399999999999 0.0260576 -0.16422300000000001 0.80507099999999998 -0.59311100000000005 0.0088950699999999997 +0.200491 -0.023558599999999999 -0.093856999999999996 0.770706 0.63719199999999998 0 +0.20824799999999999 0.031004899999999998 -0.105168 -0.56935500000000006 0.82208199999999998 -0.0039693799999999998 +0.26871099999999998 0.0059418800000000001 -0.24968699999999999 0.98630099999999998 0.16347600000000001 0.0220389 +-0.27164100000000002 0.015099400000000001 -0.21051500000000001 0.93733200000000005 -0.34834300000000001 0.0080786499999999997 +-0.18781600000000001 -0.0072686000000000001 -0.045592000000000001 0.98168800000000001 -0.168546 0.088770199999999994 +-0.196022 0.026082299999999999 -0.14058000000000001 0.80200899999999997 0.59693799999999997 0.021133699999999998 +0.26666099999999998 -0.013691500000000001 -0.16351199999999999 0.92566800000000005 -0.378249 -0.0082195600000000008 +0.20059099999999999 0.023702000000000001 -0.32591799999999999 -0.64653400000000005 0.707677 0.28493299999999999 +0.19311400000000001 -0.0075066799999999999 -0.270312 0.97698200000000002 0.21310200000000001 -0.0096424800000000001 +0.26895599999999997 -0.0031393200000000001 -0.24762200000000001 0.99864299999999995 -0.0479032 -0.020431600000000001 +-0.27381699999999998 0.0061934499999999997 -0.14516100000000001 0.98469600000000002 -0.17036999999999999 0.036711500000000001 +-0.19701399999999999 -0.027499699999999998 -0.16069900000000001 0.76527900000000004 -0.64368700000000001 0.0038850400000000002 +0.20139599999999999 0.0248122 -0.114759 0.76266 -0.64599399999999996 -0.032272599999999999 +-0.21070900000000001 -0.038559000000000003 -0.089387900000000006 -0.45116699999999998 0.89229599999999998 -0.015978900000000001 +-0.21542 0.040755300000000001 -0.26552599999999998 0.37143799999999999 0.92844599999999999 0.0046760700000000001 +-0.238819 -0.042798799999999998 -0.141573 0.24501800000000001 0.96947300000000003 -0.0094432400000000003 +0.198712 -0.021017399999999999 -0.118183 0.83283200000000002 0.55352500000000004 0 +0.20474100000000001 -0.028157499999999999 -0.0256942 0.68344099999999997 0.72995299999999996 -0.0087109300000000004 +-0.27426200000000001 -0.0011071399999999999 -0.24233199999999999 0.99997100000000005 -0.0018345499999999999 0.00733813 +-0.22192799999999999 0.042586699999999998 -0.22759099999999999 0.20369999999999999 0.97902599999999995 -0.0038511399999999999 +0.266378 0.014297799999999999 -0.092739699999999994 0.93625199999999997 0.35081200000000001 -0.019057500000000002 +-0.27263700000000002 -0.011526 -0.317137 0.96717699999999995 0.25403900000000001 0.0057744500000000004 +0.20113700000000001 -0.024480600000000002 -0.10032099999999999 0.76681100000000002 0.64181100000000002 -0.0089372299999999991 +-0.19365099999999999 0.022697700000000001 -0.151978 0.83701099999999995 0.54711100000000001 -0.0090887699999999995 +-0.26268599999999998 0.029494200000000002 -0.20136899999999999 0.73277099999999995 -0.68006 -0.023753199999999999 +0.254334 -0.030274300000000001 -0.032307299999999997 -0.62932399999999999 0.77694799999999997 0.0174302 +-0.26685500000000001 -0.024171000000000002 -0.18169199999999999 0.833457 0.55161700000000002 -0.0326894 +0.19234899999999999 -0.00046469399999999998 -0.161414 0.99939900000000004 -0.0131856 0.0320497 +-0.18786900000000001 0.0076707800000000003 -0.129473 0.98622600000000005 0.164524 0.0170277 +0.19911300000000001 -0.021590399999999999 -0.14458499999999999 0.83750100000000005 0.54599500000000001 0.021961100000000001 +-0.20141300000000001 -0.032054800000000001 -0.13694300000000001 -0.686338 0.72725200000000001 0.0066558099999999999 +0.22675200000000001 0.038109999999999998 -0.119381 -0.10664 0.99409899999999995 0.019864099999999999 +0.25822899999999999 -0.026726199999999999 -0.30479499999999998 0.72766299999999995 -0.68591999999999997 0.0045474499999999998 +-0.268895 0.020987800000000001 -0.094838199999999998 0.87658400000000003 -0.48116999999999999 -0.0087420199999999997 +0.201599 0.025015800000000001 -0.21956899999999999 0.75051299999999999 -0.66084299999999996 -0.0040871500000000003 +-0.19209000000000001 -0.0198021 -0.274752 0.89515699999999998 -0.44570199999999999 -0.00654348 +-0.18912300000000001 0.012349600000000001 -0.056563000000000002 0.97306400000000004 0.230519 -0.0026868999999999999 +-0.270706 0.017103699999999999 -0.31622099999999997 0.92094900000000002 -0.38959899999999997 0.0081028100000000002 +0.26382499999999998 0.0195917 -0.27476600000000001 0.85561799999999999 0.51757699999999995 -0.0057022899999999996 +0.26175999999999999 0.022541200000000001 -0.23383899999999999 0.81413400000000002 0.58067299999999999 0.0020860800000000001 +-0.23288700000000001 -0.043404400000000003 -0.21837599999999999 0.051509699999999999 0.99866299999999997 -0.0043536199999999999 +0.19587299999999999 0.015827000000000001 -0.0165761 0.88482799999999995 -0.465916 0.00113517 +-0.19939899999999999 -0.030040399999999998 -0.096584600000000007 0.78401799999999999 -0.62072300000000002 -0.0042698299999999996 +0.22007699999999999 -0.036801599999999997 -0.14869099999999999 0.27115899999999998 0.96244799999999997 -0.0129161 +0.25887399999999999 0.026080599999999999 -0.10235 0.73973999999999995 0.672848 0.0077929699999999998 +-0.267011 -0.0239487 -0.122031 0.87202199999999996 0.48945 -0.0040932399999999997 +-0.24504699999999999 0.04113 -0.15698500000000001 -0.32885999999999999 0.94428299999999998 -0.013466000000000001 +0.197688 0.019554599999999998 -0.20773800000000001 0.86071200000000003 -0.50811700000000004 -0.031511699999999997 +-0.26301000000000002 -0.029170000000000001 -0.27229900000000001 0.74459200000000003 0.66751700000000003 -0.0017962200000000001 +0.19284499999999999 0.0061397800000000001 -0.30216799999999999 0.98762000000000005 -0.15626799999999999 0.0137016 +-0.19283800000000001 0.021407300000000001 -0.057210299999999999 0.89868599999999998 0.43853199999999998 -0.0073582099999999996 +-0.27001399999999998 0.018587800000000002 -0.25639499999999998 0.90115900000000004 -0.43304300000000001 -0.019643899999999999 +0.19745099999999999 0.019210100000000001 -0.31448999999999999 0.848221 -0.52963000000000005 0.00376298 +-0.21910199999999999 -0.041829499999999999 -0.179148 -0.294904 0.95547800000000005 -0.0096118100000000001 +-0.270874 -0.0167438 -0.173924 0.93531399999999998 0.35374800000000001 -0.0071307899999999997 +-0.26108799999999999 0.0310922 -0.20608599999999999 -0.653729 0.75668400000000002 0.0082041800000000002 +0.24211299999999999 0.036627199999999999 -0.10097299999999999 0.28485199999999999 0.95825300000000002 0.024705299999999999 +-0.234768 0.043240000000000001 -0.076022300000000001 -0.057460299999999999 0.99824000000000002 0.014640500000000001 +-0.21523500000000001 0.040669200000000003 -0.30836799999999998 0.36134899999999998 0.93235299999999999 0.012000500000000001 +-0.23366700000000001 0.043336199999999998 -0.13151199999999999 -0.047301900000000001 0.998811 -0.011809200000000001 +-0.18848899999999999 0.00998572 -0.31764300000000001 0.97453299999999998 0.224216 0.00363218 +-0.22878899999999999 -0.043416499999999997 -0.198458 -0.061023099999999997 0.998116 -0.0064284700000000004 +0.259465 -0.0254892 -0.23388 0.75856100000000004 -0.65137800000000001 -0.017104399999999999 +-0.18834899999999999 -0.0094621600000000007 -0.29347200000000001 0.97359300000000004 -0.22827700000000001 -0.0024059699999999999 +0.19455700000000001 -0.0128936 -0.035376600000000001 0.93912899999999999 0.34323799999999999 0.0149833 +-0.20069899999999999 -0.031340100000000003 -0.18689 -0.66930500000000004 0.74274700000000005 -0.018922999999999999 +-0.266121 -0.025220300000000001 -0.27860800000000002 0.82052999999999998 0.57147599999999998 -0.012052999999999999 +0.21517700000000001 -0.035005500000000002 -0.10428800000000001 0.37877300000000003 0.92517000000000005 -0.0243418 +0.26902199999999998 0.0023896999999999998 -0.28935 0.998811 0.040604800000000003 0.026983199999999999 +-0.19416700000000001 -0.0234334 -0.29590300000000003 0.84511400000000003 -0.53458399999999995 -0.0013344699999999999 +-0.187722 0.0061986200000000002 -0.11357399999999999 0.98269300000000004 0.18500900000000001 -0.0093055199999999994 +-0.189581 0.014061300000000001 -0.28217700000000001 0.94471700000000003 0.327739 -0.0098195899999999996 +-0.25333600000000001 -0.037209199999999998 -0.085473999999999994 0.51905000000000001 0.85450800000000005 -0.020077500000000002 +-0.18723100000000001 -0.00059077299999999995 -0.10131 0.99999800000000005 -0.0019020300000000001 0.00076617999999999999 +-0.18840299999999999 -0.00966529 -0.048162700000000003 0.96298600000000001 -0.26914900000000003 0.014698299999999999 +-0.188248 0.0090858699999999994 -0.17430300000000001 0.98535200000000001 0.169853 -0.015207099999999999 +0.19613900000000001 -0.016397100000000001 -0.30329 0.90756599999999998 0.41883399999999998 0.030039400000000001 +-0.21241499999999999 0.039354500000000001 -0.061260299999999997 0.42368899999999998 0.90577399999999997 -0.0078479299999999995 +0.20431299999999999 0.027728900000000001 -0.202788 -0.694191 0.71962300000000001 0.015543599999999999 +-0.267316 -0.023513200000000001 -0.051334400000000002 0.83611000000000002 0.54854800000000004 -0.0038879600000000002 +-0.27381 0.00628189 -0.0593809 0.98404400000000003 -0.177924 -0.00058655399999999998 +-0.27419500000000002 -0.0018778099999999999 -0.29693999999999998 0.997618 0.068566000000000002 -0.0075337499999999996 +0.26920500000000003 0.00029410900000000003 -0.062942200000000004 0.99894000000000005 -0.044412899999999998 0.0120938 +-0.18781 0.0072017899999999996 -0.29611500000000002 0.97612100000000002 0.217225 0.0011456000000000001 +-0.24799099999999999 0.039882399999999998 -0.29772399999999999 -0.35711500000000002 0.93405700000000003 0.0023660299999999999 +0.26095299999999999 -0.023693700000000002 -0.18464 0.79530500000000004 -0.60604400000000003 0.0141741 +-0.23728399999999999 0.043019799999999997 -0.14543300000000001 -0.16952100000000001 0.98546100000000003 -0.0113553 +-0.214391 0.040275600000000002 -0.20596300000000001 0.393013 0.91925699999999999 -0.022504699999999999 +-0.21285100000000001 0.039557700000000001 -0.26223600000000002 0.41950900000000002 0.90773999999999999 -0.0045876099999999998 +-0.27310200000000001 -0.0097899800000000002 -0.12865799999999999 0.97277499999999995 0.23174 -0.0024506699999999998 +-0.24884800000000001 0.039482799999999998 -0.17268600000000001 -0.449938 0.89304700000000004 -0.0046863199999999999 +-0.199184 -0.029824799999999999 -0.070736499999999994 0.70848999999999995 -0.70569800000000005 0.0056822599999999997 +0.23599400000000001 0.038004400000000001 -0.24373 0.129299 0.99148999999999998 0.0151118 +0.259629 0.025325299999999999 -0.045694499999999999 0.75754299999999997 0.65278499999999995 -0.0010468599999999999 +-0.27426400000000001 -0.00108052 -0.22234300000000001 0.998359 0.057077700000000002 0.0045640400000000001 +-0.24066599999999999 -0.042303800000000003 -0.25284600000000002 0.21351400000000001 0.976939 0.0013609799999999999 +0.21563099999999999 0.035216799999999999 -0.17105000000000001 -0.44114900000000001 0.89738399999999996 0.0094504700000000007 +-0.26684099999999999 -0.024190799999999998 -0.260959 0.82903800000000005 0.55919200000000002 0 +0.19237499999999999 -0.00077133200000000001 -0.154865 0.99943000000000004 0.030726199999999999 0.014016199999999999 +-0.25864700000000002 0.033490600000000002 -0.093292600000000003 -0.64432400000000001 0.76462200000000002 0.0141181 +-0.18781999999999999 0.0073225499999999997 -0.28084599999999998 0.98922100000000002 0.146426 0.00062768600000000002 +0.243086 0.0363664 -0.163103 0.29560900000000001 0.955179 -0.015766499999999999 +0.240179 -0.037145600000000001 -0.13025999999999999 -0.20000000000000001 0.97977300000000001 0.0066996299999999998 +0.26067099999999999 -0.024095399999999999 -0.098193000000000003 0.78421600000000002 -0.62045499999999998 0.0064980599999999999 +-0.271673 -0.0150314 -0.27562300000000001 0.93036300000000005 0.36643199999999998 -0.012342000000000001 +-0.240813 0.042264400000000001 -0.14136699999999999 -0.230075 0.97312699999999996 0.0094214599999999996 +-0.18801799999999999 -0.0082267899999999995 -0.061995300000000003 0.98088600000000004 -0.19129599999999999 -0.035604900000000002 +0.23347799999999999 -0.038224500000000002 -0.13868 -0.065990900000000005 0.99753499999999995 -0.0238715 +0.21665300000000001 -0.035693599999999999 -0.24112500000000001 0.330266 0.94370799999999999 0.018461100000000001 +-0.19051399999999999 0.016422800000000001 -0.21256700000000001 0.93553500000000001 0.35322999999999999 0.00169159 +-0.217224 0.041326000000000002 -0.131132 0.273617 0.96183399999999997 -0.00287697 +-0.26212999999999997 -0.030049699999999999 -0.096444199999999994 0.70173399999999997 0.71238400000000002 0.0088444000000000005 +0.20485800000000001 -0.0282747 -0.083775000000000002 0.70592200000000005 0.70824500000000001 0.0079479100000000007 +0.26820899999999998 -0.0083114 -0.22677900000000001 0.97889999999999999 -0.20180000000000001 -0.032119500000000002 +-0.25583499999999998 0.035459400000000002 -0.214421 -0.572245 0.82003899999999996 -0.00848374 +0.25230900000000001 -0.031691999999999998 -0.24735699999999999 -0.57301000000000002 0.81949000000000005 -0.0098076799999999992 +0.20179800000000001 0.0252147 -0.041510499999999999 0.77347600000000005 -0.63310699999999998 -0.030167099999999999 +-0.18756200000000001 0.0043698000000000001 -0.244168 0.99066200000000004 0.13625799999999999 -0.0046981599999999998 +0.20905499999999999 -0.031570099999999997 -0.047176700000000002 0.56968399999999997 0.82185399999999997 0.0040083300000000001 +-0.21616199999999999 -0.041041599999999998 -0.15907399999999999 -0.35536899999999999 0.93468700000000005 0.0085112 +0.25923800000000002 -0.025717 -0.145124 0.755413 -0.65524899999999997 0 +-0.25887300000000002 0.033306200000000001 -0.25714199999999998 -0.65829099999999996 0.75268199999999996 0.0110831 +0.268592 -0.0068794800000000003 -0.24675800000000001 0.98927500000000002 -0.14527399999999999 -0.015212099999999999 +-0.21498 0.040550099999999999 -0.31566 0.31301899999999999 0.949739 -0.0039024699999999999 +-0.230846 -0.043582999999999997 -0.116538 0.014413 0.99989099999999997 0.0030620000000000001 +0.20383100000000001 0.027247500000000001 -0.089301199999999997 -0.69816800000000001 0.71574199999999999 0.016578499999999999 +-0.27093099999999998 -0.016621199999999999 -0.325513 0.82384800000000002 0.42781400000000003 -0.37181799999999998 +0.22031899999999999 0.036866400000000001 -0.13897300000000001 -0.29403800000000002 0.95564199999999999 0.017033300000000001 +0.19398899999999999 0.010774300000000001 -0.078752299999999997 0.96440599999999999 -0.26416000000000001 -0.0118578 +-0.187802 -0.0071106800000000003 -0.28081600000000001 0.98788600000000004 -0.15517400000000001 -0.0012748200000000001 +-0.218751 -0.041735399999999999 -0.13886299999999999 -0.33570699999999998 0.94195099999999998 0.0054783799999999997 +-0.21671399999999999 0.0411896 -0.206097 0.30762499999999998 0.95147099999999996 -0.0083621500000000005 +-0.26105499999999998 -0.031125199999999999 -0.15540899999999999 0.67983199999999999 0.73329 0.010671999999999999 +0.26911099999999999 0.0013684400000000001 -0.25406299999999998 0.99951599999999996 0.030770700000000002 -0.0045191299999999997 +-0.27415600000000001 0.0023205500000000002 -0.21171400000000001 0.99953000000000003 -0.029979100000000002 -0.0064339799999999997 +-0.20401900000000001 0.034280400000000003 -0.111794 0.58030499999999996 0.814357 -0.0083429699999999999 +0.215526 0.035167700000000003 -0.0293694 -0.400592 0.91611600000000004 0.016035899999999999 +-0.19934399999999999 0.029984799999999999 -0.234511 0.720086 0.69378600000000001 -0.0117416 +-0.20778099999999999 0.0369149 -0.26318900000000001 0.51585899999999996 0.85635399999999995 0.0233914 +-0.18749299999999999 -0.0035814900000000001 -0.26649899999999999 0.99839 -0.056678100000000002 -0.0022578899999999998 +-0.19656299999999999 0.026854800000000002 -0.29074499999999998 0.81081700000000001 0.58529100000000001 0.0031431499999999999 +-0.20315800000000001 0.033677499999999999 -0.23888100000000001 0.637853 0.77005199999999996 -0.012775699999999999 +0.20972499999999999 -0.032038700000000003 -0.30220599999999997 0.55140500000000003 0.83404199999999995 -0.018043500000000001 +0.25982 0.0251346 -0.030842499999999998 0.75277700000000003 0.65825699999999998 0.0049598100000000003 +0.20009399999999999 -0.022992100000000001 -0.0485371 0.7903 0.61267000000000005 -0.00777643 +-0.26807900000000001 -0.022423999999999999 -0.0837788 0.85328400000000004 0.52124400000000004 0.0145611 +0.23372100000000001 0.038203300000000003 -0.0275274 0.113541 0.99351599999999995 0.0058895400000000004 +-0.26619100000000001 -0.025119200000000001 -0.0656032 0.82634300000000005 0.56315800000000005 -0.0031419299999999998 +0.21901100000000001 -0.036516100000000003 -0.065934300000000001 0.26129000000000002 0.96511999999999998 -0.016486399999999998 +-0.190139 -0.0156182 -0.075191099999999997 0.938245 -0.34596100000000002 -0.00274332 +-0.22464799999999999 0.043054299999999997 -0.19600100000000001 0.152527 0.98829900000000004 0 +0.20638200000000001 -0.029697999999999999 -0.18881600000000001 0.63555799999999996 0.77196200000000004 0.0118619 +0.19403400000000001 -0.0109411 -0.32190000000000002 0.96094100000000005 0.27675499999999997 0 +-0.24015300000000001 -0.042441300000000001 -0.32339200000000001 0.222751 0.97477400000000003 0.014071800000000001 +0.192327 0.00021293700000000001 -0.27011200000000002 0.99992000000000003 -0.012655899999999999 0.00034663499999999998 +0.19995399999999999 0.022791800000000001 -0.26512000000000002 0.79571700000000001 -0.60540499999999997 -0.017865599999999999 +0.23157700000000001 0.038390800000000003 -0.038881899999999997 0.0086943999999999997 0.99974099999999999 -0.021015200000000001 +-0.26966400000000001 0.0193388 -0.22794600000000001 0.88440300000000005 -0.46650999999999998 0.0141085 +-0.23274300000000001 0.0434171 -0.075470499999999996 -0.027704300000000001 0.99943400000000004 0.0190717 +-0.24423400000000001 0.041347799999999997 -0.143203 -0.30313400000000001 0.95294400000000001 -0.00283622 +0.201574 -0.024990100000000001 -0.26061200000000001 0.74262399999999995 0.66904300000000005 0.029868700000000001 +-0.24909300000000001 -0.039368500000000001 -0.27885500000000002 0.42779400000000001 0.90375899999999998 -0.0145395 +-0.19917699999999999 -0.029818399999999998 -0.126026 0.72622399999999998 -0.68737599999999999 0.010561600000000001 +0.217447 0.036063699999999997 -0.105684 -0.37377500000000002 0.92744099999999996 -0.0120263 +-0.196989 0.0274633 -0.31908900000000001 0.77932500000000005 0.62652300000000005 0.0110169 +-0.18795300000000001 -0.0079853200000000006 -0.19970399999999999 0.97919500000000004 -0.201122 0.026975200000000001 +0.19809099999999999 0.0201303 -0.27634700000000001 0.851244 -0.524281 -0.022645499999999999 +-0.27395900000000001 -0.0045715599999999997 -0.12923399999999999 0.99552700000000005 0.094370999999999997 0.0043877899999999999 +0.19764100000000001 0.019487299999999999 -0.174204 0.86214100000000005 -0.50661400000000001 -0.0074265299999999998 +0.261467 -0.0229596 -0.116836 0.72513499999999997 -0.68859300000000001 0.0044172600000000001 +0.225823 0.038028699999999999 -0.12695500000000001 -0.12982199999999999 0.99125300000000005 0.023730000000000001 +0.19926099999999999 0.0218012 -0.093173300000000001 0.82902399999999998 -0.55883799999999995 0.020491800000000001 +-0.18851499999999999 -0.0100815 -0.23638799999999999 0.97451600000000005 -0.22426499999999999 -0.0048445600000000004 +0.21129200000000001 0.033136199999999998 -0.029669500000000001 -0.52092300000000002 0.853356 -0.020577700000000001 +0.21318300000000001 0.034075599999999998 -0.237735 -0.45302300000000001 0.89132800000000001 -0.017451500000000002 +-0.27208300000000002 0.013591600000000001 -0.16902900000000001 0.94195700000000004 -0.33438899999999999 0.030021300000000001 +-0.25765900000000003 -0.034182400000000002 -0.15343499999999999 0.60660499999999995 0.79500300000000002 0 +0.19286900000000001 -0.0064166700000000002 -0.077132400000000004 0.98867700000000003 0.149725 0.0100482 +-0.195081 -0.024739500000000001 -0.063060699999999997 0.83279899999999996 -0.55341200000000002 -0.013483500000000001 +0.20802300000000001 -0.030847300000000001 -0.28214699999999998 0.55636200000000002 0.83093399999999995 -0.0032905299999999998 +-0.26958399999999999 0.019510300000000001 -0.16922999999999999 0.89783400000000002 -0.44028099999999998 -0.0068591600000000004 +0.19300500000000001 -0.0071003899999999998 -0.096745100000000001 0.97813399999999995 0.203148 -0.0445505 +0.221417 -0.037160699999999998 -0.17931900000000001 0.22489500000000001 0.97436699999999998 0.0054905600000000002 +0.19839499999999999 -0.020564599999999999 -0.060180299999999999 0.81999 0.57235000000000003 0.0056135500000000001 +0.25827499999999998 0.026680300000000001 -0.15259200000000001 0.74000299999999997 0.67189600000000005 -0.0308475 +-0.18853500000000001 0.010155300000000001 -0.099570900000000004 0.97003499999999998 0.24296599999999999 0 +0.213814 -0.034369700000000003 -0.020131199999999998 0.445104 0.89540500000000001 0.0114964 +0.26231700000000002 0.021745299999999999 -0.073430999999999996 0.82179800000000003 0.56975699999999996 -0.0049047099999999996 +-0.27319900000000003 -0.0094284999999999994 -0.32184200000000002 0.97596000000000005 0.21699299999999999 0.020393700000000001 +0.19420299999999999 0.011570799999999999 -0.13655400000000001 0.94314399999999998 -0.33223200000000003 -0.010038 +0.26212999999999997 0.022012 -0.057155200000000003 0.80661700000000003 0.59100200000000003 0.0091999200000000003 +0.26286799999999999 0.020959100000000001 -0.088493100000000005 0.84903200000000001 0.52832199999999996 0.0045059000000000002 +-0.27333800000000003 -0.00890845 -0.229433 0.974576 0.22403200000000001 -0.0034194 +-0.23728099999999999 -0.043020000000000003 -0.30196299999999998 0.174764 0.98458699999999999 -0.0067037399999999997 +0.24011099999999999 0.037163500000000002 -0.15179100000000001 0.23504900000000001 0.97192699999999999 0.0104549 +0.231766 -0.038374199999999997 -0.19669800000000001 -0.036061200000000002 0.99907100000000004 -0.023608799999999999 +0.24897900000000001 0.033784700000000001 -0.066711199999999998 0.48424600000000001 0.87475099999999995 -0.017808899999999999 +0.19555800000000001 0.01515 -0.195857 0.94163600000000003 -0.33662399999999998 -0.0025800100000000002 +0.19440099999999999 -0.0123114 -0.021749000000000001 0.93135900000000005 0.364095 -0.0021432600000000001 +0.25663799999999998 -0.028317200000000001 -0.038677299999999998 0.71432300000000004 -0.69979499999999994 0.0054922199999999999 +-0.227739 -0.043324700000000001 -0.104516 -0.108511 0.99274499999999999 -0.0517945 +0.25435999999999998 0.030255500000000001 -0.15645700000000001 0.64217299999999999 0.76649699999999998 -0.0098145300000000001 +0.25839699999999999 -0.026557799999999999 -0.224518 0.71059399999999995 -0.70358299999999996 0.0051330799999999999 +0.25858799999999998 -0.0263672 -0.17305000000000001 0.75339900000000004 -0.65532500000000005 -0.054219700000000003 +0.207709 0.030627100000000001 -0.23763999999999999 -0.62297400000000003 0.78177200000000002 0.027136899999999999 +-0.229771 0.0435025 -0.23938400000000001 0.0272838 0.99962499999999999 -0.00221455 +0.26350400000000002 -0.020051099999999999 -0.294103 0.851989 -0.52319300000000002 0.0195841 +-0.26975100000000002 -0.019152200000000001 -0.23749400000000001 0.89280099999999996 0.45024799999999998 0.013568999999999999 +0.26641199999999998 -0.014225700000000001 -0.21384700000000001 0.92296500000000004 -0.38375500000000001 0.0294408 +0.22487399999999999 -0.037945699999999999 -0.156193 0.11292199999999999 0.99360300000000001 0.0011027400000000001 +0.25968799999999997 -0.025266199999999999 -0.14422499999999999 0.755413 -0.65524899999999997 0 +0.218969 -0.036504799999999997 -0.212783 0.30785200000000001 0.95108599999999999 0.025730099999999999 +0.20215 0.025566100000000001 -0.18889700000000001 0.74968000000000001 -0.66075399999999995 0.037200200000000003 +0.26022400000000001 -0.024731 -0.081554600000000005 0.73985599999999996 -0.67275099999999999 -0.0043410999999999996 +0.19872400000000001 -0.021034299999999999 -0.136187 0.85892100000000005 0.51209700000000002 -0.00328378 +-0.21614700000000001 0.041037499999999998 -0.146899 0.35832599999999998 0.93359000000000003 -0.00364927 +0.20721899999999999 -0.0302837 -0.092460700000000007 0.57566300000000004 0.81762199999999996 0.0103672 +-0.21324000000000001 0.039738700000000002 -0.227105 0.38775700000000002 0.92170799999999997 0.0099794700000000007 +-0.188503 -0.010038699999999999 -0.29707299999999998 0.97141200000000005 -0.2374 -0.00074075699999999998 +-0.23252700000000001 -0.0434359 -0.22765299999999999 0.052683500000000001 0.99860599999999999 0.0031356299999999999 +0.19258900000000001 -0.0032182700000000001 -0.14532900000000001 0.98941599999999996 0.14478199999999999 0.0096564300000000006 +0.244814 -0.035727000000000002 -0.20067199999999999 -0.38648900000000003 0.92207099999999997 0.0202624 +0.230741 0.038459100000000003 -0.067234699999999994 -0.089363200000000004 0.99595900000000004 0.0089669699999999995 +-0.224996 -0.043084699999999997 -0.059131499999999997 -0.150481 0.98859799999999998 -0.0054425000000000003 +-0.2286 -0.043400000000000001 -0.20216200000000001 -0.077737100000000003 0.99687199999999998 -0.0142376 +-0.21404599999999999 0.040114499999999997 -0.232406 0.41288000000000002 0.91076599999999996 0.0059103999999999997 +-0.197578 -0.028218900000000002 -0.052612800000000001 0.78384100000000001 -0.62078100000000003 0.015008499999999999 +0.20619799999999999 -0.029569000000000002 -0.28048699999999999 0.618703 0.78560099999999999 -0.0060884299999999997 +-0.27301399999999998 -0.010119299999999999 -0.230154 0.963418 0.26782099999999998 0.0098798199999999992 +0.26322000000000001 0.0204564 -0.024634400000000001 0.85168500000000003 0.52396100000000001 -0.0099213500000000007 +0.23621700000000001 0.037984900000000002 -0.14047200000000001 0.12141299999999999 0.99251599999999995 0.0130451 +0.19489300000000001 0.0137252 -0.12380099999999999 0.92139499999999996 -0.38814199999999999 -0.019391700000000001 +0.242672 0.0364774 -0.0551566 0.30160799999999999 0.953399 -0.0079016299999999998 +0.26705699999999999 -0.0126082 -0.142461 0.92154700000000001 -0.388241 0.0045949600000000004 +0.247722 -0.034370900000000003 -0.080750100000000005 -0.44675399999999998 0.89462600000000003 0.0074257000000000004 +0.21987599999999999 -0.0367479 -0.051797500000000003 0.28713100000000003 0.95786400000000005 -0.0071762700000000002 +-0.254245 0.0365727 -0.17810999999999999 -0.52911399999999997 0.84846699999999997 0.0119539 +0.238257 0.0376605 -0.090334600000000001 0.23311999999999999 0.97223999999999999 0.0200888 +0.21993299999999999 0.0367631 -0.071150500000000005 -0.271453 0.96242700000000003 0.0068897300000000002 +0.248947 -0.033799599999999999 -0.30299900000000002 -0.48425200000000002 0.87492800000000004 0 +-0.23711599999999999 -0.043034500000000003 -0.20530699999999999 0.10495699999999999 0.99446999999999997 0.0037221699999999999 +-0.206035 -0.035692099999999997 -0.225185 -0.555836 0.831202 -0.0122541 +-0.20466300000000001 -0.034731600000000001 -0.215062 -0.58796499999999996 0.80888599999999999 0 +-0.23583999999999999 -0.0431461 -0.27249400000000001 0.083999799999999999 0.99646500000000005 0.0014334199999999999 +-0.22136500000000001 -0.042436000000000001 -0.15434899999999999 -0.21079000000000001 0.97726999999999997 0.022585999999999998 +0.26470300000000002 0.0178906 -0.22778699999999999 0.87509999999999999 0.48355999999999999 -0.019225099999999998 +-0.198489 -0.029130099999999999 -0.21573000000000001 0.72602500000000003 -0.68756700000000004 -0.0117748 +0.22700300000000001 0.038131999999999999 -0.13630700000000001 -0.091942599999999999 0.99536599999999997 -0.0281689 +-0.19400000000000001 0.0231956 -0.31954500000000002 0.83876700000000004 0.54433799999999999 0.0128428 +0.239097 0.037435400000000001 -0.0358331 0.21973300000000001 0.97551900000000002 -0.00888392 +0.26175700000000002 -0.0225449 -0.14390600000000001 0.78473899999999996 -0.61969799999999997 0.01264 +0.20703099999999999 0.0301523 -0.098693600000000006 -0.60883100000000001 0.79232499999999995 0.039312399999999997 +-0.229769 -0.043502199999999998 -0.16001299999999999 0.0037120199999999999 0.99998500000000001 -0.00414664 +-0.19977700000000001 0.030417900000000001 -0.16528300000000001 0.73148599999999997 0.681782 -0.0100807 +0.24362900000000001 -0.036221099999999999 -0.27044299999999999 -0.258436 0.96590399999999998 -0.0155021 +-0.19047800000000001 -0.016344600000000001 -0.21731 0.92425800000000002 -0.38128000000000001 0.019293299999999999 +0.19909099999999999 -0.021559499999999999 -0.059946300000000001 0.81999 0.57235000000000003 0.0056135500000000001 +-0.220137 0.0421068 -0.14644399999999999 0.25026700000000002 0.96793600000000002 0.021586299999999999 +0.22720199999999999 -0.0381494 -0.323069 -0.065554399999999999 0.99370999999999998 -0.090795000000000001 +-0.22574900000000001 0.043150599999999997 -0.24531500000000001 0.10277799999999999 0.99469099999999999 -0.0051776799999999996 +-0.25693700000000003 0.034687700000000002 -0.28675 -0.59937600000000002 0.80042899999999995 0.0079077100000000001 +-0.223354 0.042941100000000003 -0.10097100000000001 0.17390900000000001 0.98475800000000002 0.0028345800000000002 +-0.26476699999999997 0.027152900000000001 -0.22222600000000001 0.79411900000000002 -0.60775199999999996 -0.0035269699999999999 +-0.243532 -0.041536099999999999 -0.087260199999999996 0.31483899999999998 0.94913499999999995 0.00446299 +0.19415399999999999 0.0113901 -0.081432900000000003 0.94822899999999999 -0.31736500000000001 0.0118356 +-0.207675 0.036840100000000001 -0.062832899999999997 0.54479500000000003 0.83841600000000005 -0.016058800000000002 +-0.22371199999999999 -0.042972299999999998 -0.19413900000000001 -0.15906899999999999 0.98726700000000001 0.0011727300000000001 +-0.18876299999999999 0.0110072 -0.170094 0.97219800000000001 0.23369000000000001 0.0148004 +0.219668 0.0366919 -0.031958300000000002 -0.32086999999999999 0.94655500000000004 0.032801200000000003 +0.26204499999999997 -0.022133699999999999 -0.029282800000000001 0.82227700000000004 -0.56900300000000004 -0.0098126299999999993 +-0.24643999999999999 0.040605799999999997 -0.28410099999999999 -0.370587 0.92879800000000001 0 +0.20019200000000001 0.0231308 -0.18987799999999999 0.83778200000000003 -0.54581800000000003 0.0143042 +-0.18981300000000001 0.0149184 -0.18207599999999999 0.94119699999999995 0.337644 0.0120804 +0.25854700000000003 0.0264075 -0.16434199999999999 0.76454800000000001 0.64427199999999996 -0.019463899999999999 +-0.24099400000000001 -0.042215900000000001 -0.19638900000000001 0.23036300000000001 0.97306899999999996 0.0083878700000000004 +-0.262577 0.029602799999999999 -0.289939 0.720302 -0.69366099999999997 0 +0.25580999999999998 -0.0291451 -0.229883 -0.64971999999999996 0.76012900000000005 -0.0081906099999999992 +0.246082 -0.035135600000000003 -0.252724 -0.44920900000000002 0.89334199999999997 0.0123097 +-0.19359499999999999 -0.0226173 -0.056372499999999999 0.85726400000000003 -0.51485899999999996 0.0042460700000000002 +0.193768 -0.0099496399999999992 -0.058493299999999998 0.96307600000000004 0.269094 -0.0085218700000000008 +-0.22214300000000001 -0.042644399999999999 -0.17829300000000001 -0.215054 0.97659600000000002 0.0033770800000000002 +0.25653599999999999 0.028419099999999999 -0.12285699999999999 0.69348699999999996 0.72043800000000002 0.0067413300000000002 +0.22198999999999999 -0.037314300000000002 -0.14918400000000001 0.21461 0.97653500000000004 -0.0179186 +0.247831 -0.034320200000000002 -0.14954000000000001 -0.42884100000000003 0.90307999999999999 -0.023258500000000001 +0.259077 0.025877600000000001 -0.23168 0.77739400000000003 0.62887400000000004 0.013278099999999999 +0.26494800000000002 0.017364600000000001 -0.22195699999999999 0.87888999999999995 0.47590300000000002 -0.032682000000000003 +-0.18770999999999999 0.0060596299999999999 -0.18724399999999999 0.99345499999999998 0.112243 -0.021174599999999998 +0.19487199999999999 0.0136808 -0.035893300000000003 0.949013 -0.31519900000000001 0.0049545700000000002 +-0.221694 -0.042523900000000003 -0.29455599999999998 -0.204097 0.97888900000000001 -0.0109795 +0.208429 -0.031131700000000002 -0.18201100000000001 0.55542499999999995 0.83150900000000005 -0.0098052899999999995 +0.22442300000000001 0.037906299999999997 -0.32357000000000002 -0.15488199999999999 0.987842 0.0134208 +0.22175600000000001 -0.037251699999999999 -0.22676099999999999 0.22478799999999999 0.97438000000000002 -0.0073173099999999996 +0.195272 -0.014538199999999999 -0.224302 0.92828500000000003 0.37186799999999998 0 +0.203823 0.027239300000000001 -0.067621500000000001 -0.69358900000000001 0.72030300000000003 -0.0098936300000000005 +0.19669 0.017576899999999999 -0.18796599999999999 0.88642500000000002 -0.46286300000000002 0.0028257299999999998 +0.24570600000000001 -0.035311000000000002 -0.19157299999999999 -0.37537100000000001 0.92680899999999999 -0.0110294 +0.196633 -0.017455399999999999 -0.18399599999999999 0.90826200000000001 0.41807100000000003 -0.016625999999999998 +-0.18931300000000001 -0.0130615 -0.077947299999999997 0.95410899999999998 -0.29801299999999997 0.029413999999999999 +0.25797500000000001 0.026980199999999999 -0.083710599999999996 0.71649300000000005 0.69678899999999999 -0.033501999999999997 +-0.188109 0.0085652699999999998 -0.16425600000000001 0.97921100000000005 0.202599 0.0099925799999999992 +-0.19054099999999999 0.016479799999999999 -0.29388300000000001 0.91384600000000005 0.40547 0.021886200000000001 +0.26549899999999999 0.016182200000000001 -0.17557400000000001 0.90252900000000003 0.43054999999999999 0.00821501 +-0.19212899999999999 0.0198873 -0.27528200000000003 0.90098800000000001 0.43367699999999998 -0.011979999999999999 +-0.26444099999999998 0.027619600000000001 -0.22999600000000001 0.79224799999999995 -0.61019900000000005 0 +0.204652 0.0280684 -0.115117 -0.69191800000000003 0.72191700000000003 0.0092632800000000005 +-0.25079000000000001 0.038577199999999999 -0.23508899999999999 -0.42619400000000002 0.90461499999999995 0.0055851 +-0.24177000000000001 -0.042007999999999997 -0.26674399999999998 0.25838699999999998 0.965808 -0.021215700000000001 +0.215165 -0.034999700000000002 -0.17765700000000001 0.41872599999999999 0.90805899999999995 -0.0098734200000000008 +-0.19995199999999999 0.030593499999999999 -0.144096 0.70439399999999996 0.70978300000000005 -0.0061240499999999998 +-0.18995300000000001 0.0152205 -0.10962 0.947496 0.31975999999999999 0.00210932 +0.19609599999999999 0.0163044 -0.191909 0.90452200000000005 -0.426311 -0.0099930699999999997 +0.26884200000000003 0.0044398700000000003 -0.23808499999999999 0.99590100000000004 0.090373599999999998 -0.0036718599999999999 +0.217195 -0.035946400000000003 -0.229851 0.330957 0.94364599999999998 0 +-0.21328 -0.0397577 -0.139934 -0.414993 0.90968899999999997 -0.015684699999999999 +0.21699099999999999 0.035850899999999998 -0.140565 -0.35973100000000002 0.93289100000000003 0.0175306 +0.26302599999999998 -0.020732799999999999 -0.023290700000000001 0.84327300000000005 -0.53748499999999999 0 +0.25893899999999997 -0.026015900000000002 -0.044101399999999999 0.77909799999999996 -0.62690199999999996 0 +0.25616499999999998 -0.028790199999999998 -0.25696099999999999 -0.65190300000000001 0.75731999999999999 0.038595499999999998 +-0.273119 0.0097272699999999997 -0.17229700000000001 0.97152400000000005 -0.23677999999999999 0.0087129200000000007 +0.25852399999999998 0.026431099999999999 -0.076594499999999996 0.73192500000000005 0.681365 -0.0053423899999999998 +-0.26261000000000001 0.0295704 -0.30474800000000002 0.74583999999999995 -0.66598100000000005 0.013834300000000001 +0.21516099999999999 0.034997899999999998 -0.15304000000000001 -0.36315900000000001 0.93165699999999996 -0.011403699999999999 +0.26253300000000002 0.021437600000000001 -0.31830700000000001 0.84136500000000003 0.54046400000000006 0.0019519100000000001 +0.19705600000000001 -0.018362400000000001 -0.31386900000000001 0.888181 0.45948800000000001 0.0022174400000000002 +0.25497300000000001 0.029826800000000001 -0.31502400000000003 0.62983699999999998 0.776451 0.0207449 +0.25438899999999998 0.0302358 -0.068646799999999994 0.59419500000000003 0.80432099999999995 0 +0.26804600000000001 -0.0089166899999999997 -0.28671600000000003 0.97367099999999995 -0.226052 -0.0294314 +-0.22353200000000001 -0.0429567 -0.31637799999999999 -0.16971700000000001 0.98541599999999996 -0.0123485 +0.193631 -0.00943862 -0.27957500000000002 0.97556100000000001 0.21972700000000001 -0.00108085 +-0.23313800000000001 0.043382499999999997 -0.10403999999999999 -0.040162999999999997 0.99904199999999999 0.017377199999999999 +0.25276300000000002 -0.031374300000000001 -0.29739500000000002 -0.61125799999999997 0.79141499999999998 0.0051581700000000001 +0.19664499999999999 -0.017481900000000002 -0.113315 0.90198500000000004 0.43176799999999999 0 +0.20738400000000001 0.030399800000000001 -0.14653099999999999 -0.62951599999999996 0.77674299999999996 -0.019477499999999998 +-0.19409699999999999 -0.0233346 -0.089321899999999996 0.84563500000000003 -0.53369 0.0087581599999999992 +0.23252500000000001 0.038307899999999999 -0.29439700000000002 0.041979500000000003 0.99907100000000004 0.0097292300000000002 +0.225212 0.037975299999999997 -0.28534100000000001 -0.18625900000000001 0.98239600000000005 0.0143172 +-0.27101500000000001 0.016442499999999999 -0.30526900000000001 0.92399299999999995 -0.38241000000000003 0 +-0.215 0.040559600000000001 -0.16569900000000001 0.350966 0.93634700000000004 0.0088278899999999997 +0.25468400000000002 -0.030028699999999998 -0.011577499999999999 -0.62583699999999998 0.77988299999999999 -0.0104689 +0.268627 -0.0067480300000000003 -0.15371399999999999 0.98593600000000003 -0.16705900000000001 -0.0046532700000000001 +-0.25486199999999998 -0.036141100000000002 -0.32178299999999999 0.54598899999999995 0.83775599999999995 0.0077764000000000002 +-0.21432200000000001 0.040243399999999999 -0.29939399999999999 0.357236 0.93400899999999998 0.0030683799999999999 +0.26892199999999999 -0.0035326400000000001 -0.152728 0.99549200000000004 -0.094139200000000006 0.0115332 +0.23180500000000001 0.038370799999999997 -0.17935400000000001 -0.041583299999999997 0.99906499999999998 0.011820600000000001 +-0.19209899999999999 -0.019821399999999999 -0.20213999999999999 0.89383400000000002 -0.44839699999999999 0 +0.247362 -0.034538600000000003 -0.029452300000000001 -0.45524399999999998 0.89036400000000004 -0.00206121 +0.25953900000000002 0.0254161 -0.31273499999999999 0.70725000000000005 0.70682 -0.0142107 +-0.20113500000000001 0.031776100000000002 -0.29448200000000002 0.68024700000000005 0.73272599999999999 0.0194171 +0.202399 -0.025815500000000002 -0.13150800000000001 0.73836000000000002 0.67440199999999995 0.0026323200000000001 +0.19392599999999999 0.0105366 -0.14682100000000001 0.96273200000000003 -0.270426 0.0039821700000000002 +-0.20653199999999999 -0.036040000000000003 -0.106833 -0.54984900000000003 0.83522300000000005 -0.0083048800000000006 +0.246585 -0.034901300000000003 -0.176007 -0.417186 0.90881199999999995 0.0041603300000000003 +0.22054699999999999 0.036927599999999998 -0.077576900000000004 -0.24185699999999999 0.97030300000000003 0.0042644199999999997 +-0.20638400000000001 -0.035936599999999999 -0.15499099999999999 -0.54501500000000003 0.83829900000000002 -0.014616499999999999 +-0.199795 -0.030436000000000001 -0.27670800000000001 -0.68764599999999998 0.72598099999999999 -0.0097067799999999999 +-0.249444 0.039204900000000001 -0.318247 -0.46437400000000001 0.88558300000000001 0.0099594599999999998 +0.19522800000000001 -0.0144429 -0.227386 0.93570600000000004 0.35273199999999999 0.0059508399999999998 +0.19572800000000001 0.015515299999999999 -0.10353 0.92129499999999998 -0.38885999999999998 0.00190771 +0.21393300000000001 0.034425499999999998 -0.028295500000000001 -0.42803400000000003 0.90366500000000005 0.013306699999999999 +-0.205904 0.035600399999999997 -0.13104399999999999 0.566415 0.82389900000000005 -0.019074299999999999 +0.25492599999999999 -0.029859299999999998 -0.32450400000000001 -0.63405100000000003 0.76388299999999998 -0.12026000000000001 +0.215141 0.034988600000000002 -0.229933 -0.39060299999999998 0.920408 0.0166959 +0.211369 0.033190299999999999 -0.0851711 -0.50981799999999999 0.86016400000000004 0.0142492 +0.23889099999999999 0.0374904 -0.057886 0.23199 0.97267199999999998 -0.0094527699999999992 +-0.212057 -0.039187600000000003 -0.32100000000000001 -0.39233400000000002 0.91980300000000004 0.0060481900000000002 +-0.19376399999999999 0.022858400000000001 -0.319552 0.86690999999999996 0.49845099999999998 -0.0035660000000000002 +-0.26741700000000002 0.023369500000000001 -0.062074400000000002 0.82365900000000003 -0.56706999999999996 -0.0041858199999999998 +-0.190856 -0.0171551 -0.27209699999999998 0.91970700000000005 -0.39260600000000001 0 +-0.27276400000000001 0.011050900000000001 -0.26446799999999998 0.95776899999999998 -0.28743800000000003 0.00764016 +-0.19608700000000001 0.026176000000000001 -0.303672 0.82701000000000002 0.56217600000000001 0.0037012899999999999 +0.24360999999999999 0.036226099999999997 -0.324716 0.37149799999999999 0.90206299999999995 0.21970799999999999 +-0.19409100000000001 0.023326199999999998 -0.0892458 0.85594199999999998 0.51602899999999996 -0.032822999999999998 +0.199796 0.022565999999999999 -0.018931 0.818577 -0.57439099999999998 -0.0026602000000000002 +0.19304099999999999 0.0072362099999999999 -0.12507499999999999 0.98167000000000004 -0.19000600000000001 0.014861299999999999 +0.25781999999999999 0.027134999999999999 -0.079161599999999999 0.72819900000000004 0.68518000000000001 -0.015951799999999999 +-0.24652199999999999 0.040567499999999999 -0.107449 -0.34105099999999999 0.94001100000000004 -0.0080234399999999997 +-0.18885299999999999 0.0113437 -0.060122599999999998 0.97645199999999999 0.21568799999999999 0.0044160800000000002 +0.19270699999999999 -0.00456012 -0.22512499999999999 0.99113899999999999 0.132494 -0.0094096900000000001 +0.26078699999999999 -0.023930400000000001 -0.124268 0.74699899999999997 -0.66378999999999999 -0.037094799999999997 +-0.236979 -0.043046500000000001 -0.0544865 0.10931 0.99388699999999996 0.0155029 +0.21052799999999999 0.032601699999999997 -0.15095700000000001 -0.52748899999999999 0.84952700000000003 0.0077400400000000001 +-0.27385700000000002 0.0057351299999999997 -0.214445 0.990734 -0.135768 0.00365212 +0.19300500000000001 -0.0070988400000000004 -0.025329000000000001 0.98502699999999999 0.17155999999999999 -0.017018999999999999 +-0.21646699999999999 -0.041123399999999997 -0.176539 -0.32139899999999999 0.94677999999999995 -0.0176077 +0.25502000000000002 0.029793500000000001 -0.25081199999999998 0.63785599999999998 0.77014199999999999 0.0045760499999999999 +-0.252085 -0.037973100000000003 -0.297989 0.52626799999999996 0.85023899999999997 -0.0116109 +-0.191636 -0.0188299 -0.32168200000000002 0.93071700000000002 -0.35788700000000001 0.075386300000000003 +-0.214058 0.040120400000000001 -0.0495945 0.39190199999999997 0.919956 -0.0097161899999999995 +-0.249639 0.039114000000000003 -0.31062800000000002 -0.44200699999999998 0.897011 0.0014588699999999999 +0.213139 0.034055099999999998 -0.157469 -0.449073 0.892872 -0.033356700000000003 +0.238012 0.037726000000000003 -0.100411 0.179283 0.98379700000000003 0.00098922500000000004 +-0.205729 -0.035478000000000003 -0.30626500000000001 -0.59441600000000006 0.804118 0.0080142900000000003 +0.23216500000000001 -0.0383393 -0.166463 -0.00030468900000000002 0.99976900000000002 0.021474300000000002 +-0.18728600000000001 0.00122583 -0.14982100000000001 0.99956999999999996 0.028535600000000001 -0.00676108 +-0.24501999999999999 -0.041137199999999999 -0.076838500000000004 0.281333 0.95960999999999996 0 +-0.25525199999999998 -0.035867599999999999 -0.18490200000000001 0.60260800000000003 0.79801999999999995 0.0053649300000000004 +0.22528100000000001 -0.037981300000000003 -0.22870699999999999 0.13965900000000001 0.99018399999999995 0.0054997099999999997 +-0.22822300000000001 -0.043367000000000003 -0.086366999999999999 -0.100135 0.99379499999999998 0.048414499999999999 +0.25032700000000002 -0.033079600000000001 -0.080263500000000002 -0.50337900000000002 0.86399800000000004 -0.010826199999999999 +0.23524999999999999 -0.038069499999999999 -0.035420800000000002 -0.15914300000000001 0.987035 -0.020874500000000001 +-0.21662300000000001 -0.041165300000000002 -0.18413199999999999 -0.31234299999999998 0.94990300000000005 0.011214399999999999 +-0.19778599999999999 -0.028427000000000001 -0.072907600000000003 0.74900599999999995 -0.662327 -0.017682400000000001 +0.247747 0.034359000000000001 -0.22403000000000001 0.42776900000000001 0.90381999999999996 0.0111021 +0.20034099999999999 -0.023345000000000001 -0.30164800000000003 0.79196699999999998 0.61055000000000004 -0.0041860200000000004 +0.231545 0.0383936 -0.316133 0.025602699999999999 0.99921199999999999 -0.030324899999999998 +0.231433 0.0384035 -0.035368400000000001 -0.0096516499999999995 0.99987099999999995 -0.0128139 +0.19520299999999999 0.014389600000000001 -0.226858 0.91076699999999999 -0.41128300000000001 0.036744100000000002 +-0.19188 0.019352100000000001 -0.239764 0.87945799999999996 0.47589199999999998 -0.0090176700000000002 +-0.236592 0.043080300000000002 -0.13830600000000001 -0.13782700000000001 0.99045300000000003 0.0026431800000000002 +-0.18781200000000001 -0.0072217000000000002 -0.113722 0.97418000000000005 -0.22498099999999999 0.018901899999999999 +-0.24048700000000001 -0.042351699999999999 -0.15337500000000001 0.26339800000000002 0.96455299999999999 0.016126000000000001 +0.19909399999999999 0.021563200000000001 -0.21602399999999999 0.82433900000000004 -0.56603800000000004 -0.00809554 +-0.25591000000000003 0.035406899999999998 -0.167328 -0.56251399999999996 0.82666899999999999 0.0140281 +0.19709399999999999 0.018443500000000002 -0.018694499999999999 0.88443700000000003 -0.46666000000000002 0 +-0.228435 -0.043385600000000003 -0.13138 -0.071891499999999997 0.99679200000000001 0.035165299999999997 +0.22783 0.038204399999999999 -0.042577700000000003 -0.11604399999999999 0.99313499999999999 -0.0146915 +-0.21407699999999999 0.0401293 -0.19452900000000001 0.34773799999999999 0.93759199999999998 0 +0.22331400000000001 0.037668899999999998 -0.234432 -0.23285600000000001 0.97195900000000002 -0.032772099999999998 +-0.19051599999999999 0.016427299999999999 -0.23098299999999999 0.92064100000000004 0.39040999999999998 0 +-0.27339000000000002 0.0087142699999999997 -0.242815 0.97778799999999999 -0.209587 0.0019991200000000001 +0.266959 0.0129759 -0.165801 0.93965699999999996 0.342117 0 +0.19372800000000001 -0.0097990500000000001 -0.039134599999999999 0.96781099999999998 0.251585 0.0069152299999999996 +-0.23814099999999999 0.042944900000000001 -0.27822200000000002 -0.16994400000000001 0.98527699999999996 0.018650099999999999 +0.221105 -0.037077199999999998 -0.088753700000000005 0.256855 0.966445 0.0029995199999999999 +-0.18849099999999999 0.0099934800000000008 -0.26994000000000001 0.97467499999999996 0.21836800000000001 0.048207800000000002 +0.23658899999999999 0.037952399999999997 -0.079355700000000001 0.142956 0.98971100000000001 0.00591955 +0.26854 -0.0070753600000000002 -0.030339600000000001 0.98199700000000001 -0.188892 -0.00100811 +-0.26209500000000002 -0.030085299999999999 -0.107867 0.73492199999999996 0.67796699999999999 0.0158347 +-0.19494300000000001 0.024541899999999998 -0.121 0.84016999999999997 0.54230999999999996 -0.0037586400000000002 +-0.239449 -0.042629899999999998 -0.21560099999999999 0.223519 0.97434699999999996 -0.026196400000000002 +0.26855899999999999 -0.0070037399999999996 -0.068468799999999996 0.97265999999999997 -0.23222400000000001 -0.00225566 +0.26769900000000002 0.010214900000000001 -0.25836399999999998 0.96825799999999995 0.249893 0.0055066200000000003 +-0.26042999999999999 0.031750199999999999 -0.16641400000000001 -0.69236699999999995 0.72153900000000004 -0.0031752099999999999 +0.20438100000000001 0.027796999999999999 -0.25022699999999998 -0.67872600000000005 0.73431800000000003 0.010409099999999999 +-0.229133 -0.043446600000000002 -0.31462099999999998 -0.045531500000000003 0.99870099999999995 0.022865799999999999 +0.21994 0.036764900000000003 -0.0153816 -0.25640099999999999 0.96657099999999996 0 +0.25453599999999998 -0.0301324 -0.197491 -0.590835 0.806724 0.0105129 +-0.18726200000000001 0.00094320600000000004 -0.121637 0.99899300000000002 0.040058000000000003 0.020202000000000001 +0.246804 -0.034798900000000001 -0.14943699999999999 -0.41927799999999998 0.90680700000000003 -0.043664399999999999 +0.268399 0.0075997 -0.30965599999999999 0.97952799999999995 0.20130899999999999 -0.000566848 +-0.239898 -0.042509699999999997 -0.10063999999999999 0.21889400000000001 0.97565299999999999 0.0136621 +0.21809600000000001 0.036270700000000003 -0.073799400000000001 -0.33639400000000003 0.94169499999999995 -0.0070041000000000001 +0.21657499999999999 0.0356572 -0.123499 -0.35375200000000001 0.93532800000000005 -0.0045299600000000004 +0.206959 -0.030101599999999999 -0.18104899999999999 0.56852400000000003 0.82265299999999997 0.0047151299999999997 +0.26219500000000001 0.0219197 -0.010315400000000001 0.80412099999999997 0.59443500000000005 0.0061012100000000001 +0.20707600000000001 0.030183600000000001 -0.13950399999999999 -0.64636000000000005 0.76300800000000002 0.0060546300000000001 +-0.20181099999999999 0.032452399999999999 -0.047325899999999997 0.63202899999999995 0.77458099999999996 0.023750299999999998 +-0.18767300000000001 -0.0056347300000000001 -0.119856 0.98583100000000001 -0.16697100000000001 -0.016053399999999999 +-0.19809299999999999 0.0287338 -0.23765500000000001 0.75988500000000003 0.65004499999999998 0.0040994999999999998 +0.21884400000000001 0.036471099999999999 -0.17444499999999999 -0.31338899999999997 0.94950500000000004 -0.015089399999999999 +0.24199899999999999 0.036657799999999997 -0.16789799999999999 0.34072599999999997 0.93993400000000005 -0.020716700000000001 +0.26621899999999998 0.0146398 -0.083151199999999995 0.91989299999999996 0.39138600000000001 -0.024791199999999999 +0.20025599999999999 0.023222799999999998 -0.144923 0.78945799999999999 -0.61380000000000001 0.0024407000000000001 +0.223604 -0.037746700000000001 -0.15505099999999999 0.18456 0.982769 0.010158800000000001 +-0.20558999999999999 -0.035380099999999998 -0.28188200000000002 -0.61826599999999998 0.78596100000000002 0.0036336099999999998 +-0.25608799999999998 -0.035282000000000001 -0.248723 0.59204299999999999 0.805674 0.0193428 +0.192805 0.0056868099999999996 -0.15523100000000001 0.99141000000000001 -0.13031100000000001 -0.0111615 +0.19595099999999999 0.015994399999999999 -0.18696099999999999 0.90651999999999999 -0.42215999999999998 -0.0016113200000000001 +0.22997699999999999 -0.038392200000000001 -0.018923200000000001 0.053652600000000002 0.99855899999999997 -0.0013700299999999999 +0.19852400000000001 -0.0207485 -0.25516 0.83073799999999998 0.55666300000000002 0 +0.25446099999999999 0.030185300000000002 -0.20000000000000001 0.63200999999999996 0.77490700000000001 0.0090740899999999999 +-0.274003 0.0040660999999999996 -0.27227699999999999 0.99761500000000003 -0.068976200000000001 -0.0024253199999999999 +0.215061 0.034951200000000002 -0.17460999999999999 -0.46432299999999999 0.88566599999999995 0 +-0.228938 0.043429599999999999 -0.13631299999999999 0.0277355 0.999529 0.0130971 +-0.24044499999999999 0.042363100000000001 -0.060883800000000002 -0.24282799999999999 0.97001099999999996 -0.0106249 +-0.218695 0.041720300000000002 -0.22015899999999999 0.25862800000000002 0.96582900000000005 0.016931499999999999 +0.26516699999999999 -0.016895299999999999 -0.178149 0.89846999999999999 -0.43902999999999998 -0.0017626199999999999 +0.24337500000000001 0.036289000000000002 -0.025002099999999999 0.286082 0.95819799999999999 0.0035866299999999999 +0.250832 -0.032726400000000003 -0.28758699999999998 -0.49907400000000002 0.86639699999999997 0.016748900000000001 +-0.25977 -0.032409899999999998 -0.13376099999999999 0.66583499999999995 0.74609099999999995 0.00341873 +-0.27382499999999999 0.0061078900000000004 -0.26997900000000002 0.99058900000000005 -0.13675599999999999 -0.0055884799999999998 +-0.24207300000000001 0.041926699999999997 -0.25833400000000001 -0.24954200000000001 0.96833199999999997 -0.0078732300000000002 +0.22350100000000001 0.037719000000000003 -0.102007 -0.20910400000000001 0.97783500000000001 -0.0106719 +0.25661899999999999 0.028335599999999999 -0.223111 0.65440500000000001 0.755965 -0.0164633 +-0.27109899999999998 0.0162617 -0.19467699999999999 0.93400000000000005 -0.35723700000000003 -0.0050936499999999999 +0.20532500000000001 0.028741099999999999 -0.106489 -0.63588299999999998 0.77178199999999997 -0.0024015199999999999 +0.20860600000000001 -0.031255400000000003 -0.269646 0.56015700000000002 0.82816299999999998 0.019247299999999998 +0.22148799999999999 -0.037179700000000003 -0.097709099999999993 0.242003 0.970001 0.023074799999999999 +0.26901900000000001 0.0024147700000000001 -0.098865599999999998 0.99957600000000002 0.0288402 -0.0039790800000000003 +0.23879900000000001 0.037515199999999999 -0.12748000000000001 0.19603499999999999 0.98050800000000005 -0.0132043 +-0.213528 0.039872999999999999 -0.183419 0.41566199999999998 0.90951700000000002 0.0018309800000000001 +-0.190358 0.0160871 -0.214172 0.93309200000000003 0.35950500000000002 0.0097343900000000008 +-0.19300200000000001 -0.021758699999999999 -0.15012900000000001 0.85467599999999999 -0.51911200000000002 -0.0072162800000000003 +-0.20491899999999999 0.0349106 -0.134795 0.58351600000000003 0.81186100000000005 -0.019760099999999999 +-0.26658399999999999 0.024558 -0.30507200000000001 0.832673 -0.55355900000000002 -0.0150998 +-0.21580299999999999 0.040933999999999998 -0.24229600000000001 0.34089999999999998 0.94008599999999998 -0.0049765199999999999 +0.26370900000000003 0.0197582 -0.14718500000000001 0.84508499999999998 0.53462799999999999 0.0023084099999999999 +-0.27166800000000002 -0.015041799999999999 -0.063524200000000003 0.93948100000000001 0.34260200000000002 0 +-0.20646500000000001 -0.035993400000000002 -0.29890099999999997 -0.57084400000000002 0.82078499999999999 0.0212035 +-0.20765600000000001 0.0368268 -0.22678400000000001 0.51976100000000003 0.85429100000000002 0.0059632599999999997 +0.19726099999999999 0.018800999999999998 -0.21511 0.87108399999999997 -0.49113000000000001 0.0018471900000000001 +0.19775599999999999 -0.0196519 -0.169154 0.86321400000000004 0.50343099999999996 0.0376564 +0.222079 -0.037338099999999999 -0.25012600000000001 0.211785 0.97726299999999999 -0.0101858 +0.202621 0.026037899999999999 -0.208786 0.76061599999999996 -0.64917899999999995 0.0054354700000000004 +0.19426499999999999 0.0118047 -0.26596999999999998 0.95941100000000001 -0.28192299999999998 0.0070592199999999997 +-0.237013 -0.043043499999999998 -0.32513799999999998 0.125051 0.97866699999999995 -0.16301399999999999 +0.26015199999999999 -0.024802500000000002 -0.084870200000000007 0.77088599999999996 -0.63691799999999998 0.0083475600000000004 +-0.21091799999999999 0.0386564 -0.058252999999999999 0.48886000000000002 0.872359 0.0025060099999999999 +-0.25557200000000002 -0.035643300000000003 -0.185978 0.59791000000000005 0.80154400000000003 0.0055984900000000002 +-0.25599 0.035351199999999999 -0.17943799999999999 -0.56997100000000001 0.82091400000000003 0.0351186 +0.246369 0.035001999999999998 -0.066356200000000004 0.46786499999999998 0.88359299999999996 -0.0191354 +-0.18938099999999999 0.0133162 -0.121124 0.95482199999999995 0.297178 0 +0.19384899999999999 -0.010251400000000001 -0.223715 0.97028400000000004 0.240171 -0.0294401 +0.20439499999999999 -0.027811200000000001 -0.0169675 0.741367 0.67072100000000001 0.022539900000000002 +0.21320800000000001 -0.034087199999999998 -0.210117 0.48489500000000002 0.87453999999999998 -0.0074976399999999999 +0.194442 0.012465800000000001 -0.12948599999999999 0.94274800000000003 -0.33348699999999998 0.0036051299999999998 +0.19237899999999999 -0.00081148400000000001 -0.212951 0.99834999999999996 0.057089300000000003 0.0061544199999999999 +-0.187699 -0.0059353699999999997 -0.318716 0.99217599999999995 -0.124846 0 +0.19242799999999999 -0.00137656 -0.037345000000000003 0.99751199999999995 0.069842899999999999 0.0095810300000000008 +0.19444 -0.0124569 -0.29297400000000001 0.94481700000000002 0.32749699999999998 0.0081298800000000008 +0.26533099999999998 0.016542999999999999 -0.240311 0.885243 0.46435700000000002 0.026773999999999999 +0.22439999999999999 -0.037904199999999999 -0.15004700000000001 0.15317700000000001 0.98790800000000001 -0.0239673 +-0.21923400000000001 0.041864800000000001 -0.23176099999999999 0.27302199999999999 0.96190100000000001 -0.014341899999999999 +-0.19409899999999999 0.023337 -0.20269300000000001 0.85772599999999999 0.51400900000000005 -0.0100331 +0.19401499999999999 0.0108696 -0.16545299999999999 0.95358500000000002 -0.30109200000000003 -0.0044528099999999998 +-0.221495 -0.042470800000000003 -0.27978799999999998 -0.21334900000000001 0.97694700000000001 -0.0075136600000000001 +0.26832099999999998 0.0078931299999999999 -0.297954 0.97704400000000002 0.21165700000000001 -0.024226000000000001 +-0.24457300000000001 0.041257000000000002 -0.20955699999999999 -0.33283200000000002 0.94296599999999997 -0.0062462200000000002 +0.19461999999999999 0.013126799999999999 -0.080235799999999996 0.92693199999999998 -0.37511100000000003 0.00938984 +0.233149 -0.038253299999999997 -0.28471000000000002 -0.080964900000000006 0.99670899999999996 0.0040279799999999996 +-0.201206 0.031847399999999998 -0.31826399999999999 0.69625400000000004 0.71779499999999996 0 +-0.21559500000000001 0.040836999999999998 -0.15193100000000001 0.330013 0.94384599999999996 -0.015676800000000001 +0.25806800000000002 -0.026887299999999999 -0.056617399999999998 0.710368 -0.70382900000000004 0.0017580199999999999 +0.253446 -0.030895800000000001 -0.175371 -0.62634299999999998 0.77939700000000001 -0.0153574 +-0.208616 -0.037499400000000002 -0.29514899999999999 -0.53026899999999999 0.84773399999999999 0.0127195 +-0.22176199999999999 -0.042542200000000002 -0.325959 -0.23944499999999999 0.96221000000000001 -0.129687 +0.26449600000000001 -0.018334900000000001 -0.022128399999999999 0.85839399999999999 -0.512795 -0.0141951 +0.194188 0.011517299999999999 -0.210843 0.94880799999999998 -0.314496 0.029242799999999999 +0.26716699999999999 -0.012199700000000001 -0.149093 0.94778799999999996 -0.31778800000000001 -0.026611800000000001 +0.26705200000000001 -0.012629899999999999 -0.061391300000000003 0.94269400000000003 -0.33313700000000002 -0.018673800000000001 +0.25958900000000001 -0.025365200000000001 -0.247089 -0.70290200000000003 0.711287 0.00076492200000000002 +-0.242449 -0.041826099999999998 -0.280667 0.28218300000000002 0.95925899999999997 -0.0139814 +0.22781399999999999 0.038203000000000001 -0.22683300000000001 -0.095735899999999999 0.99536899999999995 0.0087106800000000002 +-0.217584 -0.041422800000000003 -0.12851000000000001 -0.28155000000000002 0.959507 0.0087399899999999996 +-0.195879 0.025879099999999999 -0.080322699999999997 0.81762000000000001 0.575743 0.0041048600000000001 +0.19284100000000001 -0.0060921700000000001 -0.082800600000000002 0.98440300000000003 0.17566200000000001 0.0096908900000000006 +-0.210037 0.038245599999999998 -0.25140899999999999 0.48948799999999998 0.87199800000000005 -0.0045369199999999998 +-0.19542499999999999 -0.025229700000000001 -0.122631 0.803454 -0.595248 0.0118756 +0.20158000000000001 -0.024996899999999999 -0.12920599999999999 0.73750199999999999 0.67519200000000001 0.014360700000000001 +-0.2152 -0.0406527 -0.26856200000000002 -0.37992999999999999 0.92501100000000003 0.0027588999999999999 +0.254492 0.030163200000000001 -0.26085999999999998 0.63314700000000002 0.77402800000000005 -0.0022418199999999998 +-0.26438200000000001 0.027703999999999999 -0.25445800000000002 0.75989600000000002 -0.65000199999999997 0.0074809500000000001 +0.19850499999999999 -0.0207222 -0.23346 0.80714399999999997 0.59007500000000002 -0.0181721 +0.211039 -0.032959500000000003 -0.12210699999999999 0.52365200000000001 0.85175900000000004 0.017168900000000001 +-0.19900699999999999 -0.0296482 -0.19717000000000001 0.75888900000000004 -0.65122000000000002 -0.00093774099999999997 +-0.26950000000000002 0.019692100000000001 -0.054949199999999997 0.89683100000000004 -0.44232100000000002 0.0067792399999999997 +-0.268762 -0.0212742 -0.21357000000000001 0.86389000000000005 0.50368000000000002 0 +0.19364100000000001 -0.0094741300000000007 -0.264459 0.96338000000000001 0.26811000000000001 0.0039774800000000003 +0.20105500000000001 0.0243641 -0.193906 0.77870499999999998 -0.62692499999999995 0.024146000000000001 +-0.27052199999999998 0.017499799999999999 -0.21723999999999999 0.906833 -0.42145899999999997 -0.0050530100000000001 +-0.264685 0.027269999999999999 -0.32413399999999998 0.75201300000000004 -0.65644499999999995 -0.059637900000000001 +0.25382700000000002 0.030629099999999999 -0.0297982 0.59721900000000006 0.80206200000000005 0.00497344 +-0.26096900000000001 0.031210999999999999 -0.24685199999999999 -0.69795099999999999 0.71614299999999997 -0.0019118900000000001 +0.19325000000000001 -0.0080151000000000007 -0.141181 0.97565800000000003 0.21929899999999999 0 +-0.19059899999999999 -0.0166053 -0.18454200000000001 0.933674 -0.35743599999999998 -0.022217400000000002 +-0.24259500000000001 0.041786799999999999 -0.19589599999999999 -0.25356899999999999 0.96728800000000004 -0.0075576699999999998 +-0.22639599999999999 -0.043207200000000001 -0.21012 -0.086926500000000004 0.99620299999999995 0.0047371399999999999 +0.25875399999999998 -0.026200899999999999 -0.087757399999999999 0.73004599999999997 -0.68335000000000001 0.0080773200000000007 +0.209171 0.031650699999999997 -0.14480199999999999 -0.56652400000000003 0.82379899999999995 -0.0201455 +0.25289600000000001 0.031281000000000003 -0.32175599999999999 0.59405699999999995 0.80429200000000001 -0.0145208 +-0.26724700000000001 0.023612000000000001 -0.18785499999999999 0.87654500000000002 -0.481103 -0.0144463 +-0.21265100000000001 -0.039464399999999997 -0.23560300000000001 -0.411134 0.9113 0.022364499999999999 +-0.193991 -0.023182999999999999 -0.0492065 0.83724600000000005 -0.546821 0.0022441800000000001 +-0.19172800000000001 0.019025500000000001 -0.11705699999999999 0.89201600000000003 0.45152100000000001 -0.020855499999999999 +-0.251332 -0.038324400000000002 -0.0960226 0.43403199999999997 0.90088299999999999 -0.0051028599999999999 +0.21510399999999999 0.034971099999999998 -0.097656000000000007 -0.41617399999999999 0.90912499999999996 -0.017071099999999999 +0.25626500000000002 -0.028689900000000001 -0.25357400000000002 -0.66793599999999997 0.74417599999999995 -0.0080051400000000009 +0.20737 0.030389900000000001 -0.245342 -0.59877800000000003 0.80062900000000004 -0.0213788 +0.23432700000000001 -0.038150299999999998 -0.18213199999999999 -0.088434600000000002 0.99605600000000005 -0.0071585599999999996 +0.192662 -0.0040459700000000003 -0.188196 0.99262700000000004 0.119423 0.020752900000000001 +-0.27415 0.0023860399999999999 -0.18770999999999999 0.999888 -0.0128992 0.00763929 +-0.27391900000000002 -0.00503565 -0.13001299999999999 0.99405699999999997 0.10865 0.0068485400000000002 +0.26093699999999997 0.023716500000000001 -0.287491 0.80133100000000002 0.59805799999999998 -0.013972500000000001 +0.25787199999999999 0.027082999999999999 -0.074280499999999999 0.73115399999999997 0.68218500000000004 -0.0061374899999999998 +0.192498 0.0021775499999999999 -0.23461399999999999 0.99978299999999998 -0.018313800000000002 0.0099579100000000004 +0.26891300000000001 0.0036332399999999998 -0.25029299999999999 0.99660599999999999 0.082314700000000005 0.00076228199999999998 +0.236455 -0.037964100000000001 -0.319745 -0.11049399999999999 0.99376500000000001 -0.0148982 +0.26786900000000002 0.0095788699999999997 -0.21063699999999999 0.96331 0.26812399999999997 -0.011961100000000001 +0.24226700000000001 -0.036586100000000003 -0.116021 -0.32842100000000002 0.94386899999999996 0.035372599999999997 +-0.19900399999999999 -0.029644899999999998 -0.093206899999999995 0.74332699999999996 -0.66863799999999995 0.019717499999999999 +0.209538 -0.031908199999999998 -0.074309799999999995 0.54084200000000004 0.84086799999999995 0.020755599999999999 +-0.24588199999999999 0.040865899999999997 -0.13796800000000001 -0.34067399999999998 0.93981199999999998 0.026332600000000001 +-0.189967 0.01525 -0.090209499999999998 0.93827899999999997 0.34562599999999999 0.0132339 +0.26101400000000002 -0.023605600000000001 -0.11948300000000001 0.75960700000000003 -0.65020900000000004 -0.015018 +0.265432 -0.0163261 -0.068597900000000003 0.90044800000000003 -0.43496400000000002 0 +0.200434 0.023477100000000001 -0.25013099999999999 0.798709 -0.60158599999999995 0.0125816 +-0.21288299999999999 -0.039572499999999997 -0.20493400000000001 -0.39745000000000003 0.917624 0 +0.25744699999999998 0.027507500000000001 -0.133105 0.70849700000000004 0.70565800000000001 0.0088159699999999994 +-0.27067000000000002 -0.017182599999999999 -0.16767599999999999 0.92714600000000003 0.37468299999999999 -0.00349556 diff --git a/Data/data/points_3/spheres.ply b/Data/data/points_3/spheres.ply index 13901fd744f..6eb225f1b02 100644 Binary files a/Data/data/points_3/spheres.ply and b/Data/data/points_3/spheres.ply differ diff --git a/Data/data/polylines_3/wavy_circle.polylines.txt b/Data/data/polylines_3/wavy_circle.polylines.txt new file mode 100644 index 00000000000..5e087d6adea --- /dev/null +++ b/Data/data/polylines_3/wavy_circle.polylines.txt @@ -0,0 +1 @@ +249 -0.00044776375000000015 -0.15158287499999998 0.14355584375 0.00051719999999999999 -0.15390949999999998 0.1399854375 0.0022136895312500002 -0.15600634375 0.13584029687500002 0.0041386681249999998 -0.158018875 0.13127575 0.0057890990624999998 -0.16009256250000001 0.12644712499999999 0.0066619456249999995 -0.162372875 0.12150975 0.0072473301562499997 -0.16440267187499999 0.11677771874999998 0.0080353750000000009 -0.16572481249999998 0.11256512499999999 0.0095162024999999994 -0.16588215625 0.1091860625 0.012179934999999999 -0.1644175625 0.106954625 0.0155895453125 -0.16188871874999999 0.10527840468750001 0.019308006250000002 -0.15885331250000001 0.10356499375 0.022898290625000001 -0.15586903125000001 0.10122198437499999 0.02592337125 -0.15349356250000001 0.097656968750000003 0.028240319375 -0.15183309375000001 0.093200604687500008 0.029706206249999999 -0.15099381249999999 0.088183549999999999 0.030178103124999998 -0.15108190625000001 0.082936462500000002 0.029513081249999996 -0.1522035625 0.077789999999999998 0.028047992187499995 -0.15402029687499999 0.072674532812499998 0.026119687499999999 -0.156193625 0.067520431249999999 0.024065018749999997 -0.15838506250000001 0.062258065625000004 0.0222208375 -0.160256125 0.056817806250000005 0.020616862499999996 -0.16178118750000001 0.051116020000000005 0.0192828125 -0.162934625 0.045069073750000001 0.018248406250000002 -0.16369081249999998 0.038593334375000003 0.0175433625 -0.16402412500000002 0.031605168749999996 0.017195706249999998 -0.16394103125000001 0.024375962187500003 0.017233462499999998 -0.16344800000000001 0.017177100000000001 0.017684656249999996 -0.16255150000000002 0.010279967499999999 0.018577312499999998 -0.16125800000000001 0.0039559499999999997 0.019910501562499999 -0.159546140625 -0.0018876065624999999 0.021683293749999999 -0.1573945625 -0.0073433562500000004 0.023894759375000001 -0.15478190624999999 -0.012503953125 0.026543968750000001 -0.15168681249999999 -0.017462051249999999 0.029368848437499998 -0.148455078125 -0.02256357375 0.032107324999999999 -0.14543250000000002 -0.028154443750000001 0.034497325000000002 -0.14296487500000002 -0.034580584374999994 0.036276774999999997 -0.14139800000000002 -0.042187918749999997 0.0377402265625 -0.14035635937500002 -0.050481304687499992 0.039182231249999998 -0.13946443749999998 -0.0589656 0.040897340624999994 -0.13834671874999999 -0.067145662499999995 0.043180106250000003 -0.13662768749999998 -0.074526350000000005 0.046007814062499999 -0.13431401562500001 -0.081334895312500016 0.049357750000000006 -0.13141237500000003 -0.087798531250000006 0.053207199999999996 -0.12792943750000002 -0.094144490624999994 0.05753345 -0.12387187500000001 -0.10060000624999998 0.061717399999999999 -0.119860625 -0.10693843281249998 0.065139950000000002 -0.11651662499999998 -0.112933125 0.067182000000000006 -0.11446081249999998 -0.1183574375 0.067224449999999991 -0.11431412499999999 -0.122984725 0.0662185546875 -0.11513465625000001 -0.12680496250000001 0.065115568749999991 -0.1159805 -0.129808125 0.064866746874999992 -0.11590974999999998 -0.13198418750000002 0.066423343750000002 -0.1139805 -0.13332312500000001 0.06901592656250001 -0.11086219531250001 -0.13431079687500003 0.071875062500000003 -0.10722428125 -0.13543306250000001 0.074231318750000011 -0.10373620312500001 -0.13717578124999999 0.075315262500000008 -0.10106740624999999 -0.14002481249999998 0.075569846874999999 -0.098929328124999993 -0.14347859374999999 0.075438024999999992 -0.097033406250000009 -0.14703556249999999 0.075362750000000006 -0.09509107812500002 -0.15019415624999999 0.075786975000000006 -0.092813781250000005 -0.15245281249999998 0.076494642187500003 -0.090307684374999989 -0.15411345312499999 0.077269693750000007 -0.087678956249999995 -0.15547800000000001 0.077896071875 -0.085033765624999993 -0.15684837500000001 0.078157718749999994 -0.082478281250000007 -0.15852650000000001 0.078261873437500004 -0.07984195312499999 -0.16035350000000001 0.078415774999999993 -0.076954231250000005 -0.1621705 0.078826662500000005 -0.073644565624999991 -0.163818625 0.079701775000000002 -0.06974240625 -0.16513899999999998 0.080892934375000003 -0.065279512500000011 -0.16623523437499999 0.082251962499999998 -0.060287643750000008 -0.16721093749999999 0.083630681250000019 -0.054798559375000007 -0.16816971875 0.084880912500000003 -0.048844018750000003 -0.1692151875 0.085746651562499998 -0.042876184375000008 -0.17037795312500001 0.08597189375 -0.037347218750000001 -0.17168862500000001 0.08530063437499999 -0.032709284375000001 -0.1731778125 0.083476868750000002 -0.029414543750000001 -0.17487612499999999 0.081076593750000009 -0.026951447343750001 -0.17656346875000001 0.078675806250000008 -0.024808445625000002 -0.17801974999999998 0.076850503125000011 -0.022473989062500001 -0.17902487499999997 0.076176681250000003 -0.019436528124999998 -0.17935874999999998 0.076097146874999994 -0.01583333171875 -0.1792486875 0.076054706249999993 -0.011801668750000001 -0.178922 0.07549216562500001 -0.0074788081249999999 -0.17860599999999999 0.073852331250000014 -0.00300201875 -0.17852800000000002 0.071628676562500007 0.0016061698437499999 -0.17843910937500002 0.069314675000000006 0.0063232281250000001 -0.1780904375 0.0674038 0.011126626562499999 -0.17723309375000001 0.066389525000000005 0.015993835625000001 -0.17561818750000002 0.065723070312500007 0.020868507343750002 -0.17360778125000001 0.064855656250000004 0.02569429375 -0.17156393750000001 0.063238503125000012 0.030414846874999995 -0.16984871875000002 0.06032283125 0.034973818749999996 -0.1688241875 0.056685209375000004 0.039590285937500004 -0.16812126562500002 0.05290220625 0.044483325000000004 -0.167370875 0.04955039062500001 0.0498720125 -0.16620393750000001 0.047206331250000004 0.055975424999999995 -0.16425137500000001 0.046001935937500002 0.062654393749999995 -0.16147376562500002 0.046069112499999995 0.069769750000000005 -0.15783168750000001 0.047539768749999996 0.077182325000000024 -0.15328571875000002 0.050545812499999995 0.084752950000000007 -0.14779643750000002 0.053832048437500002 0.092210568749999999 -0.14215992187500001 0.056143281250000003 0.099284125000000001 -0.13717225 0.056224315625000007 0.1057025625 -0.13362949999999998 0.052819956250000008 0.111194825 -0.13232774999999999 0.047350539062500002 0.11616792499999999 -0.13228214062499999 0.041236400000000006 0.12102887499999999 -0.13250781249999999 0.035897875000000003 0.1261846875 -0.13201990624999999 0.032755300000000001 0.13204237499999999 -0.1298335625 0.0312962484375 0.13831884375 -0.1263746734375 0.031008293750000002 0.144731 -0.12206913124999999 0.031379009375000003 0.15099575000000004 -0.11734282812499999 0.031895968750000003 0.15683000000000002 -0.11262165625000001 0.032337139062500006 0.162292734375 -0.1078587140625 0.032480487500000002 0.1674429375 -0.10300709999999999 0.032103981250000004 0.17233959374999999 -0.0980199125 0.030985587500000002 0.17704168749999999 -0.092850249999999995 0.029623448437499998 0.18156332812499998 -0.087445717187499994 0.028515706250000002 0.185918625 -0.081753918749999988 0.028160503125 0.1901216875 -0.075722459374999995 0.029055981250000001 0.194186625 -0.069298943749999994 0.030810435937499998 0.19806173437499999 -0.062651806249999997 0.033032162500000004 0.2016953125 -0.055949481250000002 0.035329456250000002 0.20503565625 -0.049360403125000001 0.0373106125 0.20803106249999997 -0.043053006249999998 0.038971143750000006 0.21074198437499997 -0.036935625906249998 0.040306562499999997 0.21322887499999998 -0.030916597375 0.041312381249999995 0.21555218749999999 -0.024904255937500001 0.041984112499999997 0.21777237499999999 -0.018806936874999999 0.041904646875000007 0.21981740625000001 -0.012924143249999999 0.040656874999999995 0.22161524999999999 -0.0075553781249999997 0.037823687499999994 0.223093875 -0.0030001445625000003 0.032987975000000003 0.22418125 0.0004420543749999999 0.026840775000000001 0.22501265625 0.0032544520625000001 0.020073125000000001 0.225723375 0.005920281874999999 0.013376062500000001 0.22644868750000002 0.008922777187499998 0.0074406249999999993 0.22732387500000001 0.012745171374999999 0.0022362734374999993 0.22828865625 0.017294818312500002 -0.0022675312500000009 0.22928274999999998 0.022479071874999999 -0.0061013281250000013 0.23024587499999999 0.028205285937499998 -0.009295656250000001 0.23111775000000001 0.034380814374999999 -0.012001940625000001 0.23185134374999999 0.040826047343749998 -0.01437160625 0.232399625 0.047361374999999997 -0.016556078125000002 0.23271556249999997 0.053807187499999999 -0.018706781249999999 0.232752125 0.059983875000000006 -0.020512975000000003 0.23260457812500002 0.065722012499999996 -0.02166391875 0.23236818749999999 0.070852174999999989 -0.021848871874999995 0.23213821875000001 0.075204937499999999 -0.02075709375 0.23200993749999999 0.078610874999999997 -0.018900001562500001 0.23188954687499999 0.081397607812500009 -0.016789012499999999 0.23168325000000001 0.083892756250000006 -0.01493554375 0.23129725000000001 0.086423940625000001 -0.013851012500000001 0.23063774999999997 0.089318781250000007 -0.013517095312500001 0.22965070312499997 0.092567076562500017 -0.013915468750000002 0.22828206249999999 0.096158625000000011 -0.015027809374999999 0.22647778125000001 0.10008322500000003 -0.016835793750000001 0.22418381249999997 0.10433067500000001 -0.019081315625000001 0.221610671875 0.1086314203125 -0.021506268750000002 0.21896887500000001 0.11271590625 -0.023852546874999998 0.21646893750000001 0.11631457812500001 -0.025862043750000001 0.21432137499999998 0.11915788125 -0.027318535937500003 0.21247871874999996 0.1214152046875 -0.028005800000000004 0.21089349999999998 0.1232559375 -0.027707612500000003 0.20951824999999999 0.12484946875 -0.026207750000000002 0.20830549999999998 0.1263651875 -0.024019689062500002 0.20705470312500002 0.12790987500000001 -0.021656906249999996 0.20556531249999999 0.12959031250000003 -0.019632878124999996 0.20363678124999998 0.13151328125 -0.018461081249999997 0.20106856249999999 0.13378556250000001 -0.01772186265625 0.19787992187499998 0.13637639062500001 -0.016995569374999998 0.194090125 0.13925500000000002 -0.015862548437499999 0.1897184375 0.14239062500000002 -0.013903146874999998 0.18478412499999999 0.14575250000000001 -0.011594140781250001 0.17948867187499998 0.14918307812500001 -0.0094123062500000004 0.17403356249999999 0.1525248125 -0.0078344193750000003 0.16862028124999998 0.15562015625 -0.0073372562500000002 0.16345031249999997 0.1583115625 -0.0076914048437499985 0.15829707812499999 0.16072368750000002 -0.0086674531249999985 0.15293400000000001 0.16298118750000001 -0.010035989062499999 0.1471345 0.16520871875000001 -0.011567600625 0.14067200000000002 0.16753093750000003 -0.012941553125 0.13389270312500001 0.16987346875000001 -0.013837111874999999 0.12714281250000001 0.1721619375 -0.0139335421875 0.12076853125000001 0.17432196875 -0.012910109374999999 0.1151160625 0.17627918749999999 -0.011091616562499998 0.10994047187499999 0.17807721874999999 -0.008802866874999999 0.10499682499999999 0.17975968749999999 -0.006368663437499999 0.10004018749999999 0.18137021875000001 -0.0041138093749999993 0.094825624999999997 0.18295243749999998 -0.0021896909374999997 0.089397835937500003 0.18448971874999998 -0.00074769437500000016 0.083801518749999998 0.1859654375 6.0794062499999806e-05 0.078081371875 0.18736296874999997 8.4388124999999845e-05 0.072282093749999998 0.18866568750000001 -0.00045768156250000007 0.066525795312499997 0.18986332812500001 -0.0013461843750000001 0.060934587499999998 0.19094562500000001 -0.0023618896875000003 0.055630581250000005 0.19190231249999998 -0.0032855668750000006 0.0507358875 0.192723125 -0.0041462484375000006 0.046102293749999995 0.19343028124999997 -0.0049729668750000001 0.041581587500000003 0.194046 -0.0057947546875000006 0.037025556250000001 0.1945925 -0.006640644375 0.032285987500000002 0.19509199999999999 -0.0075290317187499999 0.027498120000000001 0.19553464062499998 -0.0084783125000000015 0.022797192500000001 0.1959105625 -0.009506882500000001 0.01831844375 0.19620990624999998 -0.010633137500000001 0.014197112500000001 0.19642281249999999 -0.011580044062499999 0.010388322031250001 0.19659284375 -0.01207056875 0.006847195625 0.19676356249999999 -0.011827678124999999 0.0035288565625000001 0.19697853124999998 -0.010574338749999999 0.00038842812500000006 0.19728131249999997 -0.0088851893750000015 -0.00282278578125 0.19756589062499999 -0.0073348687500000001 -0.0063534812499999992 0.19772624999999999 -0.0064980156249999999 -0.010452354375 0.197656375 -0.0069492687500000002 -0.01536810125 0.19725025000000002 -0.00823688203125 -0.020803227968750001 0.196602 -0.0099091093749999991 -0.026460240624999999 0.19580575 -0.0115142046875 -0.032041645312499999 0.19495562500000002 -0.012600421875 -0.037249948125000001 0.19414575000000001 -0.01335302109375 -0.042319387031249996 0.19329823437499999 -0.013957262500000001 -0.047484199999999997 0.1923351875 -0.014598406250000001 -0.052978625000000001 0.19117871875 -0.015461712500000002 -0.059036899999999996 0.18975093749999999 -0.016409281250000001 -0.065412806249999997 0.18813634375000002 -0.017303212500000002 -0.071860124999999997 0.18641943750000001 -0.01800560625 -0.078132637499999991 0.18468471874999998 -0.018378562500000001 -0.083984124999999993 0.1830166875 -0.018388648437500002 -0.089415518750000006 0.18141137500000001 -0.018002431249999999 -0.094427750000000005 0.17986481249999997 -0.017186478125000001 -0.099021750000000006 0.17837303124999998 -0.015907356250000001 -0.10319845 0.17693206249999999 -0.0144205703125 -0.10705733125 0.17550526562499999 -0.012981625 -0.110697875 0.17405599999999999 -0.011846025000000001 -0.11421956249999998 0.17254762499999998 -0.011269275000000002 -0.117721875 0.17094349999999997 -0.010897881562500001 -0.12097317187499999 0.16933765625 -0.010378351250000001 -0.12374181250000001 0.16782412499999999 -0.009357190625000001 -0.12579615625000001 0.1664969375 -0.0074809062500000006 -0.12690456249999998 0.165450125 -0.0051011721874999992 -0.12751890625000001 0.16448196875000001 -0.0025696625000000001 -0.12809106249999999 0.16339075000000003 -0.00023805125000000011 -0.12907290625000001 0.16197475000000003 0.0015419874999999996 -0.13091631249999999 0.16003224999999999 0.0027162142187500001 -0.13341395312499998 0.1577565625 0.0032303893749999995 -0.13635849999999999 0.15534100000000001 0.0030302734374999993 -0.139542625 0.15297887500000001 0.0020616268749999995 -0.142759 0.15086349999999998 0.00082522296874999973 -0.14590575 0.14875067187499999 -0.0001781650000000002 -0.14888099999999999 0.1463961875 -0.00044776375000000015 -0.15158287499999998 0.14355584375 diff --git a/Documentation/doc/resources/1.8.13/menu_version.js b/Documentation/doc/resources/1.8.13/menu_version.js index 929adeeea31..6700393fefd 100644 --- a/Documentation/doc/resources/1.8.13/menu_version.js +++ b/Documentation/doc/resources/1.8.13/menu_version.js @@ -7,8 +7,8 @@ var all_versions = [ 'master', 'latest', - '5.5.1', - '5.4.3', + '5.5.2', + '5.4.4', '5.3.2', '5.2.4', '5.1.5', diff --git a/Documentation/doc/resources/1.8.14/menu_version.js b/Documentation/doc/resources/1.8.14/menu_version.js index 929adeeea31..6700393fefd 100644 --- a/Documentation/doc/resources/1.8.14/menu_version.js +++ b/Documentation/doc/resources/1.8.14/menu_version.js @@ -7,8 +7,8 @@ var all_versions = [ 'master', 'latest', - '5.5.1', - '5.4.3', + '5.5.2', + '5.4.4', '5.3.2', '5.2.4', '5.1.5', diff --git a/Documentation/doc/resources/1.8.20/menu_version.js b/Documentation/doc/resources/1.8.20/menu_version.js index 929adeeea31..6700393fefd 100644 --- a/Documentation/doc/resources/1.8.20/menu_version.js +++ b/Documentation/doc/resources/1.8.20/menu_version.js @@ -7,8 +7,8 @@ var all_versions = [ 'master', 'latest', - '5.5.1', - '5.4.3', + '5.5.2', + '5.4.4', '5.3.2', '5.2.4', '5.1.5', diff --git a/Documentation/doc/resources/1.8.4/menu_version.js b/Documentation/doc/resources/1.8.4/menu_version.js index 929adeeea31..6700393fefd 100644 --- a/Documentation/doc/resources/1.8.4/menu_version.js +++ b/Documentation/doc/resources/1.8.4/menu_version.js @@ -7,8 +7,8 @@ var all_versions = [ 'master', 'latest', - '5.5.1', - '5.4.3', + '5.5.2', + '5.4.4', '5.3.2', '5.2.4', '5.1.5', diff --git a/Documentation/doc/resources/1.9.3/BaseDoxyfile.in b/Documentation/doc/resources/1.9.3/BaseDoxyfile.in index 775ba2ce757..a2cf7003fb4 100644 --- a/Documentation/doc/resources/1.9.3/BaseDoxyfile.in +++ b/Documentation/doc/resources/1.9.3/BaseDoxyfile.in @@ -341,7 +341,7 @@ ALIASES = "cgal=%CGAL" \ "cgalPkgShortInfoBegin=
" \ "cgalPkgShortInfoEnd=
" \ "cgalPkgAuthor{1}=
\1
" \ - "cgalPkgAuthors{1}=
\1
" \ + "cgalPkgAuthors{1}=\cgalPkgAuthor{\1}" \ "cgalPkgDesc{1}=
\1
" \ "cgalPkgSince{1}=Introduced in: \cgal \1
" \ "cgalPkgDependsOn{1}=Depends on: \1
" \ diff --git a/Documentation/doc/resources/1.9.3/menu_version.js b/Documentation/doc/resources/1.9.3/menu_version.js index 929adeeea31..6700393fefd 100644 --- a/Documentation/doc/resources/1.9.3/menu_version.js +++ b/Documentation/doc/resources/1.9.3/menu_version.js @@ -7,8 +7,8 @@ var all_versions = [ 'master', 'latest', - '5.5.1', - '5.4.3', + '5.5.2', + '5.4.4', '5.3.2', '5.2.4', '5.1.5', diff --git a/Filtered_kernel/include/CGAL/Lazy.h b/Filtered_kernel/include/CGAL/Lazy.h index e062002d3e6..e7024f6220b 100644 --- a/Filtered_kernel/include/CGAL/Lazy.h +++ b/Filtered_kernel/include/CGAL/Lazy.h @@ -38,13 +38,6 @@ #include -#include -#include -#include -#include -#include -#include - #include #include #include @@ -797,13 +790,6 @@ public: } }; -// Macro helpers to build the kernel objects -#define CGAL_PARAM(z, n, t) std::declval() -#define CGAL_TYPEMAP_AC(z, n, t) typedef typename Type_mapper< t##n, LK, AK >::type A##n; -#define CGAL_TYPEMAP_EC(z, n, t) typedef typename Type_mapper< t##n, LK, EK >::type E##n; -#define CGAL_LEXACT(z,n,t) CGAL::exact( l##n ) -#define CGAL_LARGS(z, n, t) L##n const& l##n - #undef CGAL_LAZY_PRINT_TYPEID template < typename K1, typename K2 > @@ -1973,15 +1959,11 @@ struct Lazy_construction_variant { // you are on your own }; - #define CGAL_RESULT(z, n, d) \ - template< typename F, BOOST_PP_ENUM_PARAMS(n, class T) > \ - struct result { \ - BOOST_PP_REPEAT(n, CGAL_TYPEMAP_AC, T) \ - typedef typename Type_mapper< \ - decltype(std::declval()(BOOST_PP_ENUM(n, CGAL_PARAM, A))), AK, LK>::type type; \ - }; - - BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_RESULT, _) + template + struct result + { + typedef typename Type_mapper()(std::declval::type>()...)),AK,LK>::type type; + }; template decltype(auto) @@ -2120,26 +2102,23 @@ struct Lazy_construction { CGAL_NO_UNIQUE_ADDRESS AC ac; CGAL_NO_UNIQUE_ADDRESS EC ec; -#define CGAL_CONSTRUCTION_OPERATOR(z, n, d ) \ - template \ - decltype(auto) \ - operator()( BOOST_PP_ENUM(n, CGAL_LARGS, _) ) const { \ - typedef Lazy< AT, ET, E2A> Handle; \ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ - { \ - Protect_FPU_rounding P; \ - try { \ - return result_type( Handle(new Lazy_rep_n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ - } catch (Uncertain_conversion_exception&) {} \ - } \ - CGAL_BRANCH_PROFILER_BRANCH(tmp); \ - Protect_FPU_rounding P2(CGAL_FE_TONEAREST); \ - CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST); \ - return result_type( Handle(new Lazy_rep_0(ec( BOOST_PP_ENUM(n, CGAL_LEXACT, _) ))) ); \ + template + decltype(auto) + operator()(const L&... l) const { + typedef Lazy < AT, ET, E2A > Handle; + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + { + Protect_FPU_rounding P; + try { + return result_type(Handle(new Lazy_rep_n< AT, ET, AC, EC, E2A, noprune, L...>(ac, ec, l...))); + } catch (Uncertain_conversion_exception&) {} + } + CGAL_BRANCH_PROFILER_BRANCH(tmp); + Protect_FPU_rounding P2(CGAL_FE_TONEAREST); + CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST); + return result_type(Handle(new Lazy_rep_0< AT, ET, E2A >(ec(CGAL::exact(l)...)))); } - // arity 1-8 - BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_CONSTRUCTION_OPERATOR, _) // nullary decltype(auto) @@ -2149,8 +2128,6 @@ struct Lazy_construction { return result_type( Handle() ); } -#undef CGAL_CONSTRUCTION_OPERATOR - }; @@ -2174,35 +2151,32 @@ struct Lazy_construction CGAL_NO_UNIQUE_ADDRESS AC ac; CGAL_NO_UNIQUE_ADDRESS EC ec; - // acquire the result_type of the approximate kernel, map it back to the lazy kernel object - BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_RESULT, _) + template + struct result + { + typedef typename Type_mapper()(std::declval::type>()...)),AK,LK>::type type; + }; -#define CGAL_CONSTRUCTION_OPERATOR(z, n, d) \ - template \ - decltype(auto) \ - operator()( BOOST_PP_ENUM(n, CGAL_LARGS, _) ) const { \ - BOOST_PP_REPEAT(n, CGAL_TYPEMAP_EC, L) \ - BOOST_PP_REPEAT(n, CGAL_TYPEMAP_AC, L) \ - typedef typename Type_mapper()(BOOST_PP_ENUM(n, CGAL_PARAM, E))),EK,EK>::type ET; \ - typedef typename Type_mapper()(BOOST_PP_ENUM(n, CGAL_PARAM, A))),AK,AK>::type AT; \ - typedef Lazy< AT, ET, E2A> Handle; \ - typedef typename result::type result_type; \ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ - { \ - Protect_FPU_rounding P; \ - try { \ - return result_type( Handle(new Lazy_rep_n(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \ - } catch (Uncertain_conversion_exception&) {} \ - } \ - CGAL_BRANCH_PROFILER_BRANCH(tmp); \ - Protect_FPU_rounding P2(CGAL_FE_TONEAREST); \ - CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST); \ - return result_type( Handle(new Lazy_rep_0(ec( BOOST_PP_ENUM(n, CGAL_LEXACT, _) ))) ); \ + template + decltype(auto) + operator()(const L&... l) const { + typedef typename Type_mapper()(std::declval::type>()...)),EK,EK>::type ET; + typedef typename Type_mapper()(std::declval::type>()...)),AK,AK>::type AT; + typedef Lazy Handle; + typedef typename result::type result_type; + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + { + Protect_FPU_rounding P; + try { + return result_type(Handle(new Lazy_rep_n (ac, ec, l...))); + } catch (Uncertain_conversion_exception&) {} + } + CGAL_BRANCH_PROFILER_BRANCH(tmp); + Protect_FPU_rounding P2(CGAL_FE_TONEAREST); + CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST); + return result_type(Handle(new Lazy_rep_0 (ec(CGAL::exact(l)...)))); } - // arity 1-8 - BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_CONSTRUCTION_OPERATOR, _) - // nullary decltype(auto) operator()() const @@ -2218,10 +2192,6 @@ struct Lazy_construction } //namespace CGAL -#undef CGAL_TYPEMAP_AC -#undef CGAL_TYPEMAP_EC -#undef CGAL_LEXACT -#undef CGAL_LARGS #include diff --git a/Heat_method_3/doc/Heat_method_3/PackageDescription.txt b/Heat_method_3/doc/Heat_method_3/PackageDescription.txt index c13822436f1..682deab736b 100644 --- a/Heat_method_3/doc/Heat_method_3/PackageDescription.txt +++ b/Heat_method_3/doc/Heat_method_3/PackageDescription.txt @@ -12,7 +12,7 @@ \cgalPkgPicture{heat-method-small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Keenan Crane, Christina Vaz, Andreas Fabri} +\cgalPkgAuthors{Keenan Crane, Christina Vaz, and Andreas Fabri} \cgalPkgDesc{The package provides an algorithm that solves the single- or multiple-source shortest path problem by returning an approximation of the geodesic distance for all vertices of a triangle mesh to the closest vertex in a given set of diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/PlaneH3.h b/Homogeneous_kernel/include/CGAL/Homogeneous/PlaneH3.h index a3f5e33858f..6b05951a064 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/PlaneH3.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/PlaneH3.h @@ -48,6 +48,7 @@ public: PlaneH3() {} PlaneH3(const Point_3&, const Point_3&, const Point_3& ); + PlaneH3(Origin, const Point_3&, const Point_3& ); PlaneH3(const RT& a, const RT& b, const RT& c, const RT& d ); PlaneH3(const Point_3&, const Ray_3& ); @@ -175,6 +176,16 @@ PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, const typename PlaneH3::Point_3& r) { new_rep(p,q,r); } +template < class R > +CGAL_KERNEL_INLINE +PlaneH3::PlaneH3(Origin, + const typename PlaneH3::Point_3& q, + const typename PlaneH3::Point_3& r) +{ + typename PlaneH3::Point_3 p(0,0,0); + new_rep(p,q,r); +} + template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const RT& a, const RT& b, @@ -190,37 +201,37 @@ PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p , template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, - const typename PlaneH3::Segment_3& s) + const typename PlaneH3::Segment_3& s) { new_rep(p, s.source(), s.target() ); } template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p , - const typename PlaneH3::Ray_3& r) + const typename PlaneH3::Ray_3& r) { new_rep(p, r.start(), r.start() + r.direction().to_vector() ); } template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Line_3& l , - const typename PlaneH3::Point_3& p) + const typename PlaneH3::Point_3& p) { new_rep(l.point(0), p, l.point(1) ); } template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Segment_3& s, - const typename PlaneH3::Point_3& p) + const typename PlaneH3::Point_3& p) { new_rep(s.source(), p, s.target() ); } template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Ray_3& r, - const typename PlaneH3::Point_3& p) + const typename PlaneH3::Point_3& p) { new_rep(r.start(), p, r.start() + r.direction().to_vector() ); } template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, - const typename PlaneH3::Direction_3& d) + const typename PlaneH3::Direction_3& d) { Vector_3 ov = d.to_vector(); new_rep( ov.hx()*p.hw(), @@ -232,7 +243,7 @@ PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, - const typename PlaneH3::Vector_3& ov) + const typename PlaneH3::Vector_3& ov) { new_rep( ov.hx()*p.hw(), ov.hy()*p.hw(), @@ -254,8 +265,8 @@ PlaneH3::PlaneH3(Origin, template < class R > CGAL_KERNEL_INLINE PlaneH3::PlaneH3(const typename PlaneH3::Point_3& p, - const typename PlaneH3::Direction_3& d1, - const typename PlaneH3::Direction_3& d2) + const typename PlaneH3::Direction_3& d1, + const typename PlaneH3::Direction_3& d2) { new_rep( p, p + d1.to_vector(), p + d2.to_vector() ); } template < class R > diff --git a/Hyperbolic_triangulation_2/doc/Hyperbolic_triangulation_2/PackageDescription.txt b/Hyperbolic_triangulation_2/doc/Hyperbolic_triangulation_2/PackageDescription.txt index 0481775afa0..eb96082b7c3 100644 --- a/Hyperbolic_triangulation_2/doc/Hyperbolic_triangulation_2/PackageDescription.txt +++ b/Hyperbolic_triangulation_2/doc/Hyperbolic_triangulation_2/PackageDescription.txt @@ -21,7 +21,7 @@ \cgalPkgPicture{Hyperbolic_triangulation_2/fig/ht-120px.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Mikhail Bogdanov, Iordan Iordanov, and Monique Teillaud} +\cgalPkgAuthors{Mikhail Bogdanov, Iordan Iordanov, and Monique Teillaud} \cgalPkgDesc{This package enables building and handling Delaunay triangulations of point sets in the Poincaré disk model of the hyperbolic plane. Triangulations are built incrementally and can be modified by insertion and removal of vertices; point location facilities are also offered, as well as primitives to diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 1fe8877acd6..b7cccb78915 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -23,6 +23,12 @@ Release date: June 2023 `CGAL::Polygon_mesh_processing::triangulate_and_refine_hole()`, and `CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole()` which have output iterators for vertices and faces as parameter. They are replaced by overloads with two additional named parameters. +- added functions `CGAL::Polygon_mesh_processing::region_growing_of_planes_on_faces()` and `CGAL::Polygon_mesh_processing::detect_corners_of_regions()` + that allow to have a partition into planar regions of a mesh using the region growing algorithm from the [Shape Detection](https://doc.cgal.org/5.6/Manual/packages.html#PkgShapeDetection) package. + +- Added the function `CGAL::Polygon_mesh_processing::surface_Delaunay_remeshing()`, that remeshes a surface triangle mesh following the +CGAL tetrahedral Delaunay refinement algorithm. + - Added the function `CGAL::Polygon_mesh_processing::surface_Delaunay_remeshing()`, that remeshes a surface triangle mesh using the Delaunay refinement algorithm from the 3D Mesh Generation package. @@ -32,6 +38,26 @@ Release date: June 2023 - This new package wraps all the existing code that deals with a `MeshComplex_3InTriangulation_3` to describe 3D simplicial meshes, and makes the data structure independent from the tetrahedral mesh generation package. +### [Shape Detection](https://doc.cgal.org/5.6/Manual/packages.html#PkgShapeDetection) (breaking change, major changes) + +- **Breaking change**: The region growing part of the package have been reworked to fix design issues introduced with the handling `FaceGraph` models. + In particular, the notion of `Item` has been introduced to reference an element in the input range of elements. Region maps now operates on `Item` and no longer on the value type + of the input range. +- **Breaking change**: The method `update()` in the concept `RegionType` returns now + a `boolean` instead of `void` that is used inside the class `Region_growing` for detecting if + the input conditions for the new region are satisfied. This change affects only user-defined + types of regions. +- **Breaking change**: The constructors of all models used together with the region growing algorithm now enable users + to provide parameters through the named parameters mechanism. +- All fitting classes in the region growing framework are now using better versions of the region + conditions, more precise and faster, including the correct normal orientations. +- Added new models of the concept `RegionType` for getting linear regions in a set of 2D and 3D + segments and on 2D and 3D polylines. +- Added the `Polyline_graph` class for extracting a set of polylines from a face graph, which splits + this graph into a set of user-defined regions. +- Added new shapes to the Region Growing algorithm on a point set: circles in 2D, spheres in 3D, + and cylinders in 3D. + ### [2D Arrangements](https://doc.cgal.org/5.6/Manual/packages.html#PkgArrangementOnSurface2) - Fixed some code that handles geodesic-curves on spheres that compare x- and y-coordinates on the boundary of the parameter space. It mainly effected the naive point-location. diff --git a/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt b/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt index 15927fd0590..b6007293b4e 100644 --- a/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt +++ b/Jet_fitting_3/doc/Jet_fitting_3/PackageDescription.txt @@ -7,7 +7,7 @@ \cgalPkgDescriptionBegin{Estimation of Local Differential Properties of Point-Sampled Surfaces,PkgJetFitting3} \cgalPkgPicture{DavidDetail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Marc Pouget and Frédéric Cazals} +\cgalPkgAuthors{Marc Pouget and Frédéric Cazals} \cgalPkgDesc{For a surface discretized as a point cloud or a mesh, it is desirable to estimate pointwise differential quantities. More precisely, first order properties correspond to the normal or the tangent plane; second order properties provide the principal curvatures and directions, third order properties provide the directional derivatives of the principal curvatures along the curvature lines, etc. This package allows the estimation of local differential quantities of a surface from a point sample.} \cgalPkgManuals{Chapter_Estimation_of_Local_Differential_Properties_of_Point-Sampled_Surfaces,PkgJetFitting3Ref} \cgalPkgSummaryEnd diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 3dee6912b54..71aa268e6d3 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -2044,6 +2044,10 @@ namespace CommonKernelFunctors { operator()(Return_base_tag, const Point_3& p, const Point_3& q, const Point_3& r) const { return Rep(p, q, r); } + Rep // Plane_3 + operator()(Return_base_tag, Origin o, const Point_3& q, const Point_3& r) const + { return Rep(o, q, r); } + Rep // Plane_3 operator()(Return_base_tag, const Point_3& p, const Direction_3& d) const { return Rep(p, d); } diff --git a/Kernel_23/include/CGAL/Plane_3.h b/Kernel_23/include/CGAL/Plane_3.h index 7823c98065c..104191a5d64 100644 --- a/Kernel_23/include/CGAL/Plane_3.h +++ b/Kernel_23/include/CGAL/Plane_3.h @@ -73,6 +73,9 @@ public: Plane_3(const Point_3& p, const Point_3& q, const Point_3& r) : Rep(typename R::Construct_plane_3()(Return_base_tag(), p, q, r)) {} + Plane_3(Origin o, const Point_3& q, const Point_3& r) + : Rep(typename R::Construct_plane_3()(Return_base_tag(), o, q, r)) {} + Plane_3(const Point_3& p, const Direction_3& d) : Rep(typename R::Construct_plane_3()(Return_base_tag(), p, d)) {} diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/bin/cgal_release.py b/Maintenance/infrastructure/cgal.geometryfactory.com/bin/cgal_release.py new file mode 100644 index 00000000000..d7656664faa --- /dev/null +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/bin/cgal_release.py @@ -0,0 +1,51 @@ +'''Python module to create and publish CGAL releases from a branch''' + +import os + +class Release: + '''class to create a CGAL release from a branch + optionally, the release can be internal + ''' + + def __init__(self, branch, internal=False) : + self.branch = branch + self.internal = internal + self.cwd = f'$HOME/CGAL/create_internal_release-{self.branch}-branch' + self.repo = f'$HOME/CGAL/branches/CGAL-{self.branch}-branch.git' + self.extra_options = ' --public' + + def command(self): + '''return the command to create and publish the release''' + return f"PATH=/home/lrineau/bin-cmake3:/bin:/usr/bin:/home/lrineau/bin; cd {self.cwd} && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release {self.repo}{self.extra_options} --do-it" + + def __str__(self) : + msg = f"{'internal ' if self.internal else ''}release from {self.branch}\n" \ + f"cwd: {self.cwd}\nrepo: {self.repo}\n" \ + f"command:\n{self.command()}" + return msg + + def __call__(self) : + if os.system(self.command()) != 0 : + raise RuntimeError(f"Error while creating {'internal ' if self.internal else ''}release from {self.branch}") + + INTERNAL = True + +class InternalRelease(Release) : + '''class to create an internal CGAL release from a branch''' + def __init__(self, branch) : + super().__init__(branch, Release.INTERNAL) + self.extra_options = ' --integration' + +integration = InternalRelease("integration") +integration.repo = '$HOME/CGAL/branches/integration.git' +integration.cwd = '$HOME/CGAL/create_internal_release' +master = Release("master") +master.repo = '$HOME/CGAL/branches/master.git' +master.cwd = '$HOME/CGAL/create_internal_release' + +def release(branch) : + '''Convenience function to create a release from a branch''' + return Release(branch) + +if __name__ == '__main__': + print("This file is a Python module. Use create_internal_release_of_the_day.py instead.") diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/bin/create_internal_release_of_the_day.py b/Maintenance/infrastructure/cgal.geometryfactory.com/bin/create_internal_release_of_the_day.py new file mode 100644 index 00000000000..43f4c3a9d69 --- /dev/null +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/bin/create_internal_release_of_the_day.py @@ -0,0 +1,39 @@ +#! /bin/python3 + +'''This script is called by a cron job every day. + It creates and publish a release tarball. +''' + +import sys +import os +import datetime +import locale +from pathlib import Path +sys.path.append(Path(__file__)) +from cgal_release import release, integration, master + +# Define a dictionary that maps day of the week to an action +actions = { + "Monday": integration, + "Tuesday": integration, + "Wednesday": integration, + "Thursday": integration, + "Friday": release("5.5"), + "Saturday": release("5.4"), + "Sunday": master +} + +if __name__ == '__main__': + # Get the current day of the week, or get it from the command line + locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + try: + DAY_OF_THE_WEEK = sys.argv[1] + except IndexError: + DAY_OF_THE_WEEK = datetime.datetime.now().strftime("%A") + + # Look up the action for the current day of the week in the dictionary + create_release = actions[DAY_OF_THE_WEEK] + + # Then create the release tarball + if os.system(create_release.command()) != 0 : + raise RuntimeError(f"ERROR while creating release tarball") diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index 03e9c354bc3..758fd180e8e 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -16,19 +16,19 @@ LC_CTYPE=en_US.UTF-8 5,15,25,35,45,55 * * * * cd $HOME/CGAL/collect_and_public_testresults; ./treat_result_collection || echo ERROR # Create internal release -# The script also updates the manual tools. - -# "master" alone -0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --public || echo ERROR -# "integration" -0 21 * * Mon,Tue,Wed cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it || echo ERROR -# from branch 5.5 -0 21 * * Fri cd $HOME/CGAL/create_internal_release-5.5-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.5-branch.git --public --do-it || echo ERROR -# from branch 5.4 -0 21 * * Sat,Thu cd $HOME/CGAL/create_internal_release-5.4-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.4-branch.git --public --do-it || echo ERROR - +0 21 * * * python3 /home/lrineau/CGAL/branches/local-master.git/Maintenance/infrastructure/cgal.geometryfactory.com/bin/create_internal_release_of_the_day.py ## Older stuff + +## "master" alone +#0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --public || echo ERROR +## "integration" +#0 21 * * Mon,Tue,Wed cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it || echo ERROR +## from branch 5.5 +#0 21 * * Fri cd $HOME/CGAL/create_internal_release-5.5-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.5-branch.git --public --do-it || echo ERROR +## from branch 5.4 +#0 21 * * Sat,Thu cd $HOME/CGAL/create_internal_release-5.4-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.4-branch.git --public --do-it || echo ERROR + # from branch 5.3 #0 21 * * Sat cd $HOME/CGAL/create_internal_release-5.3-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.3-branch.git --public --do-it || echo ERROR # from branch 5.2 diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index 08462c8341c..8cf21dda78d 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -37,7 +37,7 @@ \cgalPkgDescriptionBegin{3D Mesh Generation,PkgMesh3} \cgalPkgPicture{Mesh_3/fig/multilabel_mesher_small.jpg} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, Mariette Yvinec} +\cgalPkgAuthors{Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, and Mariette Yvinec} \cgalPkgDesc{This package is devoted to the generation of isotropic simplicial meshes discretizing 3D domains. The domain to be meshed is a region of 3D space that has to be bounded. The region may be connected or composed of multiple components and/or subdivided in several subdomains. The domain is input as an oracle able to answer queries, of a few different types, on the domain. Boundary and subdivision surfaces are either smooth or piecewise smooth surfaces, formed with planar or curved surface patches. Surfaces may exhibit 1-dimensional features (e.g. crease edges) and 0-dimensional features (e.g. singular points as corners tips, cusps or darts), that have to be fairly approximated in the mesh. Optionally, the algorithms support multi-core shared-memory architectures to take advantage of available parallelism.} \cgalPkgManuals{Chapter_3D_Mesh_Generation,PkgMesh3Ref} \cgalPkgSummaryEnd diff --git a/Mesh_3/include/CGAL/lloyd_optimize_mesh_3.h b/Mesh_3/include/CGAL/lloyd_optimize_mesh_3.h index 54c239802e8..cc325cb1e93 100644 --- a/Mesh_3/include/CGAL/lloyd_optimize_mesh_3.h +++ b/Mesh_3/include/CGAL/lloyd_optimize_mesh_3.h @@ -135,7 +135,7 @@ namespace CGAL { * \note This function requires the \ref thirdpartyEigen library. */ template -Mesh_optimization_return_code lloyd_optimize_mesh_3(C3T3& c3t3, MeshDomain& domain,const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code lloyd_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain,const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -153,7 +153,7 @@ template -Mesh_optimization_return_code lloyd_optimize_mesh_3(C3T3& c3t3,MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) +Mesh_optimization_return_code lloyd_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) { return lloyd_optimize_mesh_3(c3t3,domain, internal_np::combine_named_parameters(np1, np2, nps...)); } diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h index 64105159344..7160b9944d4 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -417,7 +417,7 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_false > * \sa `odt_optimize_mesh_3()` */ template -C3T3 make_mesh_3(MeshDomain& domain, MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) +C3T3 make_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -443,7 +443,7 @@ template -C3T3 make_mesh_3(MeshDomain& domain, MeshCriteria& criteria, +C3T3 make_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Mesh_3/include/CGAL/odt_optimize_mesh_3.h b/Mesh_3/include/CGAL/odt_optimize_mesh_3.h index 5c1d39e36f0..95e9f159bb6 100644 --- a/Mesh_3/include/CGAL/odt_optimize_mesh_3.h +++ b/Mesh_3/include/CGAL/odt_optimize_mesh_3.h @@ -130,7 +130,7 @@ namespace CGAL { * \sa `CGAL::lloyd_optimize_mesh_3()` */ template -Mesh_optimization_return_code odt_optimize_mesh_3(C3T3& c3t3, MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code odt_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -148,7 +148,7 @@ template -Mesh_optimization_return_code odt_optimize_mesh_3(C3T3& c3t3, MeshDomain& domain, +Mesh_optimization_return_code odt_optimize_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Mesh_3/include/CGAL/perturb_mesh_3.h b/Mesh_3/include/CGAL/perturb_mesh_3.h index e5be05310df..3de2ff074a9 100644 --- a/Mesh_3/include/CGAL/perturb_mesh_3.h +++ b/Mesh_3/include/CGAL/perturb_mesh_3.h @@ -102,7 +102,7 @@ namespace CGAL { * */ template -Mesh_optimization_return_code perturb_mesh_3(C3T3& c3t3, MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code perturb_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -120,7 +120,7 @@ template -Mesh_optimization_return_code perturb_mesh_3(C3T3& c3t3, MeshDomain& domain, +Mesh_optimization_return_code perturb_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Mesh_3/include/CGAL/refine_mesh_3.h b/Mesh_3/include/CGAL/refine_mesh_3.h index 94a44676b0c..3f11e81ce8a 100644 --- a/Mesh_3/include/CGAL/refine_mesh_3.h +++ b/Mesh_3/include/CGAL/refine_mesh_3.h @@ -261,7 +261,7 @@ private: * \sa `CGAL::parameters::no_odt()` */ template -void refine_mesh_3(C3T3& c3t3, MeshDomain& domain, MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) +void refine_mesh_3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -291,7 +291,7 @@ template -void refine_mesh_3(C3T3& c3t3, MeshDomain& domain, MeshCriteria& criteria, +void refine_mesh_3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_vertical_decomposition_2.h b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_vertical_decomposition_2.h index 28e560c6fd3..132f04b2963 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_vertical_decomposition_2.h +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_vertical_decomposition_2.h @@ -4,7 +4,7 @@ namespace CGAL { \ingroup PkgMinkowskiSum2Ref The `Polygon_vertical_decomposition_2` class implements a convex -decompistion of a polygon or a polygon with holes into pseudo trapezoids +decomposition of a polygon or a polygon with holes into pseudo trapezoids utilizing the CGAL::decompose() free function of the \ref chapterArrangement_on_surface_2 "2D Arrangements" package. diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt b/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt index 23009c9f2ba..bb770a24620 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt @@ -8,7 +8,7 @@ \cgalPkgDescriptionBegin{2D Minkowski Sums,PkgMinkowskiSum2} \cgalPkgPicture{Minkowski_sum_2/fig/Minkowski_sum_2.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Ron Wein, Alon Baram, Eyal Flato, Efi Fogel, Michael Hemmer, Sebastian Morr} +\cgalPkgAuthors{Ron Wein, Alon Baram, Eyal Flato, Efi Fogel, Michael Hemmer, and Sebastian Morr} \cgalPkgDesc{This package consists of functions that compute the Minkowski sum of two simple straight-edge polygons in the plane. It also contains functions for computing the Minkowski sum of a polygon and a disc, an operation known as offsetting or dilating a polygon. The package can compute the exact representation of the offset polygon, or provide a guaranteed approximation of the offset.} \cgalPkgManuals{Chapter_2D_Minkowski_Sums,PkgMinkowskiSum2Ref} \cgalPkgSummaryEnd diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp index 09c0ad4b089..6ac0708dd2f 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum.cpp @@ -40,9 +40,9 @@ static const char* strategy_names[] = { "small-side angle-bisector decomposition", "optimal convex decomposition", "Hertel-Mehlhorn decomposition", - "Greene decomosition", + "Greene decomposition", "Triangulation", - "Vertical decomosition" + "Vertical decomposition" }; Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_2& p, Polygon_2& q, diff --git a/Nef_2/include/CGAL/Nef_2/PM_checker.h b/Nef_2/include/CGAL/Nef_2/PM_checker.h index a971ee5b946..4000d0d497e 100644 --- a/Nef_2/include/CGAL/Nef_2/PM_checker.h +++ b/Nef_2/include/CGAL/Nef_2/PM_checker.h @@ -220,7 +220,7 @@ check_boundary_is_clockwise_weakly_polygon() const } while (hvit != hend); // now e_boundary_at_v_min is highest starting edge in bundle!! - int winding_around_globally=0; + CGAL_assertion_code(int winding_around_globally=0); Halfedge_around_face_const_circulator hfit(e_boundary_at_v_min),hstart(hfit); Halfedge_const_handle e_prev = next(e_boundary_at_v_min); @@ -229,7 +229,7 @@ check_boundary_is_clockwise_weakly_polygon() const Direction d_prev = direction(e_prev); CGAL_For_all_backwards(hstart,hfit) { Direction d_curr = direction(hfit); - if ( d_curr < d_prev ) ++winding_around_globally; + CGAL_assertion_code(if ( d_curr < d_prev ) ++winding_around_globally); d_prev = d_curr; } CGAL_assertion(winding_around_globally == 1); @@ -262,10 +262,10 @@ check_is_triangulation() const for( eit = this->halfedges_begin(); eit != this->halfedges_end(); ++eit) { if (on_boundary[eit]) continue; hit = hend = eit; - int edges_in_face_cycle=0; + CGAL_assertion_code(int edges_in_face_cycle=0); CGAL_For_all(hit,hend) { error_status << PE(hit); - ++edges_in_face_cycle; + CGAL_assertion_code(++edges_in_face_cycle); } CGAL_assertion_msg(edges_in_face_cycle==3,error_status.str().c_str()); CGAL_assertion_msg( diff --git a/Nef_3/include/CGAL/Nef_3/K3_tree.h b/Nef_3/include/CGAL/Nef_3/K3_tree.h index 81eb55e4c4a..3bec191d7c2 100644 --- a/Nef_3/include/CGAL/Nef_3/K3_tree.h +++ b/Nef_3/include/CGAL/Nef_3/K3_tree.h @@ -23,13 +23,11 @@ #include #include #include + #include - -#include #include #include -#include #undef CGAL_NEF_DEBUG #define CGAL_NEF_DEBUG 503 diff --git a/Nef_S2/include/CGAL/Nef_S2/SM_const_decorator.h b/Nef_S2/include/CGAL/Nef_S2/SM_const_decorator.h index 2f71b2cc9d6..e1e1762dc8f 100644 --- a/Nef_S2/include/CGAL/Nef_S2/SM_const_decorator.h +++ b/Nef_S2/include/CGAL/Nef_S2/SM_const_decorator.h @@ -299,13 +299,13 @@ check_integrity_and_topological_planarity(bool faces) const EI(shalfedges_begin(),shalfedges_end(),'e'); #endif SVertex_const_handle v; - int iso_vert_num=0; + CGAL_assertion_code(int iso_vert_num=0); /* check the source links of out edges and count isolated vertices */ CGAL_forall_svertices(v,*this) { if ( is_isolated(v) ) { if ( faces ) CGAL_assertion_msg(v->incident_sface() != SFace_const_handle(), get_svertex_index(v).c_str()); - ++iso_vert_num; + CGAL_assertion_code(++iso_vert_num); } else { CGAL_assertion_code(SHalfedge_const_handle e=first_out_edge(v)); CGAL_assertion_msg(e != SHalfedge_const_handle(), get_svertex_index(v).c_str()); diff --git a/Nef_S2/include/CGAL/Nef_S2/Sphere_circle.h b/Nef_S2/include/CGAL/Nef_S2/Sphere_circle.h index 664adc4ab13..4562fab0c9d 100644 --- a/Nef_S2/include/CGAL/Nef_S2/Sphere_circle.h +++ b/Nef_S2/include/CGAL/Nef_S2/Sphere_circle.h @@ -57,7 +57,7 @@ Sphere_circle() : Base() {} /*{\Mcreate creates some great circle.}*/ Sphere_circle(const Sphere_point& p, const Sphere_point&q) - : Base(Point_3(0,0,0),p,q) + : Base(CGAL::ORIGIN,p,q) /*{\Mcreate creates a great circle through $p$ and $q$. If $p$ and $q$ are not antipodal on $S_2$, then this circle is unique and oriented such that a walk along |\Mvar| meets $p$ just before the shorter segment @@ -104,9 +104,9 @@ Sphere_circle(Sphere_circle c, const Sphere_point& p) { CGAL_assertion(!c.has_on(p)); if ( c.has_on_negative_side(p) ) c=c.opposite(); if ( p == c.orthogonal_pole() ) - *this = Sphere_circle(Base(Point_3(0,0,0),p,CGAL::ORIGIN+c.base1())); + *this = Sphere_circle(Base(CGAL::ORIGIN,p,CGAL::ORIGIN+c.base1())); else - *this = Sphere_circle(Base(Point_3(0,0,0),p,c.orthogonal_pole())); + *this = Sphere_circle(Base(CGAL::ORIGIN,p,c.orthogonal_pole())); } /*{\Moperations 4 2}*/ diff --git a/Nef_S2/include/CGAL/Nef_S2/Sphere_direction.h b/Nef_S2/include/CGAL/Nef_S2/Sphere_direction.h index 138c5ba91a6..962a3e13268 100644 --- a/Nef_S2/include/CGAL/Nef_S2/Sphere_direction.h +++ b/Nef_S2/include/CGAL/Nef_S2/Sphere_direction.h @@ -51,14 +51,14 @@ Sphere_direction(const Sphere_circle& c) : Base(c) {} Sphere_direction(const Sphere_point& p, const Sphere_point&q) - : Base(Point_3(0,0,0),p,q) + : Base(CGAL::ORIGIN,p,q) /*{\Mcreate creates a direction that describes the orientation of the great circle through $p$ and $q$ (oriented such that the segment $pq$ is the shorter one of the two possible ones. \precond $p$ and $q$ are not opposite on $S_2$.}*/ { CGAL_assertion(p!=q.opposite()); - Point_3 p1(0,0,0), p4 = CGAL::ORIGIN + ((Base*) this)->orthogonal_vector(); - if ( CGAL::orientation(p1,p,q,p4) != CGAL::POSITIVE ) + Point_3 p4 = CGAL::ORIGIN + ((Base*) this)->orthogonal_vector(); + if ( R().orientation_3_object()(CGAL::ORIGIN,p,q,p4) != CGAL::POSITIVE ) *this = Sphere_direction(opposite()); } @@ -95,18 +95,20 @@ bool strictly_ordered_ccw_at(const Sphere_point& p, const Sphere_direction& d2, const Sphere_direction& d3) { CGAL_assertion(d1.has_on(p) && d2.has_on(p) && d3.has_on(p)); - typename R::Point_3 p0(0,0,0); - typename R::Point_3 p1(CGAL::ORIGIN + d1.orthogonal_vector()); - typename R::Point_3 p2(CGAL::ORIGIN + d2.orthogonal_vector()); - typename R::Point_3 p3(CGAL::ORIGIN + d3.orthogonal_vector()); + typedef typename R::Vector_3 Vector_3; + Vector_3 v0 = p - CGAL::ORIGIN; + Vector_3 v1 = d1.orthogonal_vector(); + Vector_3 v2 = d2.orthogonal_vector(); + Vector_3 v3 = d3.orthogonal_vector(); if ( d1 == d3 ) return false; - if ( CGAL::orientation(p0,p,p1,p3) == CGAL::POSITIVE ) { - return CGAL::orientation(p0,p,p1,p2) == CGAL::POSITIVE && - CGAL::orientation(p0,p,p3,p2) == CGAL::NEGATIVE; + typename R::Orientation_3 orientation = R().orientation_3_object(); + if ( orientation(v0,v1,v3) == CGAL::POSITIVE ) { + return orientation(v0,v1,v2) == CGAL::POSITIVE && + orientation(v0,v3,v2) == CGAL::NEGATIVE; } else { - return CGAL::orientation(p0,p,p1,p2) == CGAL::POSITIVE || - CGAL::orientation(p0,p,p3,p2) == CGAL::NEGATIVE; + return orientation(v0,v1,v2) == CGAL::POSITIVE || + orientation(v0,v3,v2) == CGAL::NEGATIVE; } } diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index 4ab46f8993c..0066aa35de1 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -17,7 +17,7 @@ \cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox} \cgalPkgPicture{optimal_bounding_box.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Konstantinos Katrioplas, Mael Rouxel-Labbé} +\cgalPkgAuthors{Konstantinos Katrioplas and Mael Rouxel-Labbé} \cgalPkgDesc{This package provides functions to compute tight oriented bounding boxes around a point set or a polygon mesh.} \cgalPkgManuals{Chapter_Building_Optimal_Bounding_Box,PkgOptimalBoundingBoxRef} \cgalPkgSummaryEnd diff --git a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h index fde1549a865..7ac83c723f5 100644 --- a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h +++ b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/scene.h @@ -432,10 +432,10 @@ public: m_pwsrec->list_output(std::back_inserter(isolated_points), std::back_inserter(edges)); - int vertex_count = 0; + CGAL_assertion_code(int vertex_count = 0); for (std::vector::iterator it = isolated_points.begin(); it != isolated_points.end(); it++) { - vertex_count++; + CGAL_assertion_code(vertex_count++); std::cout << *it << std::endl; } CGAL_assertion(vertex_count == 18); diff --git a/Optimal_transportation_reconstruction_2/doc/Optimal_transportation_reconstruction_2/PackageDescription.txt b/Optimal_transportation_reconstruction_2/doc/Optimal_transportation_reconstruction_2/PackageDescription.txt index 1e4d7a84d0e..66636bca10b 100644 --- a/Optimal_transportation_reconstruction_2/doc/Optimal_transportation_reconstruction_2/PackageDescription.txt +++ b/Optimal_transportation_reconstruction_2/doc/Optimal_transportation_reconstruction_2/PackageDescription.txt @@ -12,7 +12,7 @@ \cgalPkgDescriptionBegin{Optimal Transportation Curve Reconstruction, PkgOptimalTransportationReconstruction2} \cgalPkgPicture{RS_2_small.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Pierre Alliez, David Cohen-Steiner, Fernando de Goes, Clément Jamin, Ivo Vigan} +\cgalPkgAuthors{Pierre Alliez, David Cohen-Steiner, Fernando de Goes, Clément Jamin, and Ivo Vigan} \cgalPkgDesc{This package provides an algorithm to reconstruct and simplify a shape from a point set in the plane, possibly hampered with noise and outliers. It generates as output a set of line segments and isolated points, which approximate the input point set.} \cgalPkgManuals{Chapter_Optimal_Transportation_Curve_Reconstruction, PkgOptimalTransportationReconstruction2Ref} \cgalPkgSummaryEnd diff --git a/Orthtree/doc/Orthtree/PackageDescription.txt b/Orthtree/doc/Orthtree/PackageDescription.txt index 4da4712b416..22b02350771 100644 --- a/Orthtree/doc/Orthtree/PackageDescription.txt +++ b/Orthtree/doc/Orthtree/PackageDescription.txt @@ -21,7 +21,7 @@ \cgalPkgDescriptionBegin{Quadtrees\, Octrees\, and Orthtrees,PkgOrthtree} \cgalPkgPicture{octree_thumbnail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Jackson Campolattaro, Simon Giraudot, Cédric Portaneri, Tong Zhao, Pierre Alliez} +\cgalPkgAuthors{Jackson Campolattaro, Simon Giraudot, Cédric Portaneri, Tong Zhao, and Pierre Alliez} \cgalPkgDesc{The Orthtree package provides a data structure that subdivides space, with specializations for 2D (Quadtree) and 3D (Octree), along with a collection of algorithms for operating on these structures.} \cgalPkgManuals{Chapter_Orthtree,PkgOrthtreeRef} \cgalPkgSummaryEnd diff --git a/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h index 2c42a1b9800..570d1fb610b 100644 --- a/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h @@ -312,7 +312,7 @@ struct C3t3_initializer * \sa `odt_optimize_mesh_3()` */ template -C3T3 make_periodic_3_mesh_3(MeshDomain& domain, MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) +C3T3 make_periodic_3_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -339,7 +339,7 @@ template -C3T3 make_periodic_3_mesh_3(MeshDomain& domain, MeshCriteria& criteria, +C3T3 make_periodic_3_mesh_3(const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Periodic_3_mesh_3/include/CGAL/optimize_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/optimize_periodic_3_mesh_3.h index 0a7c1e5ef4c..b9ed2f3a327 100644 --- a/Periodic_3_mesh_3/include/CGAL/optimize_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/optimize_periodic_3_mesh_3.h @@ -34,7 +34,7 @@ namespace CGAL { * Further information can be found in the documentation of the function `perturb_mesh_3()`. */ template -Mesh_optimization_return_code perturb_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code perturb_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -50,7 +50,7 @@ template -Mesh_optimization_return_code perturb_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, +Mesh_optimization_return_code perturb_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) @@ -131,7 +131,7 @@ Mesh_optimization_return_code exude_periodic_3_mesh_3(const CGAL_NP_CLASS_1& np * Further information can be found in the documentation of the function `odt_optimize_mesh_3()`. */ template -Mesh_optimization_return_code odt_optimize_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code odt_optimize_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -148,7 +148,7 @@ template -Mesh_optimization_return_code odt_optimize_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, +Mesh_optimization_return_code odt_optimize_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) @@ -180,7 +180,7 @@ Mesh_optimization_return_code odt_optimize_periodic_3_mesh_3(const CGAL_NP_CLASS * \note This function requires the \ref thirdpartyEigen library. */ template -Mesh_optimization_return_code lloyd_optimize_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain,const CGAL_NP_CLASS& np = parameters::default_values()) +Mesh_optimization_return_code lloyd_optimize_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain,const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -197,7 +197,7 @@ template -Mesh_optimization_return_code lloyd_optimize_periodic_3_mesh_3(C3T3& c3t3,MeshDomain& domain, +Mesh_optimization_return_code lloyd_optimize_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h index f013a73e9d8..5197b36d752 100644 --- a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h @@ -298,7 +298,7 @@ void project_points(C3T3& c3t3, * \sa `odt_optimize_periodic_3_mesh_3()` */ template -void refine_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) +void refine_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -328,7 +328,7 @@ template -void refine_periodic_3_mesh_3(C3T3& c3t3, MeshDomain& domain, MeshCriteria& criteria, +void refine_periodic_3_mesh_3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria, const CGAL_NP_CLASS_1& np1, const CGAL_NP_CLASS_2& np2, const NP& ... nps) diff --git a/Periodic_4_hyperbolic_triangulation_2/doc/Periodic_4_hyperbolic_triangulation_2/PackageDescription.txt b/Periodic_4_hyperbolic_triangulation_2/doc/Periodic_4_hyperbolic_triangulation_2/PackageDescription.txt index eae9f7d96c5..f5b7200ee7e 100644 --- a/Periodic_4_hyperbolic_triangulation_2/doc/Periodic_4_hyperbolic_triangulation_2/PackageDescription.txt +++ b/Periodic_4_hyperbolic_triangulation_2/doc/Periodic_4_hyperbolic_triangulation_2/PackageDescription.txt @@ -23,7 +23,7 @@ \cgalPkgPicture{Periodic_4_hyperbolic_triangulation_2/fig/new-triangulation-120px.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Iordan Iordanov and Monique Teillaud} +\cgalPkgAuthors{Iordan Iordanov and Monique Teillaud} \cgalPkgDesc{This package enables building and handling triangulations of point sets on the two dimensional hyperbolic Bolza surface. Triangulations are built incrementally and can be modified by insertion or removal of vertices. Point location facilities are also offered. The package provides Delaunay diff --git a/Point_set_3/doc/Point_set_3/PackageDescription.txt b/Point_set_3/doc/Point_set_3/PackageDescription.txt index 0b747c1f538..271b13b4634 100644 --- a/Point_set_3/doc/Point_set_3/PackageDescription.txt +++ b/Point_set_3/doc/Point_set_3/PackageDescription.txt @@ -55,7 +55,7 @@ \cgalPkgDescriptionBegin{3D Point Set, PkgPointSet3} \cgalPkgPicture{point_set_3.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Simon Giraudot} +\cgalPkgAuthor{Simon Giraudot} \cgalPkgDesc{This component provides the user with a flexible 3D point set data structure. The user can define any additional property needed such as normal vectors, colors or labels. \cgal algorithms can be easily applied to this data structure.} \cgalPkgManuals{Chapter_Point_Set_3, PkgPointSet3Ref} \cgalPkgSummaryEnd diff --git a/Point_set_3/include/CGAL/Point_set_3.h b/Point_set_3/include/CGAL/Point_set_3.h index 7c85500db92..2d0f2083dcc 100644 --- a/Point_set_3/include/CGAL/Point_set_3.h +++ b/Point_set_3/include/CGAL/Point_set_3.h @@ -35,6 +35,49 @@ namespace CGAL { +template ::Kernel::Vector_3> +class Point_set_3; + +/// \cond SKIP_IN_MANUAL +namespace internal { + template + class Point_set_3_index + { + public: +#ifdef CGAL_POINT_SET_3_USE_STD_SIZE_T_AS_SIZE_TYPE + typedef std::size_t size_type; +#else + typedef boost::uint32_t size_type; +#endif + typedef CGAL::Point_set_3 Point_set_3; + + private: + friend class CGAL::Point_set_3; + friend class Properties::Property_container; + template friend class Properties::Property_array; + template friend struct Property_map; + friend class std::vector; + size_type value; + + public: + Point_set_3_index(const Point_set_3_index& index) : value(static_cast(index)) { } + Point_set_3_index(const std::size_t& value) : value(static_cast(value)) { } + Point_set_3_index() : value(static_cast(-1)) { } + Point_set_3_index operator= (const Point_set_3_index& index) { value = index.value; return *this; } + + operator std::size_t() const { return static_cast(value); } + bool operator== (const Point_set_3_index& index) const { return value == index.value; } + bool operator!= (const Point_set_3_index& index) const { return value != index.value; } + bool operator< (const Point_set_3_index& index) const { return value < index.value; } + Point_set_3_index& operator++ () { ++value; return *this; } + Point_set_3_index& operator-- () { --value; return *this; } + Point_set_3_index operator++ (int) { Point_set_3_index tmp(*this); ++value; return tmp; } + Point_set_3_index operator-- (int) { Point_set_3_index tmp(*this); --value; return tmp; } +}; +/// \endcond +} // namespace internal + /*! \ingroup PkgPointSet3Ref @@ -75,7 +118,7 @@ namespace CGAL { */ template ::Kernel::Vector_3> + typename Vector> class Point_set_3 { public: @@ -85,7 +128,7 @@ public: typedef Vector Vector_type; typedef Point_set_3 Point_set; - class Index; + using Index = internal::Point_set_3_index; typedef typename Properties::Property_container Base; @@ -105,45 +148,15 @@ public: }; /// \endcond - /*! - \brief This represents a point with associated properties. - \cgalModels `::Index` - \cgalModels `LessThanComparable` - \cgalModels `Hashable` +#ifdef DOXYGEN_RUNNING + /*! + \brief This represents a point with associated properties. + \cgalModels `::Index` + \cgalModels `LessThanComparable` + \cgalModels `Hashable` */ - class Index - { - /// \cond SKIP_IN_MANUAL - public: -#ifdef CGAL_POINT_SET_3_USE_STD_SIZE_T_AS_SIZE_TYPE - typedef std::size_t size_type; -#else - typedef boost::uint32_t size_type; + class Index; #endif - private: - friend class Point_set_3; - friend class Properties::Property_container; - template friend class Properties::Property_array; - template friend struct Property_map; - friend class std::vector; - size_type value; - - public: - Index (const Index& index) : value (static_cast(index)) { } - Index (const std::size_t& value) : value (static_cast(value)) { } - Index () : value (static_cast(-1)) { } - Index operator= (const Index& index) { value = index.value; return *this; } - /// \cond SKIP_IN_MANUAL - operator std::size_t() const { return static_cast(value); } - bool operator== (const Index& index) const { return value == index.value; } - bool operator!= (const Index& index) const { return value != index.value; } - bool operator< (const Index& index) const { return value < index.value; } - Index& operator++ () { ++ value; return *this; } - Index& operator-- () { -- value; return *this; } - Index operator++ (int) { Index tmp(*this); ++ value; return tmp; } - Index operator-- (int) { Index tmp(*this); -- value; return tmp; } - /// \endcond - }; typedef Point Point_3; ///< The point type typedef Vector Vector_3; ///< The vector type @@ -694,7 +707,6 @@ public: \sa `number_of_removed_points()` */ std::size_t garbage_size () const { return number_of_removed_points(); } - /// \endcond /*! \brief returns `true` if there are elements marked as removed, `false` otherwise. @@ -1275,9 +1287,6 @@ private: }; // end of class Point_set_3 - - - /*! \brief Append `other` at the end of `ps`. @@ -1303,8 +1312,8 @@ Point_set_3& operator+=(Point_set_3& ps, /// \cond SKIP_IN_MANUAL // specialization for default named parameters -template -struct Point_set_processing_3_np_helper, NamedParameters, NP_TAG> +template +struct Point_set_processing_3_np_helper, NamedParameters, DPM, DVM> { typedef typename std::iterator_traits::iterator>::value_type Value_type; @@ -1313,9 +1322,9 @@ struct Point_set_processing_3_np_helper, NamedParamet typedef typename Point_set_3::template Property_map DefaultPMap; typedef const typename Point_set_3::template Property_map DefaultConstPMap; - typedef typename internal_np::Lookup_named_param_def ::type Point_map; // public - typedef typename internal_np::Lookup_named_param_def ::type Const_point_map; // public typedef typename internal_np::Lookup_named_param_def < @@ -1374,5 +1383,23 @@ struct Point_set_processing_3_np_helper, NamedParamet } // namespace CGAL +namespace boost { +template +std::size_t hash_value(const typename CGAL::internal::Point_set_3_index& i) +{ + return i; +} +} // namespace boost + +namespace std { +template +struct hash< CGAL::internal::Point_set_3_index > { + std::size_t operator()(const CGAL::internal::Point_set_3_index& i) const + { + std::size_t ret = i; + return ret; + } +}; +} // namespace std #endif // CGAL_POINT_SET_3_H diff --git a/Point_set_3/test/Point_set_3/point_set_test.cpp b/Point_set_3/test/Point_set_3/point_set_test.cpp index 4ba80d07ed5..f436114762d 100644 --- a/Point_set_3/test/Point_set_3/point_set_test.cpp +++ b/Point_set_3/test/Point_set_3/point_set_test.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include @@ -126,6 +128,9 @@ int main (int, char**) test (p_before == p_after, "points should not change when clearing properties."); + std::unordered_set std_hash; + boost::unordered_set boost_hash; + std::cerr << nb_success << "/" << nb_test << " test(s) succeeded." << std::endl; return EXIT_SUCCESS; diff --git a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt index bf0029d6c94..f9e3c5b663e 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt @@ -35,7 +35,7 @@ format. \cgalPkgDescriptionBegin{Point Set Processing,PkgPointSetProcessing3} \cgalPkgPicture{point_set_processing_detail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Simon Giraudot, Clément Jamin, Florent Lafarge, Quentin Mérigot, Jocelyn Meyron, Laurent Saboret, Nader Salman, Shihao Wu, Necip Fazil Yildiran} +\cgalPkgAuthors{Pierre Alliez, Simon Giraudot, Clément Jamin, Florent Lafarge, Quentin Mérigot, Jocelyn Meyron, Laurent Saboret, Nader Salman, Shihao Wu, and Necip Fazil Yildiran} \cgalPkgDesc{This \cgal component implements methods to analyze and process unorganized point sets. The input is an unorganized point set, possibly with normal attributes (unoriented or oriented). The point set can be analyzed to measure its average spacing, and processed through functions devoted to the simplification, outlier removal, smoothing, normal estimation, normal orientation, feature edges estimation and registration.} \cgalPkgManuals{Chapter_Point_Set_Processing,PkgPointSetProcessing3Ref} \cgalPkgSummaryEnd diff --git a/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/PackageDescription.txt b/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/PackageDescription.txt index c3965089082..f615d0988b3 100644 --- a/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/PackageDescription.txt +++ b/Poisson_surface_reconstruction_3/doc/Poisson_surface_reconstruction_3/PackageDescription.txt @@ -4,7 +4,7 @@ \cgalPkgDescriptionBegin{Poisson Surface Reconstruction,PkgPoissonSurfaceReconstruction3} \cgalPkgPicture{surface_reconstruction_points_detail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Laurent Saboret, Gaël Guennebaud} +\cgalPkgAuthors{Pierre Alliez, Laurent Saboret, and Gaël Guennebaud} \cgalPkgDesc{This package implements a surface reconstruction method: Poisson Surface Reconstruction. It takes as input a set of points with oriented normals and computes an implicit function. The \cgal surface mesh generator can then be used to extract an iso-surface from this function. } \cgalPkgManuals{Chapter_Poisson_Surface_Reconstruction,PkgPoissonSurfaceReconstruction3Ref} \cgalPkgSummaryEnd diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Doxyfile.in b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Doxyfile.in index 52bde2b920c..5623c654d58 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Doxyfile.in +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Doxyfile.in @@ -8,8 +8,10 @@ WARN_IF_UNDOCUMENTED = false INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h INPUT += ${CGAL_Mesh_3_INCLUDE_DIR}/CGAL/Polygon_mesh_processing/surface_Delaunay_remeshing.h \ - ${CGAL_Mesh_3_INCLUDE_DIR}/CGAL/Mesh_facet_topology.h + ${CGAL_Mesh_3_INCLUDE_DIR}/CGAL/Mesh_facet_topology.h \ + ${CGAL_Shape_detection_INCLUDE_DIR}/CGAL/Polygon_mesh_processing/region_growing.h STRIP_FROM_PATH += ${CGAL_Mesh_3_INCLUDE_DIR} +STRIP_FROM_PATH += ${CGAL_Shape_detection_INCLUDE_DIR} # macros to be used inside the code ALIASES += "cgalDescribePolylineType=A polyline is defined as a sequence of points, each pair of contiguous points defines a segment of the polyline. If the first and last points of the polyline are identical, the polyline is closed." diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index 3906fe9dab3..8141fbd16f2 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -75,7 +75,7 @@ \cgalPkgPicture{hole_filling_ico.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Sébastien Loriot, Mael Rouxel-Labbé, Jane Tournois, Ilker %O. Yaz} +\cgalPkgAuthors{Sébastien Loriot, Mael Rouxel-Labbé, Jane Tournois, and Ilker %O. Yaz} \cgalPkgDesc{This package provides a collection of methods and classes for polygon mesh processing, ranging from basic operations on simplices, to complex geometry processing algorithms such as Boolean operations, remeshing, repairing, collision and intersection detection, and more.} @@ -248,6 +248,8 @@ The page \ref bgl_namedparameters "Named Parameters" describes their usage. - `CGAL::Polygon_mesh_processing::extract_boundary_cycles()` - `CGAL::Polygon_mesh_processing::transform()` - `CGAL::Polygon_mesh_processing::triangle()` +- `CGAL::Polygon_mesh_processing::region_growing_of_planes_on_faces()` +- `CGAL::Polygon_mesh_processing::detect_corners_of_regions()` \cgalCRPSection{I/O Functions} - \link PMP_IO_grp `CGAL::Polygon_mesh_processing::IO::read_polygon_mesh()`\endlink diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/dependencies b/Polygon_mesh_processing/doc/Polygon_mesh_processing/dependencies index feea196d305..52a669c84d0 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/dependencies +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/dependencies @@ -16,5 +16,6 @@ Surface_mesh_deformation Surface_mesh_simplification Triangulation_2 Mesh_3 +Shape_detection diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h index 77e7909201d..89a3cd82904 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h @@ -707,7 +707,7 @@ public: Border_edge_map is_marked_1(intersection_edges1, tm1); std::size_t nb_patches_tm1 = connected_components(tm1, - bind_property_maps(fids1,make_property_map(&tm1_patch_ids[0])), + make_compose_property_map(fids1,make_property_map(&tm1_patch_ids[0])), parameters::edge_is_constrained_map(is_marked_1) .face_index_map(fids1)); @@ -720,7 +720,7 @@ public: Border_edge_map is_marked_2(intersection_edges2, tm2); std::size_t nb_patches_tm2 = connected_components(tm2, - bind_property_maps(fids2,make_property_map(&tm2_patch_ids[0])), + make_compose_property_map(fids2,make_property_map(&tm2_patch_ids[0])), parameters::edge_is_constrained_map(is_marked_2) .face_index_map(fids2)); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h index 7ee732f4e83..e4e658a49b5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h @@ -148,7 +148,7 @@ public: std::size_t nb_patches_tm1 = connected_components(tm1, - bind_property_maps(fids1,make_property_map(&tm1_patch_ids[0])), + make_compose_property_map(fids1,make_property_map(&tm1_patch_ids[0])), parameters::edge_is_constrained_map(ecm1) .face_index_map(fids1)); @@ -228,7 +228,7 @@ public: } } - keep_connected_components(tm1, cc_to_keep, bind_property_maps(fids1,make_property_map(&tm1_patch_ids[0]))); + keep_connected_components(tm1, cc_to_keep, make_compose_property_map(fids1,make_property_map(&tm1_patch_ids[0]))); } }; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Output_builder_for_autorefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Output_builder_for_autorefinement.h index 5db5f0911ec..b130a2d1612 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Output_builder_for_autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Output_builder_for_autorefinement.h @@ -349,7 +349,7 @@ public: is_intersection(intersection_edges); std::size_t nb_patches = connected_components(tm, - bind_property_maps(fids,make_property_map(patch_ids)), + make_compose_property_map(fids,make_property_map(patch_ids)), parameters::edge_is_constrained_map(is_intersection) .face_index_map(fids)); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h index 721f4fd5773..ee3d3159491 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h @@ -306,7 +306,7 @@ struct Side_of_helper typedef CGAL::Pointer_property_map::type Id_to_box; Id_to_box id_to_box = CGAL::make_property_map(face_bboxes); - typedef Property_map_binder BPM; + typedef Compose_property_map BPM; BPM bpm(fid, id_to_box); Compute_bbox compute_bbox(bpm); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 1388ebaeb22..62c1dc6d3e2 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -113,6 +113,7 @@ void simplify_range(HalfedgeRange& halfedge_range, std::set edges_to_test(halfedge_range.begin(), halfedge_range.end()); int collapsed_n = 0; + while(!edges_to_test.empty()) { const halfedge_descriptor h = *(edges_to_test.begin()); @@ -165,12 +166,11 @@ void simplify_range(HalfedgeRange& halfedge_range, edges_to_test.insert(prev_h); if(next_h!=opoh && get(range_halfedges, next_h)) edges_to_test.insert(next_h); - ++collapsed_n; } } } - + CGAL_USE(collapsed_n); #ifdef CGAL_PMP_SNAP_DEBUG std::cout << "collapsed " << collapsed_n << " edges" << std::endl; #endif diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h index daa4d767e8b..faeb7c83b75 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h @@ -434,7 +434,7 @@ void orient(TriangleMesh& tm, // set the connected component id of each face std::size_t nb_cc = connected_components(tm, - bind_property_maps(fid_map,make_property_map(face_cc)), + make_compose_property_map(fid_map,make_property_map(face_cc)), parameters::face_index_map(fid_map)); // extract a vertex with max z coordinate for each connected component @@ -844,7 +844,7 @@ volume_connected_components(const TriangleMesh& tm, // set the connected component id of each face const std::size_t nb_cc = connected_components(tm, - bind_property_maps(fid_map,make_property_map(face_cc)), + make_compose_property_map(fid_map,make_property_map(face_cc)), parameters::face_index_map(fid_map)); // contains for each CC the CC that are in its bounded side @@ -1354,6 +1354,8 @@ void orient_to_bound_a_volume(TriangleMesh& tm, typedef typename GetGeomTraits::type GT; typedef typename GetInitializedFaceIndexMap::type FaceIndexMap; + if (is_empty(tm)) return; + CGAL_precondition(is_closed(tm)); CGAL_precondition(is_triangle_mesh(tm)); @@ -1376,7 +1378,7 @@ void orient_to_bound_a_volume(TriangleMesh& tm, parameters::vertex_point_map(vpm) .geom_traits(gt) .nesting_levels(boost::ref(nesting_levels)) - .face_connected_component_map(bind_property_maps(fid_map,make_property_map(face_cc))) + .face_connected_component_map(make_compose_property_map(fid_map,make_property_map(face_cc))) .i_used_for_volume_orientation(true) .do_orientation_tests(true) .is_cc_outward_oriented(boost::ref(is_cc_outward_oriented)) diff --git a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h index d2e95b0a795..d6cbd420478 100644 --- a/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h +++ b/Polygon_mesh_processing/include/CGAL/Rigid_triangle_mesh_collision_detection.h @@ -579,7 +579,7 @@ public: std::size_t nb_cc = Polygon_mesh_processing::connected_components( - tm, bind_property_maps(fid_map, make_property_map(cc_ids)), + tm, make_compose_property_map(fid_map, make_property_map(cc_ids)), parameters::face_index_map(fid_map)); if (nb_cc != 1) { diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_orient_cc.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_orient_cc.cpp index ae913ff8f5a..827e169310b 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_orient_cc.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_orient_cc.cpp @@ -43,7 +43,7 @@ bool test_orientation(const TriangleMesh& tm, bool is_positive, const NamedParam // set the connected component id of each face std::size_t nb_cc = PMP::connected_components(tm, - CGAL::bind_property_maps(fid_map,CGAL::make_property_map(face_cc)), + CGAL::make_compose_property_map(fid_map,CGAL::make_property_map(face_cc)), CGAL::parameters::face_index_map(fid_map)); // extract a vertex with max z coordinate for each connected component diff --git a/Polygonal_surface_reconstruction/doc/Polygonal_surface_reconstruction/PackageDescription.txt b/Polygonal_surface_reconstruction/doc/Polygonal_surface_reconstruction/PackageDescription.txt index b02e6886d14..2bbf0b19b6e 100644 --- a/Polygonal_surface_reconstruction/doc/Polygonal_surface_reconstruction/PackageDescription.txt +++ b/Polygonal_surface_reconstruction/doc/Polygonal_surface_reconstruction/PackageDescription.txt @@ -9,7 +9,7 @@ \cgalPkgPicture{polyfit.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Liangliang Nan} +\cgalPkgAuthor{Liangliang Nan} \cgalPkgDesc{This package provides a method for piecewise planar object reconstruction from point clouds. The method takes as input an unordered point set (and optionally planar segments) of a piecewise planar object and outputs a lightweight and watertight surface mesh interpolating the input point set. The @@ -33,4 +33,4 @@ robust to noise and outliers.} ## Classes ## - `CGAL::Polygonal_surface_reconstruction` -*/ \ No newline at end of file +*/ diff --git a/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/polyfit_example_with_region_growing.cpp b/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/polyfit_example_with_region_growing.cpp index 530d1422de4..8f3876b581d 100644 --- a/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/polyfit_example_with_region_growing.cpp +++ b/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/polyfit_example_with_region_growing.cpp @@ -42,7 +42,7 @@ Sphere_neighbor_query Neighbor_query; typedef CGAL::Shape_detection::Point_set:: Least_squares_plane_fit_region Region_type; typedef CGAL::Shape_detection:: -Region_growing Region_growing; +Region_growing Region_growing; typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::Polygonal_surface_reconstruction Polygonal_surface_reconstruction; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h index e90637f0b03..db87cc01bfd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_function.h @@ -276,7 +276,7 @@ edge_criteria(double edge_size, Mesh_fnt::Polyhedral_domain_tag) std::make_pair(QSharedPointer(sizing_field_ptr), QSharedPointer(patches_ids_vector_p)); - std::cerr << "USE SIZING FIELD!\n"; + std::cerr << "Note: Mesh_3 is using a sizing field based on AABB tree.\n"; return Edge_criteria(*sizing_field_ptr); } else { return Edge_criteria(edge_size); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index 23cf18f9b56..fc344cec857 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include #include @@ -182,112 +184,76 @@ private: Scene_surface_mesh_item* sm_item, Point_set_demo_point_set_shape_detection_dialog& dialog) { - using Face_range = typename SMesh::Face_range; - - using Neighbor_query = - CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; - using Region_type = - CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; - - using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; - using Region_growing = CGAL::Shape_detection::Region_growing; - CGAL::Random rand(static_cast(time(nullptr))); - const SMesh& mesh = *(sm_item->polyhedron()); - scene->setSelectedItem(-1); - const Face_range face_range = faces(mesh); + SMesh& mesh = *(sm_item->polyhedron()); // Set parameters. - const double max_distance_to_plane = - dialog.epsilon(); - const double max_accepted_angle = - dialog.normal_tolerance(); - const std::size_t min_region_size = - dialog.min_points(); + const double max_distance_to_plane = dialog.epsilon(); + const double max_accepted_angle = dialog.normal_tolerance(); + const std::size_t min_region_size = dialog.min_points(); - // Region growing. - Neighbor_query neighbor_query(mesh); - const Vertex_to_point_map vertex_to_point_map(get(CGAL::vertex_point, mesh)); - Region_type region_type( - mesh, - max_distance_to_plane, max_accepted_angle, min_region_size, - vertex_to_point_map); + std::vector region_ids(num_faces(mesh)); + std::size_t nb_regions = + CGAL::Polygon_mesh_processing::region_growing_of_planes_on_faces( + mesh, + CGAL::make_property_map(region_ids), + CGAL::parameters:: + maximum_distance(max_distance_to_plane). + maximum_angle(max_accepted_angle). + minimum_region_size(min_region_size)); - Region_growing region_growing( - face_range, neighbor_query, region_type); + std::cerr << "* " << nb_regions << " regions have been found" << std::endl; - std::vector< std::vector > regions; - region_growing.detect(std::back_inserter(regions)); - std::cerr << "* " << regions.size() << - " regions have been found" - << std::endl; + typedef typename boost::property_map >::type Patch_id_pmap; + Patch_id_pmap pidmap = get(CGAL::face_patch_id_t(), mesh); - // Output result as a new colored item. - Scene_surface_mesh_item *colored_item = new Scene_surface_mesh_item; - colored_item->setName(QString("%1 (region growing)").arg(sm_item->name())); - SMesh& fg = *(colored_item->polyhedron()); - - fg = mesh; - const Face_range fr = faces(fg); - - colored_item->setItemIsMulticolor(true); - colored_item->computeItemColorVectorAutomatically(false); - auto& color_vector = colored_item->color_vector(); - color_vector.clear(); - - for (std::size_t i = 0; i < regions.size(); ++i) { - for (const std::size_t idx : regions[i]) { - const auto fit = fr.begin() + idx; - fg.property_map("f:patch_id").first[*fit] = - static_cast(i); - } - CGAL::Random rnd(static_cast(i)); - color_vector.push_back(QColor( - 64 + rnd.get_int(0, 192), - 64 + rnd.get_int(0, 192), - 64 + rnd.get_int(0, 192))); - } - if(color_vector.empty()) + bool has_unassigned = false; + for(SMesh::Face_index f : faces(mesh)) { - for(const auto& f : faces(fg)) + std::size_t region_id = region_ids[f]; + if (region_id != std::size_t(-1)) + put(pidmap, f, static_cast(region_id)+1); + else { - fg.property_map("f:patch_id").first[f] = - static_cast(0); + has_unassigned = true; + put(pidmap, f, 0); } - CGAL::Random rnd(static_cast(0)); - color_vector.push_back(QColor( - 64 + rnd.get_int(0, 192), - 64 + rnd.get_int(0, 192), - 64 + rnd.get_int(0, 192))); } - colored_item->invalidateOpenGLBuffers(); - scene->addItem(colored_item); + + sm_item->setItemIsMulticolor(true); + sm_item->computeItemColorVectorAutomatically(true); + sm_item->invalidateOpenGLBuffers(); + scene->itemChanged(sm_item); + + if (has_unassigned) + { + // hack to get unassigned as black + sm_item->color_vector()[0]=QColor().black(); + sm_item->computeItemColorVectorAutomatically(false); + sm_item->invalidateOpenGLBuffers(); + scene->itemChanged(sm_item); + } } void detect_shapes_with_region_growing ( Scene_points_with_normal_item* item, Point_set_demo_point_set_shape_detection_dialog& dialog) { - using Point_map = typename Point_set::Point_map; - using Normal_map = typename Point_set::Vector_map; - using Neighbor_query = - CGAL::Shape_detection::Point_set::Sphere_neighbor_query; + CGAL::Shape_detection::Point_set::Sphere_neighbor_query_for_point_set; + using Sorting = + CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting_for_point_set; using Region_type = - CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region; + CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region_for_point_set; using Region_growing = - CGAL::Shape_detection::Region_growing; + CGAL::Shape_detection::Region_growing; // Set parameters. - const double search_sphere_radius = - dialog.cluster_epsilon(); - const double max_distance_to_plane = - dialog.epsilon(); - const double max_accepted_angle = - dialog.normal_tolerance(); - const std::size_t min_region_size = - dialog.min_points(); + const double search_sphere_radius = dialog.cluster_epsilon(); + const double max_distance_to_plane = dialog.epsilon(); + const double max_accepted_angle = dialog.normal_tolerance(); + const std::size_t min_region_size = dialog.min_points(); // Get a point set. CGAL::Random rand(static_cast(time(nullptr))); @@ -336,18 +302,20 @@ private: QApplication::setOverrideCursor(Qt::BusyCursor); // Region growing set up. - Neighbor_query neighbor_query( - *points, - search_sphere_radius, - points->point_map()); - - Region_type region_type( - *points, - max_distance_to_plane, max_accepted_angle, min_region_size, - points->point_map(), points->normal_map()); + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_sphere_neighbor_query( + *points, CGAL::parameters:: + sphere_radius(search_sphere_radius)); + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_region( + *points, CGAL::parameters:: + maximum_distance(max_distance_to_plane). + maximum_angle(max_accepted_angle). + minimum_region_size(min_region_size)); + Sorting sorting = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_sorting( + *points, neighbor_query); + sorting.sort(); Region_growing region_growing( - *points, neighbor_query, region_type); + *points, sorting.ordered(), neighbor_query, region_type); std::vector groups; groups.resize(1); @@ -359,7 +327,7 @@ private: // The actual shape detection. CGAL::Real_timer t; t.start(); - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); t.stop(); @@ -367,19 +335,28 @@ private: " shapes found in " << t.time() << " second(s)" << std::endl; std::vector planes; - CGAL::Shape_detection::internal::create_planes_from_points( - *points, points->point_map(), regions, planes); + planes.reserve(regions.size()); + for (const auto& region : regions) { + planes.push_back(region.first); + } + CGAL_precondition(planes.size() == regions.size()); + + const CGAL::Identity_property_map plane_identity_map; + CGAL::internal::Dynamic_property_map plane_index_map; + + for (Point_set::Index idx : *points) + put(plane_index_map, idx, get(region_growing.region_map(), idx)); if (dialog.regularize()) { std::cerr << "Regularization of planes... " << std::endl; CGAL::Shape_regularization::Planes::regularize_planes( planes, - CGAL::Identity_property_map(), + plane_identity_map, *points, points->point_map(), - CGAL::parameters::plane_index_map( - CGAL::Shape_detection::RG::Point_to_shape_index_map(*points, regions)). + CGAL::parameters:: + plane_index_map(plane_index_map). regularize_parallelism(true). regularize_orthogonality(true). regularize_coplanarity(true). @@ -403,10 +380,10 @@ private: Scene_points_with_normal_item *point_item = new Scene_points_with_normal_item; - for (const std::size_t idx : regions[index]) { - point_item->point_set()->insert(points->point(*(points->begin() + idx))); + for (auto &item : regions[index].second) { + point_item->point_set()->insert(points->point(item)); if (dialog.add_property()) - shape_id[*(points->begin() + idx)] = index; + shape_id[item] = index; } unsigned char r, g, b; @@ -417,9 +394,9 @@ private: std::size_t nb_colored_pts = 0; if (dialog.generate_colored_point_set()) { - for(std::size_t idx : regions[index]) { + for(Point_set::Index item : regions[index].second) { auto it = colored_item->point_set()->insert( - points->point(*(points->begin() + idx))); + points->point(item)); ++nb_colored_pts; colored_item->point_set()->set_color(*it, r, g, b); } @@ -463,8 +440,7 @@ private: Scene_surface_mesh_item* sm_item = nullptr; sm_item = new Scene_surface_mesh_item; - using Plane = CGAL::Shape_detection::RG::Plane; - boost::shared_ptr rg_plane(new Plane(*points, points->point_map(), regions[index], plane)); + boost::shared_ptr rg_plane(boost::make_shared(plane)); build_alpha_shape( *(point_item->point_set()), rg_plane, sm_item, search_sphere_radius); @@ -472,7 +448,7 @@ private: if (sm_item){ sm_item->setColor(point_item->color ()); sm_item->setName(QString("%1%2_alpha_shape").arg(QString::fromStdString(ss.str())) - .arg(QString::number(regions[index].size()))); + .arg(QString::number(regions[index].second.size()))); sm_item->setRenderingMode(Flat); sm_item->invalidateOpenGLBuffers(); scene->addItem(sm_item); @@ -481,7 +457,7 @@ private: scene->changeGroup(sm_item, groups[0]); } } - ss << regions[index].size(); + ss << regions[index].second.size(); point_item->setName(QString::fromStdString(ss.str())); point_item->setRenderingMode(item->renderingMode()); @@ -515,14 +491,15 @@ private: Scene_points_with_normal_item *pts_full = new Scene_points_with_normal_item; pts_full->point_set()->add_normal_map(); + CGAL::structure_point_set( *points, planes, boost::make_function_output_iterator(build_from_pair((*(pts_full->point_set())))), search_sphere_radius, points->parameters(). - plane_map(CGAL::Identity_property_map()). - plane_index_map(CGAL::Shape_detection::RG::Point_to_shape_index_map(*points, regions))); + plane_map(plane_identity_map). + plane_index_map(plane_index_map)); if (pts_full->point_set()->empty()) delete pts_full; @@ -663,7 +640,8 @@ private: CGAL::Shape_detection::Plane_map(), *points, points->point_map(), - CGAL::parameters::plane_index_map( + CGAL::parameters:: + plane_index_map( CGAL::Shape_detection::Point_to_shape_index_map(*points, planes)). regularize_parallelism(true). regularize_orthogonality(true). @@ -970,9 +948,7 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetectShapesSM_t dialog.groupBox_3->setEnabled(true); // Update scene. - scene->itemChanged(index); QApplication::restoreOverrideCursor(); - sm_item->setVisible(false); } } diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 758fcac5dcc..7b3051fdd3e 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -304,6 +305,17 @@ void Scene_c3t3_item::compute_bbox() const } _bbox = Bbox(result.xmin(), result.ymin(), result.zmin(), result.xmax(), result.ymax(), result.zmax()); + + if (boost::empty(c3t3().cells_in_complex())) + { + for (Tr::Vertex_handle v : c3t3().triangulation().finite_vertex_handles()) + { + if(v->in_dimension() != -1) //skip far points + result += v->point().bbox(); + } + _bbox = Bbox(result.xmin(), result.ymin(), result.zmin(), + result.xmax(), result.ymax(), result.zmax()); + } } } diff --git a/Polyhedron/demo/Polyhedron/include/Point_set_3.h b/Polyhedron/demo/Polyhedron/include/Point_set_3.h index 943d18681cc..e72edbd9084 100644 --- a/Polyhedron/demo/Polyhedron/include/Point_set_3.h +++ b/Polyhedron/demo/Polyhedron/include/Point_set_3.h @@ -579,9 +579,9 @@ namespace CGAL { // specialization for default named parameters -template -struct Point_set_processing_3_np_helper<::Point_set_3, NamedParameters, NP_TAG> - : public Point_set_processing_3_np_helper::Base, NamedParameters, NP_TAG> +template +struct Point_set_processing_3_np_helper<::Point_set_3, NamedParameters, DPM, DVM> + : public Point_set_processing_3_np_helper::Base, NamedParameters, DPM, DVM> {}; } diff --git a/Principal_component_analysis/doc/Principal_component_analysis/PackageDescription.txt b/Principal_component_analysis/doc/Principal_component_analysis/PackageDescription.txt index 3ecb09e7502..10fd2d3f734 100644 --- a/Principal_component_analysis/doc/Principal_component_analysis/PackageDescription.txt +++ b/Principal_component_analysis/doc/Principal_component_analysis/PackageDescription.txt @@ -21,7 +21,7 @@ \cgalPkgDescriptionBegin{Principal Component Analysis,PkgPrincipalComponentAnalysisD} \cgalPkgPicture{teaserLeastSquaresFitting.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Sylvain Pion and Ankit Gupta} +\cgalPkgAuthors{Pierre Alliez, Sylvain Pion, and Ankit Gupta} \cgalPkgDesc{This package provides functions to compute global information about the shape of a set of 2D or 3D objects. It provides the computation of axis-aligned bounding boxes for point sets, and barycenters of weighted point sets. In addition, it provides computation of centroids (center of mass) and linear least squares fitting for point sets as well as for sets of other bounded objects. More specifically, it is possible to fit 2D lines to 2D segments, circles, disks, iso rectangles and triangles, as well as to fit 3D lines or 3D planes to 3D segments, triangles, iso cuboids, tetrahedra, spheres and balls. The common interface to these functions takes an iterator range of objects.} \cgalPkgManuals{Chapter_Principal_Component_Analysis,PkgPrincipalComponentAnalysisDRef} \cgalPkgSummaryEnd diff --git a/Property_map/include/CGAL/property_map.h b/Property_map/include/CGAL/property_map.h index 2a17deb4b83..0da2528a3da 100644 --- a/Property_map/include/CGAL/property_map.h +++ b/Property_map/include/CGAL/property_map.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -101,49 +102,6 @@ make_OR_property_map(const PM1& pm1, const PM2& pm2) return OR_property_map(pm1, pm2); } -// A property map that uses the result of a property map as key. -template -struct Property_map_binder -{ - typedef typename boost::property_traits::key_type key_type; - typedef typename boost::property_traits::value_type value_type; - typedef typename boost::property_traits::reference reference; - typedef boost::read_write_property_map_tag category; - - KeyMap key_map; - ValueMap value_map; - - Property_map_binder(const KeyMap& key_map = KeyMap(), - const ValueMap& value_map = ValueMap()) - : key_map(key_map), value_map(value_map) - { } - - template - Property_map_binder(const VM& value_map, - std::enable_if_t::value>* = nullptr) - : value_map(value_map) - { } - - friend - reference get(const Property_map_binder& map, key_type k) - { - return get(map.value_map, get(map.key_map,k)); - } - friend - void put(const Property_map_binder& map, key_type k, const value_type& v) - { - put(map.value_map, get(map.key_map,k), v); - } -}; - -template -Property_map_binder -bind_property_maps(const KeyMap& src, const ValueMap& tgt) -{ - return Property_map_binder(src, tgt); -} - - /// Property map that accesses a value from an iterator /// /// \cgalModels `ReadablePropertyMap` @@ -160,28 +118,192 @@ struct Input_iterator_property_map{ /// Free function to use a get the value from an iterator using Input_iterator_property_map. inline friend reference - get(Input_iterator_property_map,InputIterator it){ return *it; } + get(Input_iterator_property_map, const InputIterator& it){ return *it; } }; +#ifdef DOXYGEN_RUNNING +/// \ingroup PkgPropertyMapRef +/// Property map that composes two property maps, +/// that is a call on an instance `Compose_property_map compose_property_map(key_map, value_map)` of `get(compose_property_map, k)` returns `get(value_map, get(key_map, k))`. +template +struct Compose_property_map +{ + ///< Use the key type of `KeyMap` as keytype + typedef typename boost::property_traits::key_type key_type; + ///< Use the value type of `ValueMap` as value type + typedef typename boost::property_traits::value_type value_type; + ///< Use the reference type of `ValueMap` as reference + typedef typename boost::property_traits::reference reference; + ///< Use the category of the `ValueMap` + typedef typename boost::property_traits::category category; + + /// Constructor + Compose_property_map(KeyMap key_map = KeyMap(), + ValueMap value_map = ValueMap()); +}; +#else +template ::category> +struct Compose_property_map; + +template +struct Compose_property_map +{ + typedef typename boost::property_traits::key_type key_type; + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::category category; + + KeyMap key_map; + ValueMap value_map; + + Compose_property_map(KeyMap key_map = KeyMap(), + ValueMap value_map = ValueMap()) + : key_map(key_map), value_map(value_map) + {} + + Compose_property_map(Default, + ValueMap value_map = ValueMap()) + : value_map(value_map) + {} + + friend + reference get(Compose_property_map map, const key_type& k) + { + return get(map.value_map, get(map.key_map,k)); + } +}; + +template +struct Compose_property_map +{ + typedef typename boost::property_traits::key_type key_type; + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::category category; + + KeyMap key_map; + ValueMap value_map; + + Compose_property_map(KeyMap key_map = KeyMap(), + ValueMap value_map = ValueMap()) + : key_map(key_map), value_map(value_map) + {} + + Compose_property_map(Default, + ValueMap value_map = ValueMap()) + : value_map(value_map) + {} + + friend + void put(Compose_property_map map, const key_type& k, const value_type& v) + { + put(map.value_map, get(map.key_map,k), v); + } +}; + +template +struct Compose_property_map +{ + typedef typename boost::property_traits::key_type key_type; + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::category category; + + KeyMap key_map; + ValueMap value_map; + + Compose_property_map(KeyMap key_map = KeyMap(), + ValueMap value_map = ValueMap()) + : key_map(key_map), value_map(value_map) + {} + + Compose_property_map(Default, + ValueMap value_map = ValueMap()) + : value_map(value_map) + {} + + friend + reference get(Compose_property_map map, const key_type& k) + { + return get(map.value_map, get(map.key_map,k)); + } + + friend + void put(const Compose_property_map& map, const key_type& k, const value_type& v) + { + put(map.value_map, get(map.key_map,k), v); + } +}; + +template +struct Compose_property_map +{ + typedef typename boost::property_traits::key_type key_type; + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::reference reference; + typedef typename boost::property_traits::category category; + + KeyMap key_map; + ValueMap value_map; + + Compose_property_map(KeyMap key_map = KeyMap(), + ValueMap value_map = ValueMap()) + : key_map(key_map), value_map(value_map) + {} + + Compose_property_map(Default, + ValueMap value_map = ValueMap()) + : value_map(value_map) + {} + + friend + reference get(Compose_property_map map, const key_type& k) + { + return get(map.value_map, get(map.key_map,k)); + } + + friend + void put(Compose_property_map map, key_type k, const value_type& v) + { + put(map.value_map, get(map.key_map,k), v); + } + + decltype(auto) + operator[](const key_type& k) const + { + return value_map[get(key_map, k)]; + } +}; +#endif +/// \ingroup PkgPropertyMapRef +/// \relates Compose_property_map +/// returns `Compose_property_maps(km,vm)` +template +Compose_property_map +make_compose_property_map(const KeyMap& km, const ValueMap& vm) +{ + return Compose_property_map(km, vm); +} + /// \ingroup PkgPropertyMapRef /// Property map that converts a `T*` pointer (or in general an iterator /// over `T` elements) to the `T` object. /// /// \cgalModels `LvaluePropertyMap` -template +template struct Dereference_property_map - : public boost::put_get_helper > + : public boost::put_get_helper::reference, Dereference_property_map > { - typedef T* key_type; ///< typedef to 'T*' - typedef T value_type; ///< typedef to 'T' - typedef T& reference; ///< typedef to 'T&' + typedef Iter key_type; ///< typedef to 'T*' + typedef std::remove_const_t value_type; ///< typedef to 'T' + typedef typename std::iterator_traits::reference reference; ///< typedef to 'T&' typedef boost::lvalue_property_map_tag category; ///< `boost::lvalue_property_map_tag` /// Access a property map element. /// /// @tparam Iter Type convertible to `key_type`. - template - value_type& operator[](Iter it) const { return *it; } + template // template kept for backward compatibility + reference operator[](const Iter_& it) const { return *it; } }; /// Free function to create a `Dereference_property_map` property map. @@ -211,11 +333,14 @@ struct Identity_property_map typedef T& reference; typedef boost::lvalue_property_map_tag category; - value_type& operator[](key_type& k) const { return k; } + T& operator[](T& k) const { return k; } + const T& operator[](const T& k) const { return k; } + T operator[](T&& k) const { return std::forward(k); } - friend value_type& get(const Self&, key_type& k) { return k; } - friend const value_type& get(const Self&, const key_type& k) { return k; } - friend void put(const Self&, key_type& k, const value_type& v) { k = v; } + friend T& get(const Self&, T& k) { return k; } + friend const T& get(const Self&, const T& k) { return k; } + friend T get(const Self&, T&& k) { return std::forward(k); } + friend void put(const Self&, T& k, const T& v) { k = v; } /// \endcond }; @@ -600,6 +725,57 @@ make_cartesian_converter_property_map(Vpm vpm) return Cartesian_converter_property_map(vpm); } +/// \ingroup PkgPropertyMapRef +/// A property map with `std::size_t` as key-type that can be used +/// to access the i'th element in a container with random access. +/// \cgalModels `LvaluePropertyMap`, constness being than of `Container`. +template +class Random_access_property_map +{ + Container& m_container; + +public: + using Iterator = std::conditional_t::value, + typename Container::const_iterator, + typename Container::iterator>; + typedef std::size_t key_type; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef boost::lvalue_property_map_tag category; + + + Random_access_property_map(Container& container) + : m_container(container){} + + friend reference get (Random_access_property_map map, key_type index) + { + return map.m_container[index]; + } + + template + friend void put (Random_access_property_map map, Key index, const value_type& value, + std::enable_if_t::value>* = 0) + { + map.m_container[index]=value; + } + + decltype(auto) + operator[](key_type index) const + { + return m_container[index]; + } +}; + +/// \ingroup PkgPropertyMapRef +/// \relates Random_access_property_map +/// returns `Random_access_property_map(container)` +template +Random_access_property_map +make_random_access_property_map(Container& container) +{ + return Random_access_property_map(container); +} + /// \cond SKIP_IN_MANUAL // Syntaxic sugar for transform_iterator+pmap_to_unary_function template diff --git a/SMDS_3/doc/SMDS_3/PackageDescription.txt b/SMDS_3/doc/SMDS_3/PackageDescription.txt index 8b5ad64a507..013642d6c36 100644 --- a/SMDS_3/doc/SMDS_3/PackageDescription.txt +++ b/SMDS_3/doc/SMDS_3/PackageDescription.txt @@ -26,7 +26,7 @@ \cgalPkgPicture{knot_small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, Mariette Yvinec} +\cgalPkgAuthors{Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, and Mariette Yvinec} \cgalPkgDesc{This package provides a data structure to store three-dimensional simplicial meshes and their subcomplexes. It provides an API for tetrahedral meshes generated with %CGAL or not, diff --git a/STL_Extension/include/CGAL/In_place_list.h b/STL_Extension/include/CGAL/In_place_list.h index 246453abeab..135fbe1d3c5 100644 --- a/STL_Extension/include/CGAL/In_place_list.h +++ b/STL_Extension/include/CGAL/In_place_list.h @@ -27,7 +27,6 @@ #include #include #include -#include namespace CGAL { @@ -175,7 +174,6 @@ namespace internal { }; - template std::size_t hash_value(const In_place_list_iterator& i) { @@ -189,7 +187,7 @@ template { const T* ptr = i.operator->(); return reinterpret_cast(ptr)/ sizeof(T); - } + } } @@ -792,8 +790,7 @@ namespace std { std::size_t operator()(const CGAL::internal::In_place_list_iterator& i) const { - const T* ptr = i.operator->(); - return reinterpret_cast(ptr)/ sizeof(T); + return CGAL::internal::hash_value(i); } }; @@ -803,8 +800,7 @@ namespace std { std::size_t operator()(const CGAL::internal::In_place_list_const_iterator& i) const { - const T* ptr =i.operator->(); - return reinterpret_cast(ptr)/ sizeof(T); + return CGAL::internal::hash_value(i); } }; #endif // CGAL_CFG_NO_STD_HASH diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index c3c4755b9cf..94b2668f092 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -257,18 +257,21 @@ CGAL_add_named_parameter(reorient_bbox_t, reorient_bbox, reorient_bbox) CGAL_add_named_parameter(distance_tolerance_t, distance_tolerance, distance_tolerance) CGAL_add_named_parameter(angle_tolerance_t, angle_tolerance, angle_tolerance) CGAL_add_named_parameter(debug_t, debug, debug) - -// region growing -CGAL_add_named_parameter(k_neighbors_t, k_neighbors, k_neighbors) -CGAL_add_named_parameter(distance_threshold_t, distance_threshold, distance_threshold) -CGAL_add_named_parameter(angle_threshold_t, angle_threshold, angle_threshold) -CGAL_add_named_parameter(min_region_size_t, min_region_size, min_region_size) -CGAL_add_named_parameter(regularize_t, regularize, regularize) CGAL_add_named_parameter(graphcut_beta_t, graphcut_beta, graphcut_beta) +// List of named parameters used in Shape_detection package +CGAL_add_named_parameter(maximum_angle_t, maximum_angle, maximum_angle) +CGAL_add_named_parameter(maximum_distance_t, maximum_distance, maximum_distance) +CGAL_add_named_parameter(minimum_region_size_t, minimum_region_size, minimum_region_size) +CGAL_add_named_parameter(sphere_radius_t, sphere_radius, sphere_radius) +CGAL_add_named_parameter(k_neighbors_t, k_neighbors, k_neighbors) +CGAL_add_named_parameter(item_map_t, item_map, item_map) +CGAL_add_named_parameter(cosine_of_maxium_angle_t, cosine_of_maxium_angle, cosine_of_maxium_angle) +CGAL_add_named_parameter(minimum_radius_t, minimum_radius, minimum_radius) +CGAL_add_named_parameter(maximum_radius_t, maximum_radius, maximum_radius) + // List of named parameters used in Shape_regularization package CGAL_add_named_parameter(minimum_length_t, minimum_length, minimum_length) -CGAL_add_named_parameter(maximum_angle_t, maximum_angle, maximum_angle) CGAL_add_named_parameter(maximum_offset_t, maximum_offset, maximum_offset) CGAL_add_named_parameter(regularize_parallelism_t, regularize_parallelism, regularize_parallelism) CGAL_add_named_parameter(regularize_orthogonality_t, regularize_orthogonality, regularize_orthogonality) diff --git a/STL_Extension/include/CGAL/vector.h b/STL_Extension/include/CGAL/vector.h index c10a8fdd53a..192baedacdc 100644 --- a/STL_Extension/include/CGAL/vector.h +++ b/STL_Extension/include/CGAL/vector.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,13 @@ public: } }; +template < class T, class Ref, class Ptr> +std::size_t hash_value(const vector_iterator& i) +{ + Ptr ptr = i.operator->(); + return reinterpret_cast(ptr)/ sizeof(T); +} + template < class T, class Ref, class Ptr> inline vector_iterator operator+( std::ptrdiff_t n, vector_iterator i) { @@ -609,4 +617,31 @@ void vector::insert( iterator position, size_type n, const T& x) { } //namespace CGAL +namespace std { + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4099) // For VC10 it is class hash +#endif + +#ifndef CGAL_CFG_NO_STD_HASH + + template < class T, class Ref, class Ptr> + struct hash > + : public CGAL::cpp98::unary_function, std::size_t> { + + std::size_t operator()(const CGAL::internal::vector_iterator& i) const + { + return CGAL::internal::hash_value(i); + } + }; + +#endif // CGAL_CFG_NO_STD_HASH + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +} // namespace std + #endif // CGAL_VECTOR_H // diff --git a/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/PackageDescription.txt b/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/PackageDescription.txt index cbe16d9ac84..08d1f716eb2 100644 --- a/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/PackageDescription.txt +++ b/Scale_space_reconstruction_3/doc/Scale_space_reconstruction_3/PackageDescription.txt @@ -12,7 +12,7 @@ \cgalPkgDescriptionBegin{Scale-Space Surface Reconstruction,PkgScaleSpaceReconstruction3} \cgalPkgPicture{knot_thumb.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Thijs van Lankveld} +\cgalPkgAuthor{Thijs van Lankveld} \cgalPkgDesc{This method allows to reconstruct a surface that interpolates a set of 3D points using either an alpha shape or the advancing front surface reconstruction method. The output interpolates the point set (as opposed to approximating the point set). How the surface connects the points depends on a scale variable, which can be estimated semi-automatically.} \cgalPkgManuals{Chapter_Scale_space_reconstruction,PkgScaleSpaceReconstruction3Ref} \cgalPkgSummaryEnd diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h index 4141ee1eb25..47410046e0e 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_surface_reconstruction_3.h @@ -62,8 +62,8 @@ public: #endif #ifdef DOXYGEN_RUNNING - typedef unspecified_type Facet_iterator; ///< defines an iterator over the points. - typedef const unspecified_type Facet_const_iterator; ///< defines a constant iterator over the points. + typedef unspecified_type Facet_iterator; ///< defines an iterator over the facets. + typedef const unspecified_type Facet_const_iterator; ///< defines a constant iterator over the facets. #else typedef typename std::vector Facet_vector; typedef typename Facet_vector::iterator Facet_iterator; diff --git a/Scripts/developer_scripts/list_cgal_workflows_last_run.sh b/Scripts/developer_scripts/list_cgal_workflows_last_run.sh new file mode 100644 index 00000000000..e3d830bf15d --- /dev/null +++ b/Scripts/developer_scripts/list_cgal_workflows_last_run.sh @@ -0,0 +1,73 @@ +#!/bin/bash +echo "| repo | workflow | branch | event | runs on | status of last run | state | annotation | date | date since last runs | file |" +echo "| :--: | :--------: | :----: | :---: | :------: | :------------------: | :---: | :--------: | :----: | :------------------: | :----: |" +actualdate=$EPOCHSECONDS +for repo in $(gh api orgs/CGAL/repos --jq '.[].full_name' | grep -v dev ) +do + if [ "$repo" != "CGAL/CNRS" ] && [ "$repo" != "CGAL/GeometryFactory" ] + then + default_branch=$(gh api repos/$repo --jq '.default_branch') + workflows=$(gh api repos/$repo/actions/workflows) + workflows_count=$(jq '.total_count' <<< "$workflows") + for ((i=0;iMovable Separability of Sets \cgalCite{t-mss-85} is a class of problems that deal with moving sets of objects, such as polygons in the plane; the challenge is to avoid collisions between the objects diff --git a/Shape_detection/benchmark/Shape_detection/README.md b/Shape_detection/benchmark/Shape_detection/README.md index b7eab3675f9..b0015eea7c7 100644 --- a/Shape_detection/benchmark/Shape_detection/README.md +++ b/Shape_detection/benchmark/Shape_detection/README.md @@ -6,8 +6,8 @@ Results (Point Set 2): Test #1 sphere_radius = 1 min_region_size = 5 - distance_threshold = 4.5 - angle_threshold = 45 + max_distance = 4.5 + max_angle = 45 ----- Time elapsed: 0.138831 Number of detected regions: 794 @@ -18,8 +18,8 @@ Test #1 Test #2 sphere_radius = 3 min_region_size = 5 - distance_threshold = 4.5 - angle_threshold = 45 + max_distance = 4.5 + max_angle = 45 ----- Time elapsed: 0.069098 Number of detected regions: 3063 @@ -30,8 +30,8 @@ Test #2 Test #3 sphere_radius = 6 min_region_size = 5 - distance_threshold = 4.5 - angle_threshold = 45 + max_distance = 4.5 + max_angle = 45 ----- Time elapsed: 0.077703 Number of detected regions: 2508 @@ -42,8 +42,8 @@ Test #3 Test #4 sphere_radius = 9 min_region_size = 5 - distance_threshold = 4.5 - angle_threshold = 45 + max_distance = 4.5 + max_angle = 45 ----- Time elapsed: 0.093415 Number of detected regions: 2302 diff --git a/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_2.cpp b/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_2.cpp index f1886f0d286..93eba00217a 100644 --- a/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_2.cpp +++ b/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_2.cpp @@ -8,12 +8,12 @@ #include // CGAL includes. -#include +#include #include #include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -30,27 +30,25 @@ using Normal_map = CGAL::Second_of_pair_property_map; using Neighbor_query = SD::Point_set::Sphere_neighbor_query; using Region_type = SD::Point_set::Least_squares_line_fit_region; -using Region_growing = SD::Region_growing; +using Region_growing = SD::Region_growing; -using Timer = CGAL::Timer; -using Region = std::vector; +using Timer = CGAL::Real_timer; void benchmark_region_growing_on_point_set_2( - const std::size_t test_count, - const Input_range& input_range, - const FT sphere_radius, - const FT distance_threshold, - const FT angle_threshold, - const std::size_t min_region_size) { + const std::size_t test_count, const Input_range& input_range, + const FT sphere_radius, const FT distance_threshold, + const FT angle_threshold, const std::size_t min_region_size) { // Create instances of the parameter classes. Neighbor_query neighbor_query( - input_range, - sphere_radius); + input_range, CGAL::parameters::sphere_radius(sphere_radius)); Region_type region_type( input_range, - distance_threshold, angle_threshold, min_region_size); + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size)); // Create an instance of the region growing class. Region_growing region_growing( @@ -58,7 +56,7 @@ void benchmark_region_growing_on_point_set_2( // Run the algorithm. Timer timer; - std::vector regions; + Region_growing::Result_type regions; timer.start(); region_growing.detect(std::back_inserter(regions)); @@ -67,17 +65,17 @@ void benchmark_region_growing_on_point_set_2( // Compute the number of points assigned to all found regions. std::size_t number_of_assigned_points = 0; for (const auto& region : regions) - number_of_assigned_points += region.size(); + number_of_assigned_points += region.second.size(); - std::vector unassigned_points; - region_growing.unassigned_items(std::back_inserter(unassigned_points)); + Region_growing::Unassigned_type unassigned_points; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); // Print statistics. std::cout << "Test #" << test_count << std::endl; std::cout << " sphere_radius = " << sphere_radius << std::endl; std::cout << " min_region_size = " << min_region_size << std::endl; - std::cout << " distance_threshold = " << distance_threshold << std::endl; - std::cout << " angle_threshold = " << angle_threshold << std::endl; + std::cout << " max_distance = " << distance_threshold << std::endl; + std::cout << " max_angle = " << angle_threshold << std::endl; std::cout << " -----" << std::endl; std::cout << " Time elapsed: " << timer.time() << std::endl; std::cout << " Number of detected regions: " << regions.size() << std::endl; @@ -89,26 +87,21 @@ void benchmark_region_growing_on_point_set_2( int main(int argc, char *argv[]) { // Load xyz data either from a local folder or a user-provided file. - std::ifstream in(argc > 1 ? argv[1] : "data/point_set_2.xyz"); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/buildings_outline.xyz")); CGAL::IO::set_ascii_mode(in); if (!in) { - std::cout << - "Error: cannot read the file point_set_2.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; + std::cout << "ERROR: cannot read the file buildings_outline.xyz!" << std::endl; return EXIT_FAILURE; } - Input_range input_range; FT a, b, c, d, e, f; - + Input_range input_range; while (in >> a >> b >> c >> d >> e >> f) input_range.push_back(std::make_pair(Point_2(a, b), Vector_2(d, e))); in.close(); - // Default parameter values for the data file point_set_2.xyz. + // Default parameter values for the data file buildings_outline.xyz. const FT distance_threshold = FT(45) / FT(10); const FT angle_threshold = FT(45); const std::size_t min_region_size = 5; diff --git a/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_3.cpp b/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_3.cpp index 2660463dbc0..c602ae0d20e 100644 --- a/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_3.cpp +++ b/Shape_detection/benchmark/Shape_detection/benchmark_region_growing_on_point_set_3.cpp @@ -8,12 +8,12 @@ #include // CGAL includes. -#include +#include #include #include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -32,26 +32,22 @@ using Normal_map = CGAL::Second_of_pair_property_map; using Neighbor_query = SD::Point_set::K_neighbor_query; using Region_type = SD::Point_set::Least_squares_plane_fit_region; -using Region_growing = SD::Region_growing; +using Region_growing = SD::Region_growing; -using Timer = CGAL::Timer; -using Region = std::vector; +using Timer = CGAL::Real_timer; void create_input_range( - const std::size_t num_copies, - const Input_range& input, - Input_range& output, + const std::size_t num_copies, const Input_range& input, Input_range& output, const bool save = false) { const Point_2 a = Point_2(-0.25147, -0.49995); - const Point_2 b = Point_2( 0.25147, -0.49995); + const Point_2 b = Point_2(+0.25147, -0.49995); output.reserve(num_copies * input.size()); for (std::size_t i = 0; i < num_copies; ++i) { const FT x1 = i * a.x(); const FT y1 = i * a.y(); - const FT x2 = i * b.x(); const FT y2 = i * b.y(); @@ -60,24 +56,17 @@ void create_input_range( const Vector_2 tr = Vector_2(p1, p2); for (const auto& item : input) { - const Point_3& p = item.first; const Vector_3& n = item.second; - - const Point_3 q = Point_3( - p.x() + tr.x(), - p.y() + tr.y(), - p.z()); - + const Point_3 q = Point_3(p.x() + tr.x(), p.y() + tr.y(), p.z()); output.push_back(std::make_pair(q, n)); } } if (save) { - const std::string path = - "path_to_out_folder/"; - const std::string fullpath = - path + "bench_point_set_3-" + std::to_string(num_copies) + ".xyz"; + const std::string path = "path_to_out_folder/"; + const std::string fullpath = path + "bench_point_set_3-" + + std::to_string(num_copies) + ".xyz"; std::ofstream out(fullpath); for (const auto& item : output) @@ -87,24 +76,23 @@ void create_input_range( } void benchmark_region_growing_on_point_set_3( - const std::size_t num_copies, - const Input_range& input, - const std::size_t k, - const FT distance_threshold, - const FT angle_threshold, - const std::size_t min_region_size) { + const std::size_t num_copies, const Input_range& input, + const std::size_t k, const FT distance_threshold, + const FT angle_threshold, const std::size_t min_region_size) { Input_range input_range; create_input_range(num_copies, input, input_range); // Create instances of the parameter classes. Neighbor_query neighbor_query( - input_range, - k); + input_range, CGAL::parameters::k_neighbors(k)); Region_type region_type( input_range, - distance_threshold, angle_threshold, min_region_size); + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size)); // Create an instance of the region growing class. Region_growing region_growing( @@ -112,7 +100,7 @@ void benchmark_region_growing_on_point_set_3( // Run the algorithm. Timer timer; - std::vector regions; + std::vector regions; timer.start(); region_growing.detect(std::back_inserter(regions)); @@ -125,26 +113,21 @@ void benchmark_region_growing_on_point_set_3( int main(int argc, char *argv[]) { // Load xyz data either from a local folder or a user-provided file. - std::ifstream in(argc > 1 ? argv[1] : "data/point_set_3.xyz"); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/building.xyz")); CGAL::IO::set_ascii_mode(in); if (!in) { - std::cout << - "Error: cannot read the file point_set_3.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; + std::cout << "ERROR: cannot read the file building.xyz!" << std::endl; return EXIT_FAILURE; } Input_range input; Point_3 p; Vector_3 n; - while (in >> p >> n) input.push_back(std::make_pair(p, n)); in.close(); - // Default parameter values for the data file point_set_3.xyz. + // Default parameter values for the data file building.xyz. const std::size_t k = 12; const FT distance_threshold = FT(2); const FT angle_threshold = FT(20); diff --git a/Shape_detection/doc/Shape_detection/Concepts/EfficientRANSACTraits.h b/Shape_detection/doc/Shape_detection/Concepts/EfficientRANSACTraits.h index 867a55fec70..5441f324e94 100644 --- a/Shape_detection/doc/Shape_detection/Concepts/EfficientRANSACTraits.h +++ b/Shape_detection/doc/Shape_detection/Concepts/EfficientRANSACTraits.h @@ -13,8 +13,7 @@ Point and normal property maps have to be provided to extract the points and the normals from the input. \cgalHasModel -- `CGAL::Shape_detection::Efficient_RANSAC_traits`, -- `CGAL::Shape_detection::deprecated::Shape_detection_traits` +- `CGAL::Shape_detection::Efficient_RANSAC_traits` */ class EfficientRANSACTraits{ diff --git a/Shape_detection/doc/Shape_detection/Concepts/NeighborQuery.h b/Shape_detection/doc/Shape_detection/Concepts/NeighborQuery.h index 1438be81fc0..5495e5d0c9a 100644 --- a/Shape_detection/doc/Shape_detection/Concepts/NeighborQuery.h +++ b/Shape_detection/doc/Shape_detection/Concepts/NeighborQuery.h @@ -6,24 +6,28 @@ A concept that describes the set of methods used by the `CGAL::Shape_detection:: to access neighbors of an item. \cgalHasModel -- `CGAL::Shape_detection::Point_set::K_neighbor_query`, -- `CGAL::Shape_detection::Point_set::Sphere_neighbor_query`, +- `CGAL::Shape_detection::Point_set::K_neighbor_query` +- `CGAL::Shape_detection::Point_set::Sphere_neighbor_query` +- `CGAL::Shape_detection::Polygon_mesh::Polyline_graph` - `CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query` */ class NeighborQuery { public: + /// The reference type to the elements of the input range, e.g., a const_iterator of the input range. + typedef unspecified_type Item; + /*! - fills `neighbors` with the indices of all items, which are connected to the - item with the index `query_index`. + fills `neighbors` with the `Items` of all items, which are connected to the + `Item` query. `CGAL::Shape_detection::Region_growing` calls this function each time when a new query item is selected. */ void operator()( - const std::size_t query_index, - std::vector& neighbors) { + Item query_index, + std::vector& neighbors) { } }; diff --git a/Shape_detection/doc/Shape_detection/Concepts/RegionType.h b/Shape_detection/doc/Shape_detection/Concepts/RegionType.h index 5d29c2dec7a..8a43af29e13 100644 --- a/Shape_detection/doc/Shape_detection/Concepts/RegionType.h +++ b/Shape_detection/doc/Shape_detection/Concepts/RegionType.h @@ -5,35 +5,53 @@ A concept that describes the set of methods used by the `CGAL::Shape_detection::Region_growing` to maintain a region. -A region is represented by a set of `indices` of the items, which are included in -this region. +A region is represented by a set items, which are included in this region. \cgalHasModel -- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_region`, -- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region`, +- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_region` +- `CGAL::Shape_detection::Segment_set::Least_squares_line_fit_region` - `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region` */ class RegionType { public: + /// The parameters of the primitive covering the region. + typedef unspecified_type Primitive; + + /// The reference type to the elements of the input range, e.g., a const_iterator of the input range. + typedef unspecified_type Item; + + // The region types is defined by a vector of Items. + typedef std::vector Region; + /*! - checks if the item with the index `index_to`, which is a neighbor of the item - with the index `index_from`, can be added to the region represented by `indices`. + a model of `ReadWritePropertyMap` whose key type is `Item` + and value type is `std::size_t`. This map associates item of the input range + to the index of the region it belongs to. + */ + typedef unspecified_type Region_index_map; + + /*! + checks if the item `to`, which is a neighbor of the item + `from`, can be added to the region represented by `region`. `CGAL::Shape_detection::Region_growing` calls this function each time when trying to add a new item to a region. If this function returns `true`, the - item with the index `index_to`, is added to the region, otherwise ignored. + item with the index `to`, is added to the region, otherwise ignored. */ bool is_part_of_region( - const std::size_t index_from, - const std::size_t index_to, - const std::vector& indices) { - + const Item from, + const Item to, + const Region ®ion) { } /*! - checks if the region represented by `indices` satisfies all necessary conditions. + checks if `region` satisfies all necessary conditions. `CGAL::Shape_detection::Region_growing` calls this function at the end of each propagation phase. If this function returns `true`, the region is accepted, @@ -41,20 +59,32 @@ public: available for region growing again. */ bool is_valid_region( - const std::vector& indices) { - + const Region& region) { } /*! - enables to update any information that is maintained with the region - represented by `indices`. + provides the last primitive that has been fitted with the region. + */ + + Primitive primitive() const { + } + + /*! + enables to update any information about the region represented by the collection of Items `region`. `CGAL::Shape_detection::Region_growing` calls this function each time when a - new seed item is selected. In this case, `indices.size() = 1`. This function - is also called periodically when enlarging the region. In this case, `indices.size() > 1`. + new seed item is selected. This case can be identified by checking the + condition `region.size() == 1`. This function is also called periodically + when enlarging the region. This case can be identified by checking the + condition `region.size() > 1`. + + This function also returns a Boolean at the first call when a new region + with one seed item is being created. When it is `true`, the new region is + further propagated, otherwise, it is rejected. */ - void update( - const std::vector& indices) { + bool update( + const Region& region) { + } } }; diff --git a/Shape_detection/doc/Shape_detection/Doxyfile.in b/Shape_detection/doc/Shape_detection/Doxyfile.in index 894086d1932..41b38171cae 100644 --- a/Shape_detection/doc/Shape_detection/Doxyfile.in +++ b/Shape_detection/doc/Shape_detection/Doxyfile.in @@ -1,7 +1,7 @@ @INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Shape Detection" -EXTRACT_ALL = NO -HIDE_UNDOC_CLASSES = YES -WARN_IF_UNDOCUMENTED = NO -PREDEFINED = DOXYGEN_NS \ No newline at end of file +EXTRACT_ALL = NO +HIDE_UNDOC_CLASSES = YES +WARN_IF_UNDOCUMENTED = NO +EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Polygon_mesh_processing diff --git a/Shape_detection/doc/Shape_detection/PackageDescription.txt b/Shape_detection/doc/Shape_detection/PackageDescription.txt index 4c7078a46ff..78ea0359c2d 100644 --- a/Shape_detection/doc/Shape_detection/PackageDescription.txt +++ b/Shape_detection/doc/Shape_detection/PackageDescription.txt @@ -1,34 +1,33 @@ + +// RANSAC /*! \defgroup PkgShapeDetectionRef Shape Detection Reference -\defgroup PkgShapeDetectionRG Region Growing -\ingroup PkgShapeDetectionRef - -Reference Manual for the Region Growing shape detection component. - -\defgroup PkgShapeDetectionRGConcepts Concepts -\ingroup PkgShapeDetectionRG - -Concepts used for the parameters of the `CGAL::Shape_detection::Region_growing`. - -\defgroup PkgShapeDetectionRGOnPoints Point Set -\ingroup PkgShapeDetectionRG - -Models that can be used with the `CGAL::Shape_detection::Region_growing` -for shape detection in a point set. - -\defgroup PkgShapeDetectionRGOnMesh Polygon Mesh -\ingroup PkgShapeDetectionRG - -Models that can be used with the `CGAL::Shape_detection::Region_growing` -for shape detection on a polygon mesh. - -\addtogroup PkgShapeDetectionRG - \defgroup PkgShapeDetectionRANSAC Efficient RANSAC \ingroup PkgShapeDetectionRef -Reference Manual for the Efficient RANSAC shape detection component. +Classified Reference Manual for the Efficient RANSAC shape detection component. + +# Concepts # +- `EfficientRANSACTraits` + +# Algorithm # +- `CGAL::Shape_detection::Efficient_RANSAC_traits` +- `CGAL::Shape_detection::Efficient_RANSAC` + +# Shapes # +- `CGAL::Shape_detection::Plane` +- `CGAL::Shape_detection::Sphere` +- `CGAL::Shape_detection::Cylinder` +- `CGAL::Shape_detection::Cone` +- `CGAL::Shape_detection::Torus` + +# Shape Interface # +- `CGAL::Shape_detection::Shape_base` + +# Property Maps # +- `CGAL::Shape_detection::Plane_map` +- `CGAL::Shape_detection::Point_to_shape_index_map` \defgroup PkgShapeDetectionRANSACConcepts Concepts \ingroup PkgShapeDetectionRANSAC @@ -45,12 +44,86 @@ Shape models that can be used with the `CGAL::Shape_detection::Efficient_RANSAC` Property maps that can be used with the `CGAL::Shape_detection::Efficient_RANSAC`. -\addtogroup PkgShapeDetectionRANSAC +*/ -\defgroup PkgShapeDetectionDEPR Deprecated +// Region growing + +/*! + +\defgroup PkgShapeDetectionRG Region Growing \ingroup PkgShapeDetectionRef -Deprecated components. +Classified Reference Manual for the Region Growing shape detection component. + +# Concepts # +- `NeighborQuery` +- `RegionType` + +# Algorithm # +- `CGAL::Shape_detection::Region_growing<%NeighborQuery, %RegionType, RegionMap>` + +# Point Set # +## Neighbord Query Classes ## +- `CGAL::Shape_detection::Point_set::K_neighbor_query` +- `CGAL::Shape_detection::Point_set::Sphere_neighbor_query` + +## Sorting and Fitting Classes ## +- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_sorting` + +- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_sorting` + +- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting` + +- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_sorting` + +- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_region` +- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_sorting` + +## Convenience Aliases and Functions for `%CGAL::Point_set_3` ## + +When the input point set is an instance of the class `CGAL::Point_set_3`, template aliases and free functions are provided +to simplify the definition and creation of the different classes. The naming convention used is to append a suffix `_for_point_set` to the neighbor query, sorting and fitting classes. Free functions are prefixed by `make_` followed by the class name in lower case. For the complete list see \ref PkgShapeDetectionRGOnPointSet3. + +# Segment Set # +- `CGAL::Shape_detection::Segment_set::Least_squares_line_fit_region` +- `CGAL::Shape_detection::Segment_set::Least_squares_line_fit_sorting` + +# Polygon Mesh # +- `CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query` +- `CGAL::Shape_detection::Polygon_mesh::Polyline_graph` +- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region` +- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` + + +\defgroup PkgShapeDetectionRGConcepts Concepts +\ingroup PkgShapeDetectionRG + +Concepts used for the parameters of the `CGAL::Shape_detection::Region_growing`. + +\defgroup PkgShapeDetectionRGOnPoints Point Set +\ingroup PkgShapeDetectionRG + +\defgroup PkgShapeDetectionRGOnPointSet3 Convenience Aliases and Functions for Point_set_3 +\ingroup PkgShapeDetectionRG + +Models that can be used with the `CGAL::Shape_detection::Region_growing` +for shape detection in a point set. + +\defgroup PkgShapeDetectionRGOnSegments Segment Set +\ingroup PkgShapeDetectionRG + +Models that can be used with the `CGAL::Shape_detection::Region_growing` +for shape detection in a segment set. + +\defgroup PkgShapeDetectionRGOnMesh Polygon Mesh +\ingroup PkgShapeDetectionRG + +Models that can be used with the `CGAL::Shape_detection::Region_growing` +for shape detection on a polygon mesh. \addtogroup PkgShapeDetectionRef @@ -61,17 +134,13 @@ Deprecated components. \cgalPkgAuthors{Sven Oesau, Yannick Verdie, Clément Jamin, Pierre Alliez, Florent Lafarge, Simon Giraudot, Thien Hoang, and Dmitry Anisimov} \cgalPkgDesc{This package implements the Efficient RANSAC (RANdom SAmple Consensus) approach for detecting arbitrary shapes in an unorganized point set with unoriented normals -and the Region Growing approach for detecting shapes in a set of arbitrary items. -With the Efficient RANSAC approach, five canonical shapes can be detected: planes, spheres, -cylinders, cones, and tori. Additional shapes can be detected, given a custom shape class by the user. -For the Region Growing approach, this package provides three particular shape detection components: -detecting lines in a 2D point set, detecting planes in a 3D point set, and detecting planes -on a polygon mesh.} +and the Region Growing approach for detecting shapes in a set of arbitrary items.} \cgalPkgManuals{Chapter_Shape_Detection, PkgShapeDetectionRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{4.7} +\cgalPkgDependsOn{\ref thirdpartyEigen} \cgalPkgBib{cgal:ovja-pssd} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} @@ -81,59 +150,10 @@ on a polygon mesh.} \cgalClassifedRefPages -## Efficient RANSAC ## +- \link PkgShapeDetectionRANSAC Efficient RANSAC \endlink -### Concepts ### -- `EfficientRANSACTraits` +- \link PkgShapeDetectionRG Region Growing \endlink -### Algorithm ### -- `CGAL::Shape_detection::Efficient_RANSAC_traits` -- `CGAL::Shape_detection::Efficient_RANSAC` -### Shapes ### -- `CGAL::Shape_detection::Plane` -- `CGAL::Shape_detection::Sphere` -- `CGAL::Shape_detection::Cylinder` -- `CGAL::Shape_detection::Cone` -- `CGAL::Shape_detection::Torus` - -### Shape Interface ### -- `CGAL::Shape_detection::Shape_base` - -### Property Maps ### -- `CGAL::Shape_detection::Plane_map` -- `CGAL::Shape_detection::Point_to_shape_index_map` - -## Region Growing ## - -### Concepts ### -- `NeighborQuery` -- `RegionType` - -### Algorithm ### -- `CGAL::Shape_detection::Region_growing` - -### Point Set ### -- `CGAL::Shape_detection::Point_set::K_neighbor_query` -- `CGAL::Shape_detection::Point_set::Sphere_neighbor_query` -- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_region` -- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_region` -- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region` -- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_region` -- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_region` -- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_sorting` -- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_sorting` -- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting` -- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_sorting` -- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_sorting` - -### Polygon Mesh ### -- `CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query` -- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region` -- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` - -## Deprecated Components ## -- `CGAL::Shape_detection::deprecated::Shape_detection_traits` -- `CGAL::Shape_detection::deprecated::Region_growing_depr` */ diff --git a/Shape_detection/doc/Shape_detection/Shape_detection.txt b/Shape_detection/doc/Shape_detection/Shape_detection.txt index 40e14fec0e4..c51a84aad19 100644 --- a/Shape_detection/doc/Shape_detection/Shape_detection.txt +++ b/Shape_detection/doc/Shape_detection/Shape_detection.txt @@ -105,6 +105,7 @@ A lower probability provides a higher reliability and determinism at the cost of \subsection Shape_detection_RANSACExamples Examples + The main class `Shape_detection::Efficient_RANSAC` takes a template parameter `Shape_detection::Efficient_RANSAC_traits` that defines the geometric types and input format. Property maps provide a means to interface with the user-specific data structures. The first parameter of the `Shape_detection::Efficient_RANSAC_traits` class is the common `Kernel`. @@ -217,7 +218,7 @@ A higher value for `epsilon`, that is a more tolerant error, leads to fewer but \cgalFigureEnd \cgalFigureBegin{Efficient_RANSAC_performance_probability, Efficient_RANSAC/prob_graph.png} -The graph depicts the time, coverage, and the number of detected primitives against the search endurance parameter, that is `probability` to miss the largest shape at each iteration. +The graph depicts the runtime, coverage, and the number of detected primitives against the search endurance parameter, that is `probability` to miss the largest shape at each iteration. The number of shapes is stable and the coverage increases when the `probability` is lowered. The running time increases significantly as many more candidates are generated during each iteration of the algorithm. \cgalFigureEnd @@ -228,90 +229,57 @@ The running time increases significantly as many more candidates are generated d This shape detection component is based on the region growing algorithm applied to a set of user-specified items. Shapes are detected by growing regions from seed items, where each region is created as follows: --# Pick the next available seed item; +-# Pick the next available item; -# Find its neighbors in the data set; -# Include those neighbors, which satisfy the region requirements; -# Repeat the procedure for all included neighbors; -# If no further neighbor satisfies the requirements, start a new region. -Together with the generic algorithm's implementation `CGAL::Shape_detection::Region_growing`, three particular instances of this algorithm are provided: +Together with the generic algorithm's implementation `CGAL::Shape_detection::Region_growing`, five particular instances of this algorithm are provided: - Line and circle detection in a \ref Shape_detection_RegionGrowingPoints "2D point set"; +- Line detection in a \ref Shape_detection_RegionGrowingSegments "2D/3D segment set"; - Plane, sphere, and cylinder detection in a \ref Shape_detection_RegionGrowingPoints "3D point set"; - Plane detection on a \ref Shape_detection_RegionGrowingMesh "polygon mesh". Other instances can be easily added by the user, as explained below. - \subsection Shape_detection_RegionGrowingFramework Framework -The main class `CGAL::Shape_detection::Region_growing` is parameterized by +The class `CGAL::Shape_detection::Region_growing` provides an implementation of the region growing algorithm. This algorithm can detect geometric primitives among a set of input geometric objects. Each such geometric object is identified using an item. The item is, in general but not necessarily, a lightweight class that uniquely identify a geometric object like an iterator over a container of geometric object, an integer pointing to the cell of a vector, a `face_descriptor` representing a face in a model of `FaceGraph`,... The geometric object is retrieved using a property map with the item as key type and the geometric object as value type. The class `CGAL::Shape_detection::Region_growing` is constructed by providing an input range with each element being converted to an item thanks to another property map passed to the constructor. For most cases the default is fine and conveniences alias and functions are provided for the `CGAL::Point_set_3` class (see \ref PkgShapeDetectionRGOnPointSet3). -- `InputRange` that stores a range of user-defined input items; -- \ref Shape_detection_RegionGrowingFramework_connectivity "NeighborQuery" that provides the means for accessing neighbors of an item; -- \ref Shape_detection_RegionGrowingFramework_conditions "RegionType" that provides the means for validating regions; -- \ref Shape_detection_RegionGrowingFramework_seeding "SeedMap" that defines the seeding order of items. +The algorithm provided by `CGAL::Shape_detection::Region_growing` works using two classes that are respectively models of the following concepts: + +- `NeighborQuery`: responsible for providing the neighbors of an item; +- `RegionType`: responsible for the definition of a region from a list of items as well as for validating the addition of an item to an already defined region; + +Additionally, a range of items can be provided as input seeds when constructing the `Region_growing` class. It defines the seeding order of items that is which items are used first to grow regions from. Such items are referred to as *seed* items. When not provided, the order used is that of the input range. Also note that the seed range may not contain all items of the `input_range`. In such case, items not provided and not reached by the region growing algorithm will have not region assigned. Using this generic framework, users can grow any type of regions on a set of arbitrary items with their own propagation and seeding conditions (see \ref Shape_detection_RegionGrowingFramework_examples "an example"). -\subsubsection Shape_detection_RegionGrowingFramework_connectivity Neighborhood - -The concept `NeighborQuery` provides the means for accessing neighbors of an item. -To create a model that respects this concept, the user has to provide an overload of the operator: - -- `NeighborQuery::operator()()` that has to fill a vector with indices of all items, which -are neighbors of the query item. - - -\subsubsection Shape_detection_RegionGrowingFramework_conditions Regions - -The concept `RegionType` provides the means for validating regions. In fact, a model -of this concept maintains a description of the region type that is used in region growing. -To create a model that respect this concept, three functions have to be defined: - -- `RegionType::is_part_of_region()` This function checks if an item satisfies -all necessary region requirements and can be added to a region. It is called per item. - -- `RegionType::is_valid_region()` This function checks if a region satisfies -all necessary region requirements. It is called per region. - -- `RegionType::update()` This utility function enables to update any information, -which is maintained with the region. - - -\subsubsection Shape_detection_RegionGrowingFramework_seeding Seeding - -The `SeedMap` property map, provided as an optional parameter to the main class, enables -to define the seeding order of items that is which items are used first to grow regions from. -Such items are referred to as *seed* items. The `SeedMap` maps the index of an item to its order -number in the overall region growing processing queue. The default map is the identity one -that is the seed index of the item equals to the item's index in the `input_range`. -If it maps to `std::size_t(-1)`, then the corresponding item is skipped. - - \subsubsection Shape_detection_RegionGrowingFramework_examples Examples -This toy example shows how to define one's own \ref Shape_detection_RegionGrowingFramework_connectivity "NeighborQuery" and -\ref Shape_detection_RegionGrowingFramework_conditions "RegionType" classes, which are used to parameterize the -`CGAL::Shape_detection::Region_growing`. It also shows how to skip unnecessary items and change their default seeding order. +This toy example shows how to define a custom models of`NeighborQuery` and +`RegionType` concept, which are used to parameterize the +`CGAL::Shape_detection::Region_growing`. -We choose a simple custom object item. We define four such objects, where for each object, we manually -store indices of its neighbors. The operator `NeighborQuery::operator()()` does nothing but accessing these neighbors. -The `RegionType` class defines the three necessary functions: +We choose a simple custom object item. We define three such objects, where for each object, we manually +provide the iterators to its neighbors. The operator `NeighborQuery::operator()()` does nothing but accessing those neighbors. +The `Region_type` class defines the necessary types and functions: -- `RegionType::is_part_of_region()` - `true` if the first and second objects are neighbors, -- `RegionType::is_valid_region()` - always `true` after the first call to the function `update()`, -- `RegionType::update()` - updates the internal flag from the default `false` to `true`. +- `Region_type::Primitive` This type represents the parameters of the primitive, e.g., in case of a sphere it could be a struct containing a `Point_3` for the center and a floating point number for the radius. -We also define a `SeedMap`, such that the second object is handled first, while the first object follows. -Moreover, the last object is always skipped. Notice that in this example, the container with objects is `std::vector`, -which is random access. However, the generic region growing algorithm can be applied -to any other type of container, e.g. `std::list`. +- `Region_type::Item` - a `const_iterator` of `std::vector` +- `Region_type::Region_index_map` - an unordered map from `Region_type::Item` to `std::size_t` encapsuled in a `boost::associative_property_map`. +- `Region_type::Primitive` - a `std::size_t` +- `Region_type::is_part_of_region()` - `true` if the first and second objects are neighbors, +- `Region_type::is_valid_region()` - always `true` after the first call to the function `update()`, +- `Region_type::update()` - updates the internal flag from the default `false` to `true`. The result of using these classes with the region growing main class is that the first two objects form the first region, -the third object forms the second region, and the last object is skipped. +the third object forms the second region. \cgalExample{Shape_detection/region_growing_with_custom_classes.cpp} @@ -330,8 +298,8 @@ or planes (see \ref Shape_detection_RegionGrowingPoints_examples "3D Example") A 3D point set depicted with one color per detected plane. \cgalFigureEnd -in a 2D or 3D point set respectively, this \cgal component provides the corresponding models of the concepts \ref Shape_detection_RegionGrowingFramework_connectivity "NeighborQuery" -and \ref Shape_detection_RegionGrowingFramework_conditions "RegionType". In particular, it provides two different ways to define neighbors of a point: +in a 2D or 3D point set respectively, this \cgal component provides the corresponding models of the concepts `NeighborQuery` +and `RegionType`. In particular, it provides two different ways to define neighbors of a point: - Fuzzy sphere neighbors search via `CGAL::Shape_detection::Point_set::Sphere_neighbor_query`. This class creates a circle (in 2D case) or a sphere (in 3D case) centered at the query point with a user-specified sphere radius. @@ -351,45 +319,48 @@ The component also provides The program associates all points from a region to the best-fit object (2D line, 2D circle, 3D plane, 3D sphere, etc.) and controls the quality of this fit. -The quality of region growing in a point set (2D or 3D) can be improved by slightly sacrificing the running time. -To achieve this, one can sort indices of input points with respect to some quality criteria. These quality criteria -can be included through the \ref Shape_detection_RegionGrowingFramework_seeding "SeedMap" input parameter. +The quality of region growing in a point set (2D or 3D) can be improved by slightly increasing the running time. +To achieve this, one can sort the input points with respect to some quality criteria. These quality criteria +can be included through the seed range (see \ref Shape_detection_RegionGrowingFramework for more details). We provide a quality sorting both for 2D and 3D points: -- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_sorting` - indices of 2D input points are sorted with respect +- `CGAL::Shape_detection::Point_set::Least_squares_line_fit_sorting` - the 2D input points are sorted with respect to the quality of the least squares line fit applied to the neighbors of each point; -- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_sorting` - indices of 2D input points are sorted with respect +- `CGAL::Shape_detection::Point_set::Least_squares_circle_fit_sorting` - the 2D input points are sorted with respect to the quality of the least squares circle fit applied to the neighbors of each point; -- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting` - indices of 3D input points are sorted with respect +- `CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting` - the 3D input points are sorted with respect to the quality of the least squares plane fit applied to the neighbors of each point. -- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_sorting` - indices of 3D input points are sorted with respect +- `CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_sorting` - the 3D input points are sorted with respect to the quality of the least squares sphere fit applied to the neighbors of each point. -- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_sorting` - indices of 3D input points are sorted with respect +- `CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_sorting` - the 3D input points are sorted with respect to the quality of the least squares cylinder fit applied to the neighbors of each point. + \subsubsection Shape_detection_RegionGrowingPoints_parameters Parameters The classes in Section \ref Shape_detection_RegionGrowingPoints "Region Growing On Point Set" depend on a few parameters that should be defined by the user. They also have default values, but these values do not necessarily guarantee -to produce pleasant results. +to produce pleasant results. All parameter values can be specified using \ref bgl_namedparameters "Named Parameters". -The `NeighborQuery` related classes depend on the following parameters: +The `NeighborQuery` related classes depend on the parameters: -- `sphere_radius` is used by the class `CGAL::Shape_detection::Point_set::Sphere_neighbor_query` -and defines the radius of the fuzzy search sphere centered at the query point; +- `sphere_radius` in the class `CGAL::Shape_detection::Point_set::Sphere_neighbor_query`, +defines the radius of the fuzzy search sphere centered at the query point; -- `k` is used by the class `CGAL::Shape_detection::Point_set::K_neighbor_query` -and defines the number K of nearest neighbors of the query point. +- `k_neighbors` in the class `CGAL::Shape_detection::Point_set::K_neighbor_query`, +defines the number K of nearest neighbors of the query point. -The right choice of `sphere_radius` or `k` parameters plays an important role in producing a good result. -For example, if we consider the fuzzy sphere neighborhood, when `sphere_radius` is too large, we have fewer regions, and the details are not clearly separated. -Meanwhile, if `sphere_radius` is too small, we produce more regions, and the point set may be over-segmented. -Consider a 2D map of an intersection of streets in a city as in Figure \cgalFigureRef{Region_growing_parameter_sphere_radius_variation}. -Each region is painted with a unique color. As `sphere_radius` increases, the details become less clear. When `sphere_radius` = 0.3 (c), the best visual result is produced. +The right choice of the parameters above plays an important role in producing a good result. +For example, if we consider the fuzzy sphere neighborhood, when `sphere_radius` is too large, we have fewer regions, +and the details are not clearly separated. Meanwhile, if `sphere_radius` is too small, we produce more regions, +and the point set may be over-segmented. Consider a 2D map of an intersection of streets in a city as +in Figure \cgalFigureRef{Region_growing_parameter_sphere_radius_variation}. Each region is painted with +a unique color. As `sphere_radius` increases, the details become less clear. +When `sphere_radius` = 0.3 (c), the best visual result is produced. \cgalFigureBegin{Region_growing_parameter_sphere_radius_variation, Region_growing/sphere_radius_parameter_2D.png} (a) Input 2D point set; @@ -400,21 +371,22 @@ Each region is painted with a unique color. As `sphere_radius` increases, the de The `RegionType` related classes depend on the following parameters: -- `distance_threshold` - the maximum distance from a point to a line/plane; -- `angle_threshold` - the maximum accepted angle between the normal associated with a point and the normal of a line/plane; -- `min_region_size` - the minimum number of points a region must have. +- `maximum_distance` - the maximum distance from a point to a line/plane; +- `maximum_angle` - the maximum angle in degrees between the normal associated with a point and the normal of a line/plane; +- `minimum_region_size` - the minimum number of points a region must have. -The first two parameters are used by the functions `RegionType::is_part_of_region()` and `RegionType::update()`, while the third parameter is used by the function `RegionType::is_valid_region()` -explained in Section \ref Shape_detection_RegionGrowingFramework_conditions "Framework Region Type". +The first two parameters are used by the functions `RegionType::is_part_of_region()` and `RegionType::update()`, +while the third parameter is used by the function `RegionType::is_valid_region()` from the `RegionType` concept. -The right choice of `distance_threshold` and `angle_threshold` parameters is also very important. -For example, Figure \cgalFigureRef{Region_growing_parameter_angle_threshold_variation} shows that the roof top of the house can be distinguished as two planes (painted in blue and dark red) -when `angle_threshold` is strict enough (c), or it can be recognized as only one plane (painted in pale yellow) in the other case (b). +The right choice of `maximum_distance` and `maximum_angle` parameters is also very important. +For example, Figure \cgalFigureRef{Region_growing_parameter_max_angle_variation} shows that the +roof top of the house can be distinguished as two planes (painted in blue and dark red) when `maximum_angle` +is strict enough (c), or it can be recognized as only one plane (painted in pale yellow) in the other case (b). -\cgalFigureBegin{Region_growing_parameter_angle_threshold_variation, Region_growing/angle_threshold_parameter_3D.png} +\cgalFigureBegin{Region_growing_parameter_max_angle_variation, Region_growing/max_angle_parameter_3D.png} (a) Input 3D point cloud; -(b) Result when `angle_threshold` = 60 degrees; -(c) Result when `angle_threshold` = 25 degrees. +(b) Result when `maximum_angle` = 60 degrees; +(c) Result when `maximum_angle` = 25 degrees. \cgalFigureEnd @@ -430,9 +402,9 @@ Typical usage of the Region Growing component consists of five steps: -# Detect; -# Postprocess. -Given a 2D point set, we detect 2D lines using the fuzzy sphere neighborhood. We then color all points from the found regions and save them in a file (see Figure \cgalFigureRef{Region_growing_on_point_set_2}). - -The points with assigned to them normal vectors are stored in `std::vector` and the used `Kernel` is `CGAL::Simple_cartesian`, where the number type is `double`. +Given a 2D point set, we detect 2D lines using the fuzzy sphere neighborhood. We then color all points +from the found regions and save them in a file (see Figure \cgalFigureRef{Region_growing_on_point_set_2}). +A point set with normals is stored in `std::vector`. \cgalExample{Shape_detection/region_growing_lines_on_point_set_2.cpp} @@ -444,10 +416,10 @@ The following example shows a similar example, this time detecting circles inste \paragraph Shape_detection_RegionGrowingPoints_example_3D_planes Detecting 3D Planes -If we are given a 3D point set, then the example below shows how to detect 3D planes using the K nearest neighbors search. We color all points from the found regions -and save them in a file (see Figure \cgalFigureRef{Region_growing_on_point_set_3}). The example also shows how to retrieve all points, which are not assigned to any region, and how to use a custom output iterator. - -The point set with associated normals is stored in `CGAL::Point_set_3` and the used `Kernel` is `CGAL::Exact_predicates_inexact_constructions_kernel`. +If we are given a 3D point set, then the example below shows how to detect 3D planes using the K nearest neighbors search. +We color all points from the found regions and save them in a file (see Figure \cgalFigureRef{Region_growing_on_point_set_3}). +The example also shows how to retrieve all points, which are not assigned to any region, and how to use a custom output iterator. +A point set with normals is stored in `CGAL::Point_set_3`. \cgalExample{Shape_detection/region_growing_planes_on_point_set_3.cpp} @@ -463,28 +435,30 @@ The following example shows another similar example, this time detecting (infini \cgalExample{Shape_detection/region_growing_cylinders_on_point_set_3.cpp} + \subsubsection Shape_detection_RegionGrowingPoints_performance Performance -The main parameter that affects the region growing algorithm on a point set is the neighborhood size at each retrieval (`sphere_radius` or `k`). -Larger neighbor lists are often followed by a smaller number of regions, larger coverage (the ratio between the number of points assigned to regions and the total number of input points), +The main parameter that affects the region growing algorithm on a point set is the neighborhood size +at each retrieval (see `sphere_radius` or `k_neighbors`). Larger neighbor lists are often followed by a smaller number +of regions, larger coverage (the ratio between the number of points assigned to regions and the total number of input points), and longer running time. For example, for a test of about 70k 2D points with the fuzzy sphere neighborhood, the following table is produced: - + - + - + - +
sphere_radius Time (in seconds) Number of regions Number of assigned points
1 0.138831 794 4483
1.0 0.138831 794 4483
3 0.069098 3063 63038
3.0 0.069098 3063 63038
6 0.077703 2508 64906
6.0 0.077703 2508 64906
9 0.093415 2302 65334
9.0 0.093415 2302 65334
If the neighborhood size is set too low, some points might be isolated, the region size would not reach a critical mass and so will be discarded. -This does not only cause the latency in the program, but also reduces the coverage value, as can be seen when the `sphere_radius = 1`. A typical time measure for a 3D point set with the K nearest neighborhood -and well-defined parameters can be found in the following table: +This does not only cause the latency in the program, but also reduces the coverage value, as can be seen when the `sphere_radius = 1.0`. +A typical runtime measure for a 3D point set with the K nearest neighborhood and well-defined parameters can be found in the following table: @@ -503,26 +477,27 @@ and well-defined parameters can be found in the following table: \subsection Shape_detection_RegionGrowingMesh Polygon Mesh If one wants to detect planes on a polygon mesh, this \cgal component provides the corresponding models of the concepts -\ref Shape_detection_RegionGrowingFramework_connectivity "NeighborQuery" and \ref Shape_detection_RegionGrowingFramework_conditions "RegionType". -In particular, it has +`NeighborQuery` and `RegionType`. +In particular, it provides - `CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query` class that retrieves all edge-adjacent faces of a face, and - `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region` class that fits a 3D plane to the vertices of all mesh faces, which have been added to the region so far, and controls the quality of this fit. -This component accepts any model of the concept `FaceListGraph` as a polygon mesh. A picture below gives an \ref Shape_detection_RegionGrowingMesh_examples "example" -of the region growing algorithm for detecting 3D planes on `CGAL::Surface_mesh`. +This component accepts any model of the concept `FaceListGraph` as a polygon mesh. Figure \cgalFigureRef{Region_growing_on_surface_mesh} +gives an \ref Shape_detection_RegionGrowingMesh_examples "example" of the region growing algorithm +for detecting 3D planes on `CGAL::Surface_mesh`. \cgalFigureBegin{Region_growing_on_surface_mesh, Region_growing/region_growing_on_polygon_mesh.png} A surface mesh depicted with one color per detected plane. \cgalFigureEnd -The quality of region growing on a polygon mesh can be improved by slightly sacrificing the running time. To achieve -this, one can sort indices of input faces with respect to some quality criteria. These quality criteria -can be included in region growing through the \ref Shape_detection_RegionGrowingFramework_seeding "SeedMap" -input parameter. We provide such a quality sorting: +The quality of region growing on a polygon mesh can be improved by slightly increasing the running time. To achieve +this, one can sort the input faces with respect to some quality criteria. These quality criteria +can be included in region growing through the seed range (see \ref Shape_detection_RegionGrowingFramework for more details). +We provide such a quality sorting: -- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` - indices of input faces are sorted with respect +- `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` - the input faces are sorted with respect to the quality of the least squares plane fit applied to the neighbors of each face. @@ -531,24 +506,21 @@ to the quality of the least squares plane fit applied to the neighbors of each f The `NeighborQuery` related class does not require any parameters, because edge-adjacent faces are found using the internal face graph connectivity, while the `RegionType` related class depends on three parameters: -- `distance_threshold` - the maximum distance from the furthest face vertex to a plane; -- `angle_threshold` - the maximum accepted angle between the face normal and the normal of a plane; -- `min_region_size` - the minimum number of mesh faces a region must have. +- `maximum_distance` - the maximum distance from the furthest face vertex to a plane; +- `maximum_angle` - the maximum angle in degrees between the face normal and the normal of a plane; +- `minimum_region_size` - the minimum number of mesh faces a region must have. -The first two parameters are used by the functions `RegionType::is_part_of_region()` and `RegionType::update()`, while the third parameter is used by the function `RegionType::is_valid_region()` -explained in Section \ref Shape_detection_RegionGrowingFramework_conditions "Framework Regions". The right choice of these parameters is as important as the one explained -in Section \ref Shape_detection_RegionGrowingPoints_parameters "Parameters For Region Growing On Point Set". +The first two parameters are used by the functions `RegionType::is_part_of_region()` and `RegionType::update()`, +while the third parameter is used by the function `RegionType::is_valid_region()`. The right choice of these parameters is as important +as the one explained in Section \ref Shape_detection_RegionGrowingPoints_parameters "Parameters For Region Growing On Point Set". \subsubsection Shape_detection_RegionGrowingMesh_examples Examples In the example below, we show how to use region growing to detect planes on a polygon mesh that can be either stored as `CGAL::Surface_mesh` or `CGAL::Polyhedron_3`. -If it is a surface mesh, this example also provides a way to save the result in a file (see Figure \cgalFigureRef{Region_growing_on_surface_mesh}). The used `Kernel` here is `CGAL::Exact_predicates_exact_constructions_kernel`. -Though this exact kernel provides better quality results, please note that it may significantly slow down the execution of the program, so if you need -a faster version of region growing, use a floating type based kernel. -We can improve the quality of region growing by providing a different seeding order (analogously to \ref Shape_detection_RegionGrowingPoints "Point Sets") that is why in this example we also -sort indices of input faces using the `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` and only then detect regions. +We can improve the quality of region growing by providing a different seeding order (analogously to \ref Shape_detection_RegionGrowingPoints "Point Sets") that is why in this example we also sort the input faces using the `CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting` +and only then detect regions. \cgalExample{Shape_detection/region_growing_planes_on_polygon_mesh.cpp} @@ -559,6 +531,41 @@ Since accessing neighbors of a face in a polygon mesh is fast, performance of th mostly depends on the `RegionType` model's implementation, which is usually fast, too. +\subsection Shape_detection_RegionGrowingSegments Segment Set + +If one wants to detect lines in a segment set, this \cgal component provides the corresponding models of the concept +`RegionType`. In particular, it provides + +- `CGAL::Shape_detection::Segment_set::Least_squares_line_fit_region` class that fits a 2D or 3D line +to the chunks of 2D or 3D segments, respectively, and controls the quality of this fit. + +The quality of region growing in a segment set (2D or 3D) can be improved by slightly increasing the running time. +To achieve this, one can sort the input segments with respect to some quality criteria. These quality criteria +can be included through the seed range (see \ref Shape_detection_RegionGrowingFramework for more details). +We provide such a quality sorting: + +- `CGAL::Shape_detection::Segment_set::Least_squares_line_fit_sorting` - the input segments are sorted with respect +to the quality of the least squares line fit applied to the neighbors of each segment. + +If the user's input is a polygon mesh defined as a `FaceListGraph`, it is also possible to filter out all +graph edges, which split this polygon mesh into a set of regions. To achieve that, one first needs to apply +the region growing on a polygon mesh and extract a set of such regions and then provide these regions +to the class `CGAL::Shape_detection::Polygon_mesh::Polyline_graph` that returns a range of the corresponding edges, +which can later be split into a set of linear regions, as shown in the example below. + +\cgalExample{Shape_detection/region_growing_lines_on_segment_set.cpp} + + +\subsubsection Shape_detection_RegionGrowingSegments_parameters Parameters + +The line fitting class above depends on three parameters: + +- `maximum_distance` - the maximum distance from the furthest segment vertex to a line; +- `maximum_angle` - the maximum angle in degrees between the segment direction and the direction of a line; +- `minimum_region_size` - the minimum number of segments a region must have. + +The right choice of these parameters is important for producing the good results. + \section Shape_detection_Comparison Comparison The Efficient RANSAC algorithm is very quick, however, since it is not deterministic, some small shapes might be missed in the detection process. @@ -576,21 +583,6 @@ Bottom right: the output of the region growing, \f$100\%\f$ of the shapes detect Unassigned points are in black in both output images. \cgalFigureEnd - -\section Shape_detection_DeprecatedComponents Deprecated Components - -The new version (see all examples above) of the class `CGAL::Shape_detection::Region_growing` -is not compatible with the old API. For the old API, see an example below and use -`CGAL::Shape_detection::deprecated::Region_growing_depr` instead. - -\cgalExample{Shape_detection/shape_detection_basic_deprecated.cpp} - -The old API is still supported, but will be removed in the next releases. -In particular, the classes `CGAL::Shape_detection::deprecated::Region_growing_depr` and -`CGAL::Shape_detection::deprecated::Shape_detection_traits` will be removed. -Please update your code. - - \section Shape_detection_History History The Efficient RANSAC component was developed by Sven Oesau based on the prototype version created by Yannick Verdie, @@ -598,7 +590,7 @@ with the help of Clément Jamin and under the supervision of Pierre Alliez. The region growing algorithm on a 3D point set was first implemented by Simon Giraudot based on the prototype version developed by Florent Lafarge and then generalized to arbitrary items including versions for a 2D point set, a 3D point set, and a polygon mesh by Thien Hoang during the -Google Summer of Code 2018 under the supervision of Dmitry Anisimov. +Google Summer of Code 2018 under the supervision of Dmitry Anisimov. The version for segments was added later by Dmitry Anisimov. \section Shape_detection_Acknowledgments Acknowledgments diff --git a/Shape_detection/doc/Shape_detection/examples.txt b/Shape_detection/doc/Shape_detection/examples.txt index 4ebb4dabb56..3396294943b 100644 --- a/Shape_detection/doc/Shape_detection/examples.txt +++ b/Shape_detection/doc/Shape_detection/examples.txt @@ -5,12 +5,12 @@ \example Shape_detection/efficient_RANSAC_with_point_access.cpp \example Shape_detection/include/efficient_RANSAC_with_custom_shape.h \example Shape_detection/efficient_RANSAC_with_custom_shape.cpp +\example Shape_detection/region_growing_with_custom_classes.cpp \example Shape_detection/region_growing_lines_on_point_set_2.cpp \example Shape_detection/region_growing_circles_on_point_set_2.cpp \example Shape_detection/region_growing_planes_on_point_set_3.cpp \example Shape_detection/region_growing_spheres_on_point_set_3.cpp \example Shape_detection/region_growing_cylinders_on_point_set_3.cpp \example Shape_detection/region_growing_planes_on_polygon_mesh.cpp -\example Shape_detection/region_growing_with_custom_classes.cpp -\example Shape_detection/shape_detection_basic_deprecated.cpp +\example Shape_detection/region_growing_lines_on_segment_set.cpp */ diff --git a/Shape_detection/doc/Shape_detection/fig/Region_growing/angle_threshold_parameter_3D.png b/Shape_detection/doc/Shape_detection/fig/Region_growing/max_angle_parameter_3D.png similarity index 100% rename from Shape_detection/doc/Shape_detection/fig/Region_growing/angle_threshold_parameter_3D.png rename to Shape_detection/doc/Shape_detection/fig/Region_growing/max_angle_parameter_3D.png diff --git a/Shape_detection/examples/Shape_detection/CMakeLists.txt b/Shape_detection/examples/Shape_detection/CMakeLists.txt index f9f83b8095d..928e332d3cc 100644 --- a/Shape_detection/examples/Shape_detection/CMakeLists.txt +++ b/Shape_detection/examples/Shape_detection/CMakeLists.txt @@ -13,31 +13,35 @@ create_single_source_cgal_program("efficient_RANSAC_with_point_access.cpp") find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater) include(CGAL_Eigen3_support) if(TARGET CGAL::Eigen3_support) + message(STATUS "Found Eigen 3") + create_single_source_cgal_program("efficient_RANSAC_basic.cpp") create_single_source_cgal_program("efficient_RANSAC_with_callback.cpp") - - create_single_source_cgal_program("region_growing_lines_on_point_set_2.cpp") - create_single_source_cgal_program("region_growing_planes_on_point_set_3.cpp") - create_single_source_cgal_program("region_growing_cylinders_on_point_set_3.cpp") - create_single_source_cgal_program("region_growing_spheres_on_point_set_3.cpp") - create_single_source_cgal_program("region_growing_circles_on_point_set_2.cpp") - create_single_source_cgal_program("region_growing_planes_on_polygon_mesh.cpp") create_single_source_cgal_program("region_growing_with_custom_classes.cpp") - - create_single_source_cgal_program("shape_detection_basic_deprecated.cpp") + create_single_source_cgal_program("region_growing_lines_on_point_set_2.cpp") + create_single_source_cgal_program("region_growing_circles_on_point_set_2.cpp") + create_single_source_cgal_program("region_growing_planes_on_point_set_3.cpp") + create_single_source_cgal_program("region_growing_spheres_on_point_set_3.cpp") + create_single_source_cgal_program("region_growing_cylinders_on_point_set_3.cpp") + create_single_source_cgal_program("region_growing_lines_on_segment_set.cpp") + create_single_source_cgal_program("region_growing_planes_on_polygon_mesh.cpp") + add_executable(region_growing_planes_on_polyhedron region_growing_planes_on_polygon_mesh.cpp) + target_compile_definitions(region_growing_planes_on_polyhedron PUBLIC -DUSE_POLYHEDRON) + target_link_libraries(region_growing_planes_on_polyhedron PUBLIC CGAL::CGAL CGAL::Eigen3_support) foreach( target efficient_RANSAC_basic efficient_RANSAC_with_callback - region_growing_lines_on_point_set_2 - region_growing_planes_on_point_set_3 - region_growing_cylinders_on_point_set_3 - region_growing_spheres_on_point_set_3 - region_growing_circles_on_point_set_2 - region_growing_planes_on_polygon_mesh region_growing_with_custom_classes - shape_detection_basic_deprecated) + region_growing_lines_on_point_set_2 + region_growing_circles_on_point_set_2 + region_growing_planes_on_point_set_3 + region_growing_spheres_on_point_set_3 + region_growing_cylinders_on_point_set_3 + region_growing_planes_on_polygon_mesh + region_growing_lines_on_segment_set) + target_link_libraries(${target} PUBLIC CGAL::Eigen3_support) endforeach() endif() diff --git a/Shape_detection/examples/Shape_detection/README.md b/Shape_detection/examples/Shape_detection/README.md deleted file mode 100644 index b6fbaf655bd..00000000000 --- a/Shape_detection/examples/Shape_detection/README.md +++ /dev/null @@ -1,6 +0,0 @@ -README: - -Data: -To keep the size of this package small, the point_set_3.xyz file is simplified. -The full version, which is used in docs, can be found here: -https://github.com/... /data diff --git a/Shape_detection/examples/Shape_detection/include/utils.h b/Shape_detection/examples/Shape_detection/include/utils.h new file mode 100644 index 00000000000..762ee7e0806 --- /dev/null +++ b/Shape_detection/examples/Shape_detection/include/utils.h @@ -0,0 +1,309 @@ +#ifndef CGAL_SHAPE_DETECTION_EXAMPLES_UTILS_H +#define CGAL_SHAPE_DETECTION_EXAMPLES_UTILS_H + +// STL includes. +#include +#include +#include +#include +#include +#include +#include +#include + +// CGAL includes. +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Define how a color should be stored. +namespace CGAL { + template + struct Output_rep< ::std::array, F > { + const ::std::array& c; + static const bool is_specialized = true; + Output_rep(const ::std::array& c) : c(c) { } + std::ostream& operator()(std::ostream& out) const { + if (IO::is_ascii(out)) { out << int(c[0]) << " " << int(c[1]) << " " << int(c[2]); + } else { out.write(reinterpret_cast(&c), sizeof(c)); } + return out; + } + }; +} // namespace CGAL + +namespace utils { + +template +void save_point_regions_2( + const Region& regions, + const std::string fullpath, + const Point_map point_map = Point_map()) { + + using Point_3 = typename Kernel::Point_3; + using Color = std::array; + using Point_with_color = std::pair; + using PLY_Point_map = CGAL::First_of_pair_property_map; + using PLY_Color_map = CGAL::Second_of_pair_property_map; + + std::vector pwc; + srand(static_cast(time(NULL))); + + // Iterate through all regions. + for (const auto& region : regions) { + + // Generate a random color. + const Color color = + CGAL::make_array( + static_cast(rand() % 256), + static_cast(rand() % 256), + static_cast(rand() % 256)); + + // Iterate through all region items. + for (const auto item : region.second) { + const auto& point = get(point_map, item); + pwc.push_back(std::make_pair(Point_3(point.x(), point.y(), 0), color)); + } + } + + std::ofstream out(fullpath); + CGAL::IO::set_ascii_mode(out); + CGAL::IO::write_PLY_with_properties( + out, pwc, + CGAL::make_ply_point_writer(PLY_Point_map()), + std::make_tuple( + PLY_Color_map(), + CGAL::PLY_property("red"), + CGAL::PLY_property("green"), + CGAL::PLY_property("blue"))); + out.close(); +} + +template +void save_point_regions_3( + const Region& regions, + const std::string fullpath, + const Point_map point_map = Point_map()) { + + using Point_3 = typename Kernel::Point_3; + using Color = std::array; + using Point_with_color = std::pair; + using PLY_Point_map = CGAL::First_of_pair_property_map; + using PLY_Color_map = CGAL::Second_of_pair_property_map; + + std::vector pwc; + srand(static_cast(time(NULL))); + + // Iterate through all regions. + for (const auto& region : regions) { + + // Generate a random color. + const Color color = + CGAL::make_array( + static_cast(rand() % 256), + static_cast(rand() % 256), + static_cast(rand() % 256)); + + // Iterate through all region items. + for (const auto item : region.second) { + const auto& point = get(point_map, *item); + pwc.push_back(std::make_pair(point, color)); + } + } + + std::ofstream out(fullpath); + CGAL::IO::set_ascii_mode(out); + CGAL::IO::write_PLY_with_properties( + out, pwc, + CGAL::make_ply_point_writer(PLY_Point_map()), + std::make_tuple( + PLY_Color_map(), + CGAL::PLY_property("red"), + CGAL::PLY_property("green"), + CGAL::PLY_property("blue"))); + out.close(); +} + +template +void save_segment_regions_2( + const Region& regions, + const std::string fullpath, + const Segment_map segment_map = Segment_map()) { + + using Point_3 = typename Kernel::Point_3; + using Color = std::array; + using Point_with_color = std::pair; + using PLY_Point_map = CGAL::First_of_pair_property_map; + using PLY_Color_map = CGAL::Second_of_pair_property_map; + + std::vector pwc; + srand(static_cast(time(NULL))); + + // Iterate through all regions. + for (const auto& region : regions) { + + // Generate a random color. + const Color color = + CGAL::make_array( + static_cast(rand() % 256), + static_cast(rand() % 256), + static_cast(rand() % 256)); + + // Iterate through all region items. + for (const auto item : region.second) { + const auto& segment = get(segment_map, item); + const auto& s = segment.source(); + const auto& t = segment.target(); + pwc.push_back(std::make_pair(Point_3(s.x(), s.y(), 0), color)); + pwc.push_back(std::make_pair(Point_3(t.x(), t.y(), 0), color)); + } + } + + std::ofstream out(fullpath); + CGAL::IO::set_ascii_mode(out); + CGAL::IO::write_PLY_with_properties( + out, pwc, + CGAL::make_ply_point_writer(PLY_Point_map()), + std::make_tuple( + PLY_Color_map(), + CGAL::PLY_property("red"), + CGAL::PLY_property("green"), + CGAL::PLY_property("blue"))); + out.close(); +} + +template +void save_segment_regions_3( + const Regions& regions, + const std::string fullpath, + const Segment_map segment_map = Segment_map()) { + + using Point_3 = typename Kernel::Point_3; + using Color = std::array; + using Point_with_color = std::pair; + using PLY_Point_map = CGAL::First_of_pair_property_map; + using PLY_Color_map = CGAL::Second_of_pair_property_map; + + std::vector pwc; + srand(static_cast(time(NULL))); + + // Iterate through all regions. + for (const auto& region : regions) { + + // Generate a random color. + const Color color = + CGAL::make_array( + static_cast(rand() % 256), + static_cast(rand() % 256), + static_cast(rand() % 256)); + + // Iterate through all region items. + for (const auto &item : region.second) { + const auto& segment = get(segment_map, item); + pwc.push_back(std::make_pair(segment.source(), color)); + pwc.push_back(std::make_pair(segment.target(), color)); + } + } + + std::ofstream out(fullpath); + CGAL::IO::set_ascii_mode(out); + CGAL::IO::write_PLY_with_properties( + out, pwc, + CGAL::make_ply_point_writer(PLY_Point_map()), + std::make_tuple( + PLY_Color_map(), + CGAL::PLY_property("red"), + CGAL::PLY_property("green"), + CGAL::PLY_property("blue"))); + out.close(); +} + +// Define an insert iterator. +template< +typename Item, +typename Output_range, +typename Point_map, +typename Primitive> +struct Insert_point_colored_by_region_index { + using argument_type = std::pair< Primitive, std::vector >; + using result_type = void; + using Color_map = + typename Output_range:: template Property_map; + + const Point_map m_point_map; + Output_range& m_output_range; + std::size_t& m_number_of_regions; + Color_map m_red, m_green, m_blue; + + Insert_point_colored_by_region_index( + const Point_map point_map, + Output_range& output_range, + std::size_t& number_of_regions) : + m_point_map(point_map), + m_output_range(output_range), + m_number_of_regions(number_of_regions) { + m_red = m_output_range.template add_property_map("red", 0).first; + m_green = m_output_range.template add_property_map("green", 0).first; + m_blue = m_output_range.template add_property_map("blue", 0).first; + } + + result_type operator()(const argument_type& region) { + + CGAL::Random rand(static_cast(m_number_of_regions)); + const unsigned char r = static_cast(64 + rand.get_int(0, 192)); + const unsigned char g = static_cast(64 + rand.get_int(0, 192)); + const unsigned char b = static_cast(64 + rand.get_int(0, 192)); + + for (Item index : region.second) { + const auto& point = get(m_point_map, index); + const auto it = m_output_range.insert(point); + + m_red[*it] = r; + m_green[*it] = g; + m_blue[*it] = b; + } + ++m_number_of_regions; + } +}; + +template +void save_polygon_mesh_regions( + Polygon_mesh& polygon_mesh, + const Region& regions, + const std::string fullpath) { + + using Color = CGAL::IO::Color; + srand(static_cast(time(NULL))); + + using Face_property_color = CGAL::dynamic_face_property_t; + using Face_color_map = typename boost::property_map::type; + Face_color_map face_color = get(Face_property_color(), polygon_mesh); + + // Iterate through all regions. + std::ofstream out(fullpath); + for (const auto& region : regions) { + + // Generate a random color. + const Color color( + static_cast(rand() % 256), + static_cast(rand() % 256), + static_cast(rand() % 256)); + + // Iterate through all region items. + for (const auto &item : region.second) { + put(face_color, item, color); + } + } + CGAL::IO::write_PLY(out, polygon_mesh, CGAL::parameters::face_color_map(face_color)); +} + +} // namespace utils + +#endif // CGAL_SHAPE_DETECTION_EXAMPLES_UTILS_H diff --git a/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp b/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp index 4576e724642..5e1392545fe 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_circles_on_point_set_2.cpp @@ -1,116 +1,119 @@ -#include -#include -#include - #include #include - +#include #include -#include - +#include #include -#include +#include "include/utils.h" -using Kernel = CGAL::Simple_cartesian; -using Point_3 = Kernel::Point_3; -using Vector_3 = Kernel::Vector_3; -using Point_2 = Kernel::Point_2; +// Typedefs. +using Kernel = CGAL::Simple_cartesian; +using FT = Kernel::FT; +using Point_2 = Kernel::Point_2; +using Point_3 = Kernel::Point_3; using Vector_2 = Kernel::Vector_2; +using Vector_3 = Kernel::Vector_3; -using Point_set_3 = CGAL::Point_set_3; using Point_set_2 = CGAL::Point_set_3; -using Point_map = Point_set_2::Point_map; +using Point_set_3 = CGAL::Point_set_3; + +using Point_map = Point_set_2::Point_map; using Normal_map = Point_set_2::Vector_map; -namespace Shape_detection = CGAL::Shape_detection::Point_set; +using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set; +using Region_type = CGAL::Shape_detection::Point_set::Least_squares_circle_fit_region_for_point_set; +using Sorting = CGAL::Shape_detection::Point_set::Least_squares_circle_fit_sorting_for_point_set; +using Region_growing = CGAL::Shape_detection::Region_growing; -using Neighbor_query = Shape_detection::K_neighbor_query - ; -using Region_type = Shape_detection::Least_squares_circle_fit_region - ; -using Sorting = Shape_detection::Least_squares_circle_fit_sorting - ; -using Region_growing = CGAL::Shape_detection::Region_growing - ; +int main(int argc, char** argv) { -int main (int argc, char** argv) -{ - std::ifstream ifile (argc > 1 ? argv[1] : CGAL::data_file_path("points_3/circles.ply")); - Point_set_3 points3; - ifile >> points3; + // Load ply data either from a local folder or a user-provided file. + const bool is_default_input = argc > 1 ? false : true; + std::ifstream in(is_default_input ? CGAL::data_file_path("points_3/circles.ply") : argv[1]); - std::cerr << points3.size() << " points read" << std::endl; - - // Input should have normals - assert (points3.has_normal_map()); - - Point_set_2 points; - points.add_normal_map(); - for (Point_set_3::Index idx : points3) - { - const Point_3& p = points3.point(idx); - const Vector_3& n = points3.normal(idx); - points.insert (Point_2 (p.x(), p.y()), Vector_2 (n.x(), n.y())); + CGAL::IO::set_ascii_mode(in); + if (!in) { + std::cerr << "ERROR: cannot read the input file!" << std::endl; + return EXIT_FAILURE; } - // Default parameters for data/circles.ply - const std::size_t k = 12; - const double tolerance = 0.01; - const double max_angle = 10.; + Point_set_3 point_set_3; + in >> point_set_3; + in.close(); + std::cout << "* number of input points: " << point_set_3.size() << std::endl; + assert(!is_default_input || point_set_3.size() == 1101); + assert(point_set_3.has_normal_map()); // input should have normals + + // Create a 2D point set. + Point_set_2 point_set_2; + point_set_2.add_normal_map(); + for (const auto& idx : point_set_3) { + const Point_3& point = point_set_3.point(idx); + const Vector_3& normal = point_set_3.normal(idx); + point_set_2.insert( + Point_2(point.x(), point.y()), + Vector_2(normal.x(), normal.y())); + } + + // Default parameter values for the data file circles.ply. + const std::size_t k = 16; + const FT max_distance = FT(1) / FT(100); + const FT max_angle = FT(10); const std::size_t min_region_size = 20; - // No constraint on radius - const double min_radius = 0.; - const double max_radius = std::numeric_limits::infinity(); + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query( + point_set_2, CGAL::parameters::k_neighbors(k)); - Neighbor_query neighbor_query(points, k, points.point_map()); - Region_type region_type(points, tolerance, max_angle, min_region_size, - min_radius, max_radius, - points.point_map(), points.normal_map()); + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_circle_fit_region( + point_set_2, + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); - // Sort indices - Sorting sorting(points, neighbor_query, points.point_map()); + // Sort indices. + Sorting sorting = CGAL::Shape_detection::Point_set::make_least_squares_circle_fit_sorting( + point_set_2, neighbor_query, CGAL::parameters::k_neighbors(k)); sorting.sort(); - Region_growing region_growing(points, neighbor_query, region_type, sorting.seed_map()); + // Create an instance of the region growing class. + Region_growing region_growing( + point_set_2, sorting.ordered(), neighbor_query, region_type); - // Add maps to get colored output - Point_set_3::Property_map - red = points3.add_property_map("red", 0).first, - green = points3.add_property_map("green", 0).first, - blue = points3.add_property_map("blue", 0).first; + // Add maps to get a colored output. + Point_set_2::Property_map + red = point_set_2.add_property_map("red" , 0).first, + green = point_set_2.add_property_map("green", 0).first, + blue = point_set_2.add_property_map("blue" , 0).first; + // Run the algorithm. CGAL::Random random; + std::size_t num_circles = 0; + region_growing.detect( + boost::make_function_output_iterator( + [&](const std::pair< Region_type::Primitive, typename Region_growing::Region >& region) { - std::size_t nb_circles = 0; - CGAL::Real_timer timer; - timer.start(); - region_growing.detect - (boost::make_function_output_iterator - ([&](const std::vector& region) - { - // Assign a random color to each region - unsigned char r = static_cast(random.get_int(64, 192)); - unsigned char g = static_cast(random.get_int(64, 192)); - unsigned char b = static_cast(random.get_int(64, 192)); - for (const std::size_t& idx : region) - { - red[idx] = r; - green[idx] = g; - blue[idx] = b; + // Assign a random color to each region. + const unsigned char r = static_cast(random.get_int(64, 192)); + const unsigned char g = static_cast(random.get_int(64, 192)); + const unsigned char b = static_cast(random.get_int(64, 192)); + for (auto item : region.second) { + red[item] = r; + green[item] = g; + blue[item] = b; } - ++ nb_circles; - })); - timer.stop(); - - std::cerr << nb_circles << " circles detected in " - << timer.time() << " seconds" << std::endl; - - // Save in colored_circles.ply - std::ofstream out ("colored_circles.ply"); - CGAL::IO::set_binary_mode (out); - out << points3; + ++num_circles; + } + ) + ); + std::cout << "* number of found circles: " << num_circles << std::endl; + assert(!is_default_input || num_circles == 10); + // Save regions to a file. + std::ofstream out("circles_point_set_2.ply"); + CGAL::IO::set_ascii_mode(out); + out << point_set_2; return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_cylinders_on_point_set_3.cpp b/Shape_detection/examples/Shape_detection/region_growing_cylinders_on_point_set_3.cpp index 181d3656f32..459117a4d6f 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_cylinders_on_point_set_3.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_cylinders_on_point_set_3.cpp @@ -1,97 +1,98 @@ -#include -#include -#include -#include - #include #include - +#include #include -#include - +#include #include +#include "include/utils.h" -using Kernel = CGAL::Simple_cartesian; -using Point_3 = Kernel::Point_3; +// Typedefs. +using Kernel = CGAL::Simple_cartesian; +using FT = Kernel::FT; +using Point_3 = Kernel::Point_3; using Vector_3 = Kernel::Vector_3; -using Point_set = CGAL::Point_set_3; -using Point_map = typename Point_set::Point_map; +using Point_set = CGAL::Point_set_3; +using Point_map = typename Point_set::Point_map; using Normal_map = typename Point_set::Vector_map; -namespace Shape_detection = CGAL::Shape_detection::Point_set; +using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set; +using Region_type = CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_region_for_point_set; +using Region_growing = CGAL::Shape_detection::Region_growing; -using Neighbor_query = Shape_detection::K_neighbor_query - ; -using Region_type = Shape_detection::Least_squares_cylinder_fit_region - ; -using Region_growing = CGAL::Shape_detection::Region_growing - ; +int main(int argc, char** argv) { -int main (int argc, char** argv) -{ - std::ifstream ifile (argc > 1 ? argv[1] : CGAL::data_file_path("points_3/cube.pwn")); - Point_set points; - ifile >> points; + // Load ply data either from a local folder or a user-provided file. + const bool is_default_input = argc > 1 ? false : true; + std::ifstream in(is_default_input ? CGAL::data_file_path("points_3/cylinders.ply") : argv[1]); - std::cerr << points.size() << " points read" << std::endl; + CGAL::IO::set_ascii_mode(in); + if (!in) { + std::cerr << "ERROR: cannot read the input file!" << std::endl; + return EXIT_FAILURE; + } - // Input should have normals - assert (points.has_normal_map()); + Point_set point_set; + in >> point_set; + in.close(); + std::cout << "* number of input points: " << point_set.size() << std::endl; + assert(!is_default_input || point_set.size() == 1813); + assert(point_set.has_normal_map()); // input should have normals - // Default parameters for data/cube.pwn - const std::size_t k = 24; - const double tolerance = 0.05; - const double max_angle = 5.; - const std::size_t min_region_size = 200; + // Default parameter values for the data file cuble.pwn. + const std::size_t k = 20; + const FT max_distance = FT(1) / FT(10); + const FT max_angle = FT(25); + const std::size_t min_region_size = 20; - // No constraint on radius - const double min_radius = 0.; - const double max_radius = std::numeric_limits::infinity(); + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query(point_set, CGAL::parameters::k_neighbors(k)); - Neighbor_query neighbor_query(points, k, points.point_map()); - Region_type region_type(points, tolerance, max_angle, min_region_size, - min_radius, max_radius, - points.point_map(), points.normal_map()); - Region_growing region_growing(points, neighbor_query, region_type); + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_cylinder_fit_region( + point_set, + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); - // Add maps to get colored output + // Create an instance of the region growing class. + Region_growing region_growing( + point_set, neighbor_query, region_type); + + // Add maps to get a colored output. Point_set::Property_map - red = points.add_property_map("red", 0).first, - green = points.add_property_map("green", 0).first, - blue = points.add_property_map("blue", 0).first; + red = point_set.add_property_map("red" , 0).first, + green = point_set.add_property_map("green", 0).first, + blue = point_set.add_property_map("blue" , 0).first; + // Run the algorithm. CGAL::Random random; + std::size_t num_cylinders = 0; + region_growing.detect( + boost::make_function_output_iterator( + [&](const std::pair< Region_type::Primitive, std::vector >& region) { - std::size_t nb_cylinders = 0; - CGAL::Real_timer timer; - timer.start(); - region_growing.detect - (boost::make_function_output_iterator - ([&](const std::vector& region) - { - // Assign a random color to each region - unsigned char r = static_cast(random.get_int(64, 192)); - unsigned char g = static_cast(random.get_int(64, 192)); - unsigned char b = static_cast(random.get_int(64, 192)); - for (const std::size_t& idx : region) - { - red[idx] = r; - green[idx] = g; - blue[idx] = b; + // Assign a random color to each region. + const unsigned char r = static_cast(random.get_int(64, 192)); + const unsigned char g = static_cast(random.get_int(64, 192)); + const unsigned char b = static_cast(random.get_int(64, 192)); + + for (auto id : region.second) { + put(red, id, r); + put(green, id, g); + put(blue, id, b); } - ++ nb_cylinders; - })); - timer.stop(); - - std::cerr << nb_cylinders << " cylinders detected in " - << timer.time() << " seconds" << std::endl; - - // Save in colored_cylinders.ply - std::ofstream out ("colored_cylinders.ply"); - CGAL::IO::set_binary_mode (out); - out << points; + ++num_cylinders; + } + ) + ); + std::cout << "* number of found cylinders: " << num_cylinders << std::endl; + assert(!is_default_input || num_cylinders == 2); + // Save regions to a file. + std::ofstream out("cylinders_point_set_3.ply"); + CGAL::IO::set_ascii_mode(out); + out << point_set; return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_lines_on_point_set_2.cpp b/Shape_detection/examples/Shape_detection/region_growing_lines_on_point_set_2.cpp index 54d90ab8f77..afdb5bbb75b 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_lines_on_point_set_2.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_lines_on_point_set_2.cpp @@ -1,185 +1,89 @@ -// CGAL includes. -#include -#include -#include #include - #include -#include +#include -// STL includes. -#include -#include -#include -#include -#include -#include -#include +#include "include/utils.h" -// Type declarations. -using Kernel = CGAL::Simple_cartesian; +#include +// Typedefs. +using Kernel = CGAL::Simple_cartesian; using FT = typename Kernel::FT; using Point_2 = typename Kernel::Point_2; -using Point_3 = typename Kernel::Point_3; using Vector_2 = typename Kernel::Vector_2; using Point_with_normal = std::pair; -using Input_range = std::vector; -using Point_map = CGAL::First_of_pair_property_map; -using Normal_map = CGAL::Second_of_pair_property_map; +using Point_set_2 = std::vector; -using Neighbor_query = CGAL::Shape_detection::Point_set::Sphere_neighbor_query; -using Region_type = CGAL::Shape_detection::Point_set::Least_squares_line_fit_region; -using Region_growing = CGAL::Shape_detection::Region_growing; +// we use Compose_property_map as the property maps are expected to operate on the item type +// std::size_t passed as parameter to Sphere_neighbor_query and Least_squares_line_fit_region +using Point_map = CGAL::Compose_property_map, + CGAL::First_of_pair_property_map >; +using Normal_map = CGAL::Compose_property_map, + CGAL::Second_of_pair_property_map >; -using Region = std::vector; -using Regions = std::vector; - -using Color = std::array; -using Point_with_color = std::pair; -using Pwc_vector = std::vector; -using PLY_Point_map = CGAL::First_of_pair_property_map; -using PLY_Color_map = CGAL::Second_of_pair_property_map; - -// Define how a color should be stored. -namespace CGAL { - - template - struct Output_rep< ::Color, F > { - - const ::Color& c; - static const bool is_specialized = true; - - Output_rep(const ::Color& c) : c(c) { } - - std::ostream& operator()(std::ostream& out) const { - - if (IO::is_ascii(out)) - out << int(c[0]) << " " << int(c[1]) << " " << int(c[2]); - else - out.write(reinterpret_cast(&c), sizeof(c)); - - return out; - } - }; - -} // namespace CGAL +using Neighbor_query = CGAL::Shape_detection::Point_set::Sphere_neighbor_query; +using Region_type = CGAL::Shape_detection::Point_set::Least_squares_line_fit_region; +using Region_growing = CGAL::Shape_detection::Region_growing; int main(int argc, char *argv[]) { - std::cout << std::endl << - "region_growing_on_point_set_2 example started" - << std::endl << std::endl; - - std::cout << - "Note: if 0 points are loaded, please specify the path to the file data/point_set_2.xyz by hand!" - << std::endl << std::endl; - // Load xyz data either from a local folder or a user-provided file. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_2.xyz")); - CGAL::IO::set_ascii_mode(in); + const bool is_default_input = argc > 1 ? false : true; + std::ifstream in(is_default_input ? CGAL::data_file_path("points_3/buildings_outline.xyz") : argv[1]); + CGAL::IO::set_ascii_mode(in); if (!in) { - std::cout << - "Error: cannot read the file point_set_2.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; + std::cerr << "ERROR: cannot read the input file!" << std::endl; return EXIT_FAILURE; } - Input_range input_range; FT a, b, c, d, e, f; - - while (in >> a >> b >> c >> d >> e >> f) - input_range.push_back( + Point_set_2 point_set_2; + while (in >> a >> b >> c >> d >> e >> f) { + point_set_2.push_back( std::make_pair(Point_2(a, b), Vector_2(d, e))); - + } in.close(); - std::cout << - "* loaded " - << input_range.size() << - " points with normals" - << std::endl; + std::cout << "* number of input points: " << point_set_2.size() << std::endl; + assert(!is_default_input || point_set_2.size() == 3634); - // Default parameter values for the data file point_set_2.xyz. - const FT search_sphere_radius = FT(5); - const FT max_distance_to_line = FT(45) / FT(10); - const FT max_accepted_angle = FT(45); - const std::size_t min_region_size = 5; + // Default parameter values for the data file buildings_outline.xyz. + const FT sphere_radius = FT(5); + const FT max_distance = FT(45) / FT(10); + const FT max_angle = FT(45); + const std::size_t min_region_size = 5; + + Point_map point_map(CGAL::make_random_access_property_map(point_set_2)); + Normal_map normal_map(CGAL::make_random_access_property_map(point_set_2)); // Create instances of the classes Neighbor_query and Region_type. Neighbor_query neighbor_query( - input_range, - search_sphere_radius); + boost::irange(0,point_set_2.size()), + CGAL::parameters::sphere_radius(sphere_radius) + .point_map(point_map)); Region_type region_type( - input_range, - max_distance_to_line, max_accepted_angle, min_region_size); + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size). + normal_map(normal_map). + point_map(point_map)); // Create an instance of the region growing class. Region_growing region_growing( - input_range, neighbor_query, region_type); + boost::irange(0,point_set_2.size()), neighbor_query, region_type); // Run the algorithm. - Regions regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); + std::cout << "* number of found lines: " << regions.size() << std::endl; + assert(!is_default_input || regions.size() == 72); - // Print the number of found regions. - std::cout << "* " << regions.size() << - " regions have been found" - << std::endl; - - Pwc_vector pwc; - srand(static_cast(time(nullptr))); - - // Iterate through all regions. - for (const auto& region : regions) { - - // Generate a random color. - const Color color = - CGAL::make_array( - static_cast(rand() % 256), - static_cast(rand() % 256), - static_cast(rand() % 256)); - - // Iterate through all region items. - for (const auto index : region) { - const auto& key = *(input_range.begin() + index); - - const Point_2& point = get(Point_map(), key); - pwc.push_back(std::make_pair(Point_3(point.x(), point.y(), 0), color)); - } - } - - // Save the result to a file in the user-provided path if any. - if (argc > 2) { - - const std::string path = argv[2]; - const std::string fullpath = path + "regions_point_set_2.ply"; - - std::ofstream out(fullpath); - - CGAL::IO::set_ascii_mode(out); - CGAL::IO::write_PLY_with_properties( - out, pwc, - CGAL::make_ply_point_writer(PLY_Point_map()), - std::make_tuple( - PLY_Color_map(), - CGAL::PLY_property("red"), - CGAL::PLY_property("green"), - CGAL::PLY_property("blue"))); - - std::cout << - "* found regions are saved in " - << fullpath << std::endl; - out.close(); - } - - std::cout << std::endl << - "region_growing_on_point_set_2 example finished" - << std::endl << std::endl; - + // Save regions to a file. + const std::string fullpath = (argc > 2 ? argv[2] : "lines_point_set_2.ply"); + utils::save_point_regions_2, Point_map>( + regions, fullpath, point_map); return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp b/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp new file mode 100644 index 00000000000..c283a4652fe --- /dev/null +++ b/Shape_detection/examples/Shape_detection/region_growing_lines_on_segment_set.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include +#include "include/utils.h" + +// Typedefs. +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point_3 = typename Kernel::Point_3; + +using Surface_mesh = CGAL::Surface_mesh; +using Face_range = typename Surface_mesh::Face_range; +using Edge_range = typename Surface_mesh::Edge_range; + +using One_ring_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; +using Plane_region = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; +using RG_planes = CGAL::Shape_detection::Region_growing; + +using Polyline_graph = CGAL::Shape_detection::Polygon_mesh::Polyline_graph; +using Segment_range = typename Polyline_graph::Segment_range; +using Segment_map = typename Polyline_graph::Segment_map; + +using Line_region = CGAL::Shape_detection::Segment_set::Least_squares_line_fit_region; +using Line_sorting = CGAL::Shape_detection::Segment_set::Least_squares_line_fit_sorting; +using RG_lines = CGAL::Shape_detection::Region_growing; + +int main(int argc, char *argv[]) { + + // Load data either from a local folder or a user-provided file. + const bool is_default_input = argc > 1 ? false : true; + const std::string filename = is_default_input ? CGAL::data_file_path("meshes/am.off") : argv[1]; + + Surface_mesh surface_mesh; + if (!CGAL::IO::read_polygon_mesh(filename, surface_mesh)) { + std::cerr << "ERROR: cannot read the input file!" << std::endl; + return EXIT_FAILURE; + } + const Face_range face_range = faces(surface_mesh); + const Edge_range edge_range = edges(surface_mesh); + std::cout << "* number of input faces: " << face_range.size() << std::endl; + std::cout << "* number of input edges: " << edge_range.size() << std::endl; + assert(!is_default_input || face_range.size() == 7320); + assert(!is_default_input || edge_range.size() == 10980); + + // Find planar regions. + One_ring_query one_ring_query(surface_mesh); + Plane_region plane_region(surface_mesh); + RG_planes rg_planes(face_range, one_ring_query, plane_region); + + std::vector regions; + rg_planes.detect(std::back_inserter(regions)); + std::cout << "* number of found planar regions: " << regions.size() << std::endl; + assert(!is_default_input || regions.size() == 9); + + std::string fullpath = (argc > 2 ? argv[2] : "regions_sm.ply"); + utils::save_polygon_mesh_regions(surface_mesh, regions, fullpath); + + // Find linear regions. + Polyline_graph pgraph(surface_mesh, rg_planes.region_map()); + const auto& segment_range = pgraph.segment_range(); + std::cout << "* number of extracted segments: " << segment_range.size() << std::endl; + + Line_region line_region(CGAL::parameters::segment_map(pgraph.segment_map())); + Line_sorting line_sorting( + segment_range, pgraph, CGAL::parameters::segment_map(pgraph.segment_map())); + line_sorting.sort(); + + RG_lines rg_lines( + segment_range, line_sorting.ordered(), pgraph, line_region); + + std::vector subregions; + rg_lines.detect(std::back_inserter(subregions)); + std::cout << "* number of found linear regions: " << subregions.size() << std::endl; + assert(!is_default_input || subregions.size() == 21); + + fullpath = (argc > 2 ? argv[2] : "subregions_sm.ply"); + utils::save_segment_regions_3, Segment_map>( + subregions, fullpath, pgraph.segment_map()); + + return EXIT_SUCCESS; +} diff --git a/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp b/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp index eccfa58f1a8..794d1edd5b3 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_planes_on_point_set_3.cpp @@ -1,218 +1,100 @@ -// STL includes. -#include -#include -#include -#include -#include -#include - -// Boost includes. -#include - -// CGAL includes. -#include -#include -#include - #include #include - +#include #include -#include +#include +#include -// Type declarations. -using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +#include "include/utils.h" +// Typedefs. +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; using FT = typename Kernel::FT; using Point_3 = typename Kernel::Point_3; -using Vector_3 = typename Kernel::Vector_3; -using Input_range = CGAL::Point_set_3; -using Point_map = typename Input_range::Point_map; -using Normal_map = typename Input_range::Vector_map; - -using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query; -using Region_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region; -using Region_growing = CGAL::Shape_detection::Region_growing; - -using Indices = std::vector; +using Point_set = CGAL::Point_set_3; using Output_range = CGAL::Point_set_3; -using Points_3 = std::vector; +using Point_map = typename Point_set::Point_map; +using Normal_map = typename Point_set::Vector_map; -// Define an insert iterator. -struct Insert_point_colored_by_region_index { - - using argument_type = Indices; - using result_type = void; - - using Color_map = - typename Output_range:: template Property_map; - - const Input_range& m_input_range; - const Point_map m_point_map; - Output_range& m_output_range; - std::size_t& m_number_of_regions; - - Color_map m_red, m_green, m_blue; - - Insert_point_colored_by_region_index( - const Input_range& input_range, - const Point_map point_map, - Output_range& output_range, - std::size_t& number_of_regions) : - m_input_range(input_range), - m_point_map(point_map), - m_output_range(output_range), - m_number_of_regions(number_of_regions) { - - m_red = - m_output_range.template add_property_map("red", 0).first; - m_green = - m_output_range.template add_property_map("green", 0).first; - m_blue = - m_output_range.template add_property_map("blue", 0).first; - } - - result_type operator()(const argument_type& region) { - - CGAL::Random rand(static_cast(m_number_of_regions)); - const unsigned char r = - static_cast(64 + rand.get_int(0, 192)); - const unsigned char g = - static_cast(64 + rand.get_int(0, 192)); - const unsigned char b = - static_cast(64 + rand.get_int(0, 192)); - - for (const std::size_t index : region) { - const auto& key = *(m_input_range.begin() + index); - - const Point_3& point = get(m_point_map, key); - const auto it = m_output_range.insert(point); - - m_red[*it] = r; - m_green[*it] = g; - m_blue[*it] = b; - } - ++m_number_of_regions; - } -}; // Insert_point_colored_by_region_index +using Region_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region_for_point_set; +using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set; +using Sorting = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting_for_point_set; +using Region_growing = CGAL::Shape_detection::Region_growing; +using Point_inserter = utils::Insert_point_colored_by_region_index; int main(int argc, char *argv[]) { - - std::cout << std::endl << - "region_growing_on_point_set_3 example started" - << std::endl << std::endl; - - std::cout << - "Note: if 0 points are loaded, please specify the path to the file data/point_set_3.xyz by hand!" - << std::endl << std::endl; - // Load xyz data either from a local folder or a user-provided file. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_3.xyz")); - CGAL::IO::set_ascii_mode(in); + const bool is_default_input = argc > 1 ? false : true; + std::ifstream in(is_default_input ? CGAL::data_file_path("points_3/building.xyz") : argv[1]); + CGAL::IO::set_ascii_mode(in); if (!in) { - std::cout << - "Error: cannot read the file point_set_3.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; + std::cerr << "ERROR: cannot read the input file!" << std::endl; return EXIT_FAILURE; } const bool with_normal_map = true; - Input_range input_range(with_normal_map); - - in >> input_range; + Point_set point_set(with_normal_map); + in >> point_set; in.close(); + std::cout << "* number of input points: " << point_set.size() << std::endl; + assert(!is_default_input || point_set.size() == 8075); - std::cout << - "* loaded " - << input_range.size() << - " points with normals" - << std::endl; - - // Default parameter values for the data file point_set_3.xyz. - const std::size_t k = 12; - const FT max_distance_to_plane = FT(2); - const FT max_accepted_angle = FT(20); - const std::size_t min_region_size = 50; + // Default parameter values for the data file building.xyz. + const std::size_t k = 12; + const FT max_distance = FT(2); + const FT max_angle = FT(20); + const std::size_t min_region_size = 50; // Create instances of the classes Neighbor_query and Region_type. - Neighbor_query neighbor_query( - input_range, - k, - input_range.point_map()); + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query( + point_set, CGAL::parameters::k_neighbors(k)); - Region_type region_type( - input_range, - max_distance_to_plane, max_accepted_angle, min_region_size, - input_range.point_map(), input_range.normal_map()); + Sorting sorting = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_sorting(point_set, neighbor_query); + sorting.sort(); + + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_region( + point_set, + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); // Create an instance of the region growing class. Region_growing region_growing( - input_range, neighbor_query, region_type); + point_set, sorting.ordered(), neighbor_query, region_type); // Run the algorithm. Output_range output_range; std::size_t number_of_regions = 0; - - Insert_point_colored_by_region_index inserter( - input_range, input_range.point_map(), + Point_inserter inserter( + point_set.point_map(), output_range, number_of_regions); - - CGAL::Timer timer; - - timer.start(); region_growing.detect( boost::make_function_output_iterator(inserter)); - timer.stop(); + std::cout << "* number of found planes: " << number_of_regions << std::endl; + assert(!is_default_input || number_of_regions == 7); - // Print the number of found regions. - std::cout << "* " << number_of_regions << - " regions have been found in " << timer.time() << " seconds" - << std::endl; + // Save regions to a file. + const std::string fullpath = (argc > 2 ? argv[2] : "planes_point_set_3.ply"); + std::ofstream out(fullpath); + out << output_range; + out.close(); - // Save the result to a file in the user-provided path if any. - if (argc > 2) { - - const std::string path = argv[2]; - const std::string fullpath = path + "regions_point_set_3.ply"; - - std::ofstream out(fullpath); - out << output_range; - - std::cout << "* found regions are saved in " << fullpath << std::endl; - out.close(); - } - - // Get all unassigned items. - Indices unassigned_items; - region_growing.unassigned_items(std::back_inserter(unassigned_items)); - - // Print the number of unassigned items. - std::cout << "* " << unassigned_items.size() << - " points do not belong to any region" - << std::endl; + // Get all unassigned points. + std::vector unassigned_items; + region_growing.unassigned_items(point_set, std::back_inserter(unassigned_items)); + std::cout << "* number of unassigned points: " << unassigned_items.size() << std::endl; + assert(!is_default_input || unassigned_items.size() == 538); // Store all unassigned points. - Points_3 unassigned_points; + std::vector unassigned_points; unassigned_points.reserve(unassigned_items.size()); - - for (const auto index : unassigned_items) { - const auto& key = *(input_range.begin() + index); - - const Point_3& point = get(input_range.point_map(), key); + for (const Region_type::Item &item : unassigned_items) { + const Point_3& point = get(point_set.point_map(), item); unassigned_points.push_back(point); } - std::cout << "* " << unassigned_points.size() << - " unassigned points are stored" - << std::endl; - - std::cout << std::endl << - "region_growing_on_point_set_3 example finished" - << std::endl << std::endl; - return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp b/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp index fc97fd375c9..37245edcd9d 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_planes_on_polygon_mesh.cpp @@ -1,186 +1,98 @@ -// STL includes. -#include -#include -#include -#include -#include -#include - -// CGAL includes. -#include -#include -#include -#include -#include - -#include +#include +#ifdef USE_POLYHEDRON #include - +#else +#include +#endif #include -#include - -// Type declarations. -using Kernel = CGAL::Exact_predicates_exact_constructions_kernel; +#include +#include +#include "include/utils.h" +// Typedefs. +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; using FT = typename Kernel::FT; using Point_3 = typename Kernel::Point_3; -using Color = CGAL::IO::Color; - -// Choose the type of a container for a polygon mesh. -#define USE_SURFACE_MESH - -#if defined(USE_SURFACE_MESH) - - using Polygon_mesh = CGAL::Surface_mesh; - using Face_range = typename Polygon_mesh::Face_range; - - using Neighbor_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; - using Region_type = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; - using Sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; - +#ifdef USE_POLYHEDRON +using Polygon_mesh = CGAL::Polyhedron_3; #else - - using Polygon_mesh = CGAL::Polyhedron_3; - using Face_range = typename CGAL::Iterator_range::face_iterator>; - - using Neighbor_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; - using Region_type = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; - using Sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; - +using Polygon_mesh = CGAL::Surface_mesh; #endif -using Region = std::vector; -using Regions = std::vector; - -using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; - -using Region_growing = CGAL::Shape_detection::Region_growing; +using Neighbor_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; +using Region_type = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; +using Sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; +using Region_growing = CGAL::Shape_detection::Region_growing; int main(int argc, char *argv[]) { - std::cout << std::endl << - "region_growing_on_polygon_mesh example started" - << std::endl << std::endl; - - // Load off data either from a local folder or a user-provided file. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/polygon_mesh.off")); + // Load data either from a local folder or a user-provided file. + const bool is_default_input = argc > 1 ? false : true; + const std::string filename = is_default_input ? CGAL::data_file_path("meshes/building.off") : argv[1]; + std::ifstream in(filename); CGAL::IO::set_ascii_mode(in); - if (!in) { - std::cout << - "Error: cannot read the file polygon_mesh.off!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; + Polygon_mesh polygon_mesh; + if (!CGAL::IO::read_polygon_mesh(filename, polygon_mesh)) { + std::cerr << "ERROR: cannot read the input file!" << std::endl; return EXIT_FAILURE; } + const auto& face_range = faces(polygon_mesh); + std::cout << "* number of input faces: " << face_range.size() << std::endl; + assert(!is_default_input || face_range.size() == 32245); - Polygon_mesh polygon_mesh; - in >> polygon_mesh; - - in.close(); - const Face_range face_range = faces(polygon_mesh); - - std::cout << - "* polygon mesh with " - << face_range.size() << - " faces is loaded" - << std::endl; - - // Default parameter values for the data file polygon_mesh.off. - const FT max_distance_to_plane = FT(1); - const FT max_accepted_angle = FT(45); - const std::size_t min_region_size = 5; + // Default parameter values for the data file building.off. + const FT max_distance = FT(1); + const FT max_angle = FT(45); + const std::size_t min_region_size = 5; // Create instances of the classes Neighbor_query and Region_type. Neighbor_query neighbor_query(polygon_mesh); - const Vertex_to_point_map vertex_to_point_map( - get(CGAL::vertex_point, polygon_mesh)); - Region_type region_type( polygon_mesh, - max_distance_to_plane, max_accepted_angle, min_region_size, - vertex_to_point_map); + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); // Sort face indices. Sorting sorting( - polygon_mesh, neighbor_query, - vertex_to_point_map); + polygon_mesh, neighbor_query); sorting.sort(); // Create an instance of the region growing class. Region_growing region_growing( - face_range, neighbor_query, region_type, - sorting.seed_map()); + face_range, sorting.ordered(), neighbor_query, region_type); // Run the algorithm. - Regions regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); + std::cout << "* number of found planes: " << regions.size() << std::endl; + assert(!is_default_input || regions.size() == 365); - // Print the number of found regions. - std::cout << "* " << regions.size() << - " regions have been found" - << std::endl; + const Region_growing::Region_map& map = region_growing.region_map(); - // Save the result in a file only if it is stored in CGAL::Surface_mesh. - #if defined(USE_SURFACE_MESH) - - using Face_index = typename Polygon_mesh::Face_index; - - // Save the result to a file in the user-provided path if any. - srand(static_cast(time(nullptr))); - if (argc > 2) { - - bool created; - typename Polygon_mesh::template Property_map face_color; - boost::tie(face_color, created) = - polygon_mesh.template add_property_map( - "f:color", Color(0, 0, 0)); - - if (!created) { - - std::cout << std::endl << - "region_growing_on_polygon_mesh example finished" - << std::endl << std::endl; - - return EXIT_FAILURE; + for (std::size_t i = 0; i < regions.size(); i++) + for (auto& item : regions[i].second) { + if (i != get(map, item)) { + std::cout << "Region map incorrect" << std::endl; } - - const std::string path = argv[2]; - const std::string fullpath = path + "regions_polygon_mesh.off"; - - std::ofstream out(fullpath); - - // Iterate through all regions. - for (const auto& region : regions) { - - // Generate a random color. - const Color color( - static_cast(rand() % 256), - static_cast(rand() % 256), - static_cast(rand() % 256)); - - // Iterate through all region items. - using size_type = typename Polygon_mesh::size_type; - for (const auto index : region) - face_color[Face_index(static_cast(index))] = color; - } - - out << polygon_mesh; - out.close(); - - std::cout << - "* polygon mesh is saved in " - << fullpath << std::endl; } - #endif + std::vector unassigned; + region_growing.unassigned_items(face_range, std::back_inserter(unassigned)); - std::cout << std::endl << - "region_growing_on_polygon_mesh example finished" - << std::endl << std::endl; + for (auto& item : unassigned) { + if (std::size_t(-1) != get(map, item)) { + std::cout << "Region map for unassigned incorrect" << std::endl; + } + } + + // Save regions to a file. + const std::string fullpath = (argc > 2 ? argv[2] : "planes_polygon_mesh.ply"); + utils::save_polygon_mesh_regions(polygon_mesh, regions, fullpath); return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_spheres_on_point_set_3.cpp b/Shape_detection/examples/Shape_detection/region_growing_spheres_on_point_set_3.cpp index b9ea42b68c9..b6d73ecd573 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_spheres_on_point_set_3.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_spheres_on_point_set_3.cpp @@ -1,97 +1,97 @@ -#include -#include -#include - #include #include - +#include #include -#include - +#include #include -#include +#include "include/utils.h" -using Kernel = CGAL::Simple_cartesian; -using Point_3 = Kernel::Point_3; +// Typedefs. +using Kernel = CGAL::Simple_cartesian; +using FT = Kernel::FT; +using Point_3 = Kernel::Point_3; using Vector_3 = Kernel::Vector_3; -using Point_set = CGAL::Point_set_3; -using Point_map = typename Point_set::Point_map; +using Point_set = CGAL::Point_set_3; +using Point_map = typename Point_set::Point_map; using Normal_map = typename Point_set::Vector_map; -namespace Shape_detection = CGAL::Shape_detection::Point_set; +using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set; +using Region_type = CGAL::Shape_detection::Point_set::Least_squares_sphere_fit_region_for_point_set; +using Region_growing = CGAL::Shape_detection::Region_growing; -using Neighbor_query = Shape_detection::K_neighbor_query - ; -using Region_type = Shape_detection::Least_squares_sphere_fit_region - ; -using Region_growing = CGAL::Shape_detection::Region_growing - ; +int main(int argc, char** argv) { -int main (int argc, char** argv) -{ - std::ifstream ifile (argc > 1 ? argv[1] : CGAL::data_file_path("points_3/spheres.ply")); - Point_set points; - ifile >> points; + // Load ply data either from a local folder or a user-provided file. + const bool is_default_input = argc > 1 ? false : true; + std::ifstream in(is_default_input ? CGAL::data_file_path("points_3/spheres.ply") : argv[1]); - std::cerr << points.size() << " points read" << std::endl; + CGAL::IO::set_ascii_mode(in); + if (!in) { + std::cerr << "ERROR: cannot read the input file!" << std::endl; + return EXIT_FAILURE; + } - // Input should have normals - assert (points.has_normal_map()); + Point_set point_set; + in >> point_set; + in.close(); + std::cout << "* number of input points: " << point_set.size() << std::endl; + assert(!is_default_input || point_set.size() == 5969); + assert(point_set.has_normal_map()); // input should have normals - // Default parameters for data/spheres.ply - const std::size_t k = 12; - const double tolerance = 0.01; - const double max_angle = 10.; + // Default parameter values for the data file spheres.ply. + const std::size_t k = 12; + const FT max_distance = FT(1) / FT(100); + const FT max_angle = FT(10); const std::size_t min_region_size = 50; - // No constraint on radius - const double min_radius = 0.; - const double max_radius = std::numeric_limits::infinity(); + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query( + point_set, CGAL::parameters::k_neighbors(k)); - Neighbor_query neighbor_query(points, k, points.point_map()); - Region_type region_type(points, tolerance, max_angle, min_region_size, - min_radius, max_radius, - points.point_map(), points.normal_map()); - Region_growing region_growing(points, neighbor_query, region_type); + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_sphere_fit_region( + point_set, + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); - // Add maps to get colored output + // Create an instance of the region growing class. + Region_growing region_growing( + point_set, neighbor_query, region_type); + + // Add maps to get a colored output. Point_set::Property_map - red = points.add_property_map("red", 0).first, - green = points.add_property_map("green", 0).first, - blue = points.add_property_map("blue", 0).first; + red = point_set.add_property_map("red" , 0).first, + green = point_set.add_property_map("green", 0).first, + blue = point_set.add_property_map("blue" , 0).first; - CGAL::Random random; + // Run the algorithm. + std::size_t num_spheres = 0; + region_growing.detect( + boost::make_function_output_iterator( + [&](const std::pair< Region_type::Primitive, typename Region_growing::Region>& region) { - std::size_t nb_spheres = 0; - CGAL::Real_timer timer; - timer.start(); - region_growing.detect - (boost::make_function_output_iterator - ([&](const std::vector& region) - { - // Assign a random color to each region - unsigned char r = static_cast(random.get_int(64, 192)); - unsigned char g = static_cast(random.get_int(64, 192)); - unsigned char b = static_cast(random.get_int(64, 192)); - for (const std::size_t& idx : region) - { - red[idx] = r; - green[idx] = g; - blue[idx] = b; + // Assign a random color to each region. + const unsigned char r = static_cast(CGAL::get_default_random().get_int(64, 192)); + const unsigned char g = static_cast(CGAL::get_default_random().get_int(64, 192)); + const unsigned char b = static_cast(CGAL::get_default_random().get_int(64, 192)); + for (auto item : region.second) { + red[item] = r; + green[item] = g; + blue[item] = b; } - ++ nb_spheres; - })); - timer.stop(); - - std::cerr << nb_spheres << " spheres detected in " - << timer.time() << " seconds" << std::endl; - - // Save in colored_spheres.ply - std::ofstream out ("colored_spheres.ply"); - CGAL::IO::set_binary_mode (out); - out << points; + ++num_spheres; + } + ) + ); + std::cout << "* number of found spheres: " << num_spheres << std::endl; + assert(!is_default_input || num_spheres == 10); + // Save regions to a file. + std::ofstream out("spheres_point_set_3.ply"); + CGAL::IO::set_ascii_mode(out); + out << point_set; return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/region_growing_with_custom_classes.cpp b/Shape_detection/examples/Shape_detection/region_growing_with_custom_classes.cpp index 7cf19b79345..e4e2082ebdf 100644 --- a/Shape_detection/examples/Shape_detection/region_growing_with_custom_classes.cpp +++ b/Shape_detection/examples/Shape_detection/region_growing_with_custom_classes.cpp @@ -1,45 +1,53 @@ // STL includes. -#include +#include +#include #include #include #include #include +#include // CGAL includes. +#include "include/utils.h" +#include #include -// Custom Neighbor_query, Region_type, and Seed_map classes for region growing. +// Custom Neighbor_query and Region_type classes for region growing. namespace Custom { // An object that stores indices of all its neighbors. struct Object { - std::vector neighbors; + std::vector::const_iterator> neighbors; + bool operator==(const Object& obj) const { + return neighbors == obj.neighbors; + } }; // A range of objects. - using Objects = std::vector; + using Objects = std::vector; // std::list works as well // The Neighbor_query functor that accesses neighbors stored in // the object struct above. class Neighbor_query { const Objects& m_objects; + using Item = typename Objects::const_iterator; + using Region = std::vector; + public: Neighbor_query(const Objects& objects) : m_objects(objects) { } void operator()( - const std::size_t query_index, - std::vector& neighbors) const { + const Item &query, + std::vector& neighbors) const { - std::size_t i = 0; - for (const auto& object : m_objects) { - if (i == query_index) { - - neighbors = object.neighbors; + for (auto it = m_objects.begin(); it != m_objects.end(); it++) { + if (it == query) { + neighbors = query->neighbors; return; - } ++i; + } } } }; @@ -51,136 +59,95 @@ namespace Custom { // These are the only functions that have to be defined. class Region_type { bool m_is_valid = false; + const std::vector& m_input; public: - Region_type() { } + Region_type(const std::vector &input) : m_input(input) { } + + using Primitive = std::size_t; + + using Item = std::vector::const_iterator; + using Region = std::vector; + + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + + Region_index_map region_index_map() { + Region_index_map index_map(m_region_map); + return index_map; + } bool is_part_of_region( - const std::size_t, - const std::size_t query_index, - const std::vector& region) const { + const Item, + const Item query, + const Region& region) const { - if (region.size() == 0) - return false; + if (region.size() == 0) return false; - const std::size_t index = region[0]; + auto it = m_input.begin(); - if (index == 0 && query_index == 1) return true; - if (query_index == 0 && index == 1) return true; + if (query == it || query == (it + 1)) + return true; return false; } - inline bool is_valid_region(const std::vector&) const { + inline bool is_valid_region(const Region&) const { return m_is_valid; } - void update(const std::vector&) { + Primitive primitive() { + return Primitive(); + } + + bool update(const Region&) { m_is_valid = true; - } - }; - - // The SeedMap class that uses the m_objects_map to define - // the seeding order of objects. - class Seed_map { - - public: - using key_type = std::size_t; - using value_type = std::size_t; - using reference = std::size_t; - using category = boost::readable_property_map_tag; - - Seed_map(const std::map& objects_map) - : m_objects_map(objects_map) - { } - - value_type operator[](const key_type& key) const - { - return m_objects_map.find(key)->second; - } - - friend value_type get(const Seed_map& seed_map, - const key_type& key) - { - return seed_map[key]; + return m_is_valid; } private: - const std::map& m_objects_map; + Region_unordered_map m_region_map; }; } // namespace Custom -// Type declarations. +// Typedefs. using Object = Custom::Object; using Objects = Custom::Objects; using Neighbor_query = Custom::Neighbor_query; using Region_type = Custom::Region_type; -using Seed_map = Custom::Seed_map; - -using Region = std::vector; -using Regions = std::vector; - -using Region_growing = -CGAL::Shape_detection::Region_growing; +using Region_growing = CGAL::Shape_detection::Region_growing; int main() { - std::cout << std::endl << - "region_growing_with_custom_classes example started" - << std::endl << std::endl; - // Define a range of objects, where the first two objects form // the first region, while the third object forms the second region. // Note that Objects is a random access container here, however the // same algorithm/example can work with other containers, e.g. std::list. - Objects objects; + Objects objects(3); + auto it = objects.begin(); // Region 1. - Object object1; - object1.neighbors.resize(1, 1); - objects.push_back(object1); + objects[0].neighbors.push_back(it+1); + objects[1].neighbors.push_back(it); - Object object2; - object2.neighbors.resize(1, 0); - objects.push_back(object2); + // The single third object constitutes the second region. - // Region 2. - Object object3; - objects.push_back(object3); - - // Extra object to skip. - Object object4; - objects.push_back(object4); + std::cout << "* number of input objects: " << objects.size() << std::endl; + assert(objects.size() == 3); // Create instances of the classes Neighbor_query and Region_type. Neighbor_query neighbor_query = Neighbor_query(objects); - Region_type region_type = Region_type(); - - // Create a seed map. - std::map objects_map; - objects_map[0] = 1; // the order is swapped with the next object - objects_map[1] = 0; - objects_map[2] = 2; // the default order - objects_map[3] = std::size_t(-1); // skip this object - const Seed_map seed_map(objects_map); + Region_type region_type = Region_type(objects); // Create an instance of the region growing class. Region_growing region_growing( - objects, neighbor_query, region_type, seed_map); + objects, neighbor_query, region_type); // Run the algorithm. - Regions regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - // Print the number of found regions. It must be two regions. - std::cout << "* " << regions.size() << - " regions have been found among " << objects.size() << " objects" - << std::endl; - - std::cout << std::endl << - "region_growing_with_custom_classes example finished" - << std::endl << std::endl; - + std::cout << "* number of found regions: " << regions.size() << std::endl; + assert(regions.size() == 2); return EXIT_SUCCESS; } diff --git a/Shape_detection/examples/Shape_detection/shape_detection_basic_deprecated.cpp b/Shape_detection/examples/Shape_detection/shape_detection_basic_deprecated.cpp deleted file mode 100644 index 9c5718525c9..00000000000 --- a/Shape_detection/examples/Shape_detection/shape_detection_basic_deprecated.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#if defined (_MSC_VER) && !defined (_WIN64) -#pragma warning(disable:4244) // boost::number_distance::distance() - // converts 64 to 32 bits integers -#endif - -#include - -#include -#include - -#include -#include -#include -#include - -// Type declarations. -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef std::pair Point_with_normal; -typedef std::vector Pwn_vector; -typedef CGAL::First_of_pair_property_map Point_map; -typedef CGAL::Second_of_pair_property_map Normal_map; - -// In Shape_detection_traits the basic types, i.e., Point and Vector types -// as well as iterator type and property maps, are defined. -typedef CGAL::Shape_detection_3::Shape_detection_traits - Traits; -typedef CGAL::Shape_detection_3::Efficient_RANSAC Efficient_ransac; -typedef CGAL::Shape_detection_3::Region_growing_depr Region_growing; -typedef CGAL::Shape_detection_3::Plane Plane; - -// This program both works for RANSAC and Region Growing. -// This example is using deprecated code! -// Please update your code to the new version using other examples! -template -int run(const std::string filename) { - - // Points with normals. - Pwn_vector points; - - // Load a point set from a file. - // read_points takes an OutputIterator for storing the points - // and a property map to store the normal vector with each point. - - if (!CGAL::IO::read_points(filename, - std::back_inserter(points), - CGAL::parameters::point_map(Point_map()). - normal_map(Normal_map()))) { - - std::cout << "Error: cannot read the file cube.pwn" << std::endl; - return EXIT_FAILURE; - } - - // Instantiate a shape detection engine. - ShapeDetection shape_detection; - - // Provide the input data. - shape_detection.set_input(points); - - // Register planar shapes via template method. - shape_detection.template add_shape_factory(); - - // Detect registered shapes with default parameters. - shape_detection.detect(); - - // Print number of detected shapes. - std::cout << shape_detection.shapes().end() - shape_detection.shapes().begin() - << " shapes detected." << std::endl; - - return EXIT_SUCCESS; -} - -int main (int argc, char** argv) { - - if (argc > 1 && std::string(argv[1]) == "-r") { - std::cout << "Efficient RANSAC" << std::endl; - return run ((argc > 2) ? argv[2] : CGAL::data_file_path("points_3/cube.pwn")); - } - std::cout << "Region Growing" << std::endl; - return run ((argc > 1) ? argv[1] : CGAL::data_file_path("points_3/cube.pwn")); -} diff --git a/Shape_detection/include/CGAL/Polygon_mesh_processing/region_growing.h b/Shape_detection/include/CGAL/Polygon_mesh_processing/region_growing.h new file mode 100644 index 00000000000..25e6e50f9fd --- /dev/null +++ b/Shape_detection/include/CGAL/Polygon_mesh_processing/region_growing.h @@ -0,0 +1,335 @@ +// Copyright (c) 2022 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Sébastien Loriot + + +#ifndef CGAL_POLYGON_MESH_PROCESSING_REGION_GROWING_H +#define CGAL_POLYGON_MESH_PROCESSING_REGION_GROWING_H + +#include + +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Polygon_mesh_processing { + +/*! + \ingroup PkgPolygonMeshProcessingRef + \brief applies a region growing algorithm to fit planes on faces of a mesh. + + See Section \ref Shape_detection_RegionGrowing for more details on the method. + + @tparam PolygonMesh a model of `FaceListGraph` + @tparam RegionMap a model of `WritablePropertyMap` with `boost::graph_traits::%face_descriptor` as key type and `std::size_t` as value type. + @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + + @param mesh the polygon mesh whose faces are used for region growing + @param region_map a property map storing the region index of each face. Values start at `0` up to the value returned minus `1`. + `std::size_t(-1)` is put for faces with no region assigned (can only happen if `minimum_region_size > 1`). + @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + + @return the number of regions detected + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a face to a plane such that it is considered part of the region of the plane} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle (in degrees) between the normals of the supporting planes of two adjacent faces + such that they are considered part of the same region} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{25 degrees} + \cgalParamExtra{this parameter and `cosine_of_maxium_angle` are exclusive} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{The maximum angle, given as a cosine, between the normal of the supporting planes of adjacent faces + such that they are considered part of the same region} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamExtra{this parameter and `maximum_angle` are exclusive} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of faces such that a new region can be created from a set of faces} + \cgalParamType{`std::size_t`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{a property map associating points to the vertices of `mesh`} + \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `%Point_3` as value type} + \cgalParamDefault{`boost::get(CGAL::vertex_point, mesh)`} + \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + must be available in `PolygonMesh`.} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of a geometric traits class} + \cgalParamType{a class model of `Kernel`} + \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} + \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.} + \cgalParamNEnd + \cgalNamedParamsEnd + */ +template +std::size_t +region_growing_of_planes_on_faces(const PolygonMesh& mesh, + RegionMap region_map, + const NamedParameters& np = parameters::default_values()) +{ + namespace RG_PM = CGAL::Shape_detection::Polygon_mesh; + + using VPM = typename GetVertexPointMap < PolygonMesh, NamedParameters>::const_type; + using Traits = typename GetGeomTraits::type; + + using parameters::choose_parameter; + using parameters::get_parameter; + + + using Neighbor_query = RG_PM::One_ring_neighbor_query; + using Region_type = RG_PM::Least_squares_plane_fit_region; + using Sorting = RG_PM::Least_squares_plane_fit_sorting; + using Region_growing = CGAL::Shape_detection::Region_growing; + + Neighbor_query neighbor_query(mesh); + Region_type region_type(mesh, np); + Sorting sorting(mesh, neighbor_query, np); + sorting.sort(); + + std::vector regions; + Region_growing region_growing( + faces(mesh), sorting.ordered(), neighbor_query, region_type, region_map); + region_growing.detect(CGAL::Emptyset_iterator()); + + return region_growing.number_of_regions_detected(); +} + +/*! + \ingroup PkgPolygonMeshProcessingRef + \brief detects the corners on the boundary of almost planar regions by applying the region growing algorithm fitting lines on segment edges of a partition of a mesh. + + More precisely, a corner on the boundary of a region is a vertex that is either shared by at least three regions (two if it is also a vertex on the boundary of the mesh), or that is incident to two segments edges assigned to different lines. + See Section \ref Shape_detection_RegionGrowing for more details on the method. + + @tparam PolygonMesh a model of `FaceListGraph` and `EdgeListGaph` + @tparam RegionMap a model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` as key type and `std::size_t` as value type. + @tparam CornerIdMap a model of `WritablePropertyMap` with `boost::graph_traits::%vertex_descriptor` as key type and `std::size_t` as value type. + @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + + @param mesh polygon mesh for region growing. + @param region_map property map providing the region index of each face, values must be in `[0, nb_regions-1]`. + @param corner_id_map property map storing the corner index of each vertex. Values start at `0` up to the value returned minus 1. + `std::size_t(-1)` is put for vertices that are not corners. + @param nb_regions the number of patches in the partition of `mesh` defined by `region_map` + @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + + @return the number of corners detected + + \cgalNamedParamsBegin + \cgalParamNBegin{edge_is_constrained_map} + \cgalParamDescription{a property map filled by this function such that an edge is marked as constrained + if it is at the interface of two different regions or on the boundary of the mesh} + \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits::%edge_descriptor` + as key type and `bool` as value type} + \cgalParamDefault{Unused if not provided} + \cgalParamNEnd + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a line such that it is considered part of the region of the line} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{1} + \cgalParamExtra{this parameter and `cosine_of_maxium_angle` are exclusive} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between two adjacent segments + such that they are considered part of the same region} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{The maximum angle, given as a cosine, between two adjacent segments + such that they are considered part of the same region} + \cgalParamType{`GeomTraits::FT` with `GeomTraits` being the type of the parameter `geom_traits`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamExtra{this parameter and `maximum_angle` are exclusive} + \cgalParamNEnd + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{a property map associating points to the vertices of `mesh`} + \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + as key type and `%Point_3` as value type} + \cgalParamDefault{`boost::get(CGAL::vertex_point, mesh)`} + \cgalParamExtra{If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + must be available in `PolygonMesh`.} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of a geometric traits class} + \cgalParamType{a class model of `Kernel`} + \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} + \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.} + \cgalParamNEnd + \cgalNamedParamsEnd + */ +template +std::size_t +detect_corners_of_regions( + const PolygonMesh& mesh, + RegionMap region_map, + std::size_t nb_regions, + CornerIdMap corner_id_map, + const NamedParameters& np = parameters::default_values()) +{ + using parameters::choose_parameter; + using parameters::get_parameter; + using parameters::is_default_parameter; + + using Traits = typename GetGeomTraits::type; + using Graph_traits = boost::graph_traits; + using halfedge_descriptor = typename Graph_traits::halfedge_descriptor; + using edge_descriptor = typename Graph_traits::edge_descriptor; + using face_descriptor = typename Graph_traits::face_descriptor; + using vertex_descriptor = typename Graph_traits::vertex_descriptor; + + using Default_ecm = typename boost::template property_map >::type; + using Ecm = typename internal_np::Lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + Default_ecm + > ::type; + + Default_ecm dynamic_ecm; + if(!(is_default_parameter::value)) + dynamic_ecm = get(CGAL::dynamic_edge_property_t(), mesh); + Ecm ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), dynamic_ecm); + + using Polyline_graph = CGAL::Shape_detection::Polygon_mesh::Polyline_graph; + using Segment_map = typename Polyline_graph::Segment_map; + using Item = typename Polyline_graph::Item; + + using Line_region = CGAL::Shape_detection::Segment_set::Least_squares_line_fit_region; + using Line_sorting = CGAL::Shape_detection::Segment_set::Least_squares_line_fit_sorting; + using RG_lines = CGAL::Shape_detection::Region_growing; + + // mark as constrained edges at the interface of two regions + for (edge_descriptor e : edges(mesh)) + { + halfedge_descriptor h = halfedge(e, mesh); + face_descriptor f1 = face(h, mesh); + face_descriptor f2 = face(opposite(h, mesh), mesh); + // an edge is constrained if it is a border edge or if the regions assigned to the two faces are different + if (f1 == Graph_traits::null_face() || f2 == Graph_traits::null_face() || get(region_map,f1)!=get(region_map,f2)) + put(ecm, e, true); + } + + // filter trivial edges: incident to a plane with only one face + // such an edge cannot be removed and its vertices are corners + std::vector nb_faces_per_patch(nb_regions,0); + for(face_descriptor f : faces(mesh)) + { + std::size_t pid = get(region_map, f); + nb_faces_per_patch[pid]+=1; + } + + std::vector filtered_edges, trivial_edges; + for (edge_descriptor e : edges(mesh)) + { + halfedge_descriptor h=halfedge(e,mesh); + std::size_t r1 = is_border(h, mesh)?std::size_t(-1):get(region_map, face(h, mesh)); + h=opposite(h, mesh); + std::size_t r2 = is_border(h, mesh)?std::size_t(-1):get(region_map, face(h, mesh)); + if ( (r1!=std::size_t(-1) && nb_faces_per_patch[r1]==1) || (r2!=std::size_t(-1) && nb_faces_per_patch[r2]==1) ) + trivial_edges.push_back(e); + else + filtered_edges.push_back(e); + } + + Polyline_graph pgraph(mesh, filtered_edges, region_map); + const auto& segment_range = pgraph.segment_range(); + + Line_region line_region(np.segment_map(pgraph.segment_map())); + + Line_sorting line_sorting( + segment_range, pgraph, CGAL::parameters::segment_map(pgraph.segment_map())); + line_sorting.sort(); + + RG_lines rg_lines( + segment_range, pgraph, line_region); + + std::vector< std::pair > > subregions; + rg_lines.detect(std::back_inserter(subregions)); + +#ifdef CGAL_DEBUG_DETECT_CORNERS_OF_REGIONS + std::ofstream debug_corners("corners.xyz"); + debug_corners.precision(17); + std::ofstream debug_edges("contraints.polylines.txt"); + debug_edges.precision(17); +#endif + + // detect vertex corner id + std::size_t cid=0; + for (const std::pair>& r : subregions) + { + std::vector vertex_count(num_vertices(mesh), 0); + std::vector line_vertices; + auto register_vertex = [&vertex_count, &line_vertices] + (vertex_descriptor v) + { + if (vertex_count[v]==0) + line_vertices.push_back(v); + vertex_count[v]+=1; + }; + for (edge_descriptor e : r.second) + { + put(ecm, e, true); + register_vertex(source(e, mesh)); + register_vertex(target(e, mesh)); +#ifdef CGAL_DEBUG_DETECT_CORNERS_OF_REGIONS + debug_edges << "2 " << mesh.point(source(e, mesh)) << " " << mesh.point(target(e, mesh)) << "\n"; +#endif + } + + for (vertex_descriptor v : line_vertices) + if (vertex_count[v]==1) + { +#ifdef CGAL_DEBUG_DETECT_CORNERS_OF_REGIONS + debug_corners << mesh.point(v) << "\n"; +#endif + if (get(corner_id_map, v) == std::size_t(-1)) + put(corner_id_map, v, cid++); + } + } + + // process trivial edges (could be done before if needed) + for(edge_descriptor e : trivial_edges) + { +#ifdef CGAL_DEBUG_DETECT_CORNERS_OF_REGIONS + debug_edges << "2 " << mesh.point(source(e, mesh)) << " " << mesh.point(target(e, mesh)) << "\n"; +#endif + put(ecm, e, true); + if (get(corner_id_map, source(e, mesh))==std::size_t(-1)) + put(corner_id_map, source(e, mesh), cid++); + if (get(corner_id_map, target(e, mesh))==std::size_t(-1)) + put(corner_id_map, target(e, mesh), cid++); + } + + return cid; +} + +} } // end of CGAL::Polygon_mesh_processing namespace + +#endif //CGAL_POLYGON_MESH_PROCESSING_REGION_GROWING_H diff --git a/Shape_detection/include/CGAL/Shape_detection.h b/Shape_detection/include/CGAL/Shape_detection.h index ff5115480ec..074fea691d4 100644 --- a/Shape_detection/include/CGAL/Shape_detection.h +++ b/Shape_detection/include/CGAL/Shape_detection.h @@ -14,7 +14,15 @@ #ifndef CGAL_SHAPE_DETECTION_H #define CGAL_SHAPE_DETECTION_H +/// \cond SKIP_IN_MANUAL #include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection.h +* A convenience header that includes all classes for shape detection. +*/ #include #include diff --git a/Shape_detection/include/CGAL/Shape_detection/Efficient_RANSAC.h b/Shape_detection/include/CGAL/Shape_detection/Efficient_RANSAC.h index 105f9d6d513..32e00683d7f 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Efficient_RANSAC.h +++ b/Shape_detection/include/CGAL/Shape_detection/Efficient_RANSAC.h @@ -14,7 +14,15 @@ #ifndef CGAL_SHAPE_DETECTION_EFFICIENT_RANSAC_HEADERS_H #define CGAL_SHAPE_DETECTION_EFFICIENT_RANSAC_HEADERS_H +/// \cond SKIP_IN_MANUAL #include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection/Efficient_RANSAC.h +* A convenience header that includes all classes related to the efficient RANSAC algorithm. +*/ #include #include diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing.h index 2b95867164e..fbf75985850 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing.h @@ -14,10 +14,19 @@ #ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_HEADERS_H #define CGAL_SHAPE_DETECTION_REGION_GROWING_HEADERS_H +/// \cond SKIP_IN_MANUAL #include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection/Region_growing.h +* A convenience header that includes all classes related to the region growing algorithm. +*/ #include -#include -#include +#include +#include +#include #endif // CGAL_SHAPE_DETECTION_REGION_GROWING_HEADERS_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set.h new file mode 100644 index 00000000000..5d7f56838de --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set.h @@ -0,0 +1,42 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H + +/// \cond SKIP_IN_MANUAL +#include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection/Region_growing/Point_set.h +* A convenience header that includes all classes related to the region growing algorithm on a point set. +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h new file mode 100644 index 00000000000..87feb7a2bd7 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/K_neighbor_query.h @@ -0,0 +1,245 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H + +#include + +// CGAL includes. +#include +#include +#include +#include +#include +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief K nearest neighbors search in a set of 2D or 3D points. + + This class returns the K nearest neighbors of a query point in a point set. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_2` or `Kernel::Point_3` + + \cgalModels `NeighborQuery` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap> + class K_neighbor_query { + + public: + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Point_map = PointMap; + using Point_type = typename boost::property_traits::value_type; + /// \endcond + + /// Item type. Needs to be compatible to Region_type::Item. + using Item = Item_; + using Region = std::vector; + + private: + using Search_base = typename std::conditional< + std::is_same::value, + CGAL::Search_traits_2, + CGAL::Search_traits_3 >::type; + + using Search_traits = + CGAL::Search_traits_adapter; + + using Distance = + CGAL::Distance_adapter< + Item, + PointMap, + CGAL::Euclidean_distance >; + + using Splitter = + CGAL::Sliding_midpoint; + + using Search_tree = + CGAL::Kd_tree; + + using Neighbor_search = + CGAL::Orthogonal_k_neighbor_search< + Search_traits, + Distance, + Splitter, + Search_tree>; + + using Tree = + typename Neighbor_search::Tree; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes a Kd-tree with input points. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 2D or 3D points + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{k_neighbors} + \cgalParamDescription{the number of returned neighbors per each query point} + \cgalParamType{`std::size_t`} + \cgalParamDefault{12} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item from `input_range` + to `Kernel::Point_2` or to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + \pre `K > 0` + */ + template + K_neighbor_query( + const InputRange& input_range, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_distance(m_point_map) + { + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_tree_ptr.reset( new Tree(make_transform_iterator_from_property_map(make_prevent_deref(input_range.begin()), item_map), + make_transform_iterator_from_property_map(make_prevent_deref(input_range.end()), item_map), + Splitter(), + Search_traits(m_point_map)) ); + + const std::size_t K = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::k_neighbors), 12); + CGAL_precondition(K > 0); + m_number_of_neighbors = K; + m_tree_ptr->build(); + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `NeighborQuery::operator()()`. + + This operator finds the `K` closest points to the point around the query point `query` + using a Kd-tree. These references to the points are returned in `neighbors`. + + \param query + `Item` of the query point + + \param neighbors + `Items` of points, which are neighbors of the query point + + \pre `query` is a valid const_iterator of InputRange + */ + void operator()( + const Item query, + std::vector& neighbors) const { + + neighbors.clear(); + Neighbor_search neighbor_search( + *m_tree_ptr, + get(m_point_map, query), + static_cast(m_number_of_neighbors), + 0, true, m_distance); + for (auto it = neighbor_search.begin(); it != neighbor_search.end(); ++it) + neighbors.push_back(it->first); + } + + /// @} + + /// \cond SKIP_IN_MANUAL + void set_k(const std::size_t k) { + m_number_of_neighbors = k; + } + /// \endcond + + private: + Point_map m_point_map; + std::size_t m_number_of_neighbors; + Distance m_distance; + std::shared_ptr m_tree_ptr; // TODO: move constructor? + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_k_neighbor_query()`. + \relates K_neighbor_query + */ + template + using K_neighbor_query_for_point_set = + K_neighbor_query::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates K_neighbor_query + */ + template + K_neighbor_query_for_point_set + make_k_neighbor_query(const PointSet3& ps, CGAL_NP_CLASS np = parameters::default_values()) + { + return K_neighbor_query_for_point_set( + ps, np.point_map(ps.point_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_region.h new file mode 100644 index 00000000000..0aca9432166 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_region.h @@ -0,0 +1,413 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H + +#include + +// Internal includes. +#include + +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Region type based on the quality of the least squares circle + fit applied to 2D points. + + This class fits a circle to chunks of points in a 2D point set and + controls the quality of this fit. If all quality conditions are + satisfied, the chunk is accepted as a valid region, otherwise + rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is `Item` and value type is `Kernel::Point_2` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is `Item` and value type is `Kernel::Vector_2` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap, + typename NormalMap> + class Least_squares_circle_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Item type + using Item = Item_; + + /// Number type. + using FT = typename GeomTraits::FT; + + /// Region type. + using Region = std::vector; + +#ifdef DOXYGEN_RUNNING + /// Primitive + using Primitive = struct { + typename GeomTraits::Point_2 center; + typename GeomTraits::FT radius; + }; +#else + /// Primitive + using Primitive = struct P { + P(const typename GeomTraits::Point_2& c, typename GeomTraits::FT r) : center(c), radius(r) {} + + typename GeomTraits::Point_2 center; + typename GeomTraits::FT radius; + }; +#endif + /// Region map + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point_2 = typename GeomTraits::Point_2; + using Vector_2 = typename GeomTraits::Vector_2; + + using Squared_distance_2 = typename GeomTraits::Compute_squared_distance_2; + using Get_sqrt = internal::Get_sqrt; + using Sqrt = typename Get_sqrt::Sqrt; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + an optional sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a circle} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a point and the radius of a circle} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of 2D points a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{3} + \cgalParamNEnd + \cgalParamNBegin{minimum_radius} + \cgalParamDescription{the radius below which an estimated circle + is considered as invalid and discarded} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{0, no limit} + \cgalParamNEnd + \cgalParamNBegin{maximum_radius} + \cgalParamDescription{the radius above which an estimated circle + is considered as invalid and discarded.} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{+infinity, no limit} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_2`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{an instance of `NormalMap` that maps an item to `Kernel::Vector_2`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + \pre `minimum_radius >= 0` + \pre `maximum_radius >= minimum_radius` + */ + template + Least_squares_circle_fit_region( + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_sqrt(Get_sqrt::sqrt_object(m_traits)), + m_squared_distance_2(m_traits.compute_squared_distance_2_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 3); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + + m_min_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_radius), FT(0)); + CGAL_precondition(m_min_radius >= FT(0)); + + m_max_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_radius), + FT((std::numeric_limits::max)())); + CGAL_precondition(m_max_radius >= m_min_radius); + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to std::size_t + */ + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + Primitive primitive() const { + return Primitive(m_center, m_radius); + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if a point with the item `query` is within + the `maximum_distance` from the corresponding circle and if the angle between + its normal and the circle radius is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + item of the query point + + \param region + inlier items of the region + + The first parameter is not used in this implementation. + + \return Boolean `true` or `false` + + */ + bool is_part_of_region( + const Item, + const Item query, + const Region& region) const { + + // First, we need to integrate at least 6 points so that the + // computed circle means something. + if (region.size() < 6) { + return true; + } + + // TODO: Why do we get so many nan in this class? + if (std::isnan(CGAL::to_double(m_radius))) { + return false; + } + + // If radius is out of bound, nothing fits, early ending. + if (m_radius < m_min_radius || m_radius > m_max_radius) { + return false; + } + + const Point_2& query_point = get(m_point_map, query); + Vector_2 normal = get(m_normal_map, query); + + const FT sq_dist = m_squared_distance_2(query_point, m_center); + if (std::isnan(CGAL::to_double(sq_dist))) return false; + const FT distance_to_center = m_sqrt(sq_dist); + const FT distance_to_circle = CGAL::abs(distance_to_center - m_radius); + + if (distance_to_circle > m_distance_threshold) { + return false; + } + + const FT sq_norm = normal * normal; + if (std::isnan(CGAL::to_double(sq_norm))) return false; + normal = normal / m_sqrt(sq_norm); + + Vector_2 ray(m_center, query_point); + const FT sq_ray = ray * ray; + if (std::isnan(CGAL::to_double(sq_ray))) return false; + ray = ray / m_sqrt(sq_ray); + + if (CGAL::abs(normal * ray) < m_cos_value_threshold) { + return false; + } + return true; + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the estimated radius is between `minimum_radius` + and `maximum_radius` and if the `region` contains at least `min_region_size` points. + + \param region + indices of points included in the region + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return ( + (m_min_radius <= m_radius && m_radius <= m_max_radius) && + (region.size() >= m_min_region_size) + ); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares circle to all points from the `region`. + + \param region + indices of points included in the region + + \return Boolean `true` if the circle fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + + // Fit a circle. + CGAL_precondition(region.size() > 0); + FT radius; Point_2 center; + std::tie(radius, center) = internal::create_circle_2( + region, m_point_map, m_traits, false).first; + if (radius > FT(0)) { + m_radius = radius; + m_center = center; + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_circle( + const Region& region) const { + return internal::create_circle_2( + region, m_point_map, m_traits, false).first; + } + /// \endcond + + private: + const Point_map m_point_map; + const Normal_map m_normal_map; + const GeomTraits m_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + FT m_min_radius; + FT m_max_radius; + + const Sqrt m_sqrt; + const Squared_distance_2 m_squared_distance_2; + + FT m_radius; + Point_2 m_center; + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_sphere_fit_sorting()`. + \relates Least_squares_circle_fit_region + */ + template + using Least_squares_circle_fit_region_for_point_set = + Least_squares_circle_fit_region::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_circle_fit_region + */ + template + Least_squares_circle_fit_region_for_point_set + make_least_squares_circle_fit_region(const PointSet3& ps, + CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_circle_fit_region_for_point_set( + np.point_map(ps.point_map()).normal_map(ps.normal_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h new file mode 100644 index 00000000000..fee100ee27d --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_circle_fit_sorting.h @@ -0,0 +1,245 @@ +// Copyright (c) 2021 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Sorting of 2D points with respect to the local circle fit quality. + + Indices of 2D input points are sorted with respect to the quality of the + least squares circle fit applied to the neighboring points of each point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_2` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename PointMap> + class Least_squares_circle_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Neighbor_query = NeighborQuery; + using Point_map = PointMap; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename Traits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 2D points + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access point's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_2`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_circle_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_neighbor_query(neighbor_query), + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) + { + CGAL_precondition(input_range.size() > 0); + + m_ordered.resize(input_range.size()); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts `Items` of input points. + */ + void sort() { + std::size_t seed_cutoff = compute_scores(); + + CGAL_precondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + order.resize(m_ordered.size() - seed_cutoff); + + std::vector tmp(order.size()); + for (std::size_t i = 0; i < order.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input points. + */ + const Seed_range ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Point_map m_point_map; + const Traits m_traits; + Seed_range m_ordered; + std::vector m_scores; + + std::size_t compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + std::size_t seed_cutoff = 0; + for (const Item& item :m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + + m_scores[idx] = internal::create_circle_2( + neighbors, m_point_map, m_traits, true).second; + + if (m_scores[idx] == -(std::numeric_limits::max)()) + seed_cutoff++; + + idx++; + } + + return seed_cutoff; + } + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_circle_fit_sorting()`. + \relates Least_squares_circle_fit_sorting + */ + template + using Least_squares_circle_fit_sorting_for_point_set = + Least_squares_circle_fit_sorting::Kernel, + typename PointSet3::Index, + NeighborQuery, + typename PointSet3::Point_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_circle_fit_sorting + */ + template + Least_squares_circle_fit_sorting_for_point_set + make_least_squares_circle_fit_sorting(const PointSet3& ps, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_circle_fit_sorting_for_point_set + (ps, neighbor_query, np.point_map(ps.point_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_region.h new file mode 100644 index 00000000000..c1224eaeb1c --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_region.h @@ -0,0 +1,420 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H + +#include + + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Region type based on the quality of the least squares cylinder + fit applied to 3D points. + + This class fits an infinite cylinder to chunks of points in a 3D + point set and controls the quality of this fit. If all quality + conditions are satisfied, the chunk is accepted as a valid region, + otherwise rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type `Item` and value type is `Kernel::Point_3` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is `Item` and value type is `Kernel::Vector_3` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap, + typename NormalMap> + class Least_squares_cylinder_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = Item_; + using Region = std::vector; + + /// Primitive +#ifdef DOXYGEN_RUNNING + using Primitive = struct { + typename GeomTraits::Line_3 axis; + typename GeomTraits::FT radius; + }; +#else + using Primitive = struct P { + P(const typename GeomTraits::Line_3& a, const typename GeomTraits::FT r) : axis(a), radius(r) {} + + typename GeomTraits::Line_3 axis; + typename GeomTraits::FT radius; + }; +#endif + + /// Region map + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point_3 = typename GeomTraits::Point_3; + using Vector_3 = typename GeomTraits::Vector_3; + using Line_3 = typename GeomTraits::Line_3; + + using Squared_distance_3 = typename GeomTraits::Compute_squared_distance_3; + using Get_sqrt = internal::Get_sqrt; + using Sqrt = typename Get_sqrt::Sqrt; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a cylinder} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a point and the radius of a cylinder} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of 3D points a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{3} + \cgalParamNEnd + \cgalParamNBegin{minimum_radius} + \cgalParamDescription{the radius below which an estimated cylinder + is considered as invalid and discarded} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{0, no limit} + \cgalParamNEnd + \cgalParamNBegin{maximum_radius} + \cgalParamDescription{the radius above which an estimated cylinder + is considered as invalid and discarded.} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{+infinity, no limit} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `GeomTraits::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{ an instance of `NormalMap` that maps an item to `GeomTraits::Vector_3`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + \pre `minimum_radius >= 0` + \pre `maximum_radius >= minimum_radius` + */ + template + Least_squares_cylinder_fit_region( + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_sqrt(Get_sqrt::sqrt_object(m_traits)), + m_squared_distance_3(m_traits.compute_squared_distance_3_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 3); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + + m_min_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_radius), FT(0)); + CGAL_precondition(m_min_radius >= FT(0)); + + m_max_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_radius), + FT((std::numeric_limits::max)())); + CGAL_precondition(m_max_radius >= m_min_radius); + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to std::size_t + */ + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + Primitive primitive() const { + return Primitive(m_axis, m_radius); + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if a point with the index `query_index` is within + the `maximum_distance` from the corresponding cylinder and if the angle between + its normal and the cylinder radius is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + item of the query point + + \param region + inlier items of the region + + The first parameter is not used in this implementation. + + \return Boolean `true` or `false` + + */ + bool is_part_of_region( + const Item, + const Item query, + const Region& region) const { + + // First, we need to integrate at least 6 points so that the + // computed cylinder means something. + if (region.size() < 6) { + return true; + } + + if (std::isnan(CGAL::to_double(m_radius))) { + return false; + } + + // If radius is out of bound, nothing fits, early ending. + if (m_radius < m_min_radius || m_radius > m_max_radius) { + return false; + } + + const Point_3& query_point = get(m_point_map, query); + Vector_3 normal = get(m_normal_map, query); + + if (m_axis.to_vector() == Vector_3(0, 0, 0)) return false; + const FT sq_dist = m_squared_distance_3(query_point, m_axis); + if (std::isnan(CGAL::to_double(sq_dist))) return false; + const FT distance_to_center = m_sqrt(sq_dist); + const FT distance_to_cylinder = CGAL::abs(distance_to_center - m_radius); + + if (distance_to_cylinder > m_distance_threshold) { + return false; + } + + const FT sq_norm = normal * normal; + if (std::isnan(CGAL::to_double(sq_norm))) return false; + normal = normal / m_sqrt(sq_norm); + + const Point_3 proj = m_axis.projection(query_point); + Vector_3 ray(proj, query_point); + const FT sq_ray = ray * ray; + if (std::isnan(CGAL::to_double(sq_ray))) return false; + ray = ray / m_sqrt(sq_ray); + + if (CGAL::abs(normal * ray) < m_cos_value_threshold) { + return false; + } + return true; + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the estimated radius is between `minimum_radius` + and `maximum_radius` and if the `region` contains at least `min_region_size` points. + + \param region + indices of points included in the region + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return ( + (m_min_radius <= m_radius && m_radius <= m_max_radius) && + (region.size() >= m_min_region_size) + ); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares cylinder to all points from the `region`. + + \param region + indices of points included in the region + + \return Boolean `true` if the cylinder fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + if (region.size() < 6) + return true; + + // Fit a cylinder. + CGAL_precondition(region.size() >= 6); + FT radius; Line_3 axis; + std::tie(radius, axis) = internal::create_cylinder( + region, m_point_map, m_normal_map, + m_traits).first; + + if (radius >= FT(0)) { + m_radius = radius; + m_axis = axis; + } + else return false; + + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_cylinder( + const Region& region) const { + return internal::create_cylinder( + region, m_point_map, m_normal_map, + m_traits).first; + } + /// \endcond + + private: + const Point_map m_point_map; + const Normal_map m_normal_map; + const GeomTraits m_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + FT m_min_radius; + FT m_max_radius; + + const Sqrt m_sqrt; + const Squared_distance_3 m_squared_distance_3; + + FT m_radius; + Line_3 m_axis; + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_cylinder_fit_region()`. + \relates Least_squares_cylinder_fit_region + */ + template + using Least_squares_cylinder_fit_region_for_point_set = + Least_squares_cylinder_fit_region::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_cylinder_fit_region + */ + template + Least_squares_cylinder_fit_region_for_point_set + make_least_squares_cylinder_fit_region(const PointSet3& ps, + const CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_cylinder_fit_region_for_point_set + (np.point_map(ps.point_map()).normal_map(ps.normal_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h new file mode 100644 index 00000000000..278a2031d4b --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_cylinder_fit_sorting.h @@ -0,0 +1,255 @@ +// Copyright (c) 2021 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Sorting of 3D points with respect to the local cylinder fit quality. + + Indices of 3D input points are sorted with respect to the quality of the + least squares cylinder fit applied to the neighboring points of each point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type `Item` and value type is `Kernel::Point_3` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is `Item` and value type is `Kernel::Vector_3` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename PointMap, + typename NormalMap> + class Least_squares_cylinder_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Neighbor_query = NeighborQuery; + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename Traits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 3D points + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access point's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{ an instance of `NormalMap` that maps an item to `Kernel::Vector_3`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_cylinder_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_neighbor_query(neighbor_query), + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) { + + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_ordered.resize(input_range.size()); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts indices of input points. + */ + void sort() { + std::size_t seed_cutoff = compute_scores(); + CGAL_postcondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + order.resize(m_ordered.size() - seed_cutoff); + + std::vector tmp(order.size()); + for (std::size_t i = 0; i < order.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input points. + */ + const Seed_range ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Point_map m_point_map; + const Normal_map m_normal_map; + const Traits m_traits; + Seed_range m_ordered; + std::vector m_scores; + + std::size_t compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + std::size_t seed_cutoff = 0; + for (const Item& item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + + m_scores[idx] = -internal::create_cylinder( + neighbors, m_point_map, m_normal_map, m_traits).second; + + if (m_scores[idx] == -(std::numeric_limits::max)()) + seed_cutoff++; + + idx++; + } + + return seed_cutoff; + } + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_cylinder_fit_sorting()`. + \relates Least_squares_cylinder_fit_sorting + */ + template + using Least_squares_cylinder_fit_sorting_for_point_set = + Least_squares_cylinder_fit_sorting::Kernel, + typename PointSet3::Index, + NeighborQuery, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_cylinder_fit_sorting + */ + template + Least_squares_cylinder_fit_sorting_for_point_set + make_least_squares_cylinder_fit_sorting(const PointSet3& ps, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_cylinder_fit_sorting_for_point_set + (ps, neighbor_query, np.point_map(ps.point_map()).normal_map(ps.normal_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_region.h new file mode 100644 index 00000000000..6f04d915753 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_region.h @@ -0,0 +1,395 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H + +#include + +// Internal includes. +#include + +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Region type based on the quality of the least squares line + fit applied to 2D points. + + This class fits a line, using \ref PkgPrincipalComponentAnalysisDRef "PCA", + to chunks of points in a 2D point set and controls the quality of this fit. + If all quality conditions are satisfied, the chunk is accepted as a valid region, + otherwise rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_2` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Vector_2` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap, + typename NormalMap> + class Least_squares_line_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = Item_; + using Region = std::vector; + + /// Primitive + using Primitive = typename GeomTraits::Line_2; + + /// Region map + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point_2 = typename GeomTraits::Point_2; + using Vector_2 = typename GeomTraits::Vector_2; + using Line_2 = typename GeomTraits::Line_2; + + using Squared_length_2 = typename GeomTraits::Compute_squared_length_2; + using Squared_distance_2 = typename GeomTraits::Compute_squared_distance_2; + using Scalar_product_2 = typename GeomTraits::Compute_scalar_product_2; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a line} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a point and the normal of a line} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of 2D points a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{2} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_2`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{ an instance of `NormalMap` that maps an item to `Kernel::Vector_2`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + */ + template + Least_squares_line_fit_region( + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_squared_length_2(m_traits.compute_squared_length_2_object()), + m_squared_distance_2(m_traits.compute_squared_distance_2_object()), + m_scalar_product_2(m_traits.compute_scalar_product_2_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 2); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to `std::size_t`. + */ + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + Primitive primitive() const { + return m_line_of_best_fit; + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if a point with the index `query_index` is within + the `maximum_distance` from the corresponding line and if the angle between + its normal and the line's normal is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + item of the query point + + The first and third parameters are not used in this implementation. + + \return Boolean `true` or `false` + */ + bool is_part_of_region( + const Item, + const Item query, + const Region&) const { + + const Point_2& query_point = get(m_point_map, query); + const Vector_2& query_normal = get(m_normal_map, query); + + const FT a = CGAL::abs(m_line_of_best_fit.a()); + const FT b = CGAL::abs(m_line_of_best_fit.b()); + const FT c = CGAL::abs(m_line_of_best_fit.c()); + if (a == FT(0) && b == FT(0) && c == FT(0)) + return false; + + const FT squared_distance_to_fitted_line = + m_squared_distance_2(query_point, m_line_of_best_fit); + const FT squared_distance_threshold = + m_distance_threshold * m_distance_threshold; + + const FT cos_value = + m_scalar_product_2(query_normal, m_normal_of_best_fit); + const FT squared_cos_value = cos_value * cos_value; + + FT squared_cos_value_threshold = + m_cos_value_threshold * m_cos_value_threshold; + squared_cos_value_threshold *= m_squared_length_2(query_normal); + squared_cos_value_threshold *= m_squared_length_2(m_normal_of_best_fit); + + return ( + ( squared_distance_to_fitted_line <= squared_distance_threshold ) && + ( squared_cos_value >= squared_cos_value_threshold )); + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the `region` contains at least `minimum_region_size` points. + + \param region + indices of points included in the region + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return (region.size() >= m_min_region_size); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares line to all points from the `region`. + + \param region + indices of points included in the region + + \return Boolean `true` if the line fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + + CGAL_precondition(region.size() > 0); + if (region.size() == 1) { // create new reference line and normal + const Item item = region[0]; + + // The best fit line will be a line through this point with + // its normal being the point's normal. + const Point_2& point = get(m_point_map, item); + const Vector_2& normal = get(m_normal_map, item); + + if (normal == CGAL::NULL_VECTOR) + return false; + + m_line_of_best_fit = Line_2(point, normal).perpendicular(point); + m_normal_of_best_fit = m_line_of_best_fit.perpendicular( + m_line_of_best_fit.point(0)).to_vector(); + + } else { // update reference line and normal + CGAL_precondition(region.size() >= 2); + std::tie(m_line_of_best_fit, m_normal_of_best_fit) = + get_line_and_normal(region); + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_line_and_normal( + const Region& region) const { + + // The best fit line will be a line fitted to all region points with + // its normal being perpendicular to the line. + CGAL_precondition(region.size() > 0); + const Line_2 unoriented_line_of_best_fit = + internal::create_line_2( + region, m_point_map, m_traits).first; + const Vector_2 unoriented_normal_of_best_fit = + unoriented_line_of_best_fit.perpendicular( + unoriented_line_of_best_fit.point(0)).to_vector(); + + // Flip the line's normal to agree with all input normals. + long votes_to_keep_normal = 0; + for (auto item : region) { + const Vector_2& normal = get(m_normal_map, item); + const bool agrees = + m_scalar_product_2(normal, unoriented_normal_of_best_fit) > FT(0); + votes_to_keep_normal += (agrees ? 1 : -1); + } + const bool flip_normal = (votes_to_keep_normal < 0); + + const Line_2 line_of_best_fit = flip_normal + ? unoriented_line_of_best_fit.opposite() + : unoriented_line_of_best_fit; + const Vector_2 normal_of_best_fit = flip_normal + ? (-1 * unoriented_normal_of_best_fit) + : unoriented_normal_of_best_fit; + + return std::make_pair(line_of_best_fit, normal_of_best_fit); + } + /// \endcond + + private: + const Point_map m_point_map; + const Normal_map m_normal_map; + const GeomTraits m_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + + const Squared_length_2 m_squared_length_2; + const Squared_distance_2 m_squared_distance_2; + const Scalar_product_2 m_scalar_product_2; + + Line_2 m_line_of_best_fit; + Vector_2 m_normal_of_best_fit; + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_line_fit_region()`. + \relates Least_squares_line_fit_region + */ + template + using Least_squares_line_fit_region_for_point_set = + Least_squares_line_fit_region::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_line_fit_region + */ + template + Least_squares_line_fit_region_for_point_set + make_least_squares_line_fit_region(const PointSet3& ps, + const CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_line_fit_region_for_point_set + (np.point_map(ps.point_map()).normal_map(ps.normal_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h new file mode 100644 index 00000000000..9a669b80004 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_line_fit_sorting.h @@ -0,0 +1,233 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Sorting of 2D points with respect to the local line fit quality. + + Indices of 2D input points are sorted with respect to the quality of the + least squares line fit applied to the neighboring points of each point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_2` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename PointMap> + class Least_squares_line_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Neighbor_query = NeighborQuery; + using Point_map = PointMap; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename Traits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 2D points + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access point's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_2`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_line_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_neighbor_query(neighbor_query), + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) { + + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_ordered.resize(input_range.size()); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts indices of input points. + */ + void sort() { + compute_scores(); + CGAL_precondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + std::vector tmp(m_ordered.size()); + for (std::size_t i = 0; i < m_ordered.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input points. + */ + const Seed_range ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Point_map m_point_map; + const Traits m_traits; + Seed_range m_ordered; + std::vector m_scores; + + void compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + for (const Item& item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + m_scores[idx++] = internal::create_line_2( + neighbors, m_point_map, m_traits).second; + } + } + }; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_line_fit_sorting()`. + \relates Least_squares_line_fit_sorting + */ + template + using Least_squares_line_fit_sorting_for_point_set = + Least_squares_line_fit_sorting::Kernel, + typename PointSet3::Index, + NeighborQuery, + typename PointSet3::Point_map>; + + /*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_line_fit_sorting + */ + template + Least_squares_line_fit_sorting_for_point_set + make_least_squares_line_fit_sorting(const PointSet3& ps, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS np = parameters::default_values()) + { + return Least_squares_line_fit_sorting_for_point_set + (ps, neighbor_query, np.point_map(ps.point_map())); + } + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_region.h new file mode 100644 index 00000000000..b1fe82d706f --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_region.h @@ -0,0 +1,396 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H + +#include + +// Internal includes. +#include + +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Region type based on the quality of the least squares plane + fit applied to 3D points. + + This class fits a plane, using \ref PkgPrincipalComponentAnalysisDRef "PCA", + to chunks of points in a 3D point set and controls the quality of this fit. + If all quality conditions are satisfied, the chunk is accepted as a valid region, + otherwise rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_3` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Vector_3` + + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap, + typename NormalMap> + class Least_squares_plane_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = Item_; + using Region = std::vector; + + /// Primitive + using Primitive = typename GeomTraits::Plane_3; + + /// Region map + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point_3 = typename GeomTraits::Point_3; + using Vector_3 = typename GeomTraits::Vector_3; + using Plane_3 = typename GeomTraits::Plane_3; + + using Squared_length_3 = typename GeomTraits::Compute_squared_length_3; + using Squared_distance_3 = typename GeomTraits::Compute_squared_distance_3; + using Scalar_product_3 = typename GeomTraits::Compute_scalar_product_3; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a plane} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a point and the normal of a plane} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of 3D points a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{3} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{an instance of `NormalMap` that maps an item to `Kernel::Vector_3`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + */ + template + Least_squares_plane_fit_region( + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_squared_length_3(m_traits.compute_squared_length_3_object()), + m_squared_distance_3(m_traits.compute_squared_distance_3_object()), + m_scalar_product_3(m_traits.compute_scalar_product_3_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 3); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to std::size_t. + */ + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + Primitive primitive() const { + return m_plane_of_best_fit; + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if the point `query` is within + the `maximum_distance` from the corresponding plane and if the angle between + its normal and the plane's normal is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + `Item` of the query point + + The first and third parameters are not used in this implementation. + + \return Boolean `true` or `false` + + */ + bool is_part_of_region( + const Item, + const Item query, + const Region&) const { + + const Point_3& query_point = get(m_point_map, query); + const Vector_3& query_normal = get(m_normal_map, query); + + const FT a = CGAL::abs(m_plane_of_best_fit.a()); + const FT b = CGAL::abs(m_plane_of_best_fit.b()); + const FT c = CGAL::abs(m_plane_of_best_fit.c()); + const FT d = CGAL::abs(m_plane_of_best_fit.d()); + if (a == FT(0) && b == FT(0) && c == FT(0) && d == FT(0)) + return false; + + const FT squared_distance_to_fitted_plane = + m_squared_distance_3(query_point, m_plane_of_best_fit); + const FT squared_distance_threshold = + m_distance_threshold * m_distance_threshold; + + const FT cos_value = + m_scalar_product_3(query_normal, m_normal_of_best_fit); + const FT squared_cos_value = cos_value * cos_value; + + FT squared_cos_value_threshold = + m_cos_value_threshold * m_cos_value_threshold; + squared_cos_value_threshold *= m_squared_length_3(query_normal); + squared_cos_value_threshold *= m_squared_length_3(m_normal_of_best_fit); + + return ( + ( squared_distance_to_fitted_plane <= squared_distance_threshold ) && + ( squared_cos_value >= squared_cos_value_threshold )); + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the `region` contains at least `minimum_region_size` points. + + \param region + Points of the region represented as `Items`. + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return (region.size() >= m_min_region_size); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares plane to all points from the `region`. + + \param region + Points of the region represented as `Items`. + + \return Boolean `true` if the plane fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + + CGAL_precondition(region.size() > 0); + if (region.size() == 1) { // create new reference plane and normal + const Item item = region[0]; + + // The best fit plane will be a plane through this point with + // its normal being the point's normal. + const Point_3& point = get(m_point_map, item); + const Vector_3& normal = get(m_normal_map, item); + if (normal == CGAL::NULL_VECTOR) return false; + + CGAL_precondition(normal != CGAL::NULL_VECTOR); + m_plane_of_best_fit = Plane_3(point, normal); + m_normal_of_best_fit = m_plane_of_best_fit.orthogonal_vector(); + + } else { // update reference plane and normal + if (region.size() < 3) return false; + CGAL_precondition(region.size() >= 3); + std::tie(m_plane_of_best_fit, m_normal_of_best_fit) = + get_plane_and_normal(region); + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_plane_and_normal( + const Region& region) const { + + // The best fit plane will be a plane fitted to all region points with + // its normal being perpendicular to the plane. + CGAL_precondition(region.size() > 0); + const Plane_3 unoriented_plane_of_best_fit = + internal::create_plane( + region, m_point_map, m_traits).first; + const Vector_3 unoriented_normal_of_best_fit = + unoriented_plane_of_best_fit.orthogonal_vector(); + + // Flip the plane's normal to agree with all input normals. + long votes_to_keep_normal = 0; + for (Item item : region) { + const Vector_3& normal = get(m_normal_map, item); + const bool agrees = + m_scalar_product_3(normal, unoriented_normal_of_best_fit) > FT(0); + votes_to_keep_normal += (agrees ? 1 : -1); + } + const bool flip_normal = (votes_to_keep_normal < 0); + + const Plane_3 plane_of_best_fit = flip_normal + ? unoriented_plane_of_best_fit.opposite() + : unoriented_plane_of_best_fit; + const Vector_3 normal_of_best_fit = flip_normal + ? (-1 * unoriented_normal_of_best_fit) + : unoriented_normal_of_best_fit; + + return std::make_pair(plane_of_best_fit, normal_of_best_fit); + } + /// \endcond + + private: + const Point_map m_point_map; + const Normal_map m_normal_map; + const GeomTraits m_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + + const Squared_length_3 m_squared_length_3; + const Squared_distance_3 m_squared_distance_3; + const Scalar_product_3 m_scalar_product_3; + + Plane_3 m_plane_of_best_fit; + Vector_3 m_normal_of_best_fit; + }; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_plane_fit_region()`. + \relates Least_squares_plane_fit_region + */ +template +using Least_squares_plane_fit_region_for_point_set = + Least_squares_plane_fit_region::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_plane_fit_region + */ +template +Least_squares_plane_fit_region_for_point_set +make_least_squares_plane_fit_region(const PointSet3& ps, + const CGAL_NP_CLASS np = parameters::default_values()) +{ + return Least_squares_plane_fit_region_for_point_set + (np.point_map(ps.point_map()).normal_map(ps.normal_map())); +} + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h new file mode 100644 index 00000000000..209f2cf6186 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_plane_fit_sorting.h @@ -0,0 +1,234 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Sorting of 3D points with respect to the local plane fit quality. + + Indices of 3D input points are sorted with respect to the quality of the + least squares plane fit applied to the neighboring points of each point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_3` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename PointMap> + class Least_squares_plane_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Neighbor_query = NeighborQuery; + using Point_map = PointMap; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename Traits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 3D points + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access point's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_plane_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_neighbor_query(neighbor_query), + m_point_map(Point_set_processing_3_np_helper::get_const_point_map(input_range, np)), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) + { + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_ordered.resize(input_range.size()); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts `Items` of input points. + */ + void sort() { + compute_scores(); + CGAL_precondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + std::vector tmp(m_ordered.size()); + for (std::size_t i = 0; i < m_ordered.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input points. + */ + const Seed_range &ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Point_map m_point_map; + const Traits m_traits; + + Seed_range m_ordered; + std::vector m_scores; + + void compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + for (const Item& item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + + m_scores[idx++] = internal::create_plane( + neighbors, m_point_map, m_traits).second; + } + } + }; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_plane_fit_sorting()`. + \relates Least_squares_plane_fit_sorting + */ +template +using Least_squares_plane_fit_sorting_for_point_set = + Least_squares_plane_fit_sorting::Kernel, + typename PointSet3::Index, + NeighborQuery, + typename PointSet3::Point_map>; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_plane_fit_sorting + */ +template +Least_squares_plane_fit_sorting_for_point_set +make_least_squares_plane_fit_sorting(const PointSet3& ps, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS np = parameters::default_values()) +{ + return Least_squares_plane_fit_sorting_for_point_set + (ps, neighbor_query, np.point_map(ps.point_map())); +} + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_region.h new file mode 100644 index 00000000000..68285b5777b --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_region.h @@ -0,0 +1,402 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H + +#include + +// Internal includes. +#include + +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Region type based on the quality of the least squares sphere + fit applied to 3D points. + + This class fits a sphere to chunks of points in a 3D point set and + controls the quality of this fit. If all quality conditions are + satisfied, the chunk is accepted as a valid region, otherwise + rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_3` + + \tparam NormalMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Vector_3` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename PointMap, + typename NormalMap> + class Least_squares_sphere_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Point_map = PointMap; + using Normal_map = NormalMap; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = Item_; + using Region = std::vector; + + /// Primitive + using Primitive = typename GeomTraits::Sphere_3; + + /// Region map + using Region_unordered_map = std::unordered_map >; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point_3 = typename GeomTraits::Point_3; + using Vector_3 = typename GeomTraits::Vector_3; + using Sphere_3 = typename GeomTraits::Sphere_3; + + using Squared_distance_3 = typename GeomTraits::Compute_squared_distance_3; + using Get_sqrt = internal::Get_sqrt; + using Sqrt = typename Get_sqrt::Sqrt; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from a point to a sphere} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a point and the radius of a sphere} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of 3D points a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{3} + \cgalParamNEnd + \cgalParamNBegin{minimum_radius} + \cgalParamDescription{the radius below which an estimated sphere + is considered as invalid and discarded} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{0, no limit} + \cgalParamNEnd + \cgalParamNBegin{maximum_radius} + \cgalParamDescription{the radius above which an estimated sphere + is considered as invalid and discarded.} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{+infinity, no limit} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{normal_map} + \cgalParamDescription{an instance of `NormalMap` that maps an item to `Kernel::Vector_3`} + \cgalParamDefault{`NormalMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + \pre `minimum_radius >= 0` + \pre `maximum_radius >= minimum_radius` + */ + template + Least_squares_sphere_fit_region( + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_normal_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::normal_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_sqrt(Get_sqrt::sqrt_object(m_traits)), + m_squared_distance_3(m_traits.compute_squared_distance_3_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 3); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + + m_min_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_radius), FT(0)); + CGAL_precondition(m_min_radius >= FT(0)); + + m_max_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_radius), + FT((std::numeric_limits::max)())); + CGAL_precondition(m_max_radius >= m_min_radius); + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to std::size_t + */ + + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `fitted primitive via successful call of update(region) with a sufficient large region` + */ + + Primitive primitive() const { + return Sphere_3(m_center, m_radius * m_radius); + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if a point with the index `query_index` is within + the `maximum_distance` from the corresponding sphere and if the angle between + its normal and the sphere radius is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + item of the query point + + \param region + inlier items of the region + + The first parameter is not used in this implementation. + + \return Boolean `true` or `false` + */ + bool is_part_of_region( + const Item, + const Item query, + const Region& region) const { + + // First, we need to integrate at least 6 points so that the + // computed sphere means something. + if (region.size() < 6) { + return true; + } + + if (std::isnan(CGAL::to_double(m_radius))) { + return false; + } + + // If radius is out of bound, nothing fits, early ending. + if (m_radius <= m_min_radius || m_radius > m_max_radius) { + return false; + } + + const Point_3& query_point = get(m_point_map, query); + Vector_3 normal = get(m_normal_map, query); + + const FT sq_dist = m_squared_distance_3(query_point, m_center); + if (std::isnan(CGAL::to_double(sq_dist))) return false; + const FT distance_to_center = m_sqrt(sq_dist); + const FT distance_to_sphere = CGAL::abs(distance_to_center - m_radius); + + if (distance_to_sphere > m_distance_threshold) { + return false; + } + + const FT sq_norm = normal * normal; + if (std::isnan(CGAL::to_double(sq_norm))) return false; + normal = normal / m_sqrt(sq_norm); + + Vector_3 ray(m_center, query_point); + const FT sq_ray = ray * ray; + if (std::isnan(CGAL::to_double(sq_ray))) return false; + ray = ray / m_sqrt(sq_ray); + + if (CGAL::abs(normal * ray) < m_cos_value_threshold) { + return false; + } + return true; + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the estimated radius is between `minimum_radius` + and `maximum_radius` and if the `region` contains at least `min_region_size` points. + + \param region + indices of points included in the region + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return ( + (m_min_radius <= m_radius && m_radius <= m_max_radius) && + (region.size() >= m_min_region_size) + ); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares sphere to all points from the `region`. + + \param region + indices of points included in the region + + \return Boolean `true` if the sphere fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + // Fit a sphere. + CGAL_precondition(region.size() > 0); + FT radius; Point_3 center; + std::tie(radius, center) = internal::create_sphere( + region, m_point_map, m_traits, false).first; + if (radius > FT(0)) { + m_radius = radius; + m_center = center; + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_sphere( + const Region& region) const { + return internal::create_sphere( + region, m_point_map, m_traits, false).first; + } + /// \endcond + + private: + const Point_map m_point_map; + const Normal_map m_normal_map; + const GeomTraits m_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + FT m_min_radius; + FT m_max_radius; + + const Sqrt m_sqrt; + const Squared_distance_3 m_squared_distance_3; + + FT m_radius; + Point_3 m_center; + }; + + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_sphere_fit_region()`. + \relates Least_squares_sphere_fit_region + */ +template +using Least_squares_sphere_fit_region_for_point_set = + Least_squares_sphere_fit_region::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map, + typename PointSet3::Vector_map>; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_sphere_fit_region + */ +template +Least_squares_sphere_fit_region_for_point_set +make_least_squares_sphere_fit_region(const PointSet3& ps, + const CGAL_NP_CLASS np = parameters::default_values()) +{ + return Least_squares_sphere_fit_region_for_point_set + (np.point_map(ps.point_map()).normal_map(ps.normal_map())); +} + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h new file mode 100644 index 00000000000..774370e918e --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Least_squares_sphere_fit_sorting.h @@ -0,0 +1,244 @@ +// Copyright (c) 2021 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Simon Giraudot +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + + /*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Sorting of 3D points with respect to the local sphere fit quality. + + Indices of 3D input points are sorted with respect to the quality of the + least squares sphere fit applied to the neighboring points of each point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Point_3` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename PointMap> + class Least_squares_sphere_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Neighbor_query = NeighborQuery; + using Point_map = PointMap; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename Traits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 3D points + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access point's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_sphere_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_neighbor_query(neighbor_query), + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) { + + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_ordered.resize(input_range.size()); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts indices of input points. + */ + void sort() { + std::size_t seed_cutoff = compute_scores(); + CGAL_postcondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + order.resize(m_ordered.size() - seed_cutoff); + + std::vector tmp(order.size()); + for (std::size_t i = 0; i < order.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input points. + */ + const Seed_range &ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Point_map m_point_map; + const Traits m_traits; + Seed_range m_ordered; + std::vector m_scores; + + std::size_t compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + std::size_t seed_cutoff = 0; + for (const Item& item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + + m_scores[idx] = internal::create_sphere( + neighbors, m_point_map, m_traits, true).second; + + if (m_scores[idx] == -(std::numeric_limits::max)()) + seed_cutoff++; + + idx++; + } + + return seed_cutoff; + } + }; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_least_squares_sphere_fit_sorting()`. + \relates Least_squares_sphere_fit_sorting + */ +template +using Least_squares_sphere_fit_sorting_for_point_set = + Least_squares_sphere_fit_sorting::Kernel, + typename PointSet3::Index, + NeighborQuery, + typename PointSet3::Point_map>; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Least_squares_sphere_fit_sorting + */ +template +Least_squares_sphere_fit_sorting_for_point_set +make_least_squares_sphere_fit_sorting(const PointSet3& ps, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS np = parameters::default_values()) +{ + return Least_squares_sphere_fit_sorting_for_point_set + (ps, neighbor_query, np.point_map(ps.point_map())); +} + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h new file mode 100644 index 00000000000..e36658c45b5 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Point_set/Sphere_neighbor_query.h @@ -0,0 +1,243 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H + +#include + +// CGAL includes. +#include +#include +#include +#include +#include +#include + +// Internal includes. +#include + +namespace CGAL { +namespace Shape_detection { +namespace Point_set { + +/*! + \ingroup PkgShapeDetectionRGOnPoints + + \brief Fuzzy sphere neighbors search in a set of 2D or 3D points. + + This class returns all neighbors of a query point, which fall in a sphere of + the fixed radius centered at this point. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given point. Must be a model of `Hashable`. + + \tparam PointMap + a model of `ReadablePropertyMap` whose key type is `Item_` and value type is `GeomTraits::Point_2` or `GeomTraits::Point_3` + + \cgalModels `NeighborQuery` +*/ +template< +typename GeomTraits, +typename Item_, +typename PointMap> +class Sphere_neighbor_query { + +public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Traits = GeomTraits; + using Point_map = PointMap; + using Point_type = typename boost::property_traits::value_type; + + using Item = Item_; + using Region = std::vector; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// @} + +private: + using Search_base = typename std::conditional< + std::is_same::value, + CGAL::Search_traits_2, + CGAL::Search_traits_3 >::type; + + using Search_traits = + CGAL::Search_traits_adapter; + + using Splitter = + CGAL::Sliding_midpoint; + + using Fuzzy_sphere + = CGAL::Fuzzy_sphere; + + using Tree + = CGAL::Kd_tree; + +public: + /// \name Initialization + /// @{ + + /*! + \brief initializes a Kd-tree with input points. + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 2D or 3D points + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{sphere_radius} + \cgalParamDescription{the fixed radius of the fuzzy sphere used for + searching neighbors of a query point} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{point_map} + \cgalParamDescription{an instance of `PointMap` that maps an item from `input_range` + to `Kernel::Point_2` or to `Kernel::Point_3`} + \cgalParamDefault{`PointMap()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + \pre `sphere_radius > 0` + */ + template + Sphere_neighbor_query( + const InputRange& input_range, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_point_map(parameters::choose_parameter(parameters::get_parameter(np, internal_np::point_map))) + { + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_tree_ptr.reset( new Tree(make_transform_iterator_from_property_map(make_prevent_deref(input_range.begin()), item_map), + make_transform_iterator_from_property_map(make_prevent_deref(input_range.end()), item_map), + Splitter(), + Search_traits(m_point_map)) ); + + CGAL_precondition(input_range.size() > 0); + m_sphere_radius = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::sphere_radius), FT(1)); + CGAL_precondition(m_sphere_radius > FT(0)); + m_tree_ptr->build(); + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `NeighborQuery::operator()()`. + + This operator finds all points, which fall into a sphere + of the fixed radius `sphere_radius` centered at the query point. + The references of those neighbors are returned in `neighbors`. + + \param query + `Item` of the query point + + \param neighbors + `Items` of points, which are neighbors of the query point + + \pre `query` is a valid const_iterator of InputRange + */ + void operator()( + const Item query, + std::vector& neighbors) const { + + neighbors.clear(); + const Fuzzy_sphere sphere( + get(m_point_map, query), m_sphere_radius, FT(0), m_tree_ptr->traits()); + m_tree_ptr->search(std::back_inserter(neighbors), sphere); + } + + /// @} + + /// \cond SKIP_IN_MANUAL + void set_sphere_radius(const FT sphere_radius) { + m_sphere_radius = sphere_radius; + } + + void operator()( + const Point_type& sphere_center, + std::vector& neighbors) const { + + neighbors.clear(); + const Fuzzy_sphere sphere( + sphere_center, m_sphere_radius, FT(0), m_tree_ptr->traits()); + m_tree_ptr->search(std::back_inserter(neighbors), sphere); + } + /// \endcond + +private: + const Point_map m_point_map; + + FT m_sphere_radius; + std::shared_ptr m_tree_ptr; +}; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + shortcut to ease the definition of the class when using `CGAL::Point_set_3`. + To be used together with `make_sphere_neighbor_query()`. + \relates Sphere_neighbor_query + */ +template +using Sphere_neighbor_query_for_point_set = + Sphere_neighbor_query::Kernel, + typename PointSet3::Index, + typename PointSet3::Point_map>; + +/*! + \ingroup PkgShapeDetectionRGOnPointSet3 + returns an instance of the sorting class to be used with `CGAL::Point_set_3`, with point and normal maps added to `np`. + \relates Sphere_neighbor_query + */ +template +Sphere_neighbor_query_for_point_set +make_sphere_neighbor_query(const PointSet3& ps, CGAL_NP_CLASS np = parameters::default_values()) +{ + return Sphere_neighbor_query_for_point_set( + ps, np.point_map(ps.point_map())); +} + +} // namespace Point_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh.h new file mode 100644 index 00000000000..73443a13b8f --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh.h @@ -0,0 +1,33 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H + +/// \cond SKIP_IN_MANUAL +#include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection/Region_growing/Polygon_mesh.h +* A convenience header that includes all classes related to the region growing algorithm on a polygon mesh. +*/ + +#include +#include + +#include +#include + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_region.h new file mode 100644 index 00000000000..8a3e133c0b9 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_region.h @@ -0,0 +1,438 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Polygon_mesh { + + /*! + \ingroup PkgShapeDetectionRGOnMesh + + \brief Region type based on the quality of the least squares plane + fit applied to faces of a polygon mesh. + + This class fits a plane, using \ref PkgPrincipalComponentAnalysisDRef "PCA", + to chunks of faces in a polygon mesh and controls the quality of this fit. + If all quality conditions are satisfied, the chunk is accepted as a valid region, + otherwise rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam PolygonMesh + a model of `FaceListGraph` + + \tparam VertexToPointMap + a model of `ReadablePropertyMap` whose key type is the vertex type of a polygon mesh and + value type is `Kernel::Point_3` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename PolygonMesh, + typename VertexToPointMap = typename boost::property_map::const_type> + class Least_squares_plane_fit_region { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Face_graph = PolygonMesh; + using Vertex_to_point_map = VertexToPointMap; + + using face_descriptor = typename boost::graph_traits::face_descriptor; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = face_descriptor; + using Region = std::vector; + + /// Primitive + using Primitive = typename GeomTraits::Plane_3; + + /// Region map + using Region_index_map = typename boost::property_map >::const_type; + + /// @} + + private: + using Point_3 = typename GeomTraits::Point_3; + using Vector_3 = typename GeomTraits::Vector_3; + using Plane_3 = typename GeomTraits::Plane_3; + + using Squared_length_3 = typename GeomTraits::Compute_squared_length_3; + using Squared_distance_3 = typename GeomTraits::Compute_squared_distance_3; + using Scalar_product_3 = typename GeomTraits::Compute_scalar_product_3; + using Cross_product_3 = typename GeomTraits::Construct_cross_product_vector_3; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param pmesh + an instance of `PolygonMesh` that represents a polygon mesh + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from the furthest vertex of a face to a plane} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the normal of a face and the normal of a plane} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of faces a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{an instance of `VertexToPointMap` that maps a polygon mesh + vertex to `Kernel::Point_3`} + \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `faces(tmesh).size() > 0` + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + */ + template + Least_squares_plane_fit_region( + const PolygonMesh& pmesh, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_face_graph(pmesh), + m_vertex_to_point_map(parameters::choose_parameter(parameters::get_parameter( + np, internal_np::vertex_point), get_const_property_map(CGAL::vertex_point, pmesh))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_squared_length_3(m_traits.compute_squared_length_3_object()), + m_squared_distance_3(m_traits.compute_squared_distance_3_object()), + m_scalar_product_3(m_traits.compute_scalar_product_3_object()), + m_cross_product_3(m_traits.construct_cross_product_vector_3_object()) { + + CGAL_precondition(faces(m_face_graph).size() > 0); + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 1); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps each face to a std::size_t + */ + Region_index_map region_index_map() { + return get(CGAL::dynamic_face_property_t(), m_face_graph); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region. + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + + Primitive primitive() const { + return m_plane_of_best_fit; + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if the face `query` is within + the `maximum_distance` from the corresponding plane and if the angle between + its normal and the plane's normal is within the `maximum_angle`. If both conditions + are satisfied, it returns `true`, otherwise `false`. + + \param query + `Item` of the query face + + The first and third parameters are not used in this implementation. + + \return Boolean `true` or `false` + + \pre `query` is a valid const_iterator of `input_range` + */ + bool is_part_of_region( + const Item, + const Item query, + const Region&) const { + + const FT squared_distance_to_fitted_plane = get_max_squared_distance(query); + if (squared_distance_to_fitted_plane < FT(0)) return false; + const FT squared_distance_threshold = + m_distance_threshold * m_distance_threshold; + + const Vector_3 face_normal = get_face_normal(query); + const FT cos_value = m_scalar_product_3(face_normal, m_normal_of_best_fit); + const FT squared_cos_value = cos_value * cos_value; + + FT squared_cos_value_threshold = + m_cos_value_threshold * m_cos_value_threshold; + squared_cos_value_threshold *= m_squared_length_3(face_normal); + squared_cos_value_threshold *= m_squared_length_3(m_normal_of_best_fit); + + return ( + ( squared_distance_to_fitted_plane <= squared_distance_threshold ) && + ( squared_cos_value >= squared_cos_value_threshold )); + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the `region` contains at least `minimum_region_size` faces. + + \param region + Faces of the region represented as `Items`. + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return (region.size() >= m_min_region_size); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares plane to all vertices of the faces + from the `region`. + + \param region + Faces of the region represented as `Items`. + + \return Boolean `true` if the plane fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + + CGAL_precondition(region.size() > 0); + if (region.size() == 1) { // create new reference plane and normal + const Item face = region[0]; + + // The best fit plane will be a plane through this face centroid with + // its normal being the face's normal. + const Point_3 face_centroid = get_face_centroid(face); + const Vector_3 face_normal = get_face_normal(face); + if (face_normal == CGAL::NULL_VECTOR) return false; + + CGAL_precondition(face_normal != CGAL::NULL_VECTOR); + m_plane_of_best_fit = Plane_3(face_centroid, face_normal); + m_normal_of_best_fit = m_plane_of_best_fit.orthogonal_vector(); + + } else { // update reference plane and normal + CGAL_precondition(region.size() >= 2); + std::tie(m_plane_of_best_fit, m_normal_of_best_fit) = + get_plane_and_normal(region); + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_plane_and_normal( + const Region& region) const { + + // The best fit plane will be a plane fitted to all vertices of all + // region faces with its normal being perpendicular to the plane. + // Given that the points, and no normals, are used in estimating + // the plane, the estimated normal will point into an arbitray + // one of the two possible directions. + // We flip it into the correct direction (the one that the majority + // of faces agree with) below. + // This fix is proposed by nh2: + // https://github.com/CGAL/cgal/pull/4563 + const Plane_3 unoriented_plane_of_best_fit = + internal::create_plane_from_faces( + m_face_graph, region, m_vertex_to_point_map, m_traits).first; + const Vector_3 unoriented_normal_of_best_fit = + unoriented_plane_of_best_fit.orthogonal_vector(); + + // Compute actual direction of plane's normal sign + // based on faces, which belong to that region. + // Approach: each face gets one vote to keep or flip the current plane normal. + long votes_to_keep_normal = 0; + for (const auto &face : region) { + const Vector_3 face_normal = get_face_normal(face); + const bool agrees = + m_scalar_product_3(face_normal, unoriented_normal_of_best_fit) > FT(0); + votes_to_keep_normal += (agrees ? 1 : -1); + } + const bool flip_normal = (votes_to_keep_normal < 0); + + const Plane_3 plane_of_best_fit = flip_normal + ? unoriented_plane_of_best_fit.opposite() + : unoriented_plane_of_best_fit; + const Vector_3 normal_of_best_fit = flip_normal + ? (-1 * unoriented_normal_of_best_fit) + : unoriented_normal_of_best_fit; + + return std::make_pair(plane_of_best_fit, normal_of_best_fit); + } + /// \endcond + + private: + const Face_graph& m_face_graph; + const Vertex_to_point_map m_vertex_to_point_map; + const GeomTraits m_traits; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + + const Squared_length_3 m_squared_length_3; + const Squared_distance_3 m_squared_distance_3; + const Scalar_product_3 m_scalar_product_3; + const Cross_product_3 m_cross_product_3; + + Plane_3 m_plane_of_best_fit; + Vector_3 m_normal_of_best_fit; + + // Compute centroid of the face. + template + Point_3 get_face_centroid(const Face& face) const { + + const auto hedge = halfedge(face, m_face_graph); + const auto vertices = vertices_around_face(hedge, m_face_graph); + CGAL_precondition(vertices.size() > 0); + + FT sum = FT(0), x = FT(0), y = FT(0), z = FT(0); + for (const auto vertex : vertices) { + const Point_3& point = get(m_vertex_to_point_map, vertex); + x += point.x(); + y += point.y(); + z += point.z(); + sum += FT(1); + } + CGAL_precondition(sum > FT(0)); + x /= sum; + y /= sum; + z /= sum; + return Point_3(x, y, z); + } + + // Compute normal of the face. + template + Vector_3 get_face_normal(const Face& face) const { + + const auto hedge = halfedge(face, m_face_graph); + const auto vertices = vertices_around_face(hedge, m_face_graph); + CGAL_precondition(vertices.size() >= 3); + + auto vertex = vertices.begin(); + const Point_3& point1 = get(m_vertex_to_point_map, *vertex); ++vertex; + const Point_3& point2 = get(m_vertex_to_point_map, *vertex); ++vertex; + const Point_3& point3 = get(m_vertex_to_point_map, *vertex); + + const Vector_3 u = point2 - point1; + const Vector_3 v = point3 - point1; + const Vector_3 face_normal = m_cross_product_3(u, v); + return face_normal; + } + + // The maximum squared distance from the vertices of the face + // to the best fit plane. + template + FT get_max_squared_distance(const Face& face) const { + + FT max_squared_distance = -FT(1); + const FT a = CGAL::abs(m_plane_of_best_fit.a()); + const FT b = CGAL::abs(m_plane_of_best_fit.b()); + const FT c = CGAL::abs(m_plane_of_best_fit.c()); + const FT d = CGAL::abs(m_plane_of_best_fit.d()); + if (a == FT(0) && b == FT(0) && c == FT(0) && d == FT(0)) + return max_squared_distance; + + const auto hedge = halfedge(face, m_face_graph); + const auto vertices = vertices_around_face(hedge, m_face_graph); + CGAL_precondition(vertices.size() > 0); + + for (const auto vertex : vertices) { + const Point_3& point = get(m_vertex_to_point_map, vertex); + const FT squared_distance = m_squared_distance_3(point, m_plane_of_best_fit); + max_squared_distance = (CGAL::max)(squared_distance, max_squared_distance); + } + CGAL_precondition(max_squared_distance >= FT(0)); + return max_squared_distance; + } + }; + +} // namespace Polygon_mesh +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_sorting.h new file mode 100644 index 00000000000..84e0891e0f9 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Least_squares_plane_fit_sorting.h @@ -0,0 +1,196 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Polygon_mesh { + + /*! + \ingroup PkgShapeDetectionRGOnMesh + + \brief Sorting of polygon mesh faces with respect to the local plane fit quality. + + `Items` of faces in a polygon mesh are sorted with respect to the quality of the + least squares plane fit applied to the vertices of incident faces of each face. + + \tparam GeomTraits + a model of `Kernel` + + \tparam PolygonMesh + a model of `FaceListGraph` + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam VertexToPointMap + a model of `ReadablePropertyMap` whose key type is the vertex type of a polygon mesh and + value type is `Kernel::Point_3` + */ + template< + typename GeomTraits, + typename PolygonMesh, + typename NeighborQuery, + typename VertexToPointMap = typename boost::property_map::const_type> + class Least_squares_plane_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Face_graph = PolygonMesh; + using Neighbor_query = NeighborQuery; + using Vertex_to_point_map = VertexToPointMap; + /// \endcond + + /// Item type. + using Item = typename boost::graph_traits::face_descriptor; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename GeomTraits::FT; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param pmesh + an instance of `PolygonMesh` that represents a polygon mesh + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access face's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{an instance of `VertexToPointMap` that maps a polygon mesh + vertex to `Kernel::Point_3`} + \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `faces(pmesh).size() > 0` + */ + template + Least_squares_plane_fit_sorting( + const PolygonMesh& pmesh, + NeighborQuery& neighbor_query, + const CGAL_NP_CLASS& np = parameters::default_values()) : + m_face_graph(pmesh), + m_neighbor_query(neighbor_query), + m_vertex_to_point_map(parameters::choose_parameter(parameters::get_parameter( + np, internal_np::vertex_point), get_const_property_map(CGAL::vertex_point, pmesh))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) { + + CGAL_precondition(faces(pmesh).size() > 0); + + m_ordered.resize(faces(pmesh).size()); + + std::size_t index = 0; + for (Item item : faces(pmesh)) + m_ordered[index++] = item; + m_scores.resize(m_ordered.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts `Items` of input faces. + */ + void sort() { + compute_scores(); + CGAL_precondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + std::vector tmp(m_ordered.size()); + for (std::size_t i = 0; i < m_ordered.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input faces. + */ + const Seed_range &ordered() { + return m_ordered; + } + /// @} + + private: + const Face_graph& m_face_graph; + Neighbor_query& m_neighbor_query; + const Vertex_to_point_map m_vertex_to_point_map; + const GeomTraits m_traits; + Seed_range m_ordered; + std::vector m_scores; + + void compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + for (Item item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + m_scores[idx++] = internal::create_plane_from_faces( + m_face_graph, neighbors, m_vertex_to_point_map, m_traits).second; + } + } + }; + +} // namespace Polygon_mesh +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/One_ring_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/One_ring_neighbor_query.h new file mode 100644 index 00000000000..635d23d5fec --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/One_ring_neighbor_query.h @@ -0,0 +1,114 @@ +// Copyright (c) 2018 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H + +#include + +// Internal includes. +#include + +namespace CGAL { +namespace Shape_detection { +namespace Polygon_mesh { + + /*! + \ingroup PkgShapeDetectionRGOnMesh + + \brief Edge-adjacent faces connectivity in a polygon mesh. + + This class returns all faces, which are edge-adjacent to a query face in a + polygon mesh being a `PolygonMesh`. + + \tparam PolygonMesh + a model of `FaceListGraph` + + \tparam FaceRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` and + value type is the face type of a polygon mesh + + \cgalModels `NeighborQuery` + */ + template + class One_ring_neighbor_query + { + using face_descriptor = typename boost::graph_traits::face_descriptor; + using Face_graph = PolygonMesh; + public: + /// Item type. + using Item = typename boost::graph_traits::face_descriptor; + using Region = std::vector; + + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \param pmesh + an instance of a `PolygonMesh` that represents a polygon mesh + + \pre `faces(pmesh).size() > 0` + */ + One_ring_neighbor_query(const PolygonMesh& pmesh) + : m_face_graph(pmesh) + {} + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `NeighborQuery::operator()()`. + + This operator retrieves all faces, + which are edge-adjacent to the face `query`. + These `Items` are returned in `neighbors`. + + \param query + `Item` of the query face + + \param neighbors + `Items` of faces, which are neighbors of the query face + + \pre `query_index < faces(pmesh).size()` + */ + void operator()( + const Item query, + std::vector& neighbors) const { + + neighbors.clear(); + const auto query_hedge = halfedge(query, m_face_graph); + + for (face_descriptor face : faces_around_face(query_hedge, m_face_graph)) + { + if (face != boost::graph_traits::null_face()) + { + neighbors.push_back(face); + } + } + } + + /// @} + + private: + const Face_graph& m_face_graph; + }; + +} // namespace Polygon_mesh +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Polyline_graph.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Polyline_graph.h new file mode 100644 index 00000000000..3c4fb0e823c --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Polygon_mesh/Polyline_graph.h @@ -0,0 +1,341 @@ +// Copyright (c) 2020 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_POLYLINE_GRAPH_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_POLYLINE_GRAPH_H + +#include + +// Internal includes. +#include + +namespace CGAL { +namespace Shape_detection { +namespace Polygon_mesh { + + /*! + \ingroup PkgShapeDetectionRGOnMesh + + \brief Polygon mesh edges connected into a graph. + + This class returns all edges, which form polylines splitting the polygon mesh + being a `PolygonMesh` into planar regions. + + \tparam PolygonMesh + a model of `FaceListGraph` + + \tparam VertexPointMap + a model of `ReadablePropertyMap` whose key type is the vertex type of a polygon mesh and + value type is `Point_3` from a \cgal %Kernel + + \cgalModels `NeighborQuery` + */ + template< + typename PolygonMesh, + typename VertexPointMap = typename boost::property_map::const_type + > + class Polyline_graph { + + using face_descriptor = typename boost::graph_traits::face_descriptor; + using edge_descriptor = typename boost::graph_traits::edge_descriptor; + using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + + private: + + struct PEdge { + std::size_t index = std::size_t(-1); + edge_descriptor ed; + std::vector neighbors; + std::pair regions; + }; + + using EdgeIndexMap = typename boost::property_map >::const_type; + + public: + /// \name Types + /// @{ + + /// Item type. + using Item = typename boost::graph_traits::edge_descriptor; + + #ifdef DOXYGEN_RUNNING + /*! + a model of `ConstRange` whose iterator type is `RandomAccessIterator` and + value type is `edge_descriptor` of the `PolygonMesh`. + */ + typedef unspecified_type Segment_range; + + /*! + a model of `ReadablePropertyMap` whose key type is the value type of `Segment_range` + and value type is `Kernel::Segment_3`. + */ + typedef unspecified_type Segment_map; + #else + /// Segment_range type. + using Segment_range = std::vector; + + using Segment_map = Segment_from_edge_descriptor_map; + #endif + + /// @} + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + \tparam FaceToRegionMap + a model of `ReadablePropertyMap` whose key type is `face_descriptor` of the `PolygonMesh` + and value type is `std::size_t` + + \tparam NamedParameters + a sequence of optional \ref bgl_namedparameters "Named Parameters" + + \param pmesh a polygon mesh + + \param face_to_region_map maps each face of `pmesh` to + a corresponding planar region id + + \param np a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{an instance of `VertexPointMap` that maps a polygon mesh + vertex to `Kernel::Point_3`} + \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `faces(pmesh).size() > 0` + \pre `edges(pmesh).size() > 0` + */ + template + Polyline_graph( + const PolygonMesh& pmesh, + FaceToRegionMap face_to_region_map, + const CGAL_NP_CLASS& np = parameters::default_values()) + : Polyline_graph(pmesh, edges(pmesh), face_to_region_map, np) + {} + + /*! + \brief initializes all internal data structures. + \tparam FaceToRegionMap + a model of `ReadablePropertyMap` whose key type is `face_descriptor` of the `PolygonMesh` + and value type is `std::size_t` + + \tparam EdgeRange a model of `ConstRange` with `edge_descriptor` as iterator value type. + + \tparam NamedParameters + a sequence of optional \ref bgl_namedparameters "Named Parameters" + + \param pmesh a polygon mesh + + \param edge_range contains all edges in `pmesh` to be considered in the graph + + \param face_to_region_map maps each face of `pmesh` to + a corresponding planar region id + + \param np a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \cgalNamedParamsBegin + \cgalParamNBegin{vertex_point_map} + \cgalParamDescription{an instance of `VertexPointMap` that maps a polygon mesh + vertex to `Kernel::Point_3`} + \cgalParamDefault{`boost::get(CGAL::vertex_point, pmesh)`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `faces(pmesh).size() > 0` + \pre `edges(pmesh).size() > 0` + */ + template + Polyline_graph( + const PolygonMesh& pmesh, + const EdgeRange& edge_range, + FaceToRegionMap face_to_region_map, + const NamedParameters& np = parameters::default_values()) + : m_vpm(parameters::choose_parameter(parameters::get_parameter( + np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, pmesh))), + m_segment_map(&pmesh, m_vpm) + { + clear(); + + m_eimap = get(CGAL::dynamic_edge_property_t(), pmesh); + + // init map + for(edge_descriptor e : edges(pmesh)) + put(m_eimap, e, std::size_t(-1)); + + // collect edges either on the boundary or having two different incident regions + for (auto edge = edge_range.begin(); edge != edge_range.end(); edge++) { + halfedge_descriptor h1 = halfedge(*edge, pmesh), + h2 = opposite(h1, pmesh); + + face_descriptor f1 = face(h1, pmesh), + f2 = face(h2, pmesh); + + std::size_t r1 = -1, r2 = -1; + + if (f1 != boost::graph_traits::null_face()) + r1 = get(face_to_region_map, f1); + if (f2 != boost::graph_traits::null_face()) + r2 = get(face_to_region_map, f2); + + if (r1 != r2) { + m_segments.push_back(*edge); + add_graph_edge(m_segments.begin() + (m_segments.size() - 1), r1, r2); + } + } + + // build adjacency between edges + typedef typename boost::property_map >::const_type VisitedVertexMap; + VisitedVertexMap visited_vertices = get(CGAL::dynamic_vertex_property_t(), pmesh); + for (std::size_t i = 0; i < m_pedges.size(); ++i) + { + put(visited_vertices, source(m_pedges[i].ed, pmesh), false); + put(visited_vertices, target(m_pedges[i].ed, pmesh), false); + } + + for (std::size_t i = 0; i < m_pedges.size(); ++i) + { + auto& pedge = m_pedges[i]; + CGAL_precondition(pedge.regions.first != pedge.regions.second); + CGAL_precondition(pedge.index != std::size_t(-1)); + + std::array vrts = { source(pedge.ed, pmesh), target(pedge.ed, pmesh) }; + + for (int k = 0; k < 2; ++k) + { + if (!get(visited_vertices, vrts[k])) + { + add_vertex_neighbors(vrts[k], pmesh); + put(visited_vertices, vrts[k], true); + } + } + } + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `NeighborQuery::operator()()`. + + This operator retrieves all edges from `segment_range()`, + which are neighbors of the edge `query`. + The `Items` are returned in `neighbors`. + + \param query + Iterator of EdgeRange of the query edge + + \param neighbors + Iterators of Segment_range of edges, which are adjacent to the query edge + + \pre `query` is a valid element of the input edge_range + */ + template + void operator()( + const I query, + std::vector& neighbors) const + { + neighbors.clear(); + const auto& pedge = m_pedges[get(m_eimap, query)]; + neighbors.resize(pedge.neighbors.size()); + for (std::size_t i = 0; i < pedge.neighbors.size(); i++) + neighbors[i] = m_pedges[pedge.neighbors[i]].ed; + } + + /*! + \brief returns an instance of `Segment_range` to access edges, which + form polylines + */ + const Segment_range &segment_range() const { + return m_segments; + } + + /*! + \brief returns an instance of `Segment_map` that maps an edge from `segment_range()` + to `Kernel::Segment_3`. + */ + const Segment_map& segment_map() const { + return m_segment_map; + } + /// @} + + /// \cond SKIP_IN_MANUAL + void clear() { + m_pedges.clear(); + } + + void release_memory() { + m_pedges.shrink_to_fit(); + } + /// \endcond + + private: + const VertexPointMap m_vpm; + EdgeIndexMap m_eimap; + + const Segment_map m_segment_map; + std::vector m_pedges; + Segment_range m_segments; + + void add_graph_edge( + typename Segment_range::const_iterator edge, const std::size_t region1, const std::size_t region2) + { + PEdge pedge; + CGAL_precondition(region1 != region2); + const std::size_t ei = m_pedges.size(); + put(m_eimap, *edge, ei); + + pedge.index = ei; + pedge.ed = *edge; + pedge.regions = {region1, region2}; + m_pedges.push_back(pedge); + } + + void add_vertex_neighbors( + const vertex_descriptor vertex, + const PolygonMesh& pmesh) + { + std::vector nei; + for (const auto& hedge : halfedges_around_target(vertex, pmesh)) + { + const auto e = edge(hedge, pmesh); + const std::size_t ei = get(m_eimap, e); + if (ei == std::size_t(-1)) continue; + if (nei.size()==2) return; + nei.push_back(ei); + } + if (nei.size()==2) + { + m_pedges[nei[0]].neighbors.push_back(nei[1]); + m_pedges[nei[1]].neighbors.push_back(nei[0]); + } + } + }; + +} // namespace Polygon_mesh +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_POLYLINE_GRAPH_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h index 573ad603c42..6b261f5769c 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing.h @@ -19,14 +19,32 @@ // STL includes. #include #include +#include // CGAL includes. #include +#include #include +#include +#include +#include namespace CGAL { namespace Shape_detection { +namespace internal { + template ::value> + struct RM_creator{ + static RegionMap create(RegionType) { return RegionMap(); } + }; + + template + struct RM_creator{ + static RegionMap create(RegionType& r ) { return r.region_index_map(); } + }; +} + /*! \ingroup PkgShapeDetectionRG @@ -36,47 +54,117 @@ namespace Shape_detection { of user-defined items - given a way to access neighbors of each item via the `NeighborQuery` parameter class and - control if items form a valid region type via the `RegionType` parameter class, - - the `SeedMap` property map enables to define the seeding order of items and skip unnecessary items. - - \tparam InputRange - must be a model of `ConstRange`. + - optional `SeedRange` defining the seeding order of items and skipping unnecessary items. \tparam NeighborQuery - must be a model of `NeighborQuery`. + a model of `NeighborQuery` \tparam RegionType - must be a model of `RegionType`. + a model of `RegionType` - \tparam SeedMap - must be an `LvaluePropertyMap` whose key and value types are `std::size_t`. - %Default is `CGAL::Identity_property_map`. + \tparam RegionMap a model of `ReadWritePropertyMap` whose key type is `Item` + and value type is `std::size_t`. */ template< - typename InputRange, - typename NeighborQuery, - typename RegionType, - typename SeedMap = CGAL::Identity_property_map > + typename NeighborQuery, + typename RegionType, + typename RegionMap = typename RegionType::Region_index_map> class Region_growing { public: - + /// \name Types /// \cond SKIP_IN_MANUAL - using Input_range = InputRange; using Neighbor_query = NeighborQuery; using Region_type = RegionType; - using Seed_map = SeedMap; - - using Visited_items = std::vector; - using Running_queue = std::queue; - using Indices = std::vector; /// \endcond - /// \name Initialization + /// Item type. + using Item = typename RegionType::Item; + using Region = std::vector; + + /// Primitive and region type + using Primitive_and_region = std::pair; + + /// Item to region property map. + using Region_map = RegionMap; + + private: + using Running_queue = std::queue; + + public: + /// \name Initialization (RegionMap is the default type) /// @{ /*! \brief initializes the region growing algorithm. + \tparam InputRange + a model of `ConstRange` + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + + \param input_range + a range of input items for region growing. + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access item's neighbors + + \param region_type + an instance of `RegionType` that is used internally to + control if items form a valid region type + + \param item_map + an instance of the property map to retrieve items from input values + + \pre `input_range.size() > 0` + */ + template + Region_growing( + const InputRange& input_range, + NeighborQuery& neighbor_query, + RegionType& region_type, + ItemMap item_map = ItemMap() +#ifndef DOXYGEN_RUNNING + , std::enable_if_t::value>* = 0 +#endif + ) : + m_neighbor_query(neighbor_query), + m_region_type(region_type), + m_region_map(internal::RM_creator::create(region_type)), + m_visited(m_visited_map) + { + CGAL_precondition(input_range.size() > 0); + m_seed_range.resize(input_range.size()); + + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + + std::size_t idx = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_seed_range[idx++] = get(item_map_, it); + + clear(input_range, item_map_); + } + + /*! + \brief initializes the region growing algorithm. + + \tparam InputRange + a model of `ConstRange` + + \tparam SeedRange + a model of `ConstRange` with `Item` as value type + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + \param input_range a range of input items for region growing @@ -88,25 +176,167 @@ namespace Shape_detection { an instance of `RegionType` that is used internally to control if items form a valid region type - \param seed_map - an instance of `SeedMap` property map that is used internally to - set the order of items in the region growing processing queue. If it maps - to `std::size_t(-1)`, the corresponding item is skipped. + \param seed_range + a vector of `Item` that is used as seeds for the region growing. + Defaults to the full input_range. + + \param item_map + an instance of the property map to retrieve items from input values \pre `input_range.size() > 0` */ + template + Region_growing( + const InputRange& input_range, + SeedRange& seed_range, + NeighborQuery& neighbor_query, + RegionType& region_type, + ItemMap item_map = ItemMap() +#ifndef DOXYGEN_RUNNING + , std::enable_if_t::value>* = 0 +#endif + ) : + m_neighbor_query(neighbor_query), + m_region_type(region_type), + m_region_map(internal::RM_creator::create(region_type)), + m_visited(m_visited_map) { + + CGAL_precondition(input_range.size() > 0); + CGAL_precondition(seed_range.size() > 0); + m_seed_range.resize(seed_range.size()); + + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + + std::size_t idx = 0; + for (auto it = seed_range.begin(); it != seed_range.end(); it++) + m_seed_range[idx++] = *it; + + clear(input_range, item_map_); + } + /// @} + + /// \name Initialization (RegionMap is a user provided type) + /// @{ + + /*! + \brief initializes the region growing algorithm. + + \tparam InputRange + a model of `ConstRange` + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + + \param input_range + a range of input items for region growing. + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access item's neighbors + + \param region_type + an instance of `RegionType` that is used internally to + control if items form a valid region type + + \param item_map + an instance of the property map to retrieve items from input values + + \param rm external property map that will be filled when calling `detect()` + + \pre `input_range.size() > 0` + */ + template Region_growing( const InputRange& input_range, NeighborQuery& neighbor_query, RegionType& region_type, - const SeedMap seed_map = SeedMap()) : - m_input_range(input_range), - m_neighbor_query(neighbor_query), - m_region_type(region_type), - m_seed_map(seed_map) { + Region_map rm, + ItemMap item_map = ItemMap()) : + m_neighbor_query(neighbor_query), + m_region_type(region_type), + m_region_map(rm), + m_visited(m_visited_map) + { + CGAL_precondition(input_range.size() > 0); + m_seed_range.resize(input_range.size()); + + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + + std::size_t idx = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_seed_range[idx++] = get(item_map_, it); + + clear(input_range, item_map_); + } + + /*! + \brief initializes the region growing algorithm. + + \tparam InputRange + a model of `ConstRange` + + \tparam SeedRange + a model of `ConstRange` with `Item` as value type + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + + \param input_range + a range of input items for region growing + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access item's neighbors + + \param region_type + an instance of `RegionType` that is used internally to + control if items form a valid region type + + \param seed_range + a vector of `Item` that is used as seeds for the region growing. + Defaults to the full input_range. + + \param item_map + an instance of the property map to retrieve items from input values + + \param rm external property map that will be filled when calling `detect()` + + \pre `input_range.size() > 0` + */ + template + Region_growing( + const InputRange& input_range, + SeedRange& seed_range, + NeighborQuery& neighbor_query, + RegionType& region_type, + Region_map rm, + ItemMap item_map = ItemMap()) : + m_neighbor_query(neighbor_query), + m_region_type(region_type), + m_region_map(rm), + m_visited(m_visited_map) { CGAL_precondition(input_range.size() > 0); - clear(); + CGAL_precondition(seed_range.size() > 0); + m_seed_range.resize(seed_range.size()); + + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); + + std::size_t idx = 0; + for (auto it = seed_range.begin(); it != seed_range.end(); it++) + m_seed_range[idx++] = *it; + + clear(input_range, item_map_); } /// @} @@ -116,46 +346,54 @@ namespace Shape_detection { /*! \brief runs the region growing algorithm and fills an output iterator - with the found regions. + with the fitted primitive and their region. - \tparam OutputIterator - must be an output iterator whose value type is `std::vector`. + \tparam PrimitiveAndRegionOutputIterator + a model of `OutputIterator` whose value type is `Primitive_and_region` - \param regions - an output iterator that stores regions, where each region is returned - as a vector of indices of the items, which belong to this region + \param region_out + an output iterator of type `PrimitiveAndRegionOutputIterator`. \return past-the-end position in the output sequence */ - template - OutputIterator detect(OutputIterator regions) { + template + PrimitiveAndRegionOutputIterator detect(PrimitiveAndRegionOutputIterator region_out = PrimitiveAndRegionOutputIterator()) { +// clear(); TODO: this is not valid to comment this clear() + m_visited_map.clear(); // tmp replacement for the line above + + Region region; + m_nb_regions = 0; - clear(); - Indices region; // Grow regions. - for (std::size_t i = 0; i < m_input_range.size(); ++i) { - const std::size_t seed_index = get(m_seed_map, i); - - // Skip items that user does not want to use. - if (seed_index == std::size_t(-1)) - continue; - - CGAL_precondition( - seed_index < m_input_range.size()); + for (auto it = m_seed_range.begin(); it != m_seed_range.end(); it++) { + const Item seed = *it; // Try to grow a new region from the index of the seed item. - if (!m_visited[seed_index]) { - propagate(seed_index, region); + if (!get(m_visited, seed)) { + const bool is_success = propagate(seed, region); // Check global conditions. - if (!m_region_type.is_valid_region(region)) + if (!is_success || !m_region_type.is_valid_region(region)) { revert(region); - else - *(regions++) = region; + } else { + *(region_out++) = std::pair(m_region_type.primitive(), region); + fill_region_map(m_nb_regions++, region); + } } } - return regions; + + return region_out; + } + + /*! + \brief provides a property map that provides the region index (or std::size_t(-1)) for each input element. + + \return Property map that maps each iterator of the input range to a region index. + */ + + const Region_map ®ion_map() { + return m_region_map; } /// @} @@ -164,33 +402,41 @@ namespace Shape_detection { /// @{ /*! - \brief fills an output iterator with indices of all unassigned items. + \brief fills an output iterator with all unassigned items. - \tparam OutputIterator - must be an output iterator whose value type is `std::size_t`. + \tparam ItemOutputIterator + a model of `OutputIterator` whose value type is `Item` + + \tparam InputRange + a model of `ConstRange + + \tparam ItemMap + a model of `ReadablePropertyMap` with `InputRange::const_iterator` as key type and `Item` as value type. + A default can be deduced using the value type of `InputRange` and `Item` to be + either `CGAL::Dereference_property_map` or `CGAL::Identity_property_map`. + + \param input_range + a range of input items for region growing \param output - an output iterator that stores indices of all items, which are not assigned - to any region + an iterator of type `PrimitiveAndRegionOutputIterator`. + + \param item_map + an instance of the property map to retrieve items from input values \return past-the-end position in the output sequence */ - template - OutputIterator unassigned_items(OutputIterator output) const { + template + ItemOutputIterator unassigned_items(const InputRange& input_range, ItemOutputIterator output, ItemMap item_map = ItemMap()) const + { + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); - // Return indices of all unassigned items. - for (std::size_t i = 0; i < m_input_range.size(); ++i) { - const std::size_t seed_index = get(m_seed_map, i); - - // Skip items that user does not want to use. - if (seed_index == std::size_t(-1)) - continue; - - CGAL_precondition( - seed_index < m_input_range.size()); - - if (!m_visited[seed_index]) - *(output++) = seed_index; + for (auto it = input_range.begin(); it != input_range.end(); it++) { + Item i = get(item_map_,it); + if (!get(m_visited, i)) + *(output++) = i; } return output; } @@ -198,22 +444,46 @@ namespace Shape_detection { /// @} /// \cond SKIP_IN_MANUAL - void clear() { + template + void clear(const InputRange& input_range, ItemMap item_map = ItemMap()) { + using Item_helper = internal::Item_map_helper; + using Item_map = typename Item_helper::type; + Item_map item_map_ = Item_helper::get(item_map); - m_visited.clear(); - m_visited.resize(m_input_range.size(), false); + m_nb_regions = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) { + Item item = get(item_map_, it); + put(m_region_map, item, std::size_t(-1)); + } + // TODO if we want to allow subranges while NeighborQuery operates on the full range + // (like for faces in a PolygonMesh) we should fill a non-visited map rather than a visited map + m_visited_map.clear(); } - void release_memory() { - - m_visited.clear(); - m_visited.shrink_to_fit(); + std::size_t number_of_regions_detected() const + { + return m_nb_regions; } /// \endcond private: + Neighbor_query& m_neighbor_query; + Region_type& m_region_type; + Region_map m_region_map; + std::vector m_seed_range; + std::size_t m_nb_regions = 0; - void propagate(const std::size_t seed_index, Indices& region) { + using VisitedMap = std::unordered_set >; + VisitedMap m_visited_map; + Boolean_property_map m_visited; + + void fill_region_map(std::size_t idx, const Region& region) { + for (auto item : region) { + put(m_region_map, item, idx); + } + } + + bool propagate(const Item &seed, Region& region) { region.clear(); // Use two queues, while running on this queue, push to the other queue; @@ -223,67 +493,109 @@ namespace Shape_detection { bool depth_index = 0; // Once the index of an item is pushed to the queue, it is pushed to the region too. - m_visited[seed_index] = true; - running_queue[depth_index].push(seed_index); - region.push_back(seed_index); + put(m_visited, seed, true); + running_queue[depth_index].push(seed); + region.push_back(seed); // Update internal properties of the region. - m_region_type.update(region); + const bool is_well_created = m_region_type.update(region); + if (!is_well_created) return false; - Indices neighbors; - while ( - !running_queue[depth_index].empty() || - !running_queue[!depth_index].empty()) { + bool grown = true; + std::vector > rejected, rejected_swap; + while (grown) { + grown = false; - // Call the next item index of the queue and remove it from the queue. - const std::size_t item_index = running_queue[depth_index].front(); - running_queue[depth_index].pop(); + Region neighbors; + while ( + !running_queue[depth_index].empty() || + !running_queue[!depth_index].empty()) { - // Get neighbors of the current item. - neighbors.clear(); - m_neighbor_query(item_index, neighbors); + while (!running_queue[depth_index].empty()) { - // Visit all found neighbors. - for (const std::size_t neighbor_index : neighbors) { + // Call the next item index of the queue and remove it from the queue. + const Item item = running_queue[depth_index].front(); + running_queue[depth_index].pop(); - // Skip items that user does not want to use. - if (neighbor_index == std::size_t(-1)) - continue; + // Get neighbors of the current item. + neighbors.clear(); + m_neighbor_query(item, neighbors); - CGAL_precondition( - neighbor_index < m_input_range.size()); + // Visit all found neighbors. + for (Item neighbor : neighbors) { - if (!m_visited[neighbor_index] && - m_region_type.is_part_of_region(item_index, neighbor_index, region)) { + if (!get(m_visited, neighbor)) { + if (m_region_type.is_part_of_region(item, neighbor, region)) { - // Add this neighbor to the other queue so that we can visit it later. - m_visited[neighbor_index] = true; - running_queue[!depth_index].push(neighbor_index); - region.push_back(neighbor_index); + // Add this neighbor to the other queue so that we can visit it later. + put(m_visited, neighbor, true); + running_queue[!depth_index].push(neighbor); + region.push_back(neighbor); + grown = true; + } + else { + // Add this neighbor to the rejected queue so I won't be checked again before refitting the primitive. + put(m_visited, neighbor, true); + rejected.push_back(std::pair(item, neighbor)); + } + } + } } + depth_index = !depth_index; } // Update internal properties of the region. - if (running_queue[depth_index].empty()) { - + // The region expanded with the current primitive to its largest extent. + // After refitting the growing may continue, but it is only continued if the refitted primitive still fits all elements of the region. + if (grown) { m_region_type.update(region); - depth_index = !depth_index; + + // Verify that associated elements are still within the tolerance. + bool fits = true; + Item former = region.front(); + for (Item item : region) { + if (!m_region_type.is_part_of_region(former, item, region)) { + fits = false; + break; + } + former = item; + } + + // The refitted primitive does not fit all elements of the region, so the growing stops here. + if (!fits) { + // Reset visited flags for items that were rejected + for (const std::pair& p : rejected) + put(m_visited, p.second, false); + return true; + } + + // Try to continue growing the region by considering formerly rejected elements. + for (const std::pair& p : rejected) { + if (m_region_type.is_part_of_region(p.first, p.second, region)) { + + // Add this neighbor to the other queue so that we can visit it later. + put(m_visited, p.second, true); + running_queue[depth_index].push(p.second); + region.push_back(p.second); + } + else rejected_swap.push_back(p); + } + rejected.clear(); + rejected.swap(rejected_swap); } } + + // Reset visited flags for items that were rejected + for (const std::pair& p : rejected) + put(m_visited, p.second, false); + + return true; } - void revert(const Indices& region) { - for (const std::size_t item_index : region) - m_visited[item_index] = false; + void revert(const Region& region) { + for (Item item : region) + put(m_visited, item, false); } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - Region_type& m_region_type; - const Seed_map m_seed_map; - - Visited_items m_visited; }; } // namespace Shape_detection diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set.h deleted file mode 100644 index 3778f8c7164..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H - -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h deleted file mode 100644 index 05789fc4330..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H - -#include - -// STL includes. -#include -#include - -// Boost includes. -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief K nearest neighbors search in a set of `Kernel::Point_2` or - `Kernel::Point_3`. - - This class returns the K nearest neighbors of a query point in a point set. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_2` or `Kernel::Point_3`. - - \cgalModels `NeighborQuery` - */ - template< - typename GeomTraits, - typename InputRange, - typename PointMap> - class K_neighbor_query { - - public: - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - - using Point = typename Point_map::value_type; - - using Index_to_point_map = - internal::Item_property_map; - - using Search_base = typename std::conditional< - std::is_same::value, - CGAL::Search_traits_2, - CGAL::Search_traits_3 >::type; - - using Search_traits = - CGAL::Search_traits_adapter; - - using Distance = - CGAL::Distance_adapter< - std::size_t, - Index_to_point_map, - CGAL::Euclidean_distance >; - - using Splitter = - CGAL::Sliding_midpoint; - - using Search_tree = - CGAL::Kd_tree; - - using Neighbor_search = - CGAL::Orthogonal_k_neighbor_search< - Search_traits, - Distance, - Splitter, - Search_tree>; - - using Tree = - typename Neighbor_search::Tree; - /// \endcond - - /// \name Initialization - /// @{ - - /*! - \brief initializes a Kd-tree with input points. - - \param input_range - an instance of `InputRange` with 2D or 3D points - - \param k - the number of returned neighbors per each query point. %Default is 12. - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_2` or to `Kernel::Point_3` - - \pre `input_range.size() > 0` - \pre `k > 0` - */ - K_neighbor_query( - const InputRange& input_range, - const std::size_t k = 12, - const PointMap point_map = PointMap()) : - m_input_range(input_range), - m_number_of_neighbors(k), - m_point_map(point_map), - m_index_to_point_map(m_input_range, m_point_map), - m_distance(m_index_to_point_map), - m_tree( - boost::counting_iterator(0), - boost::counting_iterator(m_input_range.size()), - Splitter(), - Search_traits(m_index_to_point_map)) { - - CGAL_precondition(input_range.size() > 0); - CGAL_precondition(k > 0); - - m_tree.build(); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `NeighborQuery::operator()()`. - - This operator finds indices of the `k` closest points to the point with - the index `query_index` using a Kd-tree. These indices are returned in `neighbors`. - - \param query_index - index of the query point - - \param neighbors - indices of points, which are neighbors of the query point - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - void operator()( - const std::size_t query_index, - std::vector& neighbors) const { - - CGAL_precondition(query_index < m_input_range.size()); - - Neighbor_search neighbor_search( - m_tree, - get(m_index_to_point_map, query_index), - static_cast(m_number_of_neighbors), - 0, - true, - m_distance); - - neighbors.clear(); - for (auto it = neighbor_search.begin(); it != neighbor_search.end(); ++it) - neighbors.push_back(it->first); - } - - /// @} - - private: - - // Fields. - const Input_range& m_input_range; - - const std::size_t m_number_of_neighbors; - - const Point_map m_point_map; - const Index_to_point_map m_index_to_point_map; - - Distance m_distance; - Tree m_tree; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_K_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_region.h deleted file mode 100644 index 26332dae622..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_region.h +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2020 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H - -#include - -#include -#include - -#include -#include -#include - -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Region type based on the quality of the least squares circle - fit applied to 2D points. - - This class fits a circle to chunks of points in a 2D point set and - controls the quality of this fit. If all quality conditions are - satisfied, the chunk is accepted as a valid region, otherwise - rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_3`. - - \cgalModels `RegionType` -*/ -template -class Least_squares_circle_fit_region -{ - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - using Normal_map = NormalMap; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Point_2 = typename Traits::Point_2; - using Vector_2 = typename Traits::Vector_2; - - using Squared_distance_2 = typename Traits::Compute_squared_distance_2; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - -private: - - const Input_range& m_input_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - const FT m_min_radius; - const FT m_max_radius; - - const Point_map m_point_map; - const Normal_map m_normal_map; - - const Squared_distance_2 m_squared_distance_2; - const Sqrt m_sqrt; - - Point_2 m_center; - FT m_radius; - -public: - - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range an instance of `InputRange` with 2D points and - corresponding 2D normal vectors - - \param distance_threshold the maximum distance from a point to a - circle. %Default is 1. - - \param angle_threshold the maximum accepted angle in degrees - between the normal of a point and the radius of a circle. %Default - is 25 degrees. - - \param min_region_size the minimum number of 2D points a region - must have. %Default is 3. - - \param minimum_radius the radius below which an estimated circle - is considered as invalid and discarded. %Default is 0 (no limit). - - \param maximum_radius the radius above which an estimated circle - is considered as invalid and discarded. %Default is infinity (no - limit). - - \param point_map an instance of `PointMap` that maps an item from - `input_range` to `Kernel::Point_3` - - \param normal_map an instance of `NormalMap` that maps an item - from `input_range` to `Kernel::Vector_3` - - \param traits an instance of `GeomTraits`. - - \pre `input_range.size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_circle_fit_region (const InputRange& input_range, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 3, - const FT minimum_radius = FT(0), - const FT maximum_radius = std::numeric_limits::infinity(), - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap(), - const GeomTraits traits = GeomTraits()) - : m_input_range(input_range) - , m_distance_threshold(distance_threshold) - , m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))) - , m_min_region_size(min_region_size) - , m_min_radius (minimum_radius) - , m_max_radius (maximum_radius) - , m_point_map(point_map) - , m_normal_map(normal_map) - , m_squared_distance_2(traits.compute_squared_distance_2_object()) - , m_sqrt(Get_sqrt::sqrt_object(traits)) - { - CGAL_precondition(input_range.size() > 0); - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - CGAL_precondition(minimum_radius >= 0); - CGAL_precondition(maximum_radius > minimum_radius); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a point with the index `query_index` is - within the `distance_threshold` from the corresponding circle and - if the angle between its normal and the circle radius is within - the `angle_threshold`. If both conditions are satisfied, it - returns `true`, otherwise `false`. - - \param query_index - index of the query point - - \param indices indices of the inliers of the region - - The first parameter is not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - bool is_part_of_region (const std::size_t, - const std::size_t query_index, - const std::vector& indices) const - { - CGAL_precondition(query_index < m_input_range.size()); - - // First, we need to integrate at least 6 points so that the - // computed circle means something - if (indices.size() < 6) - return true; - - // TODO: Why do we get so many nan in this class? - if (std::isnan(m_radius)) - return false; - - // If radius is out of bound, nothing fits, early ending - if (m_radius < m_min_radius || m_radius > m_max_radius) - return false; - - const auto& key = *(m_input_range.begin() + query_index); - const Point_2& query_point = get(m_point_map, key); - Vector_2 normal = get(m_normal_map, key); - - const FT sq_dist = m_squared_distance_2(query_point, m_center); - if (std::isnan(sq_dist)) return false; - FT distance_to_center = m_sqrt (sq_dist); - FT distance_to_circle = CGAL::abs (distance_to_center - m_radius); - - if (distance_to_circle > m_distance_threshold) - return false; - - const FT sq_norm = normal * normal; - if (std::isnan(sq_norm)) return false; - normal = normal / m_sqrt (sq_norm); - - Vector_2 ray (m_center, query_point); - const FT sq_ray = ray * ray; - if (std::isnan(sq_ray)) return false; - ray = ray / m_sqrt (sq_ray); - - if (CGAL::abs (normal * ray) < m_normal_threshold) - return false; - - return true; - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the estimated radius is between - `minimum_radius` and `maximum_radius` and if the `region` contains - at least `min_region_size` points. - - \param region - indices of points included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const - { - return ((m_min_radius <= m_radius && m_radius <= m_max_radius) - && (region.size() >= m_min_region_size)); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares circle to all points from the `region`. - - \param region - indices of points included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) - { - CGAL_precondition(region.size() > 0); - - auto unary_function - = [&](const std::size_t& idx) -> const Point_2& - { - return get (m_point_map, *(m_input_range.begin() + idx)); - }; - - internal::circle_fit - (make_range(boost::make_transform_iterator - (region.begin(), unary_function), - boost::make_transform_iterator - (region.end(), unary_function)), - m_sqrt, m_squared_distance_2, m_center, m_radius); - } - - /// @} - -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_sorting.h deleted file mode 100644 index 4b60f1b2de0..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_circle_fit_sorting.h +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CIRCLE_FIT_SORTING_H - -#include - -// STL includes. -#include -#include - -// CGAL includes. -#include -#include -#include - -// Internal includes. -#include -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Sorting of 2D points with respect to the local circle fit quality. - - Indices of 2D input points are sorted with respect to the quality of the - least squares circle fit applied to the neighboring points of each point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_2`. -*/ -template< - typename GeomTraits, - typename InputRange, - typename NeighborQuery, - typename PointMap> -class Least_squares_circle_fit_sorting { - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Neighbor_query = NeighborQuery; - using Point_map = PointMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - -#ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of input points. - */ - typedef unspecified_type Seed_map; -#endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 2D points - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access point's neighbors - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_2` - - \pre `input_range.size() > 0` - */ - Least_squares_circle_fit_sorting( - const InputRange& input_range, - NeighborQuery& neighbor_query, - const PointMap point_map = PointMap()) : - m_input_range(input_range), - m_neighbor_query(neighbor_query), - m_point_map(point_map), - m_to_local_converter() { - - CGAL_precondition(input_range.size() > 0); - - m_order.resize(m_input_range.size()); - for (std::size_t i = 0; i < m_input_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_input_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of input points. - */ - void sort() { - - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of input points. - */ - Seed_map seed_map() { - return Seed_map(m_order); - } - - /// @} - -private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_2 = typename Local_traits::Point_2; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - - // Functions. - void compute_scores() { - - std::vector neighbors; - std::vector points; - - typename internal::Get_sqrt::Sqrt sqrt; - typename Local_traits::Compute_squared_distance_2 squared_distance_2; - - for (std::size_t i = 0; i < m_input_range.size(); ++i) { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) { - CGAL_precondition(neighbors[j] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + neighbors[j]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == neighbors.size()); - - Local_point_2 fitted_center; - Local_FT fitted_radius; - - if (internal::circle_fit (points, sqrt, squared_distance_2, fitted_center, fitted_radius)) - { - // Score is min squared distance to sphere - m_scores[i] = Local_FT(0); - for (const Local_point_2& p : points) - m_scores[i] += abs (sqrt(squared_distance_2(p, fitted_center)) - fitted_radius); - } - else - m_scores[i] = Local_FT(std::numeric_limits::infinity()); - } - } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - const Point_map m_point_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_region.h deleted file mode 100644 index 26cc8416c14..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_region.h +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) 2020 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H - -#include - -#include -#include - -#include -#include -#include - -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Region type based on the quality of the least squares cylinder - fit applied to 3D points. - - This class fits an infinite cylinder to chunks of points in a 3D - point set and controls the quality of this fit. If all quality - conditions are satisfied, the chunk is accepted as a valid region, - otherwise rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_3`. - - \cgalModels `RegionType` -*/ -template -class Least_squares_cylinder_fit_region -{ - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - using Normal_map = NormalMap; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Point_3 = typename Traits::Point_3; - using Vector_3 = typename Traits::Vector_3; - using Line_3 = typename Traits::Line_3; - - using Squared_distance_3 = typename Traits::Compute_squared_distance_3; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - -private: - - const Input_range& m_input_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - const FT m_min_radius; - const FT m_max_radius; - - const Point_map m_point_map; - const Normal_map m_normal_map; - - const Squared_distance_3 m_squared_distance_3; - const Sqrt m_sqrt; - - Line_3 m_axis; - FT m_radius; - -public: - - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range an instance of `InputRange` with 3D points and - corresponding 3D normal vectors - - \param distance_threshold the maximum distance from a point to a - cylinder. %Default is 1. - - \param angle_threshold the maximum accepted angle in degrees - between the normal of a point and the radius of a cylinder. %Default - is 25 degrees. - - \param min_region_size the minimum number of 3D points a region - must have. %Default is 3. - - \param minimum_radius the radius below which an estimated cylinder - is considered as invalid and discarded. %Default is 0 (no limit). - - \param maximum_radius the radius above which an estimated cylinder - is considered as invalid and discarded. %Default is infinity (no - limit). - - \param point_map an instance of `PointMap` that maps an item from - `input_range` to `Kernel::Point_3` - - \param normal_map an instance of `NormalMap` that maps an item - from `input_range` to `Kernel::Vector_3` - - \param traits an instance of `GeomTraits`. - - \pre `input_range.size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_cylinder_fit_region (const InputRange& input_range, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 3, - const FT minimum_radius = FT(0), - const FT maximum_radius = std::numeric_limits::infinity(), - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap(), - const GeomTraits traits = GeomTraits()) - : m_input_range(input_range) - , m_distance_threshold(distance_threshold) - , m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))) - , m_min_region_size(min_region_size) - , m_min_radius (minimum_radius) - , m_max_radius (maximum_radius) - , m_point_map(point_map) - , m_normal_map(normal_map) - , m_squared_distance_3(traits.compute_squared_distance_3_object()) - , m_sqrt(Get_sqrt::sqrt_object(traits)) - , m_radius(std::numeric_limits::quiet_NaN()) - { - CGAL_precondition(input_range.size() > 0); - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a point with the index `query_index` is - within the `distance_threshold` from the corresponding cylinder and - if the angle between its normal and the cylinder radius is within - the `angle_threshold`. If both conditions are satisfied, it - returns `true`, otherwise `false`. - - \param query_index - index of the query point - - \param indices indices of the inliers of the region - - The first parameter is not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - bool is_part_of_region (const std::size_t, - const std::size_t query_index, - const std::vector& indices) const - { - CGAL_precondition(query_index < m_input_range.size()); - - // First, we need to integrate at least 6 points so that the - // computed cylinder means something - if (indices.size() < 6) - return true; - - // TODO: Why do we get so many nan in this class? - if (std::isnan(m_radius)) - return false; - - // If radius is out of bound, nothing fits, early ending - if (m_radius < m_min_radius || m_radius > m_max_radius) - return false; - - const auto& key = *(m_input_range.begin() + query_index); - const Point_3& query_point = get(m_point_map, key); - Vector_3 normal = get(m_normal_map, key); - - // TODO: Why do we have m_axis = 0 here sometimes? - // Should it ever happen? - if (m_axis.to_vector() == Vector_3(0, 0, 0)) return false; - const FT sq_dist = m_squared_distance_3(query_point, m_axis); - if (std::isnan(sq_dist)) return false; - FT distance_to_center = m_sqrt (sq_dist); - FT distance_to_cylinder = CGAL::abs (distance_to_center - m_radius); - - if (distance_to_cylinder > m_distance_threshold) - return false; - - const FT sq_norm = normal * normal; - if (std::isnan(sq_norm)) return false; - normal = normal / m_sqrt (sq_norm); - - Point_3 proj = m_axis.projection(query_point); - Vector_3 ray (proj, query_point); - const FT sq_ray = ray * ray; - if (std::isnan(sq_ray)) return false; - ray = ray / m_sqrt (sq_ray); - - if (CGAL::abs (normal * ray) < m_normal_threshold) - return false; - - return true; - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the estimated radius is between - `minimum_radius` and `maximum_radius` and if the `region` contains - at least `min_region_size` points. - - \param region - indices of points included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const - { - return ((m_min_radius <= m_radius && m_radius <= m_max_radius) - && (region.size() >= m_min_region_size)); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares cylinder to all points from the `region`. - - \param region - indices of points included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) - { - CGAL_precondition(region.size() > 0); - - // Shuffle to avoid always picking 2 close points - std::vector& aregion - = const_cast&>(region); - cpp98::random_shuffle (aregion.begin(), aregion.end()); - - using VT = typename std::iterator_traits::value_type; - auto unary_function - = [&](const std::size_t& idx) -> VT - { - return *(m_input_range.begin() + idx); - }; - - internal::cylinder_fit - (make_range (boost::make_transform_iterator - (region.begin(), unary_function), - boost::make_transform_iterator - (region.end(), unary_function)), - m_point_map, m_normal_map, m_sqrt, m_squared_distance_3, - m_axis, m_radius); - } - /// @} - -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_sorting.h deleted file mode 100644 index 7c01bc7a752..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_cylinder_fit_sorting.h +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2021 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H - -#include - -// STL includes. -#include -#include - -// CGAL includes. -#include -#include -#include - -// Internal includes. -#include -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Sorting of 3D points with respect to the local cylinder fit quality. - - Indices of 3D input points are sorted with respect to the quality of the - least squares cylinder fit applied to the neighboring points of each point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_3`. -*/ -template -class Least_squares_cylinder_fit_sorting -{ - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Neighbor_query = NeighborQuery; - using Point_map = PointMap; - using Normal_map = NormalMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - -#ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of input points. - */ - typedef unspecified_type Seed_map; -#endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 3D points - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access point's neighbors - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_3` - - \param normal_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Vector_3` - - \pre `input_range.size() > 0` - */ - Least_squares_cylinder_fit_sorting (const InputRange& input_range, - NeighborQuery& neighbor_query, - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap()) - : m_input_range(input_range) - , m_neighbor_query(neighbor_query) - , m_point_map(point_map) - , m_normal_map(normal_map) - , m_to_local_converter() - { - CGAL_precondition(input_range.size() > 0); - - m_order.resize(m_input_range.size()); - for (std::size_t i = 0; i < m_input_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_input_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of input points. - */ - void sort() - { - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of input points. - */ - Seed_map seed_map() - { - return Seed_map(m_order); - } - - /// @} - -private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_vector_3 = typename Local_traits::Vector_3; - using Local_line_3 = typename Local_traits::Line_3; - using Local_pwn = std::pair; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - using Local_point_map = First_of_pair_property_map; - using Local_normal_map = Second_of_pair_property_map; - - // Functions. - void compute_scores() - { - std::vector neighbors; - std::vector > points; - - typename internal::Get_sqrt::Sqrt sqrt; - typename Local_traits::Compute_squared_distance_3 squared_distance_3; - - for (std::size_t i = 0; i < m_input_range.size(); ++i) - { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) - { - CGAL_precondition(neighbors[j] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + neighbors[j]); - points.emplace_back(m_to_local_converter(get(m_point_map, key)), - m_to_local_converter(get(m_normal_map, key))); - } - CGAL_postcondition(points.size() == neighbors.size()); - - Local_line_3 fitted_line; - Local_FT fitted_radius; - - if (internal::cylinder_fit (points, Local_point_map(), Local_normal_map(), - sqrt, squared_distance_3, fitted_line, fitted_radius)) - { - // Score is min squared distance to cylinder - m_scores[i] = Local_FT(0); - for (const Local_pwn& pwn : points) - m_scores[i] += abs (sqrt(squared_distance_3(pwn.first, fitted_line)) - fitted_radius); - } - else - m_scores[i] = Local_FT(std::numeric_limits::infinity()); - } - } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - const Point_map m_point_map; - const Normal_map m_normal_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_CYLINDER_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_region.h deleted file mode 100644 index 2ccefef0eab..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_region.h +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H - -#include - -// STL includes. -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Region type based on the quality of the least squares line - fit applied to 2D points. - - This class fits a line, using \ref PkgPrincipalComponentAnalysisDRef "PCA", - to chunks of points in a 2D point set and controls the quality of this fit. - If all quality conditions are satisfied, the chunk is accepted as a valid region, - otherwise rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_2`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_2`. - - \cgalModels `RegionType` - */ - template< - typename GeomTraits, - typename InputRange, - typename PointMap, - typename NormalMap> - class Least_squares_line_fit_region { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - using Normal_map = NormalMap; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Point_2 = typename Traits::Point_2; - using Vector_2 = typename Traits::Vector_2; - using Line_2 = typename Traits::Line_2; - - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_2 = typename Local_traits::Point_2; - using Local_line_2 = typename Local_traits::Line_2; - using To_local_converter = Cartesian_converter; - - using Squared_length_2 = typename Traits::Compute_squared_length_2; - using Squared_distance_2 = typename Traits::Compute_squared_distance_2; - using Scalar_product_2 = typename Traits::Compute_scalar_product_2; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 2D points and - corresponding 2D normal vectors - - \param distance_threshold - the maximum distance from a point to a line. %Default is 1. - - \param angle_threshold - the maximum accepted angle in degrees between the normal of a point and - the normal of a line. %Default is 25 degrees. - - \param min_region_size - the minimum number of 2D points a region must have. %Default is 2. - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_2` - - \param normal_map - an instance of `NormalMap` that maps an item from `input_range` - to `Kernel::Vector_2` - - \param traits - an instance of `GeomTraits` - - \pre `input_range.size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_line_fit_region( - const InputRange& input_range, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 2, - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap(), - const GeomTraits traits = GeomTraits()) : - m_input_range(input_range), - m_distance_threshold(distance_threshold), - m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))), - m_min_region_size(min_region_size), - m_point_map(point_map), - m_normal_map(normal_map), - m_squared_length_2(traits.compute_squared_length_2_object()), - m_squared_distance_2(traits.compute_squared_distance_2_object()), - m_scalar_product_2(traits.compute_scalar_product_2_object()), - m_sqrt(Get_sqrt::sqrt_object(traits)), - m_to_local_converter() { - - CGAL_precondition(input_range.size() > 0); - - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a point with the index `query_index` is within - the `distance_threshold` from the corresponding line and if the angle - between its normal and the line's normal is within the `angle_threshold`. - If both conditions are satisfied, it returns `true`, otherwise `false`. - - \param query_index - index of the query point - - The first and third parameters are not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - bool is_part_of_region( - const std::size_t, - const std::size_t query_index, - const std::vector&) const { - CGAL_precondition(query_index < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + query_index); - const Point_2& query_point = get(m_point_map, key); - - const Vector_2& normal = get(m_normal_map, key); - const FT normal_length = m_sqrt(m_squared_length_2(normal)); - CGAL_precondition(normal_length > FT(0)); - const Vector_2 query_normal = normal / normal_length; - - const FT distance_to_fitted_line = - m_sqrt(m_squared_distance_2(query_point, m_line_of_best_fit)); - - const FT cos_value = - CGAL::abs(m_scalar_product_2(query_normal, m_normal_of_best_fit)); - - return (( distance_to_fitted_line <= m_distance_threshold ) && - ( cos_value >= m_normal_threshold )); - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the `region` contains at least `min_region_size` points. - - \param region - indices of points included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const { - return ( region.size() >= m_min_region_size ); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares line to all points from the `region`. - - \param region - indices of points included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) { - - CGAL_precondition(region.size() > 0); - if (region.size() == 1) { // create new reference line and normal - CGAL_precondition(region[0] < m_input_range.size()); - - // The best fit line will be a line through this point with - // its normal being the point's normal. - const auto& key = *(m_input_range.begin() + region[0]); - - const Point_2& point = get(m_point_map, key); - const Vector_2& normal = get(m_normal_map, key); - - const FT normal_length = m_sqrt(m_squared_length_2(normal)); - - CGAL_precondition(normal_length > FT(0)); - m_normal_of_best_fit = - normal / normal_length; - - m_line_of_best_fit = - Line_2(point, m_normal_of_best_fit).perpendicular(point); - - } else { // update reference line and normal - - std::vector points; - points.reserve(region.size()); - - for (std::size_t i = 0; i < region.size(); ++i) { - CGAL_precondition(region[i] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + region[i]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == region.size()); - - Local_line_2 fitted_line; - Local_point_2 fitted_centroid; - - // The best fit line will be a line fitted to all region points with - // its normal being perpendicular to the line. - CGAL::linear_least_squares_fitting_2( - points.begin(), points.end(), - fitted_line, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - - m_line_of_best_fit = - Line_2( - static_cast(fitted_line.a()), - static_cast(fitted_line.b()), - static_cast(fitted_line.c())); - - const Vector_2 normal = - m_line_of_best_fit.perpendicular(m_line_of_best_fit.point(0)).to_vector(); - const FT normal_length = m_sqrt(m_squared_length_2(normal)); - - CGAL_precondition(normal_length > FT(0)); - m_normal_of_best_fit = normal / normal_length; - } - } - - /// @} - - private: - - // Fields. - const Input_range& m_input_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - - const Point_map m_point_map; - const Normal_map m_normal_map; - - const Squared_length_2 m_squared_length_2; - const Squared_distance_2 m_squared_distance_2; - const Scalar_product_2 m_scalar_product_2; - const Sqrt m_sqrt; - - const To_local_converter m_to_local_converter; - - Line_2 m_line_of_best_fit; - Vector_2 m_normal_of_best_fit; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_sorting.h deleted file mode 100644 index cead838e2b8..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_line_fit_sorting.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H - -#include - -// STL includes. -#include -#include - -// CGAL includes. -#include -#include -#include -#include -#include - -// Internal includes. -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Sorting of 2D points with respect to the local line fit quality. - - Indices of 2D input points are sorted with respect to the quality of the - least squares line fit applied to the neighboring points of each point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_2`. - */ - template< - typename GeomTraits, - typename InputRange, - typename NeighborQuery, - typename PointMap> - class Least_squares_line_fit_sorting { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Neighbor_query = NeighborQuery; - using Point_map = PointMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - - #ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of input points. - */ - typedef unspecified_type Seed_map; - #endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 2D points - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access point's neighbors - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_2` - - \pre `input_range.size() > 0` - */ - Least_squares_line_fit_sorting( - const InputRange& input_range, - NeighborQuery& neighbor_query, - const PointMap point_map = PointMap()) : - m_input_range(input_range), - m_neighbor_query(neighbor_query), - m_point_map(point_map), - m_to_local_converter() { - - CGAL_precondition(input_range.size() > 0); - - m_order.resize(m_input_range.size()); - for (std::size_t i = 0; i < m_input_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_input_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of input points. - */ - void sort() { - - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of input points. - */ - Seed_map seed_map() { - return Seed_map(m_order); - } - - /// @} - - private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_2 = typename Local_traits::Point_2; - using Local_line_2 = typename Local_traits::Line_2; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - - // Functions. - void compute_scores() { - - std::vector neighbors; - std::vector points; - - for (std::size_t i = 0; i < m_input_range.size(); ++i) { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) { - CGAL_precondition(neighbors[j] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + neighbors[j]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == neighbors.size()); - - Local_line_2 fitted_line; - Local_point_2 fitted_centroid; - - m_scores[i] = CGAL::linear_least_squares_fitting_2( - points.begin(), points.end(), - fitted_line, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - } - } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - const Point_map m_point_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_region.h deleted file mode 100644 index d5c99b1da73..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_region.h +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H - -#include - -// STL includes. -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Region type based on the quality of the least squares plane - fit applied to 3D points. - - This class fits a plane, using \ref PkgPrincipalComponentAnalysisDRef "PCA", - to chunks of points in a 3D point set and controls the quality of this fit. - If all quality conditions are satisfied, the chunk is accepted as a valid region, - otherwise rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_3`. - - \cgalModels `RegionType` - */ - template< - typename GeomTraits, - typename InputRange, - typename PointMap, - typename NormalMap> - class Least_squares_plane_fit_region { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - using Normal_map = NormalMap; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Point_3 = typename Traits::Point_3; - using Vector_3 = typename Traits::Vector_3; - using Plane_3 = typename Traits::Plane_3; - - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_plane_3 = typename Local_traits::Plane_3; - using To_local_converter = Cartesian_converter; - - using Squared_length_3 = typename Traits::Compute_squared_length_3; - using Squared_distance_3 = typename Traits::Compute_squared_distance_3; - using Scalar_product_3 = typename Traits::Compute_scalar_product_3; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 3D points and - corresponding 3D normal vectors - - \param distance_threshold - the maximum distance from a point to a plane. %Default is 1. - - \param angle_threshold - the maximum accepted angle in degrees between the normal of a point and - the normal of a plane. %Default is 25 degrees. - - \param min_region_size - the minimum number of 3D points a region must have. %Default is 3. - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_3` - - \param normal_map - an instance of `NormalMap` that maps an item from `input_range` - to `Kernel::Vector_3` - - \param traits - an instance of `GeomTraits`. - - \pre `input_range.size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_plane_fit_region( - const InputRange& input_range, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 3, - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap(), - const GeomTraits traits = GeomTraits()) : - m_input_range(input_range), - m_distance_threshold(distance_threshold), - m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))), - m_min_region_size(min_region_size), - m_point_map(point_map), - m_normal_map(normal_map), - m_squared_length_3(traits.compute_squared_length_3_object()), - m_squared_distance_3(traits.compute_squared_distance_3_object()), - m_scalar_product_3(traits.compute_scalar_product_3_object()), - m_sqrt(Get_sqrt::sqrt_object(traits)), - m_to_local_converter() { - - CGAL_precondition(input_range.size() > 0); - - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a point with the index `query_index` is within - the `distance_threshold` from the corresponding plane and if the angle - between its normal and the plane's normal is within the `angle_threshold`. - If both conditions are satisfied, it returns `true`, otherwise `false`. - - \param query_index - index of the query point - - The first and third parameters are not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - bool is_part_of_region( - const std::size_t, - const std::size_t query_index, - const std::vector&) const { - - CGAL_precondition(query_index < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + query_index); - const Point_3& query_point = get(m_point_map, key); - - const Vector_3& normal = get(m_normal_map, key); - const FT normal_length = m_sqrt(m_squared_length_3(normal)); - CGAL_precondition(normal_length > FT(0)); - const Vector_3 query_normal = normal / normal_length; - - const FT distance_to_fitted_plane = - m_sqrt(m_squared_distance_3(query_point, m_plane_of_best_fit)); - - const FT cos_value = - CGAL::abs(m_scalar_product_3(query_normal, m_normal_of_best_fit)); - - return (( distance_to_fitted_plane <= m_distance_threshold ) && - ( cos_value >= m_normal_threshold )); - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the `region` contains at least `min_region_size` points. - - \param region - indices of points included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const { - return ( region.size() >= m_min_region_size ); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares plane to all points from the `region`. - - \param region - indices of points included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) { - - CGAL_precondition(region.size() > 0); - if (region.size() == 1) { // create new reference plane and normal - CGAL_precondition(region[0] < m_input_range.size()); - - // The best fit plane will be a plane through this point with - // its normal being the point's normal. - const auto& key = *(m_input_range.begin() + region[0]); - - const Point_3& point = get(m_point_map, key); - const Vector_3& normal = get(m_normal_map, key); - - const FT normal_length = m_sqrt(m_squared_length_3(normal)); - - CGAL_precondition(normal_length > FT(0)); - m_normal_of_best_fit = - normal / normal_length; - - m_plane_of_best_fit = - Plane_3(point, m_normal_of_best_fit); - - } else { // update reference plane and normal - - std::vector points; - points.reserve(region.size()); - - for (std::size_t i = 0; i < region.size(); ++i) { - CGAL_precondition(region[i] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + region[i]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == region.size()); - - Local_plane_3 fitted_plane; - Local_point_3 fitted_centroid; - - // The best fit plane will be a plane fitted to all region points with - // its normal being perpendicular to the plane. - CGAL::linear_least_squares_fitting_3( - points.begin(), points.end(), - fitted_plane, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - - m_plane_of_best_fit = - Plane_3( - static_cast(fitted_plane.a()), - static_cast(fitted_plane.b()), - static_cast(fitted_plane.c()), - static_cast(fitted_plane.d())); - - const Vector_3 normal = m_plane_of_best_fit.orthogonal_vector(); - const FT normal_length = m_sqrt(m_squared_length_3(normal)); - - CGAL_precondition(normal_length > FT(0)); - m_normal_of_best_fit = normal / normal_length; - } - } - - /// @} - - private: - - // Fields. - const Input_range& m_input_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - - const Point_map m_point_map; - const Normal_map m_normal_map; - - const Squared_length_3 m_squared_length_3; - const Squared_distance_3 m_squared_distance_3; - const Scalar_product_3 m_scalar_product_3; - const Sqrt m_sqrt; - - const To_local_converter m_to_local_converter; - - Plane_3 m_plane_of_best_fit; - Vector_3 m_normal_of_best_fit; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_sorting.h deleted file mode 100644 index 9ef5a96a759..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_plane_fit_sorting.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H - -#include - -// STL includes. -#include -#include - -// CGAL includes. -#include -#include -#include -#include -#include - -// Internal includes. -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Sorting of 3D points with respect to the local plane fit quality. - - Indices of 3D input points are sorted with respect to the quality of the - least squares plane fit applied to the neighboring points of each point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - */ - template< - typename GeomTraits, - typename InputRange, - typename NeighborQuery, - typename PointMap> - class Least_squares_plane_fit_sorting { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Neighbor_query = NeighborQuery; - using Point_map = PointMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - - #ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of input points. - */ - typedef unspecified_type Seed_map; - #endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 3D points - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access point's neighbors - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_3` - - \pre `input_range.size() > 0` - */ - Least_squares_plane_fit_sorting( - const InputRange& input_range, - NeighborQuery& neighbor_query, - const PointMap point_map = PointMap()) : - m_input_range(input_range), - m_neighbor_query(neighbor_query), - m_point_map(point_map), - m_to_local_converter() { - - CGAL_precondition(input_range.size() > 0); - - m_order.resize(m_input_range.size()); - for (std::size_t i = 0; i < m_input_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_input_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of input points. - */ - void sort() { - - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of input points. - */ - Seed_map seed_map() { - return Seed_map(m_order); - } - - /// @} - - private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_plane_3 = typename Local_traits::Plane_3; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - - // Functions. - void compute_scores() { - - std::vector neighbors; - std::vector points; - - for (std::size_t i = 0; i < m_input_range.size(); ++i) { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) { - CGAL_precondition(neighbors[j] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + neighbors[j]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == neighbors.size()); - - Local_plane_3 fitted_plane; - Local_point_3 fitted_centroid; - - m_scores[i] = CGAL::linear_least_squares_fitting_3( - points.begin(), points.end(), - fitted_plane, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - } - } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - const Point_map m_point_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_PLANE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_region.h deleted file mode 100644 index 90cb7ce5da9..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_region.h +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2020 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H - -#include - -#include -#include - -#include -#include -#include - -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Region type based on the quality of the least squares sphere - fit applied to 3D points. - - This class fits a sphere to chunks of points in a 3D point set and - controls the quality of this fit. If all quality conditions are - satisfied, the chunk is accepted as a valid region, otherwise - rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. - - \tparam NormalMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Vector_3`. - - \cgalModels `RegionType` -*/ -template -class Least_squares_sphere_fit_region -{ - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - using Normal_map = NormalMap; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Point_3 = typename Traits::Point_3; - using Vector_3 = typename Traits::Vector_3; - using Plane_3 = typename Traits::Plane_3; - - using Squared_length_3 = typename Traits::Compute_squared_length_3; - using Squared_distance_3 = typename Traits::Compute_squared_distance_3; - using Scalar_product_3 = typename Traits::Compute_scalar_product_3; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - -private: - - const Input_range& m_input_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - const FT m_min_radius; - const FT m_max_radius; - - const Point_map m_point_map; - const Normal_map m_normal_map; - - const Squared_length_3 m_squared_length_3; - const Squared_distance_3 m_squared_distance_3; - const Scalar_product_3 m_scalar_product_3; - const Sqrt m_sqrt; - - Point_3 m_center; - FT m_radius; - -public: - - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range an instance of `InputRange` with 3D points and - corresponding 3D normal vectors - - \param distance_threshold the maximum distance from a point to a - sphere. %Default is 1. - - \param angle_threshold the maximum accepted angle in degrees - between the normal of a point and the radius of a sphere. %Default - is 25 degrees. - - \param min_region_size the minimum number of 3D points a region - must have. %Default is 3. - - \param minimum_radius the radius below which an estimated sphere - is considered as invalid and discarded. %Default is 0 (no limit). - - \param maximum_radius the radius above which an estimated sphere - is considered as invalid and discarded. %Default is infinity (no - limit). - - \param point_map an instance of `PointMap` that maps an item from - `input_range` to `Kernel::Point_3` - - \param normal_map an instance of `NormalMap` that maps an item - from `input_range` to `Kernel::Vector_3` - - \param traits an instance of `GeomTraits`. - - \pre `input_range.size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_sphere_fit_region (const InputRange& input_range, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 3, - const FT minimum_radius = FT(0), - const FT maximum_radius = std::numeric_limits::infinity(), - const PointMap point_map = PointMap(), - const NormalMap normal_map = NormalMap(), - const GeomTraits traits = GeomTraits()) - : m_input_range(input_range) - , m_distance_threshold(distance_threshold) - , m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))) - , m_min_region_size(min_region_size) - , m_min_radius (minimum_radius) - , m_max_radius (maximum_radius) - , m_point_map(point_map) - , m_normal_map(normal_map) - , m_squared_length_3(traits.compute_squared_length_3_object()) - , m_squared_distance_3(traits.compute_squared_distance_3_object()) - , m_scalar_product_3(traits.compute_scalar_product_3_object()) - , m_sqrt(Get_sqrt::sqrt_object(traits)) - { - CGAL_precondition(input_range.size() > 0); - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - CGAL_precondition(minimum_radius >= 0); - CGAL_precondition(maximum_radius > minimum_radius); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a point with the index `query_index` is - within the `distance_threshold` from the corresponding sphere and - if the angle between its normal and the sphere radius is within - the `angle_threshold`. If both conditions are satisfied, it - returns `true`, otherwise `false`. - - \param query_index index of the query point - - \param indices indices of the inliers of the region - - The first parameter is not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - bool is_part_of_region (const std::size_t, - const std::size_t query_index, - const std::vector& indices) const - { - CGAL_precondition(query_index < m_input_range.size()); - - // First, we need to integrate at least 6 points so that the - // computed sphere means something - if (indices.size() < 6) - return true; - - // TODO: Why do we get so many nan in this class? - if (std::isnan(m_radius)) - return false; - - // If radius is out of bound, nothing fits, early ending - if (m_radius < m_min_radius || m_radius > m_max_radius) - return false; - - const auto& key = *(m_input_range.begin() + query_index); - const Point_3& query_point = get(m_point_map, key); - Vector_3 normal = get(m_normal_map, key); - - const FT sq_dist = m_squared_distance_3(query_point, m_center); - if (std::isnan(sq_dist)) return false; - FT distance_to_center = m_sqrt (sq_dist); - FT distance_to_sphere = CGAL::abs (distance_to_center - m_radius); - - if (distance_to_sphere > m_distance_threshold) - return false; - - const FT sq_norm = normal * normal; - if (std::isnan(sq_norm)) return false; - normal = normal / m_sqrt (sq_norm); - - Vector_3 ray (m_center, query_point); - const FT sq_ray = ray * ray; - if (std::isnan(sq_ray)) return false; - ray = ray / m_sqrt (sq_ray); - - if (CGAL::abs (normal * ray) < m_normal_threshold) - return false; - - return true; - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the estimated radius is between - `minimum_radius` and `maximum_radius` and if the `region` contains - at least `min_region_size` points. - - \param region - indices of points included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const - { - return ((m_min_radius <= m_radius && m_radius <= m_max_radius) - && (region.size() >= m_min_region_size)); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares sphere to all points from the `region`. - - \param region - indices of points included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) - { - CGAL_precondition(region.size() > 0); - - auto unary_function - = [&](const std::size_t& idx) -> const Point_3& - { - return get (m_point_map, *(m_input_range.begin() + idx)); - }; - - internal::sphere_fit - (make_range (boost::make_transform_iterator - (region.begin(), unary_function), - boost::make_transform_iterator - (region.end(), unary_function)), - m_sqrt, m_squared_distance_3, m_center, m_radius); - } - - /// @} - -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_sorting.h deleted file mode 100644 index 988a4e07d74..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Least_squares_sphere_fit_sorting.h +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) 2021 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H - -#include - -// STL includes. -#include -#include - -// CGAL includes. -#include -#include -#include - -// Internal includes. -#include -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - -/*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Sorting of 3D points with respect to the local sphere fit quality. - - Indices of 3D input points are sorted with respect to the quality of the - least squares sphere fit applied to the neighboring points of each point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_3`. -*/ -template -class Least_squares_sphere_fit_sorting -{ - -public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Neighbor_query = NeighborQuery; - using Point_map = PointMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - -#ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of input points. - */ - typedef unspecified_type Seed_map; -#endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param input_range - an instance of `InputRange` with 3D points - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access point's neighbors - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_3` - - \pre `input_range.size() > 0` - */ - Least_squares_sphere_fit_sorting (const InputRange& input_range, - NeighborQuery& neighbor_query, - const PointMap point_map = PointMap()) - : m_input_range(input_range) - , m_neighbor_query(neighbor_query) - , m_point_map(point_map) - , m_to_local_converter() - { - CGAL_precondition(input_range.size() > 0); - - m_order.resize(m_input_range.size()); - for (std::size_t i = 0; i < m_input_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_input_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of input points. - */ - void sort() - { - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of input points. - */ - Seed_map seed_map() - { - return Seed_map(m_order); - } - - /// @} - -private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - - // Functions. - void compute_scores() - { - std::vector neighbors; - std::vector points; - - typename internal::Get_sqrt::Sqrt sqrt; - typename Local_traits::Compute_squared_distance_3 squared_distance_3; - - for (std::size_t i = 0; i < m_input_range.size(); ++i) - { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) - { - CGAL_precondition(neighbors[j] < m_input_range.size()); - - const auto& key = *(m_input_range.begin() + neighbors[j]); - points.push_back(m_to_local_converter(get(m_point_map, key))); - } - CGAL_postcondition(points.size() == neighbors.size()); - - Local_point_3 fitted_center; - Local_FT fitted_radius; - - if (internal::sphere_fit (points, sqrt, squared_distance_3, fitted_center, fitted_radius)) - { - // Score is min squared distance to sphere - m_scores[i] = Local_FT(0); - for (const Local_point_3& p : points) - m_scores[i] += abs (sqrt(squared_distance_3(p, fitted_center)) - fitted_radius); - } - else - m_scores[i] = Local_FT(std::numeric_limits::infinity()); - } - } - - // Fields. - const Input_range& m_input_range; - Neighbor_query& m_neighbor_query; - const Point_map m_point_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; -}; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_LEAST_SQUARES_SPHERE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h deleted file mode 100644 index 75332fecd6c..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H - -#include - -// STL includes. -#include -#include - -// Boost includes. -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Point_set { - - /*! - \ingroup PkgShapeDetectionRGOnPoints - - \brief Fuzzy sphere neighbors search in a set of `Kernel::Point_2` - or `Kernel::Point_3`. - - This class returns all neighbors of a query point, which fall in a sphere of - the fixed radius centered at this point. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam InputRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator`. - - \tparam PointMap - must be an `LvaluePropertyMap` whose key type is the value type of the input - range and value type is `Kernel::Point_2` or `Kernel::Point_3`. - - \cgalModels `NeighborQuery` - */ - template< - typename GeomTraits, - typename InputRange, - typename PointMap> - class Sphere_neighbor_query { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Input_range = InputRange; - using Point_map = PointMap; - - using Point = typename Point_map::value_type; - /// \endcond - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// \cond SKIP_IN_MANUAL - using Index_to_point_map = - internal::Item_property_map; - - using Search_base = typename std::conditional< - std::is_same::value, - CGAL::Search_traits_2, - CGAL::Search_traits_3 >::type; - - using Search_traits = - CGAL::Search_traits_adapter; - - using Splitter = - CGAL::Sliding_midpoint; - - using Fuzzy_sphere - = CGAL::Fuzzy_sphere; - - using Tree - = CGAL::Kd_tree; - /// \endcond - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes a Kd-tree with input points. - - \param input_range - an instance of `InputRange` with 2D or 3D points - - \param sphere_radius - the fixed radius of the fuzzy sphere used for searching neighbors - of a query point. %Default is 1. - - \param point_map - an instance of `PointMap` that maps an item from `input_range` - to `Kernel::Point_2` or to `Kernel::Point_3` - - \pre `input_range.size() > 0` - \pre `sphere_radius > 0` - */ - Sphere_neighbor_query( - const InputRange& input_range, - const FT sphere_radius = FT(1), - const PointMap point_map = PointMap()) : - m_input_range(input_range), - m_sphere_radius(sphere_radius), - m_point_map(point_map), - m_index_to_point_map(m_input_range, m_point_map), - m_tree( - boost::counting_iterator(0), - boost::counting_iterator(m_input_range.size()), - Splitter(), - Search_traits(m_index_to_point_map)) { - - CGAL_precondition(input_range.size() > 0); - CGAL_precondition(sphere_radius > FT(0)); - - m_tree.build(); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `NeighborQuery::operator()()`. - - This operator finds indices of all points, which fall in a sphere - of the fixed radius `sphere_radius` centered at the query point with - the index `query_index`. These neighbors are returned in `neighbors`. - - \param query_index - index of the query point - - \param neighbors - indices of points, which are neighbors of the query point - - \pre `query_index >= 0 && query_index < input_range.size()` - */ - void operator()( - const std::size_t query_index, - std::vector& neighbors) const { - CGAL_precondition(query_index < m_input_range.size()); - - const std::size_t sphere_center = query_index; - - const Fuzzy_sphere sphere( - sphere_center, - m_sphere_radius, - FT(0), - m_tree.traits()); - - neighbors.clear(); - m_tree.search(std::back_inserter(neighbors), sphere); - } - - /// @} - - const Index_to_point_map& point_map() const { - return m_index_to_point_map; - } - - private: - - // Fields. - const Input_range& m_input_range; - - const FT m_sphere_radius; - - const Point_map m_point_map; - const Index_to_point_map m_index_to_point_map; - - Tree m_tree; - }; - -} // namespace Point_set -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_SPHERE_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh.h deleted file mode 100644 index c1c7254a5d0..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H - -#include - -#include -#include -#include - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_region.h deleted file mode 100644 index b30e0875d4b..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_region.h +++ /dev/null @@ -1,474 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H - -#include - -// STL includes. -#include - -// Boost includes. -#include -#include - -// Face graph includes. -#include -#include -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Polygon_mesh { - - /*! - \ingroup PkgShapeDetectionRGOnMesh - - \brief Region type based on the quality of the least squares plane - fit applied to faces of a polygon mesh. - - This class fits a plane, using \ref PkgPrincipalComponentAnalysisDRef "PCA", - to chunks of faces in a polygon mesh and controls the quality of this fit. - If all quality conditions are satisfied, the chunk is accepted as a valid region, - otherwise rejected. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam PolygonMesh - must be a model of `FaceListGraph`. - - \tparam FaceRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator` and - value type is the face type of a polygon mesh. - - \tparam VertexToPointMap - must be an `LvaluePropertyMap` whose key type is the vertex type of a polygon mesh and - value type is `Kernel::Point_3`. - - \cgalModels `RegionType` - */ - template< - typename GeomTraits, - typename PolygonMesh, - typename FaceRange = typename PolygonMesh::Face_range, - typename VertexToPointMap = typename boost::property_map::type> - class Least_squares_plane_fit_region { - - public: - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Face_graph = PolygonMesh; - using Face_range = FaceRange; - using Vertex_to_point_map = VertexToPointMap; - - using Point_3 = typename Traits::Point_3; - using Vector_3 = typename Traits::Vector_3; - using Plane_3 = typename Traits::Plane_3; - - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_plane_3 = typename Local_traits::Plane_3; - using To_local_converter = Cartesian_converter; - - using Squared_length_3 = typename Traits::Compute_squared_length_3; - using Squared_distance_3 = typename Traits::Compute_squared_distance_3; - using Scalar_product_3 = typename Traits::Compute_scalar_product_3; - using Cross_product_3 = typename Traits::Construct_cross_product_vector_3; - - using Get_sqrt = internal::Get_sqrt; - using Sqrt = typename Get_sqrt::Sqrt; - /// \endcond - - /// \name Types - /// @{ - - /// Number type. - typedef typename GeomTraits::FT FT; - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param pmesh - an instance of `PolygonMesh` that represents a polygon mesh - - \param distance_threshold - the maximum distance from the furthest vertex of a face to a plane. %Default is 1. - - \param angle_threshold - the maximum accepted angle in degrees between the normal of a face and - the normal of a plane. %Default is 25 degrees. - - \param min_region_size - the minimum number of faces a region must have. %Default is 1. - - \param vertex_to_point_map - an instance of `VertexToPointMap` that maps a polygon mesh - vertex to `Kernel::Point_3` - - \param traits - an instance of `GeomTraits` - - \pre `faces(pmesh).size() > 0` - \pre `distance_threshold >= 0` - \pre `angle_threshold >= 0 && angle_threshold <= 90` - \pre `min_region_size > 0` - */ - Least_squares_plane_fit_region( - const PolygonMesh& pmesh, - const FT distance_threshold = FT(1), - const FT angle_threshold = FT(25), - const std::size_t min_region_size = 1, - const VertexToPointMap vertex_to_point_map = VertexToPointMap(), - const GeomTraits traits = GeomTraits()) : - m_face_graph(pmesh), - m_face_range(faces(m_face_graph)), - m_distance_threshold(distance_threshold), - m_normal_threshold(static_cast( - std::cos( - CGAL::to_double( - (angle_threshold * static_cast(CGAL_PI)) / FT(180))))), - m_min_region_size(min_region_size), - m_vertex_to_point_map(vertex_to_point_map), - m_squared_length_3(traits.compute_squared_length_3_object()), - m_squared_distance_3(traits.compute_squared_distance_3_object()), - m_scalar_product_3(traits.compute_scalar_product_3_object()), - m_cross_product_3(traits.construct_cross_product_vector_3_object()), - m_sqrt(Get_sqrt::sqrt_object(traits)), - m_to_local_converter() { - - CGAL_precondition(m_face_range.size() > 0); - - CGAL_precondition(distance_threshold >= FT(0)); - CGAL_precondition(angle_threshold >= FT(0) && angle_threshold <= FT(90)); - CGAL_precondition(min_region_size > 0); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `RegionType::is_part_of_region()`. - - This function controls if a face with the index `query_index` is within - the `distance_threshold` from the corresponding plane and if the angle - between its normal and the plane's normal is within the `angle_threshold`. - If both conditions are satisfied, it returns `true`, otherwise `false`. - - \param query_index - index of the query face - - The first and third parameters are not used in this implementation. - - \return Boolean `true` or `false` - - \pre `query_index >= 0 && query_index < faces(pmesh).size()` - */ - bool is_part_of_region( - const std::size_t, - const std::size_t query_index, - const std::vector&) const { - - CGAL_precondition(query_index < m_face_range.size()); - - const auto face = *(m_face_range.begin() + query_index); - - Vector_3 face_normal; - get_face_normal(face, face_normal); - - const FT distance_to_fitted_plane = - get_max_face_distance(face); - if (distance_to_fitted_plane < FT(0)) - return false; - - // The sign of this scalar product is important, as it indicates - // into which side of the plane the face's normal points. - const FT cos_value = - m_scalar_product_3(face_normal, m_normal_of_best_fit); - - return (( distance_to_fitted_plane <= m_distance_threshold ) && - ( cos_value >= m_normal_threshold )); - } - - /*! - \brief implements `RegionType::is_valid_region()`. - - This function controls if the `region` contains at least `min_region_size` faces. - - \param region - indices of faces included in the region - - \return Boolean `true` or `false` - */ - inline bool is_valid_region(const std::vector& region) const { - return ( region.size() >= m_min_region_size ); - } - - /*! - \brief implements `RegionType::update()`. - - This function fits the least squares plane to all vertices of the faces - from the `region`. - - \param region - indices of faces included in the region - - \pre `region.size() > 0` - */ - void update(const std::vector& region) { - - CGAL_precondition(region.size() > 0); - if (region.size() == 1) { // create new reference plane and normal - - CGAL_precondition(region[0] < m_face_range.size()); - - // The best fit plane will be a plane through this face centroid with - // its normal being the face's normal. - const auto face = *(m_face_range.begin() + region[0]); - Point_3 face_centroid; - - get_face_centroid(face, face_centroid); - get_face_normal(face, m_normal_of_best_fit); - - m_plane_of_best_fit = - Plane_3(face_centroid, m_normal_of_best_fit); - - } else { // update reference plane and normal - - std::vector points; - for (std::size_t i = 0; i < region.size(); ++i) { - - CGAL_precondition(region[i] < m_face_range.size()); - - const auto face = *(m_face_range.begin() + region[i]); - const auto hedge = halfedge(face, m_face_graph); - - const auto vertices = vertices_around_face(hedge, m_face_graph); - for (const auto vertex : vertices) { - - const Point_3& tmp_point = get(m_vertex_to_point_map, vertex); - points.push_back(m_to_local_converter(tmp_point)); - } - } - CGAL_postcondition(points.size() > 0); - - Local_plane_3 fitted_plane; - Local_point_3 fitted_centroid; - - // The best fit plane will be a plane fitted to all vertices of all - // region faces with its normal being perpendicular to the plane. - // Given that the points, and no normals, are used in estimating - // the plane, the estimated normal will point into an arbitrary - // one of the two possible directions. - // We flip it into the correct direction (the one that the majority - // of faces agree with) below. - // This fix is proposed by nh2: - // https://github.com/CGAL/cgal/pull/4563 - CGAL::linear_least_squares_fitting_3( - points.begin(), points.end(), - fitted_plane, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - - const Plane_3 unoriented_plane_of_best_fit = - Plane_3( - static_cast(fitted_plane.a()), - static_cast(fitted_plane.b()), - static_cast(fitted_plane.c()), - static_cast(fitted_plane.d())); - - Vector_3 unoriented_plane_normal = - unoriented_plane_of_best_fit.orthogonal_vector(); - - const FT squared_length = m_squared_length_3(unoriented_plane_normal); - if (squared_length != FT(0)) { - const FT normal_length = m_sqrt(squared_length); - CGAL_precondition(normal_length > FT(0)); - unoriented_plane_normal /= normal_length; - } - - // Compute actual direction of plane's normal sign - // based on faces belonging to that region. - // Approach: - // Each face gets one vote to keep or flip the current plane normal. - Vector_3 face_normal; - long votes_to_keep_normal = 0; - - for (const std::size_t face_index : region) { - const auto face = *(m_face_range.begin() + face_index); - - get_face_normal(face, face_normal); - const bool agrees = - m_scalar_product_3(face_normal, unoriented_plane_normal) > FT(0); - votes_to_keep_normal += (agrees ? 1 : -1); - } - const bool flip_normal = (votes_to_keep_normal < 0); - - m_plane_of_best_fit = - flip_normal - ? unoriented_plane_of_best_fit.opposite() - : unoriented_plane_of_best_fit; - - m_normal_of_best_fit = - flip_normal - ? (-1 * unoriented_plane_normal) - : unoriented_plane_normal; - } - } - - /// @} - - private: - - template - void get_face_centroid( - const Face& face, - Point_3& face_centroid) const { - - const auto hedge = halfedge(face, m_face_graph); - const auto vertices = vertices_around_face(hedge, m_face_graph); - - // Compute centroid. - FT sum = FT(0); - - FT x = FT(0); - FT y = FT(0); - FT z = FT(0); - - for (const auto vertex : vertices) { - const Point_3& point = get(m_vertex_to_point_map, vertex); - - x += point.x(); - y += point.y(); - z += point.z(); - - sum += FT(1); - } - - CGAL_precondition(sum > FT(0)); - x /= sum; - y /= sum; - z /= sum; - - face_centroid = Point_3(x, y, z); - } - - template - void get_face_normal( - const Face& face, - Vector_3& face_normal) const { - - // Compute normal of the face. - const auto hedge = halfedge(face, m_face_graph); - const auto vertices = vertices_around_face(hedge, m_face_graph); - - CGAL_precondition(vertices.size() >= 3); - - auto vertex = vertices.begin(); - const Point_3& point1 = get(m_vertex_to_point_map, *vertex); ++vertex; - const Point_3& point2 = get(m_vertex_to_point_map, *vertex); ++vertex; - const Point_3& point3 = get(m_vertex_to_point_map, *vertex); - - const Vector_3 u = point2 - point1; - const Vector_3 v = point3 - point1; - face_normal = m_cross_product_3(u, v); - const FT squared_length = m_squared_length_3(face_normal); - if (squared_length == FT(0)) - return; - - const FT normal_length = m_sqrt(squared_length); - CGAL_precondition(normal_length > FT(0)); - face_normal /= normal_length; - } - - // The maximum distance from the vertices of the face to the best fit plane. - template - FT get_max_face_distance(const Face& face) const { - - const FT a = CGAL::abs(m_plane_of_best_fit.a()); - const FT b = CGAL::abs(m_plane_of_best_fit.b()); - const FT c = CGAL::abs(m_plane_of_best_fit.c()); - const FT d = CGAL::abs(m_plane_of_best_fit.d()); - - if (a == FT(0) && b == FT(0) && c == FT(0) && d == FT(0)) - return -FT(1); - - const auto hedge = halfedge(face, m_face_graph); - const auto vertices = vertices_around_face(hedge, m_face_graph); - - FT max_face_distance = -FT(1); - for (const auto vertex : vertices) { - - const Point_3& point = - get(m_vertex_to_point_map, vertex); - - const FT distance = - m_sqrt(m_squared_distance_3(point, m_plane_of_best_fit)); - - max_face_distance = - (CGAL::max)(distance, max_face_distance); - } - CGAL_postcondition(max_face_distance != -FT(1)); - - return max_face_distance; - } - - // Fields. - const Face_graph& m_face_graph; - const Face_range m_face_range; - - const FT m_distance_threshold; - const FT m_normal_threshold; - const std::size_t m_min_region_size; - - const Vertex_to_point_map m_vertex_to_point_map; - - const Squared_length_3 m_squared_length_3; - const Squared_distance_3 m_squared_distance_3; - const Scalar_product_3 m_scalar_product_3; - const Cross_product_3 m_cross_product_3; - const Sqrt m_sqrt; - - const To_local_converter m_to_local_converter; - - Plane_3 m_plane_of_best_fit; - Vector_3 m_normal_of_best_fit; - }; - -} // namespace Polygon_mesh -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_sorting.h deleted file mode 100644 index 8bcfc4eed3d..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/Least_squares_plane_fit_sorting.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H - -#include - -// STL includes. -#include - -// Boost includes. -#include -#include - -// Face graph includes. -#include -#include -#include - -// CGAL includes. -#include -#include -#include -#include -#include - -// Internal includes. -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace Polygon_mesh { - - /*! - \ingroup PkgShapeDetectionRGOnMesh - - \brief Sorting of polygon mesh faces with respect to the local plane fit quality. - - Indices of faces in a polygon mesh are sorted with respect to the quality of the - least squares plane fit applied to the vertices of neighboring faces of each face. - - \tparam GeomTraits - must be a model of `Kernel`. - - \tparam PolygonMesh - must be a model of `FaceListGraph`. - - \tparam NeighborQuery - must be a model of `NeighborQuery`. - - \tparam FaceRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator` and - value type is the face type of a polygon mesh. - - \tparam VertexToPointMap - must be an `LvaluePropertyMap` whose key type is the vertex type of a polygon mesh and - value type is `Kernel::Point_3`. - */ - template< - typename GeomTraits, - typename PolygonMesh, - typename NeighborQuery, - typename FaceRange = typename PolygonMesh::Face_range, - typename VertexToPointMap = typename boost::property_map::type> - class Least_squares_plane_fit_sorting { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - using Traits = GeomTraits; - using Face_graph = PolygonMesh; - using Neighbor_query = NeighborQuery; - using Face_range = FaceRange; - using Vertex_to_point_map = VertexToPointMap; - using Seed_map = internal::Seed_property_map; - /// \endcond - - #ifdef DOXYGEN_RUNNING - /*! - an `LvaluePropertyMap` whose key and value type is `std::size_t`. - This map provides an access to the ordered indices of polygon mesh faces. - */ - typedef unspecified_type Seed_map; - #endif - - /// @} - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param pmesh - an instance of `PolygonMesh` that represents a polygon mesh - - \param neighbor_query - an instance of `NeighborQuery` that is used internally to - access face's neighbors - - \param vertex_to_point_map - an instance of `VertexToPointMap` that maps a polygon mesh - vertex to `Kernel::Point_3` - - \pre `faces(pmesh).size() > 0` - */ - Least_squares_plane_fit_sorting( - const PolygonMesh& pmesh, - NeighborQuery& neighbor_query, - const VertexToPointMap vertex_to_point_map = VertexToPointMap()) : - m_face_graph(pmesh), - m_neighbor_query(neighbor_query), - m_face_range(faces(m_face_graph)), - m_vertex_to_point_map(vertex_to_point_map), - m_to_local_converter() { - - CGAL_precondition(m_face_range.size() > 0); - - m_order.resize(m_face_range.size()); - for (std::size_t i = 0; i < m_face_range.size(); ++i) - m_order[i] = i; - m_scores.resize(m_face_range.size()); - } - - /// @} - - /// \name Sorting - /// @{ - - /*! - \brief sorts indices of polygon mesh faces. - */ - void sort() { - - compute_scores(); - CGAL_postcondition(m_scores.size() > 0); - - Compare_scores cmp(m_scores); - std::sort(m_order.begin(), m_order.end(), cmp); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief returns an instance of `Seed_map` to access the ordered indices - of polygon mesh faces. - */ - Seed_map seed_map() { - return Seed_map(m_order); - } - - /// @} - - private: - - // Types. - using Local_traits = Exact_predicates_inexact_constructions_kernel; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_plane_3 = typename Local_traits::Plane_3; - using To_local_converter = Cartesian_converter; - using Compare_scores = internal::Compare_scores; - - // Functions. - void compute_scores() { - - std::vector neighbors; - std::vector points; - - for (std::size_t i = 0; i < m_face_range.size(); ++i) { - - neighbors.clear(); - m_neighbor_query(i, neighbors); - neighbors.push_back(i); - - points.clear(); - for (std::size_t j = 0; j < neighbors.size(); ++j) { - CGAL_precondition(neighbors[j] < m_face_range.size()); - - const auto face = *(m_face_range.begin() + neighbors[j]); - const auto hedge = halfedge(face, m_face_graph); - - const auto vertices = vertices_around_face(hedge, m_face_graph); - for (const auto vertex : vertices) { - - const auto& tmp_point = get(m_vertex_to_point_map, vertex); - points.push_back(m_to_local_converter(tmp_point)); - } - } - CGAL_postcondition(points.size() > 0); - - Local_plane_3 fitted_plane; - Local_point_3 fitted_centroid; - - m_scores[i] = CGAL::linear_least_squares_fitting_3( - points.begin(), points.end(), - fitted_plane, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - } - } - - // Fields. - const Face_graph& m_face_graph; - Neighbor_query& m_neighbor_query; - const Face_range m_face_range; - const Vertex_to_point_map m_vertex_to_point_map; - - std::vector m_order; - std::vector m_scores; - - const To_local_converter m_to_local_converter; - }; - -} // namespace Polygon_mesh -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_LEAST_SQUARES_PLANE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/One_ring_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/One_ring_neighbor_query.h deleted file mode 100644 index c14aeaaca04..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_polygon_mesh/One_ring_neighbor_query.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2018 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H - -#include - -// Boost includes. -#include -#include - -// Face graph includes. -#include -#include -#include - -// CGAL includes. -#include - -// Internal includes. -#include - -namespace CGAL { -namespace Shape_detection { -namespace Polygon_mesh { - - /*! - \ingroup PkgShapeDetectionRGOnMesh - - \brief Edge-adjacent faces connectivity in a polygon mesh. - - This class returns all faces, which are edge-adjacent to a query face in a - polygon mesh being a `PolygonMesh`. - - \tparam PolygonMesh - must be a model of `FaceListGraph`. - - \tparam FaceRange - must be a model of `ConstRange` whose iterator type is `RandomAccessIterator` and - value type is the face type of a polygon mesh. - - \cgalModels `NeighborQuery` - */ - template< - typename PolygonMesh, - typename FaceRange = typename PolygonMesh::Face_range> - class One_ring_neighbor_query { - - public: - - /// \cond SKIP_IN_MANUAL - using Face_graph = PolygonMesh; - using Face_range = FaceRange; - - using Face_to_index_map - = internal::Item_to_index_property_map; - /// \endcond - - /// \name Initialization - /// @{ - - /*! - \brief initializes all internal data structures. - - \param pmesh - an instance of a `PolygonMesh` that represents a polygon mesh - - \pre `faces(pmesh).size() > 0` - */ - One_ring_neighbor_query( - const PolygonMesh& pmesh) : - m_face_graph(pmesh), - m_face_range(faces(m_face_graph)), - m_face_to_index_map(m_face_range) { - - CGAL_precondition(m_face_range.size() > 0); - } - - /// @} - - /// \name Access - /// @{ - - /*! - \brief implements `NeighborQuery::operator()()`. - - This operator retrieves indices of all faces, - which are edge-adjacent to the face with the index `query_index`. - These indices are returned in `neighbors`. - - \param query_index - index of the query face - - \param neighbors - indices of faces, which are neighbors of the query face - - \pre `query_index >= 0 && query_index < faces(pmesh).size()` - */ - void operator()( - const std::size_t query_index, - std::vector& neighbors) const { - - neighbors.clear(); - - CGAL_precondition(query_index < m_face_range.size()); - - const auto query_face = *(m_face_range.begin() + query_index); - const auto query_hedge = halfedge(query_face, m_face_graph); - - const auto faces = faces_around_face(query_hedge, m_face_graph); - for (const auto face : faces) { - const std::size_t face_index = get(m_face_to_index_map, face); - - if (face_index != std::size_t(-1)) // not a null face - neighbors.push_back(face_index); - } - } - - /// @} - - private: - - // Fields. - const Face_graph& m_face_graph; - const Face_range m_face_range; - - const Face_to_index_map m_face_to_index_map; - }; - -} // namespace Polygon_mesh -} // namespace Shape_detection -} // namespace CGAL - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POLYGON_MESH_ONE_RING_NEIGHBOR_QUERY_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set.h new file mode 100644 index 00000000000..b2f1d2a8176 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set.h @@ -0,0 +1,30 @@ +// Copyright (c) 2020 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_H + +/// \cond SKIP_IN_MANUAL +#include +/// \endcond + +/** +* \ingroup PkgShapeDetectionRef +* \file CGAL/Shape_detection/Region_growing/Segment_set.h +* A convenience header that includes all classes related to the region growing algorithm on a segment set. +*/ + +#include +#include + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_region.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_region.h new file mode 100644 index 00000000000..70b2aa0026d --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_region.h @@ -0,0 +1,367 @@ +// Copyright (c) 2020 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_REGION_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_REGION_H + +#include + +// CGAL includes. +#include + +// Internal includes. +#include + +namespace CGAL { +namespace Shape_detection { +namespace Segment_set { + + /*! + \ingroup PkgShapeDetectionRGOnSegments + + \brief Region type based on the quality of the least squares line + fit applied to a segment set. + + This class fits a line, using \ref PkgPrincipalComponentAnalysisDRef "PCA", + to chunks of 2D or 3D segments and controls the quality of this fit. + If all quality conditions are satisfied, the chunk is accepted as a valid region, + otherwise rejected. + + \tparam GeomTraits + a model of `Kernel` + + \tparam Item_ + a descriptor representing a given segment. Must be a model of `Hashable`. + + \tparam SegmentMap + a model of `ReadablePropertyMap` whose key type is `Item` + and value type is `Kernel::Segment_2` or `Kernel::Segment_3` + + \cgalModels `RegionType` + */ + template< + typename GeomTraits, + typename Item_, + typename SegmentMap> + class Least_squares_line_fit_region { + + private: + using Segment_set_traits = typename std::conditional< + std::is_same::value, + internal::Region_growing_traits_2, + internal::Region_growing_traits_3 >::type; + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Segment_map = SegmentMap; + using Segment_type = typename Segment_map::value_type; + /// \endcond + + /// Number type. + typedef typename GeomTraits::FT FT; + + /// Item type. + using Item = Item_; + using Region = std::vector; + + /// Primitive type depends on the dimension of the input data. +#ifdef DOXYGEN_RUNNING + using Primitive = typename GeomTraits::Line_2 or typename GeomTraits::Line_3 +#else + using Primitive = typename Segment_set_traits::Line; +#endif + + /// Region map + using Region_unordered_map = std::unordered_map>; + using Region_index_map = boost::associative_property_map; + /// @} + + private: + using Point = typename Segment_set_traits::Point; + using Segment = typename Segment_set_traits::Segment; + using Vector = typename Segment_set_traits::Vector; + using Line = typename Segment_set_traits::Line; + + using Squared_length = typename Segment_set_traits::Compute_squared_length; + using Squared_distance = typename Segment_set_traits::Compute_squared_distance; + using Scalar_product = typename Segment_set_traits::Compute_scalar_product; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \tparam InputRange + a model of `ConstRange` whose iterator type is `RandomAccessIterator` + + \cgalNamedParamsBegin + \cgalParamNBegin{maximum_distance} + \cgalParamDescription{the maximum distance from the furthest vertex of a segment to a line} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{maximum_angle} + \cgalParamDescription{the maximum angle in degrees between + the direction of a segment and the direction of a line} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{25 degrees} + \cgalParamNEnd + \cgalParamNBegin{cosine_of_maxium_angle} + \cgalParamDescription{the cos value computed as `cos(maximum_angle * PI / 180)`, + this parameter can be used instead of the `maximum_angle`} + \cgalParamType{`GeomTraits::FT`} + \cgalParamDefault{`cos(25 * PI / 180)`} + \cgalParamNEnd + \cgalParamNBegin{minimum_region_size} + \cgalParamDescription{the minimum number of segments a region must have} + \cgalParamType{`std::size_t`} + \cgalParamDefault{1} + \cgalParamNEnd + \cgalParamNBegin{segment_map} + \cgalParamDescription{an instance of `SegmentMap` that maps an item from `input_range` + to `Kernel::Segment_2` or `Kernel::Segment_3`} + \cgalParamDefault{`SegmentMap()`} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `maximum_distance >= 0` + \pre `maximum_angle >= 0 && maximum_angle <= 90` + \pre `cosine_of_maxium_angle >= 0 && cosine_of_maxium_angle <= 1` + \pre `minimum_region_size > 0` + */ + template + Least_squares_line_fit_region( + const NamedParameters& np = parameters::default_values()) : + m_segment_map(parameters::choose_parameter(parameters::get_parameter( + np, internal_np::segment_map))), + m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))), + m_segment_set_traits(m_traits), + m_squared_length(m_segment_set_traits.compute_squared_length_object()), + m_squared_distance(m_segment_set_traits.compute_squared_distance_object()), + m_scalar_product(m_segment_set_traits.compute_scalar_product_object()) { + + const FT max_distance = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_distance), FT(1)); + CGAL_precondition(max_distance >= FT(0)); + m_distance_threshold = max_distance; + + const FT max_angle = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::maximum_angle), FT(25)); + CGAL_precondition(max_angle >= FT(0) && max_angle <= FT(90)); + + m_min_region_size = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::minimum_region_size), 1); + CGAL_precondition(m_min_region_size > 0); + + const FT default_cos_value = static_cast(std::cos(CGAL::to_double( + (max_angle * static_cast(CGAL_PI)) / FT(180)))); + const FT cos_value = parameters::choose_parameter( + parameters::get_parameter(np, internal_np::cosine_of_maxium_angle), default_cos_value); + CGAL_precondition(cos_value >= FT(0) && cos_value <= FT(1)); + m_cos_value_threshold = cos_value; + } + + /// @} + + /// \name Access + /// @{ + + /*! + \brief implements `RegionType::region_index_map()`. + + This function creates an empty property map that maps iterators on the input range `Item` to std::size_t. + */ + Region_index_map region_index_map() { + return Region_index_map(m_region_map); + } + + /*! + \brief implements `RegionType::primitive()`. + + This function provides the last primitive that has been fitted with the region. + + \return Primitive parameters that fits the region + + \pre `successful fitted primitive via successful call of update(region) with a sufficient large region` + */ + Primitive primitive() const { + return m_line_of_best_fit; + } + + /*! + \brief implements `RegionType::is_part_of_region()`. + + This function controls if a segment with the index `query` is within + the `maximum_distance` from the corresponding line and if the angle between the + direction of this segment and the line's direction is within the `maximum_angle`. + If both conditions are satisfied, it returns `true`, otherwise `false`. + + \param query + `Item` of the query segment + + The first and third parameters are not used in this implementation. + + \return Boolean `true` or `false` + + */ + bool is_part_of_region( + const Item, + const Item query, + const Region&) const { + + const Segment& query_segment = get(m_segment_map, query); + const Point& query_source = query_segment.source(); + const Point& query_target = query_segment.target(); + const Vector query_direction(query_source, query_target); + + const FT squared_distance_to_fitted_line = + get_max_squared_distance(query_segment); + const FT squared_distance_threshold = + m_distance_threshold * m_distance_threshold; + + const FT cos_value = + m_scalar_product(query_direction, m_direction_of_best_fit); + const FT squared_cos_value = cos_value * cos_value; + + FT squared_cos_value_threshold = + m_cos_value_threshold * m_cos_value_threshold; + squared_cos_value_threshold *= m_squared_length(query_direction); + squared_cos_value_threshold *= m_squared_length(m_direction_of_best_fit); + + return ( + ( squared_distance_to_fitted_line <= squared_distance_threshold ) && + ( squared_cos_value >= squared_cos_value_threshold )); + } + + /*! + \brief implements `RegionType::is_valid_region()`. + + This function controls if the `region` contains at least `minimum_region_size` segments. + + \param region + Segments of the region represented as `Items`. + + \return Boolean `true` or `false` + */ + inline bool is_valid_region(const Region& region) const { + return (region.size() >= m_min_region_size); + } + + /*! + \brief implements `RegionType::update()`. + + This function fits the least squares line to all segments from the `region`. + + \param region + Segments of the region represented as `Items`. + + \return Boolean `true` if the line fitting succeeded and `false` otherwise + + \pre `region.size() > 0` + */ + bool update(const Region& region) { + + CGAL_precondition(region.size() > 0); + if (region.size() == 1) { // create new reference line and direction + const Item item = region[0]; + + // The best fit line will be a line obtained from this segment + // with the same direction. + const Segment& segment = get(m_segment_map, item); + const Point& source = segment.source(); + const Point& target = segment.target(); + if (source == target) return false; + + CGAL_precondition(source != target); + m_line_of_best_fit = Line(source, target); + m_direction_of_best_fit = m_line_of_best_fit.to_vector(); + + } else { // update reference line and direction + CGAL_precondition(region.size() >= 2); + std::tie(m_line_of_best_fit, m_direction_of_best_fit) = + get_line_and_direction(region); + } + return true; + } + + /// @} + + /// \cond SKIP_IN_MANUAL + std::pair get_line_and_direction( + const Region& region) const { + + // The best fit line will be a line fitted to all region segments with + // its direction being the line's direction. + CGAL_precondition(region.size() > 0); + const Line line_of_best_fit = + m_segment_set_traits.create_line( + region, m_segment_map).first; + const Vector direction_of_best_fit = + line_of_best_fit.to_vector(); + + return std::make_pair(line_of_best_fit, direction_of_best_fit); + } + /// \endcond + + private: + const Segment_map m_segment_map; + const GeomTraits m_traits; + const Segment_set_traits m_segment_set_traits; + Region_unordered_map m_region_map; + + FT m_distance_threshold; + FT m_cos_value_threshold; + std::size_t m_min_region_size; + + const Squared_length m_squared_length; + const Squared_distance m_squared_distance; + const Scalar_product m_scalar_product; + + Line m_line_of_best_fit; + Vector m_direction_of_best_fit; + + // The maximum squared distance from the vertices of the segment + // to the best fit line. + FT get_max_squared_distance(const Segment& segment) const { + + const Point& source = segment.source(); + const Point& target = segment.target(); + const FT squared_distance_source = + m_squared_distance(source, m_line_of_best_fit); + const FT squared_distance_target = + m_squared_distance(target, m_line_of_best_fit); + return (CGAL::max)(squared_distance_source, squared_distance_target); + } + }; + +} // namespace Segment_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_REGION_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_sorting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_sorting.h new file mode 100644 index 00000000000..20a05042ff6 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Segment_set/Least_squares_line_fit_sorting.h @@ -0,0 +1,221 @@ +// Copyright (c) 2020 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H + +#include + +// Internal includes. +#include +#include + +namespace CGAL { +namespace Shape_detection { +namespace Segment_set { + + /*! + \ingroup PkgShapeDetectionRGOnSegments + + \brief Sorting of segments with respect to the local line fit quality. + + Indices of input segments are sorted with respect to the quality of the + least squares line fit applied to the vertices of incident segments of each segment. + + \tparam GeomTraits + a model of `Kernel` + + \tparam NeighborQuery + a model of `NeighborQuery` + + \tparam Item_ + a descriptor representing a given segment. Must be a model of `Hashable`. + + \tparam SegmentMap + a model of `ReadablePropertyMap` whose key type is the value type of the input + range and value type is `Kernel::Segment_2` or `Kernel::Segment_3` + */ + template< + typename GeomTraits, + typename Item_, + typename NeighborQuery, + typename SegmentMap> + class Least_squares_line_fit_sorting { + + public: + /// \name Types + /// @{ + + /// \cond SKIP_IN_MANUAL + using Neighbor_query = NeighborQuery; + using Segment_map = SegmentMap; + using Segment_type = typename boost::property_traits::value_type; + /// \endcond + + /// Item type. + using Item = Item_; + + /// Seed range. + using Seed_range = std::vector; + + /// @} + + private: + using FT = typename GeomTraits::FT; + using Segment_set_traits = typename std::conditional< + std::is_same::value, + internal::Region_growing_traits_2, + internal::Region_growing_traits_3 >::type; + using Compare_scores = internal::Compare_scores; + + public: + /// \name Initialization + /// @{ + + /*! + \brief initializes all internal data structures. + + \tparam NamedParameters + a sequence of \ref bgl_namedparameters "Named Parameters" + + \param input_range + an instance of `InputRange` with 2D or 3D segments + + \param neighbor_query + an instance of `NeighborQuery` that is used internally to + access vertex's neighbors + + \param np + a sequence of \ref bgl_namedparameters "Named Parameters" + among the ones listed below + + \tparam InputRange + a model of `ConstRange` whose iterator type is `InputIterator` + + \cgalNamedParamsBegin + \cgalParamNBegin{segment_map} + \cgalParamDescription{an instance of `SegmentMap` that maps the `Item` of a segment + to `Kernel::Segment_2` or `Kernel::Segment_3`} + \cgalParamDefault{`SegmentMap()`} + \cgalParamNEnd + \cgalParamNBegin{item_map} + \cgalParamDescription{an instance of a model of `ReadablePropertyMap` with `InputRange::const_iterator` + as key type and `Item` as value type.`} + \cgalParamDefault{A default is provided when `Item` is `InputRange::const_iterator` or its value type.} + \cgalParamNEnd + \cgalParamNBegin{geom_traits} + \cgalParamDescription{an instance of `GeomTraits`} + \cgalParamDefault{`GeomTraits()`} + \cgalParamNEnd + \cgalNamedParamsEnd + + \pre `input_range.size() > 0` + */ + template + Least_squares_line_fit_sorting( + const InputRange& input_range, + NeighborQuery& neighbor_query, + const NamedParameters& np = parameters::default_values()) + : m_neighbor_query(neighbor_query) + , m_segment_map(parameters::choose_parameter(parameters::get_parameter( + np, internal_np::segment_map))) + , m_traits(parameters::choose_parameter(parameters::get_parameter(np, internal_np::geom_traits))) + , m_segment_set_traits(m_traits) + { + CGAL_precondition(input_range.size() > 0); + + using NP_helper = internal::Default_property_map_helper; + using Item_map = typename NP_helper::type; + Item_map item_map = NP_helper::get(np); + + m_ordered.resize(input_range.size()); + + std::size_t index = 0; + for (auto it = input_range.begin(); it != input_range.end(); it++) + m_ordered[index++] = get(item_map, it); + + m_scores.resize(input_range.size()); + } + + /// @} + + /// \name Sorting + /// @{ + + /*! + \brief sorts `Items` of input segments. + */ + void sort() { + + compute_scores(); + CGAL_precondition(m_scores.size() > 0); + Compare_scores cmp(m_scores); + + std::vector order(m_ordered.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), cmp); + + std::vector tmp(m_ordered.size()); + for (std::size_t i = 0; i < m_ordered.size(); i++) + tmp[i] = m_ordered[order[i]]; + + m_ordered.swap(tmp); + } + /// @} + + /// \name Access + /// @{ + + /*! + \brief returns an instance of `Seed_range` to access the ordered `Items` + of input segments. + */ + const Seed_range &ordered() { + return m_ordered; + } + /// @} + + private: + Neighbor_query& m_neighbor_query; + const Segment_map m_segment_map; + const GeomTraits m_traits; + const Segment_set_traits m_segment_set_traits; + Seed_range m_ordered; + std::vector m_scores; + + void compute_scores() { + + std::vector neighbors; + std::size_t idx = 0; + for (const Item& item : m_ordered) { + neighbors.clear(); + m_neighbor_query(item, neighbors); + neighbors.push_back(item); + + const auto& segment = get(m_segment_map, item); + const auto& source = segment.source(); + const auto& target = segment.target(); + if (source == target) + m_scores[idx++] = FT(0); // put it at the very back + else + m_scores[idx++] = + m_segment_set_traits.create_line(neighbors, m_segment_map).second; + } + } + }; + +} // namespace Segment_set +} // namespace Shape_detection +} // namespace CGAL + +#endif // #define CGAL_SHAPE_DETECTION_REGION_GROWING_SEGMENT_SET_LEAST_SQUARES_LINE_FIT_SORTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/cylinder_fitting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/cylinder_fitting.h new file mode 100644 index 00000000000..cdef3ce8c7d --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/cylinder_fitting.h @@ -0,0 +1,267 @@ +// Copyright (c) 2022 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Sven Oesau + +// Header of the original source +// This file incorporates work covered by the following copyright and +// permission notice: +// +// David Eberly, Geometric Tools, Redmond WA 98052 +// Copyright (c) 1998-2022 +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license(the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third - parties to whom the Software is furnished to +// do so, all subject to the following : +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine - executable object code generated +// by a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON - INFRINGEMENT.IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// The code below uses the version of +// https://github.com/davideberly/GeometricTools available on 30th of May 2022. +// Version: 6.0.2022.01.06 +// + + +#ifndef CGAL_SHAPE_DETECTION_INTERNAL_CYLINDER_FITTING_H +#define CGAL_SHAPE_DETECTION_INTERNAL_CYLINDER_FITTING_H + +#include +#include +#include +#include +#include +#include + +// The algorithm for least-squares fitting of a point set by a cylinder is +// described in +// https://www.geometrictools.com/Documentation/CylinderFitting.pdf + +namespace CGAL +{ + namespace internal { + template + void preprocess(const Region& indices, + const PointMap point_map, + typename Kernel::Vector_3& average, + Eigen::VectorXd& mu, + Eigen::MatrixXd& f0, + Eigen::MatrixXd& f1, + Eigen::MatrixXd& f2) { + + average = typename Kernel::Vector_3(0, 0, 0); + + for (auto item : indices) { + average += get(point_map, item) - CGAL::ORIGIN; + } + + average = average / static_cast(indices.size()); + + Eigen::MatrixXd prod(indices.size(), 6); + prod.setZero(); + + for (std::size_t i = 0; i < indices.size(); i++) { + typename Kernel::Vector_3 p = get(point_map, indices[i]) + - average - CGAL::ORIGIN; + prod(i, 0) = p.x() * p.x(); + prod(i, 1) = p.x() * p.y(); + prod(i, 2) = p.x() * p.z(); + prod(i, 3) = p.y() * p.y(); + prod(i, 4) = p.y() * p.z(); + prod(i, 5) = p.z() * p.z(); + mu[0] += prod(i, 0); + mu[1] += 2 * prod(i, 1); + mu[2] += 2 * prod(i, 2); + mu[3] += prod(i, 3); + mu[4] += 2 * prod(i, 4); + mu[5] += prod(i, 5); + } + + mu /= static_cast(indices.size()); + + for (size_t i = 0; i < indices.size(); i++) { + Eigen::VectorXd delta(6); + delta[0] = prod(i, 0) - mu[0]; + delta[1] = 2.0 * prod(i, 1) - mu[1]; + delta[2] = 2.0 * prod(i, 2) - mu[2]; + delta[3] = prod(i, 3) - mu[3]; + delta[4] = 2.0 * prod(i, 4) - mu[4]; + delta[5] = prod(i, 5) - mu[5]; + + f0(0, 0) += prod(i, 0); + f0(0, 1) += prod(i, 1); + f0(0, 2) += prod(i, 2); + f0(1, 1) += prod(i, 3); + f0(1, 2) += prod(i, 4); + f0(2, 2) += prod(i, 5); + + typename Kernel::Vector_3 tmp = get(point_map, indices[i]) + - average - CGAL::ORIGIN; + Eigen::Vector3d v(tmp[0], tmp[1], tmp[2]); + + f1 += v * delta.transpose(); + f2 += delta * delta.transpose(); + } + + f0 = f0 * (1.0 / indices.size()); + f0(1, 0) = f0(0, 1); + f0(2, 0) = f0(0, 2); + f0(2, 1) = f0(1, 2); + f1 = f1 * (1.0 / indices.size()); + f2 = f2 * (1.0 / indices.size()); + } + + template + typename Kernel::FT fit_cylinder( + typename Kernel::Line_3& line, + typename Kernel::FT& squared_radius, + typename Kernel::Vector_3& direction, + typename Kernel::Vector_3& average, + typename Eigen::VectorXd& mu, + typename Eigen::MatrixXd& f0, + typename Eigen::MatrixXd& f1, + typename Eigen::MatrixXd& f2) { + + Eigen::VectorXd dir(3); + dir[0] = direction.x(); + dir[1] = direction.y(); + dir[2] = direction.z(); + + Eigen::MatrixXd P(3, 3); + P.setIdentity(); + P = P - (dir * dir.transpose()); + + Eigen::MatrixXd S(3, 3); + S(0, 0) = S(1, 1) = S(2, 2) = 0; + S(0, 1) = -direction.z(); + S(0, 2) = direction.y(); + S(1, 0) = direction.z(); + S(1, 2) = -direction.x(); + S(2, 0) = -direction.y(); + S(2, 1) = direction.x(); + + Eigen::MatrixXd A, Ahat, A2hat, Q; + A = P * f0 * P; + Ahat = -(S * A * S); + A2hat = Ahat * A; + + double trace = A2hat(0, 0) + A2hat(1, 1) + A2hat(2, 2); + Q = Ahat * (1.0 / trace); + + Eigen::VectorXd p(6), a, b; + p[0] = P(0, 0); + p[1] = P(0, 1); + p[2] = P(0, 2); + p[3] = P(1, 1); + p[4] = P(1, 2); + p[5] = P(2, 2); + + a = f1 * p; + b = Q * a; + + double t0 = p.transpose() * (f2 * p); + double t1 = 4.0 * a.transpose() * b; + double t2 = 4.0 * b.transpose() * f0 * b; + + line = typename Kernel::Line_3(typename Kernel::Point_3(b[0] + average[0], + b[1] + average[1], b[2] + average[2]), direction); + + squared_radius = (p.transpose() * mu) + double(b.transpose() * b); + + return t0 - t1 + t2; + } + } + + template< + typename Kernel, + typename Region, + typename PointMap, + typename NormalMap> + typename Kernel::FT fit_cylinder( + const Region& region, const PointMap point_map, + const NormalMap normal_map, + typename Kernel::Line_3& line, + typename Kernel::FT& squared_radius, + const Kernel &traits) { + + using FT = typename Kernel::FT; + using Vector_3 = typename Kernel::Vector_3; + typename Kernel::Construct_cross_product_vector_3 cross_product = + traits.construct_cross_product_vector_3_object(); + + squared_radius = -1.0; + + std::size_t nb = 0; + Vector_3 mean_axis = CGAL::NULL_VECTOR; + + // Axis direction estimation from sample normals by averaging. + for (std::size_t i = 0; i < region.size() - 1; ++i) { + Vector_3 v0 = get(normal_map, region[i]); + v0 = v0 / sqrt(v0 * v0); + Vector_3 v1 = get(normal_map, region[i + 1]); + v1 = v1 / sqrt(v1 * v1); + Vector_3 axis = cross_product(v0, v1); + if (sqrt(axis.squared_length()) < FT(1) / FT(100)) { + continue; + } + axis = axis / sqrt(axis * axis); + + if (nb != 0 && (axis * mean_axis < 0)) { + axis = -axis; + } + mean_axis = mean_axis + axis; + ++nb; + } + + // If no proper mean axis can be derived the fitting fails. + if (mean_axis * mean_axis < FT(1) / FT(100)) + return (std::numeric_limits::max)(); + + mean_axis = mean_axis / sqrt(mean_axis * mean_axis); + + typename Kernel::Vector_3 average; + + Eigen::VectorXd mu(6); + mu.setZero(); + Eigen::MatrixXd f0(3, 3); + f0.setZero(); + Eigen::MatrixXd f1(3, 6); + f1.setZero(); + Eigen::MatrixXd f2(6, 6); + f2.setZero(); + + internal::preprocess + (region, point_map, average, mu, f0, f1, f2); + + return internal::fit_cylinder + (line, squared_radius, mean_axis, average, mu, f0, f1, f2); + } +} + +#endif diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/fitting.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/fitting.h deleted file mode 100644 index b89ac3a0455..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/fitting.h +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2021 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Simon Giraudot -// - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_FITTING_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_FITTING_H - -#include - -#include -#include - -namespace CGAL { -namespace Shape_detection { -namespace internal { - -template -bool circle_fit (const PointRange& points, - const Sqrt& sqrt, - const Squared_distance_2& squared_distance_2, - Point_2& center, FT& radius) -{ - using Diagonalize_traits = Eigen_diagonalize_traits; - using Covariance_matrix = typename Diagonalize_traits::Covariance_matrix; - using Vector = typename Diagonalize_traits::Vector; - using Matrix = typename Diagonalize_traits::Matrix; - - // Use bbox to compute diagonalization with smaller coordinates to - // avoid loss of precision when inverting large coordinates - Bbox_2 bbox = bbox_2 (points.begin(), points.end()); - - // Circle least squares fitting, - // Circle of center (a,b) and radius R - // Ri = sqrt((xi - a)^2 + (yi - b)^2) - // Minimize Sum(Ri^2 - R^2)^2 - // -> Minimize Sum(xi^2 + yi^2 − 2 a*xi − 2 b*yi + a^2 + b^2 − R^2)^2 - // let B=-2a ; C=-2b; D= a^2 + b^2 - R^2 - // let ri = x^2 + y^2 - // -> Minimize Sum(D + B*xi + C*yi + ri)^2 - // -> Minimize Sum(1 + B/D*xi + C/D*yi + ri/D)^2 - // -> system of linear equations - // -> diagonalize matrix - // NB x y r - // xx xy xr - // yy yr - // rr - // - // -> center coordinates = -0.5 * eigenvector(1) / eigenvector(3) ; -0.5 * eigenvector(2) / eigenvector(3) - Covariance_matrix A - = { FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0) }; - - A[0] = static_cast(points.size()); - for (const Point_2& p : points) - { - FT x = p.x() - bbox.xmin(); - FT y = p.y() - bbox.ymin(); - FT r = x*x + y*y; - A[1] += x; - A[2] += y; - A[3] += r; - A[4] += x * x; - A[5] += x * y; - A[6] += x * r; - A[7] += y * y; - A[8] += y * r; - A[9] += r * r; - } - - Vector eigenvalues = { FT(0), FT(0), FT(0), FT(0) }; - Matrix eigenvectors = { FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0) }; - - Diagonalize_traits::diagonalize_selfadjoint_covariance_matrix - (A, eigenvalues, eigenvectors); - - // Perfect line case, no circle can be fitted - if (eigenvectors[3] == 0) - return false; - - center = Point_2 (bbox.xmin() - FT(0.5) * (eigenvectors[1] / eigenvectors[3]), - bbox.ymin() - FT(0.5) * (eigenvectors[2] / eigenvectors[3])); - - radius = FT(0); - for (const Point_2& p : points) - radius += sqrt (squared_distance_2 (p, center)); - radius /= points.size(); - - return true; -} - -template -bool sphere_fit (const PointRange& points, - const Sqrt& sqrt, - const Squared_distance_3& squared_distance_3, - Point_3& center, FT& radius) -{ - using Diagonalize_traits = Eigen_diagonalize_traits; - using Covariance_matrix = typename Diagonalize_traits::Covariance_matrix; - using Vector = typename Diagonalize_traits::Vector; - using Matrix = typename Diagonalize_traits::Matrix; - - // Use bbox to compute diagonalization with smaller coordinates to - // avoid loss of precision when inverting large coordinates - Bbox_3 bbox = bbox_3 (points.begin(), points.end()); - - // Sphere least squares fitting - // (see Least_square_circle_fit_region for details about computation) - Covariance_matrix A - = { FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0) }; - - A[0] = static_cast(points.size()); - for (const Point_3& p : points) - { - FT x = p.x() - bbox.xmin(); - FT y = p.y() - bbox.ymin(); - FT z = p.z() - bbox.zmin(); - FT r = x*x + y*y + z*z; - A[1] += x; - A[2] += y; - A[3] += z; - A[4] += r; - A[5] += x * x; - A[6] += x * y; - A[7] += x * z; - A[8] += x * r; - A[9] += y * y; - A[10] += y * z; - A[11] += y * r; - A[12] += z * z; - A[13] += z * r; - A[14] += r * r; - } - - Vector eigenvalues = { FT(0), FT(0), FT(0), FT(0), FT(0) }; - Matrix eigenvectors = { FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0), - FT(0), FT(0), FT(0), FT(0), FT(0) }; - - Diagonalize_traits::diagonalize_selfadjoint_covariance_matrix - (A, eigenvalues, eigenvectors); - - // Perfect plane case, no sphere can be fitted - if (eigenvectors[4] == 0) - return false; - - center = Point_3 (bbox.xmin() - FT(0.5) * (eigenvectors[1] / eigenvectors[4]), - bbox.ymin() - FT(0.5) * (eigenvectors[2] / eigenvectors[4]), - bbox.zmin() - FT(0.5) * (eigenvectors[3] / eigenvectors[4])); - - radius = FT(0); - for (const Point_3& p : points) - radius += sqrt (squared_distance_3 (p, center)); - radius /= points.size(); - - return true; -} - -template -bool cylinder_fit (const PointRange& points, - PointMap point_map, NormalMap normal_map, - const Sqrt& sqrt, - const Squared_distance_3& squared_distance_3, - Line_3& axis, FT& radius) -{ - using Point_3 = typename boost::property_traits::value_type; - using Vector_3 = typename boost::property_traits::value_type; - - const Point_3& ref = get(point_map, *(points.begin())); - - Vector_3 mean_axis = CGAL::NULL_VECTOR; - std::size_t nb = 0; - radius = FT(0); - Point_3 point_on_axis = ORIGIN; - for (std::size_t i = 0; i < points.size() - 1; ++ i) - { - Vector_3 v0 = get(normal_map, *std::next(points.begin(), i)); - v0 = v0 / sqrt(v0*v0); - Vector_3 v1 = get(normal_map, *std::next(points.begin(), i + 1)); - v1 = v1 / sqrt(v1*v1); - Vector_3 axis = cross_product (v0, v1); - if (sqrt(axis.squared_length()) < (FT)(0.01)) - continue; - axis = axis / sqrt(axis * axis); - - const Point_3& p0 = get(point_map, *std::next(points.begin(), i)); - const Point_3& p1 = get(point_map, *std::next(points.begin(), i + 1)); - - Vector_3 xdir = v0 - axis * (v0 * axis); - xdir = xdir / sqrt (xdir * xdir); - - Vector_3 ydir = cross_product (axis, xdir); - ydir = ydir / sqrt (ydir * ydir); - - FT v1x = v1 * ydir; - FT v1y = -v1 * xdir; - - Vector_3 d (p0, p1); - - FT ox = xdir * d; - FT oy = ydir * d; - FT ldist = v1x * ox + v1y * oy; - - FT radius = ldist / v1x; - - Point_3 point = p0 + xdir * radius; - Line_3 line (point, axis); - point = line.projection(ref); - - point_on_axis = barycenter (point_on_axis, static_cast(nb), point, FT(1)); - - radius += abs(radius); - - if (nb != 0 && axis * mean_axis < 0) - axis = -axis; - - mean_axis = mean_axis + axis; - ++ nb; - } - - if (nb == 0) - return false; - - mean_axis = mean_axis / sqrt(mean_axis * mean_axis); - axis = Line_3 (point_on_axis, mean_axis); - radius /= nb; - - radius = FT(0); - for (const auto& p : points) - { - const Point_3& p0 = get(point_map, p); - radius += sqrt(squared_distance_3(p0, axis)); - } - radius /= points.size(); - - return true; -} - -} // internal -} // namespace Shape_detection -} // namespace CGAL - - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_POINT_SET_INTERNAL_FITTING_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h index afc172dac4d..3dbaf555ac5 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/property_map.h @@ -11,168 +11,74 @@ // Author(s) : Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov // -#include - -// STL includes. -#include -#include -#include - -// CGAL includes. -#include -#include - #ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_PROPERTY_MAP_H #define CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_PROPERTY_MAP_H +#include + +// CGAL includes. +#include +#include +#include +#include + +// Boost includes. +#include + namespace CGAL { namespace Shape_detection { namespace internal { - template< - typename ItemRange, - typename PropertyMap> - class Item_property_map { +template ::type, Default>::value > +struct Default_property_map_helper +{ + using type = typename internal_np::Lookup_named_param_def::type; + static type get(const NP& np) + { + return parameters::get_parameter(np, Tag()); + } +}; - public: - using Item_range = ItemRange; - using Property_map = PropertyMap; +template +struct Default_property_map_helper +{ + struct No_property_map_given_in_named_parameters_and_no_deducible_default {}; + static const bool iterator_is_item = std::is_same::value; + static const bool value_type_is_item = std::is_same::value_type>::value; + using type = std::conditional_t, + std::conditional_t, + No_property_map_given_in_named_parameters_and_no_deducible_default>>; - using value_type = typename Property_map::value_type; - using reference = const value_type&; - using key_type = std::size_t; - using category = boost::lvalue_property_map_tag; + static type get(const NP&) + { + return type(); + } +}; - Item_property_map( - const Item_range& item_range, - const Property_map& property_map) : - m_item_range(item_range), - m_property_map(property_map) - { } +template +struct Item_map_helper +{ + using type = ItemMap; + static const ItemMap& get(const ItemMap& m) + { + return m; + } +}; - reference operator[](const key_type item_index) const { - CGAL_precondition(item_index < m_item_range.size()); - - const auto& key = *(m_item_range.begin() + item_index); - return get(m_property_map, key); - } - - friend inline reference get(const Item_property_map& item_map, - const key_type key) { - return item_map[key]; - } - - private: - const Item_range& m_item_range; - const Property_map& m_property_map; - }; - - template - class Item_to_index_property_map { - - public: - using Item_range = ItemRange; - - using Iterator = typename Item_range::const_iterator; - using Item = typename Iterator::value_type; - - using value_type = std::size_t; - using reference = std::size_t; - using key_type = Item; - using category = boost::readable_property_map_tag; - - using Item_map = std::map; - - Item_to_index_property_map(const Item_range& item_range) : - m_item_range(item_range) { - - value_type i = 0; - for (const auto& item : item_range) { - - m_item_map[item] = i; - ++i; - } - } - - value_type operator[](const key_type& key) const { - - const auto& value = m_item_map.find(key); - - if (value == m_item_map.end()) - return value_type(-1); - - return value->second; - } - - friend inline value_type get(const Item_to_index_property_map& item_to_index_map, - const key_type& key) { - return item_to_index_map[key]; - } - - private: - const Item_range& m_item_range; - Item_map m_item_map; - }; - - class Seed_property_map { - - public: - using key_type = std::size_t; - using value_type = std::size_t; - using category = boost::readable_property_map_tag; - - Seed_property_map(const std::vector& seeds) - : m_seeds(seeds) - { } - - value_type operator[](const key_type key) const { - return m_seeds[key]; - } - - friend value_type get(const Seed_property_map& seed_map, - const key_type key) { - return seed_map[key]; - } - - private: - const std::vector& m_seeds; - }; +template +struct Item_map_helper +{ + using type = typename Default_property_map_helper::type; + static type get(Default) + { + return type(); + } +}; } // namespace internal - -namespace RG { - - class Point_to_shape_index_map { - - public: - using key_type = std::size_t; - using value_type = int; - using reference = value_type; - using category = boost::readable_property_map_tag; - - Point_to_shape_index_map() { } - - template - Point_to_shape_index_map(const PointRange& points, - const std::vector< std::vector >& regions) - : m_indices(new std::vector(points.size(), -1)) - { - for (std::size_t i = 0; i < regions.size(); ++i) - for (const std::size_t idx : regions[i]) - (*m_indices)[idx] = static_cast(i); - } - - inline friend value_type get(const Point_to_shape_index_map& point_to_shape_index_map, - const key_type key) { - const auto& indices = *(point_to_shape_index_map.m_indices); - return indices[key]; - } - - private: - std::shared_ptr< std::vector > m_indices; - }; - -} // namespace RG } // namespace Shape_detection } // namespace CGAL diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/region_growing_traits.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/region_growing_traits.h new file mode 100644 index 00000000000..a934e6fa8a9 --- /dev/null +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/region_growing_traits.h @@ -0,0 +1,98 @@ +// Copyright (c) 2020 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Dmitry Anisimov +// + +#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_TRAITS_H +#define CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_TRAITS_H + +#include + +// Internal includes. +#include + +namespace CGAL { +namespace Shape_detection { +namespace internal { + + template + struct Region_growing_traits_2 { + using Point = typename GeomTraits::Point_2; + using Segment = typename GeomTraits::Segment_2; + using Vector = typename GeomTraits::Vector_2; + using Line = typename GeomTraits::Line_2; + + using Compute_squared_length = typename GeomTraits::Compute_squared_length_2; + using Compute_squared_distance = typename GeomTraits::Compute_squared_distance_2; + using Compute_scalar_product = typename GeomTraits::Compute_scalar_product_2; + + const GeomTraits& m_traits; + Region_growing_traits_2(const GeomTraits& traits) : + m_traits(traits) + { } + + decltype(auto) compute_squared_length_object() const { + return m_traits.compute_squared_length_2_object(); + } + decltype(auto) compute_squared_distance_object() const { + return m_traits.compute_squared_distance_2_object(); + } + decltype(auto) compute_scalar_product_object() const { + return m_traits.compute_scalar_product_2_object(); + } + + template + decltype(auto) create_line( + const Region& region, const ItemMap item_map) const { + return internal::create_line_2( + region, item_map, m_traits); + } + }; + + template + struct Region_growing_traits_3 { + using Point = typename GeomTraits::Point_3; + using Segment = typename GeomTraits::Segment_3; + using Vector = typename GeomTraits::Vector_3; + using Line = typename GeomTraits::Line_3; + + using Compute_squared_length = typename GeomTraits::Compute_squared_length_3; + using Compute_squared_distance = typename GeomTraits::Compute_squared_distance_3; + using Compute_scalar_product = typename GeomTraits::Compute_scalar_product_3; + + const GeomTraits& m_traits; + Region_growing_traits_3(const GeomTraits& traits) : + m_traits(traits) + { } + + decltype(auto) compute_squared_length_object() const { + return m_traits.compute_squared_length_3_object(); + } + decltype(auto) compute_squared_distance_object() const { + return m_traits.compute_squared_distance_3_object(); + } + decltype(auto) compute_scalar_product_object() const { + return m_traits.compute_scalar_product_3_object(); + } + + template + decltype(auto) create_line( + const Region& region, const ItemMap item_map) const { + return internal::create_line_3( + region, item_map, m_traits); + } + }; + +} // namespace internal +} // namespace Shape_detection +} // namespace CGAL + +#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_TRAITS_H diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h index 8a016036dea..b539bf56e5c 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/internal/utils.h @@ -15,25 +15,72 @@ #define CGAL_SHAPE_DETECTION_REGION_GROWING_INTERNAL_UTILS_H #include +#include // STL includes. +#include +#include +#include #include +#include +#include +#include // Boost headers. +#include #include +#include +#include + +// Named parameters. +#include +#include // CGAL includes. #include #include #include #include +#include #include +#include #include +#include namespace CGAL { namespace Shape_detection { namespace internal { + template + struct reference_iterator_generator { + using result_type = T; + reference_iterator_generator(T iterator) : it(iterator) { } + result_type operator() () const { + return it++; + } + mutable T it; + }; + + // TODO: this should be customisable in named function parameters + template::value> + struct hash_item {}; + + template + struct hash_item { + std::size_t operator()(T i) const { + using boost::hash_value; + return hash_value(i); + } + }; + + template + struct hash_item { + std::size_t operator()(T i) const { + using boost::hash_value; + return boost::hash_value(i.operator->()); + } + }; + template class Default_sqrt { @@ -88,139 +135,553 @@ namespace internal { template struct Compare_scores { - const std::vector& m_scores; + const std::vector& m_scores; Compare_scores(const std::vector& scores) : m_scores(scores) { } bool operator()(const std::size_t i, const std::size_t j) const { - CGAL_precondition(i < m_scores.size()); CGAL_precondition(j < m_scores.size()); - return m_scores[i] > m_scores[j]; } }; template< - typename InputRange, - typename PointMap, - typename Plane_3> - void create_planes_from_points( - const InputRange& input_range, - const PointMap point_map, - std::vector< std::vector >& regions, - std::vector& planes) { + typename Traits, + typename Region, + typename PrimitiveMap> + std::pair + create_line_2( + const Region& region, const PrimitiveMap primitive_map, const Traits&) { - using Traits = typename Kernel_traits::Kernel; using FT = typename Traits::FT; + using Line_2 = typename Traits::Line_2; - using Local_traits = - CGAL::Exact_predicates_inexact_constructions_kernel; - using To_local_converter = - Cartesian_converter; + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IConverter = CGAL::Cartesian_converter; - using Local_FT = typename Local_traits::FT; - using Local_point_3 = typename Local_traits::Point_3; - using Local_plane_3 = typename Local_traits::Plane_3; + using IFT = typename ITraits::FT; + using IPoint_2 = typename ITraits::Point_2; + using ILine_2 = typename ITraits::Line_2; - planes.clear(); - planes.reserve(regions.size()); + using Item = typename boost::property_traits::key_type; + using Primitive = typename boost::property_traits::value_type; + using EPIC_Primitive = typename std::conditional< + std::is_same::value, + typename ITraits::Point_2, typename ITraits::Segment_2 >::type; - std::vector points; - const To_local_converter to_local_converter = To_local_converter(); + std::vector elements; + CGAL_precondition(region.size() > 0); + elements.reserve(region.size()); + const IConverter iconverter = IConverter(); - for (const auto& region : regions) { - CGAL_assertion(region.size() > 0); - - points.clear(); - for (std::size_t i = 0; i < region.size(); ++i) { - - CGAL_precondition(region[i] < input_range.size()); - - const auto& key = *(input_range.begin() + region[i]); - points.push_back(to_local_converter(get(point_map, key))); - } - CGAL_postcondition(points.size() == region.size()); - - Local_plane_3 fitted_plane; - Local_point_3 fitted_centroid; - - CGAL::linear_least_squares_fitting_3( - points.begin(), points.end(), - fitted_plane, fitted_centroid, - CGAL::Dimension_tag<0>(), - Local_traits(), - CGAL::Eigen_diagonalize_traits()); - - const Plane_3 plane = Plane_3( - static_cast(fitted_plane.a()), - static_cast(fitted_plane.b()), - static_cast(fitted_plane.c()), - static_cast(fitted_plane.d())); - planes.push_back(plane); + for (Item item : region) { + const Primitive& element = get(primitive_map, item); + elements.push_back(iconverter(element)); } - CGAL_postcondition(planes.size() == regions.size()); + CGAL_precondition(elements.size() == region.size()); + + ILine_2 fitted_line; + IPoint_2 fitted_centroid; + const IFT score = CGAL::linear_least_squares_fitting_2( + elements.begin(), elements.end(), + fitted_line, fitted_centroid, + CGAL::Dimension_tag::value>(), ITraits(), + CGAL::Eigen_diagonalize_traits()); + + const Line_2 line( + static_cast(fitted_line.a()), + static_cast(fitted_line.b()), + static_cast(fitted_line.c())); + + return std::make_pair(line, static_cast(score)); + } + + template< + typename Traits, + typename Region, + typename PrimitiveMap> + std::pair + create_line_3( + const Region& region, const PrimitiveMap primitive_map, const Traits&) { + + using FT = typename Traits::FT; + using Line_3 = typename Traits::Line_3; + using Point_3 = typename Traits::Point_3; + using Direction_3 = typename Traits::Direction_3; + + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IConverter = CGAL::Cartesian_converter; + + using IFT = typename ITraits::FT; + using IPoint_3 = typename ITraits::Point_3; + using ILine_3 = typename ITraits::Line_3; + + using Item = typename boost::property_traits::key_type; + using Primitive = typename boost::property_traits::value_type; + using EPIC_Primitive = typename std::conditional< + std::is_same::value, + typename ITraits::Point_3, typename ITraits::Segment_3 >::type; + + std::vector elements; + CGAL_precondition(region.size() > 0); + elements.reserve(region.size()); + const IConverter iconverter = IConverter(); + + for (Item item : region) { + const Primitive& element = get(primitive_map, item); + elements.push_back(iconverter(element)); + } + CGAL_precondition(elements.size() == region.size()); + + ILine_3 fitted_line; + IPoint_3 fitted_centroid; + const IFT score = CGAL::linear_least_squares_fitting_3( + elements.begin(), elements.end(), + fitted_line, fitted_centroid, + CGAL::Dimension_tag::value>(), ITraits(), + CGAL::Eigen_diagonalize_traits()); + + const auto p = fitted_line.point(0); + const auto d = fitted_line.direction(); + const Point_3 init( + static_cast(p.x()), + static_cast(p.y()), + static_cast(p.z())); + const Direction_3 direction( + static_cast(d.dx()), + static_cast(d.dy()), + static_cast(d.dz())); + const Line_3 line(init, direction); + + return std::make_pair(line, static_cast(score)); + } + + template< + typename Traits, + typename Region, + typename ItemMap> + std::pair + create_plane( + const Region& region, const ItemMap item_map, const Traits&) { + + using FT = typename Traits::FT; + using Plane_3 = typename Traits::Plane_3; + + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IConverter = CGAL::Cartesian_converter; + + using IFT = typename ITraits::FT; + using IPoint_3 = typename ITraits::Point_3; + using IPlane_3 = typename ITraits::Plane_3; + + using Input_type = typename ItemMap::value_type; + using Element = typename std::conditional< + std::is_same::value, + typename ITraits::Point_3, typename ITraits::Segment_3 >::type; + + std::vector elements; + CGAL_precondition(region.size() > 0); + elements.reserve(region.size()); + const IConverter iconverter = IConverter(); + + for (auto item : region) { + const auto& element = get(item_map, item); + elements.push_back(iconverter(element)); + } + CGAL_precondition(elements.size() == region.size()); + + IPlane_3 fitted_plane; + IPoint_3 fitted_centroid; + const IFT score = CGAL::linear_least_squares_fitting_3( + elements.begin(), elements.end(), + fitted_plane, fitted_centroid, + CGAL::Dimension_tag::value>(), ITraits(), + CGAL::Eigen_diagonalize_traits()); + + const Plane_3 plane( + static_cast(fitted_plane.a()), + static_cast(fitted_plane.b()), + static_cast(fitted_plane.c()), + static_cast(fitted_plane.d())); + + return std::make_pair(plane, static_cast(score)); + } + + + template< + typename Traits, + typename InputRange, + typename Region, + typename ItemMap> + std::pair + create_plane( + const InputRange &input_range, + const ItemMap item_map, const Region& region, const Traits& traits) { + std::vector tmp; + tmp.resize(region.size()); + + for (std::size_t idx : region) + tmp[idx] = input_range.begin() + idx; + + return create_plane(tmp, item_map, traits); + } + + template< + typename Traits, + typename FaceGraph, + typename Region, + typename VertexToPointMap> + std::pair + create_plane_from_faces( + const FaceGraph& face_graph, + const Region& region, + const VertexToPointMap vertex_to_point_map, const Traits&) { + + using FT = typename Traits::FT; + using Plane_3 = typename Traits::Plane_3; + + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IConverter = CGAL::Cartesian_converter; + + using IFT = typename ITraits::FT; + using IPoint_3 = typename ITraits::Point_3; + using ITriangle_3 = typename ITraits::Triangle_3; + using IPlane_3 = typename ITraits::Plane_3; + + std::vector triangles; + CGAL_precondition(region.size() > 0); + triangles.reserve(region.size()); + const IConverter iconverter = IConverter(); + + for (const typename Region::value_type face : region) { + const auto hedge = halfedge(face, face_graph); + const auto vertices = vertices_around_face(hedge, face_graph); + CGAL_precondition(vertices.size() > 0); + + std::vector points; + for (const auto vertex : vertices) { + const auto& point = get(vertex_to_point_map, vertex); + points.push_back(iconverter(point)); + } + if (points.size()==3) + triangles.push_back(ITriangle_3(points[0], points[1], points[2])); + else + { + //use a triangulation using the centroid + std::size_t nb_edges = points.size(); + IPoint_3 c = CGAL::centroid(points.begin(), points.end()); + points.push_back(points.front()); + for (std::size_t i=0; i= region.size()); + IPlane_3 fitted_plane; + IPoint_3 fitted_centroid; + const IFT score = CGAL::linear_least_squares_fitting_3( + triangles.begin(), triangles.end(), + fitted_plane, fitted_centroid, + CGAL::Dimension_tag<2>(), ITraits(), + CGAL::Eigen_diagonalize_traits()); + + const Plane_3 plane( + static_cast(fitted_plane.a()), + static_cast(fitted_plane.b()), + static_cast(fitted_plane.c()), + static_cast(fitted_plane.d())); + return std::make_pair(plane, static_cast(score)); + } + + template< + typename Traits, + typename Region, + typename PointMap> + std::pair, + typename Traits::FT> + create_circle_2( + const Region ®ion, const PointMap point_map, + const Traits&, const bool compute_score) { + + using FT = typename Traits::FT; + using Point_2 = typename Traits::Point_2; + + typename Get_sqrt::Sqrt sqrt; + typename Traits::Compute_squared_distance_2 squared_distance_2; + + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IFT = typename ITraits::FT; + + using Diagonalize_traits = Eigen_diagonalize_traits; + using Covariance_matrix = typename Diagonalize_traits::Covariance_matrix; + + using Vector = typename Diagonalize_traits::Vector; + using Matrix = typename Diagonalize_traits::Matrix; + + // Use bbox to compute diagonalization with smaller coordinates to + // avoid loss of precision when inverting large coordinates. + FT xmin = +FT(1000000000000); + FT ymin = +FT(1000000000000); + for (auto item : region) { + const auto& point = get(point_map, item); + xmin = (CGAL::min)(xmin, point.x()); + ymin = (CGAL::min)(ymin, point.y()); + } + + // Circle least squares fitting: + // Circle of center (a, b) and radius R: + // Ri = sqrt((xi - a)^2 + (yi - b)^2) + // Minimize sum(Ri^2 - R^2)^2 + // -> Minimize sum(xi^2 + yi^2 − 2 * a * xi − 2 * b * yi + a^2 + b^2 − R^2)^2 + // Let B = -2a; C = -2b; D = a^2 + b^2 - R^2; and ri = x^2 + y^2. + // -> Minimize sum(D + B * xi + C * yi + ri)^2 + // -> Minimize sum(1 + B / D * xi + C / D * yi + ri / D)^2 + // -> system of linear equations + // -> diagonalize matrix + // NB x y r + // xx xy xr + // yy yr + // rr + // -> center coordinates = [ + // -0.5 * eigenvector(1) / eigenvector(3); + // -0.5 * eigenvector(2) / eigenvector(3); ] + Covariance_matrix A = { + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0) + }; + + A[0] = static_cast(region.size()); + for (auto &item : region) { + const auto& point = get(point_map, item); + + const IFT x = static_cast(CGAL::to_double(point.x() - xmin)); + const IFT y = static_cast(CGAL::to_double(point.y() - ymin)); + const IFT r = x * x + y * y; + + A[1] += x; + A[2] += y; + A[3] += r; + A[4] += x * x; + A[5] += x * y; + A[6] += x * r; + A[7] += y * y; + A[8] += y * r; + A[9] += r * r; + } + + Vector eigenvalues = { + IFT(0), IFT(0), IFT(0), IFT(0) + }; + Matrix eigenvectors = { + IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0) + }; + Diagonalize_traits:: + diagonalize_selfadjoint_covariance_matrix(A, eigenvalues, eigenvectors); + + // Perfect line case, no circle can be fitted. + if (eigenvectors[3] == IFT(0)) { + return std::make_pair( + std::make_pair(FT(-1), Point_2()), + -static_cast(((std::numeric_limits::max))())); + } + CGAL_assertion(eigenvectors[3] != IFT(0)); + + // Other cases. + const FT half = FT(1) / FT(2); + const Point_2 fitted_center = Point_2( + xmin - half * static_cast(eigenvectors[1] / eigenvectors[3]), + ymin - half * static_cast(eigenvectors[2] / eigenvectors[3]) + ); + + FT fitted_radius = FT(0); + for (auto &item : region) { + const auto& point = get(point_map, item); + fitted_radius += sqrt(squared_distance_2(point, fitted_center)); + } + fitted_radius /= static_cast(region.size()); + + // Compute score. + FT score = FT(-1); + if (compute_score) { + score = FT(0); + for (auto &item : region) { + const auto& point = get(point_map, item); + score -= CGAL::abs(sqrt(squared_distance_2(point, fitted_center)) + - fitted_radius); + } + } + + return std::make_pair( + std::make_pair(fitted_radius, fitted_center), score); + } + + template< + typename Traits, + typename Region, + typename PointMap> + std::pair, + typename Traits::FT> + create_sphere( + const Region ®ion, const PointMap point_map, + const Traits&, const bool compute_score) { + + using FT = typename Traits::FT; + using Point_3 = typename Traits::Point_3; + + typename Get_sqrt::Sqrt sqrt; + typename Traits::Compute_squared_distance_3 squared_distance_3; + + using ITraits = CGAL::Exact_predicates_inexact_constructions_kernel; + using IFT = typename ITraits::FT; + + using Diagonalize_traits = Eigen_diagonalize_traits; + using Covariance_matrix = typename Diagonalize_traits::Covariance_matrix; + + using Vector = typename Diagonalize_traits::Vector; + using Matrix = typename Diagonalize_traits::Matrix; + + // Use bbox to compute diagonalization with smaller coordinates to + // avoid loss of precision when inverting large coordinates. + FT xmin = +FT(1000000000000); + FT ymin = +FT(1000000000000); + FT zmin = +FT(1000000000000); + for (auto item : region) { + const auto& point = get(point_map, item); + xmin = (CGAL::min)(xmin, point.x()); + ymin = (CGAL::min)(ymin, point.y()); + zmin = (CGAL::min)(zmin, point.z()); + } + + // Sphere least squares fitting. + // See create_circle_2() above for more details on computation. + Covariance_matrix A = { + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0) + }; + + A[0] = static_cast(region.size()); + for (auto item : region) { + const auto& point = get(point_map, item); + + const IFT x = static_cast(CGAL::to_double(point.x() - xmin)); + const IFT y = static_cast(CGAL::to_double(point.y() - ymin)); + const IFT z = static_cast(CGAL::to_double(point.z() - zmin)); + const IFT r = x * x + y * y + z * z; + + A[1] += x; + A[2] += y; + A[3] += z; + A[4] += r; + A[5] += x * x; + A[6] += x * y; + A[7] += x * z; + A[8] += x * r; + A[9] += y * y; + A[10] += y * z; + A[11] += y * r; + A[12] += z * z; + A[13] += z * r; + A[14] += r * r; + } + + Vector eigenvalues = { + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0) + }; + Matrix eigenvectors = { + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0), + IFT(0), IFT(0), IFT(0), IFT(0), IFT(0) + }; + Diagonalize_traits:: + diagonalize_selfadjoint_covariance_matrix(A, eigenvalues, eigenvectors); + + // Perfect plane case, no sphere can be fitted. + if (eigenvectors[4] == IFT(0)) { + return std::make_pair( + std::make_pair(FT(-1), Point_3()), + -static_cast((std::numeric_limits::max)())); + } + CGAL_assertion(eigenvectors[4] != IFT(0)); + + // Other cases. + const FT half = FT(1) / FT(2); + const Point_3 fitted_center = Point_3( + xmin - half * static_cast(eigenvectors[1] / eigenvectors[4]), + ymin - half * static_cast(eigenvectors[2] / eigenvectors[4]), + zmin - half * static_cast(eigenvectors[3] / eigenvectors[4]) + ); + + FT fitted_radius = FT(0); + for (auto item : region) { + const auto& point = get(point_map, item); + fitted_radius += sqrt(squared_distance_3(point, fitted_center)); + } + fitted_radius /= static_cast(region.size()); + + // Compute score. + FT score = FT(-1); + if (compute_score) { + score = FT(0); + for (auto item : region) { + const auto& point = get(point_map, item); + score -= CGAL::abs(sqrt(squared_distance_3(point, fitted_center)) + - fitted_radius); + } + } + + return std::make_pair( + std::make_pair(fitted_radius, fitted_center), score); + } + + template< + typename Traits, + typename Region, + typename PointMap, + typename NormalMap> + std::pair, + typename Traits::FT> + create_cylinder( + const Region& region, const PointMap point_map, + const NormalMap normal_map, + const Traits& traits) { + + if (region.size() < 6) + return std::make_pair( + std::make_pair + (-1.0, typename Traits::Line_3()), + (std::numeric_limits::max)()); + + using FT = typename Traits::FT; + using Line_3 = typename Traits::Line_3; + + Line_3 fitted_axis; + FT squared_radius; + + FT error = fit_cylinder + (region, point_map, normal_map, fitted_axis, + squared_radius, traits); + + // A negative squared_radius is returned if the cylinder fitting failed. + // This can be the case if the normals are very close to each other. + if (squared_radius < 0) + return std::make_pair( + std::make_pair + (-1.0, typename Traits::Line_3()), + (std::numeric_limits::max)()); + + return std::make_pair( + std::make_pair(sqrt(squared_radius), fitted_axis), error); } } // namespace internal - -namespace RG { - - template - class Plane { - - public: - using Traits = GeomTraits; - using FT = typename Traits::FT; - using Point_2 = typename Traits::Point_2; - using Point_3 = typename Traits::Point_3; - using Plane_3 = typename Traits::Plane_3; - using Vector_3 = typename Traits::Vector_3; - - template< - typename Input_range, - typename Point_map> - Plane( - const Input_range& input_range, - const Point_map point_map, - const std::vector& region, - const Plane_3& plane) { - - FT x = FT(0), y = FT(0), z = FT(0); - for (const std::size_t idx : region) { - const auto& p = get(point_map, *(input_range.begin() + idx)); - x += p.x(); - y += p.y(); - z += p.z(); - } - x /= static_cast(region.size()); - y /= static_cast(region.size()); - z /= static_cast(region.size()); - - m_centroid = Point_3(x, y, z); - m_base1 = plane.base1() / static_cast(CGAL::sqrt( - CGAL::to_double(plane.base1() * plane.base1()))); - m_base2 = plane.base2() / static_cast(CGAL::sqrt( - CGAL::to_double(plane.base2() * plane.base2()))); - } - - Point_2 to_2d(const Point_3& query) const { - const Vector_3 v(m_centroid, query); - return Point_2(v * m_base1, v * m_base2); - } - - Point_3 to_3d(const Point_2& query) const { - return m_centroid + query.x() * m_base1 + query.y() * m_base2; - } - - private: - Point_3 m_centroid; - Vector_3 m_base1, m_base2; - }; - -} // namespace RG } // namespace Shape_detection } // namespace CGAL diff --git a/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h b/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h deleted file mode 100644 index d74b50c3c99..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h +++ /dev/null @@ -1,780 +0,0 @@ -// Copyright (c) 2015 INRIA Sophia-Antipolis (France). -// Copyright (c) 2017 GeometryFactory Sarl (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// Author(s) : Florent Lafarge, Simon Giraudot - -#ifndef CGAL_SHAPE_DETECTION_REGION_GROWING_DEPRECATED_H -#define CGAL_SHAPE_DETECTION_REGION_GROWING_DEPRECATED_H - -#include - -// STL includes. -#include - -// Shape detection includes. -#include - -// CGAL includes. -#include -#include -#include -#include -#include -#include - -// CGAL boost includes. -#include -#include - -// Boost includes. -#include -#include - -// Deprecated --> -#define CGAL_DEPRECATED_HEADER "" -#define CGAL_REPLACEMENT_HEADER "" - -#define CGAL_DEPRECATED_MESSAGE_DETAILS \ - "CGAL::Shape_detection_3::Region_growing<> has been replaced by the class "\ - "CGAL::Shape_detection::Region_growing<>." - -#include - -namespace CGAL { -namespace Shape_detection { - - #ifdef DOXYGEN_NS - namespace deprecated { - #endif - - /*! - \ingroup PkgShapeDetectionDEPR - \brief A shape detection algorithm using a region growing method. - - Given a point set in 3D space with unoriented normals, sampled on surfaces, - this class enables to detect subsets of connected points lying on the surface of primitive shapes. - Each input point is assigned to either none or at most one detected primitive - shape. The implementation follows \cgalCite{cgal:lm-clscm-12}. - - \tparam Traits a model of `EfficientRANSACTraits` - */ - template - class Region_growing_depr { - - public: - - /// \name Types - /// @{ - - /// \cond SKIP_IN_MANUAL - typedef typename Traits::Input_range::iterator Input_iterator; - typedef typename Traits::FT FT; ///< number type. - typedef typename Traits::Point_3 Point; ///< point type. - typedef typename Traits::Vector_3 Vector; ///< vector type. - typedef typename Traits::Plane_3 Plane; ///< plane type. - /// \endcond - - typedef typename Traits::Input_range Input_range; - ///< Model of the concept `Range` with random access iterators, providing input points and normals - /// through the following two property maps. - - typedef typename Traits::Point_map Point_map; - ///< property map to access the location of an input point. - - typedef typename Traits::Normal_map Normal_map; - ///< property map to access the unoriented normal of an input point. - - typedef CGAL::Shape_detection::Shape_base Shape; ///< shape type. - - typedef CGAL::Shape_detection::Plane Plane_shape; ///< shape type. - - #ifdef DOXYGEN_RUNNING - - typedef unspecified_type Shape_range; - ///< An `Iterator_range` with a bidirectional constant iterator type with value type `boost::shared_ptr`. - - typedef unspecified_type Plane_range; - ///< An `Iterator_range` with a bidirectional constant iterator type with value type `boost::shared_ptr`. - - #else - - struct Shape_range : public Iterator_range< - typename std::vector >::const_iterator> { - typedef Iterator_range< - typename std::vector >::const_iterator> Base; - - Shape_range(boost::shared_ptr > > - extracted_shapes) : - Base(make_range(extracted_shapes->begin(), - extracted_shapes->end())), m_extracted_shapes(extracted_shapes) { } - - private: - boost::shared_ptr > > - m_extracted_shapes; // keeps a reference to the shape vector - }; - - struct Plane_range : public Iterator_range< - typename std::vector >::const_iterator> { - typedef Iterator_range< - typename std::vector >::const_iterator> Base; - - Plane_range(boost::shared_ptr > > - extracted_shapes) : Base(make_range(extracted_shapes->begin(), - extracted_shapes->end())), m_extracted_shapes(extracted_shapes) { } - - private: - boost::shared_ptr > > - m_extracted_shapes; // keeps a reference to the shape vector - }; - - #endif - - /// \cond SKIP_IN_MANUAL - struct Filter_unassigned_points { - Filter_unassigned_points() : m_shape_index(dummy) {} - Filter_unassigned_points(const std::vector &shapeIndex) - : m_shape_index(shapeIndex) { } - - bool operator()(std::size_t x) { - if (x < m_shape_index.size()) - return m_shape_index[x] == -1; - else return true; // to prevent infinite incrementing - } - const std::vector& m_shape_index; - std::vector dummy; - }; - - typedef boost::filter_iterator > - Point_index_iterator; - ///< iterator for indices of points. - /// \endcond - -#ifdef DOXYGEN_RUNNING - typedef unspecified_type Point_index_range; - ///< An `Iterator_range` with a bidirectional iterator with value type `std::size_t` - /// as indices into the input data that has not been assigned to a shape. - /// As this range class has no `size()` method, the method - /// `Efficient_RANSAC::number_of_unassigned_points()` is provided. -#else - typedef Iterator_range Point_index_range; -#endif - - /// @} - - /// \name Parameters - /// @{ - - /*! - %Parameters for the shape detection algorithm. They are explained in detail - in Section \ref Shape_detection_RANSACParameters of the User Manual. - */ - struct Parameters { - Parameters() - : min_points((std::numeric_limits::max)()) - , epsilon(-1) - , normal_threshold((FT) 0.9) - , cluster_epsilon(-1) - { } - - std::size_t min_points; ///< Minimum number of points of a shape. %Default value: 1% of total number of input points. - FT epsilon; ///< Maximum tolerance Euclidean distance from a point and a shape. %Default value: 1% of bounding box diagonal. - FT normal_threshold; ///< Maximum tolerance normal deviation from a point's normal to the normal on shape at projected point. %Default value: 0.9 (around 25 degrees). - FT cluster_epsilon; ///< Maximum distance between points to be considered connected. %Default value: 1% of bounding box diagonal. - }; - - /// @} - - private: - - class My_point_map { - - Input_iterator input_iterator_first; - Point_map point_map; - - public: - typedef typename Point_map::value_type value_type; - typedef typename Point_map::reference reference; - typedef std::size_t key_type; - typedef boost::lvalue_property_map_tag category; - - My_point_map () { } - My_point_map (Input_iterator first, Point_map map) - : input_iterator_first (first), point_map (map) { } - - reference operator[](key_type k) const { - return get(point_map, *(input_iterator_first + k)); - } - - friend reference get (const My_point_map& pmap, key_type idx) { - return pmap[idx]; - } - }; - - typedef typename Traits::Search_traits Search_traits_base; - typedef Search_traits_adapter Search_traits; - typedef CGAL::Fuzzy_sphere Sphere; - typedef CGAL::Kd_tree Tree; - typedef CGAL::Fuzzy_sphere Fuzzy_sphere; - typedef CGAL::Orthogonal_k_neighbor_search Neighbor_search; - typedef typename Neighbor_search::Distance Distance; - - class Sort_by_planarity - { - Input_iterator m_first; - Point_map m_point_map; - My_point_map m_index_map; - Tree& m_tree; - FT m_cluster_epsilon; - mutable boost::shared_ptr > nb_points; - mutable boost::shared_ptr > score; - - public: - Sort_by_planarity (Input_iterator first, - Point_map point_map, - My_point_map index_map, - std::size_t size, Tree& tree, FT cluster_epsilon) - : m_first (first) - , m_point_map (point_map) - , m_index_map (index_map) - , m_tree (tree) - , m_cluster_epsilon (cluster_epsilon) - , nb_points (new std::vector(size, 0)) - , score (new std::vector(size, -1.)) { } - - void compute_score (const std::size_t& idx) const - { - static std::vector neighbors; - - neighbors.clear(); - Sphere fs (get(m_point_map, *(m_first + idx)), m_cluster_epsilon * 2, 0, m_tree.traits()); - m_tree.search (std::back_inserter (neighbors), fs); - - (*nb_points)[idx] = neighbors.size(); - - Plane dummy; - (*score)[idx] - = CGAL::linear_least_squares_fitting_3 - (boost::make_transform_iterator (neighbors.begin(), - CGAL::Property_map_to_unary_function(m_index_map)), - boost::make_transform_iterator (neighbors.end(), - CGAL::Property_map_to_unary_function(m_index_map)), - dummy, - CGAL::Dimension_tag<0>()); - } - - bool operator() (const std::size_t& a, const std::size_t& b) const - { - if ((*score)[a] == -1.) - compute_score(a); - if ((*score)[b] == -1.) - compute_score(b); - - // if ((*nb_points)[a] != (*nb_points)[b]) - // return (*nb_points)[a] > (*nb_points)[b]; - return (*score)[a] > (*score)[b]; - } - }; - - // Creates a function pointer for instancing shape instances. - template - static Shape *factory() { - return new ShapeT; - } - - Parameters m_options; - - // Traits class. - Traits m_traits; - - // Maps index into points to assigned extracted primitive. - std::vector m_shape_index; - std::size_t m_num_available_points; - std::size_t m_num_total_points; - - // Give the index of the subset of point i. - std::vector m_index_subsets; - - boost::shared_ptr > > m_extracted_shapes; - - std::vector m_shape_factories; - - // Iterators of input data. - bool m_valid_iterators; - Input_iterator m_input_iterator_first, m_input_iterator_beyond; - Point_map m_point_map; - Normal_map m_normal_map; - My_point_map m_index_map; - Tree* m_tree; - - public: - - /// \name Initialization - /// @{ - - /*! - Constructs an empty shape detection object. - */ - Region_growing_depr (Traits t = Traits()) - : m_traits(t) - , m_num_available_points(0) - , m_num_total_points(0) - , m_valid_iterators(false) - , m_tree (nullptr) - {} - - /*! - Releases all memory allocated by this instances including shapes. - */ - ~Region_growing_depr() { - clear(); - } - - /*! - Retrieves the traits class. - */ - const Traits& - traits() const - { - return m_traits; - } - - /*! - Retrieves the point property map. - */ - const Point_map& point_map() const { return m_point_map; } - - /*! - Retrieves the normal property map. - */ - const Normal_map& normal() const { return m_normal_map; } - - Input_iterator input_iterator_first() const - { - return m_input_iterator_first; - } - - Input_iterator input_iterator_beyond() const - { - return m_input_iterator_beyond; - } - - /*! - Sets the input data. The range must stay valid - until the detection has been performed and the access to the - results is no longer required. This function first calls `clear()`. - */ - void set_input( - Input_range& input_range, - ///< range of input data. - Point_map point_map = Point_map(), - ///< property map to access the position of an input point. - Normal_map normal_map = Normal_map() - ///< property map to access the normal of an input point. - ) - { - m_point_map = point_map; - m_normal_map = normal_map; - - m_input_iterator_first = input_range.begin(); - m_input_iterator_beyond = input_range.end(); - - m_index_map = My_point_map (m_input_iterator_first, m_point_map); - clear(); - - m_extracted_shapes = - boost::make_shared > >(); - - m_num_available_points = m_num_total_points = std::distance( - m_input_iterator_first, m_input_iterator_beyond); - - m_valid_iterators = true; - } - /*! - Registers in the detection engine the shape type `ShapeType` that must inherit from `Shape_base`. - For example, for registering a plane as detectable shape you should call - `region_growing.add_shape_factory< Shape_detection::Plane >();`. - - Note that if your call is within a template, you should add the - `template` keyword just before `add_shape_factory`: - `region_growing.template add_shape_factory< - Shape_detection::Plane >();`. - - \note So far, region growing algorithm only supports plane detection. - */ - template - void add_shape_factory() { - CGAL_static_assertion_msg ((boost::is_convertible::value), - "Region growing only supports Plane shapes."); - - m_shape_factories.push_back(factory); - } - - /*! - Constructs internal data structures required for the shape detection. - These structures only depend on the input data, i.e. the points and - normal vectors. This method is called by `detect()`, if it was not called - before by the user. - */ - bool preprocess() { - if (m_num_total_points == 0) - return false; - - m_tree = new Tree (boost::counting_iterator(0), - boost::counting_iterator(m_num_total_points), - typename Tree::Splitter(), - m_index_map); - m_tree->build(); - return true; - } - /// @} - - /// \name Memory Management - /// @{ - /*! - Removes all shape types registered for detection. - */ - void clear_shape_factories() { - m_shape_factories.clear(); - } - - /*! - Removes all detected shapes. - All internal structures are cleaned, including formerly detected shapes. - Thus iterators and ranges retrieved through `shapes()`, `planes()` and `indices_of_unassigned_points()` - are invalidated. - */ - void clear() - { - // If there is no data yet, there are no data structures. - if (!m_valid_iterators) - return; - - if (m_tree != nullptr) - { - delete m_tree; - m_tree = nullptr; - } - - std::vector().swap(m_shape_index); - - m_extracted_shapes = - boost::make_shared > >(); - - m_num_available_points = m_num_total_points; - } - - /// @} - - /// \name Detection - /// @{ - - /*! - Performs the shape detection. - - \param options %Parameters for shape detection. - - \param callback can be omitted if the algorithm should be run - without any callback. It is called regularly when the algorithm - is running: the current advancement (between 0. and 1.) is - passed as parameter. If it returns `true`, then the algorithm - continues its execution normally; if it returns `false`, the - algorithm is stopped. Note that this interruption may leave the - class in an invalid state. - - \return `true` if shape types have been registered and - input data has been set. Otherwise, `false` is returned. - */ - bool detect(const Parameters &options = Parameters(), - const std::function& callback - = std::function()) - { - // No shape types for detection or no points provided, exit. - if (m_shape_factories.size() == 0 || - (m_input_iterator_beyond - m_input_iterator_first) == 0) - return false; - - if (!preprocess()) - return false; - - // Reset data structures possibly used by former search. - m_extracted_shapes = - boost::make_shared > >(); - m_num_available_points = m_num_total_points; - - m_options = options; - - Bbox_3 bbox = CGAL::bbox_3 - (boost::make_transform_iterator (m_input_iterator_first, - CGAL::Property_map_to_unary_function(m_point_map)), - boost::make_transform_iterator (m_input_iterator_beyond, - CGAL::Property_map_to_unary_function(m_point_map))); - - FT bbox_diagonal = (FT) CGAL::sqrt( - (bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) - + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) - + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); - - // Epsilon or cluster_epsilon have been set by the user? - // If not, derive from bounding box diagonal. - m_options.epsilon = (m_options.epsilon < 0) - ? bbox_diagonal * (FT) 0.01 : m_options.epsilon; - - m_options.cluster_epsilon = (m_options.cluster_epsilon < 0) - ? bbox_diagonal * (FT) 0.01 : m_options.cluster_epsilon; - - // Minimum number of points has been set? - m_options.min_points = - (m_options.min_points >= m_num_available_points) ? - (std::size_t)((FT)0.01 * m_num_available_points) : - m_options.min_points; - m_options.min_points = (m_options.min_points < 10) ? 10 : m_options.min_points; - - // Initializing the shape index - m_shape_index.assign(m_num_available_points, -1); - - Distance tr_dist (m_index_map); - - // Initialization structures. - int class_index = -1; - - if (callback && !callback(0.)) - return false; - - std::vector neighbors; - - std::vector sorted_indices (m_num_total_points); - std::copy (boost::counting_iterator(0), - boost::counting_iterator(m_num_total_points), - sorted_indices.begin()); -#define SORT_INDICES -#ifdef SORT_INDICES - std::sort (sorted_indices.begin(), - sorted_indices.end(), - Sort_by_planarity(m_input_iterator_first, m_point_map, m_index_map, - m_num_total_points, *m_tree, m_options.cluster_epsilon)); -#endif - std::vector fits(m_num_total_points, -1.); - m_num_available_points = m_num_total_points; - std::vector index_container; - std::vector index_container_former_ring; - std::set index_container_current_ring; - - std::size_t num_to_test = 1 + m_num_total_points - m_options.min_points; - for (std::size_t I = 0; I < num_to_test; ++ I) - { - if (callback && !callback(1. - (m_num_available_points / double(m_num_total_points)))) - return false; - - std::size_t i = sorted_indices[I]; - - Input_iterator it = m_input_iterator_first + i; - - if (m_shape_index[i] != -1) - continue; - - m_shape_index[i] = ++ class_index; - - int conti = 0; // to accelerate least_square fitting - - Vector plane_normal = get(m_normal_map, *it); - plane_normal = plane_normal / std::sqrt(plane_normal * plane_normal); - - Plane optimal_plane(get(m_point_map, *it), - plane_normal); - - // initialization containers - - index_container.clear(); - index_container.push_back(i); - - index_container_former_ring.clear(); - index_container_former_ring.push_back(i); - - index_container_current_ring.clear(); - - // propagation - bool propagation = true; - do - { - propagation = false; - - for (typename std::vector::iterator icfrit = index_container_former_ring.begin(); - icfrit != index_container_former_ring.end(); ++ icfrit) - { - std::size_t point_index = *icfrit; - - Input_iterator pit = m_input_iterator_first + point_index; - - neighbors.clear(); - Sphere fs (get(m_point_map, *pit), m_options.cluster_epsilon, 0, m_tree->traits()); - m_tree->search (std::back_inserter (neighbors), fs); - - for (std::size_t nb = 0; nb < neighbors.size(); ++ nb) - { - std::size_t neighbor_index = neighbors[nb]; - Input_iterator nbit = m_input_iterator_first + neighbor_index; - - if (m_shape_index[neighbor_index] != -1) - continue; - - const Point& neighbor = get(m_point_map, *nbit); - double distance = CGAL::squared_distance(neighbor, optimal_plane); - - Vector normal = get(m_normal_map, *nbit); - normal = normal / std::sqrt (normal * normal); - - if (distance > m_options.epsilon * m_options.epsilon - || std::fabs(normal * plane_normal) < m_options.normal_threshold) - continue; - - m_shape_index[neighbor_index] = class_index; - propagation = true; - index_container_current_ring.insert(neighbor_index); - } - } - - // update containers - index_container_former_ring.clear(); - index_container_former_ring.reserve (index_container_current_ring.size()); - index_container.reserve (index_container.size() + index_container_current_ring.size()); - for (typename std::set::iterator lit = index_container_current_ring.begin(); - lit != index_container_current_ring.end(); ++lit) - { - index_container_former_ring.push_back(*lit); - index_container.push_back(*lit); - } - index_container_current_ring.clear(); - - conti++; - if (index_container.size() < 5) - continue; - - if ((conti < 10) || (conti<50 && conti % 10 == 0) || (conti>50 && conti % 500 == 0)) - { - std::list listp; - for (typename std::vector::iterator icit = index_container.begin(); - icit != index_container.end(); ++ icit) - listp.push_back(get (m_point_map, *(m_input_iterator_first + *icit))); - - Plane reajusted_plane; - CGAL::linear_least_squares_fitting_3(listp.begin(), - listp.end(), - reajusted_plane, - CGAL::Dimension_tag<0>()); - optimal_plane = reajusted_plane; - plane_normal = optimal_plane.orthogonal_vector(); - plane_normal = plane_normal / std::sqrt(plane_normal * plane_normal); - } - } - while (propagation); - - if (index_container.size() >= m_options.min_points) - { - Shape *p = (Shape *) (*(m_shape_factories.begin()))(); - - // BUG something fishy around here. - m_num_available_points -= index_container.size(); - - p->compute (index_container, m_input_iterator_first, m_traits, - m_point_map, m_normal_map, m_options.epsilon, m_options.normal_threshold); - p->m_indices.clear(); - std::copy (index_container.begin(), index_container.end(), - std::back_inserter (p->m_indices)); - - Plane_shape* ps = dynamic_cast(p); - CGAL_assume (ps != nullptr); - ps->update (optimal_plane); - m_extracted_shapes->push_back (boost::shared_ptr(p)); - } - else - { - class_index--; - m_shape_index[i] = -1; - for (typename std::vector::iterator icit = index_container.begin(); - icit != index_container.end(); ++ icit) - m_shape_index[*icit] = -1; - } - } - return true; - } - - /// @} - - /// \name Access - /// @{ - /*! - Returns an `Iterator_range` with a bidirectional iterator with value type - `boost::shared_ptr` over the detected shapes in the order of detection. - - \note So far, region growing algorithm only supports plane - detection, so this method is equivalent to `planes()` except - that it returns planes with the abstract type `Shape`. - */ - Shape_range shapes() const { - return Shape_range(m_extracted_shapes); - } - - /*! - Returns an `Iterator_range` with a bidirectional iterator with - value type `boost::shared_ptr` over only the - detected planes in the order of detection. - */ - Plane_range planes() const { - boost::shared_ptr > > planes - = boost::make_shared > >(); - - for (std::size_t i = 0; i < m_extracted_shapes->size(); ++ i) - { - boost::shared_ptr pshape - = boost::dynamic_pointer_cast((*m_extracted_shapes)[i]); - - // Ignore all shapes other than plane. - if (pshape != boost::shared_ptr()) - planes->push_back (pshape); - } - return Plane_range(planes); - } - - /*! - Number of points not assigned to a shape. - */ - std::size_t number_of_unassigned_points() { - return m_num_available_points; - } - - /*! - Returns an `Iterator_range` with a bidirectional iterator with the value type - `std::size_t` as indices into the input data that has not been assigned to a shape. - */ - Point_index_range indices_of_unassigned_points() { - Filter_unassigned_points fup(m_shape_index); - - Point_index_iterator p1 = - boost::make_filter_iterator( - fup, - boost::counting_iterator(0), - boost::counting_iterator(m_shape_index.size())); - - return make_range(p1, Point_index_iterator(p1.end())); - } - /// @} - }; - - #ifdef DOXYGEN_NS - } // namespace deprecated - #endif - -} // namespace Shape_detection -} // namespace CGAL - -// --< - -#endif // CGAL_SHAPE_DETECTION_REGION_GROWING_DEPRECATED_H diff --git a/Shape_detection/include/CGAL/Shape_detection/deprecated/Shape_detection_traits.h b/Shape_detection/include/CGAL/Shape_detection/deprecated/Shape_detection_traits.h deleted file mode 100644 index c4f890cb7c0..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection/deprecated/Shape_detection_traits.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2015 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Sven Oesau, Yannick Verdie, Clément Jamin, Pierre Alliez -// - -#ifndef CGAL_SHAPE_DETECTION_SHAPE_DETECTION_TRAITS_DEPRECATED_H -#define CGAL_SHAPE_DETECTION_SHAPE_DETECTION_TRAITS_DEPRECATED_H - -#include - -// CGAL includes. -#include - -// Deprecated --> -#define CGAL_DEPRECATED_HEADER "" -#define CGAL_REPLACEMENT_HEADER "" - -#define CGAL_DEPRECATED_MESSAGE_DETAILS \ - "CGAL::Shape_detection_3::Shape_detection_traits<> has been replaced by the class "\ - "CGAL::Shape_detection::Efficient_RANSAC_traits<>." - -#include - -namespace CGAL { -namespace Shape_detection { - - #ifdef DOXYGEN_NS - namespace deprecated { - #endif - - /*! - \ingroup PkgShapeDetectionDEPR - \brief A traits class to use with the shape detection - classes `Efficient_RANSAC` and `deprecated::Region_growing`. - - \cgalModels `EfficientRANSACTraits` - - \tparam Gt a model of the concept `#Kernel` with `Gt::FT` being - `float` or `double`. - - \tparam InputRange is a model of `Range` with random access iterators, - providing input points and normals through the following two property maps. - - \tparam InputPointMap is a model of `ReadablePropertyMap` with - `std::iterator_traits::%value_type` as key type and - `Gt::Point_3` as value type. - - \tparam InputNormalMap is a model of `ReadablePropertyMap` with - `std::iterator_traits::%value_type` as key type and - `Gt::Vector_3` as value type. - */ - template - struct Shape_detection_traits { - /// - typedef typename Gt::FT FT; - /// - typedef typename Gt::Point_3 Point_3; - /// - typedef typename Gt::Vector_3 Vector_3; - /// - typedef typename Gt::Sphere_3 Sphere_3; - /// - typedef typename Gt::Segment_3 Segment_3; - /// - typedef typename Gt::Line_3 Line_3; - /// - typedef typename Gt::Circle_2 Circle_2; - /// - typedef typename Gt::Plane_3 Plane_3; - /// - typedef typename Gt::Point_2 Point_2; - /// - typedef typename Gt::Vector_2 Vector_2; - /// - typedef InputRange Input_range; - /// - typedef InputPointMap Point_map; - /// - typedef InputNormalMap Normal_map; - /// - typedef CGAL::Search_traits_3 Search_traits; - /// - Shape_detection_traits(const Gt& gt = Gt()) - : m_gt(gt) { } - - typedef typename Gt::Construct_point_3 Construct_point_3; - Construct_point_3 construct_point_3_object() const - { return m_gt.construct_point_3_object(); } - - typedef typename Gt::Construct_vector_3 Construct_vector_3; - Construct_vector_3 construct_vector_3_object() const - { return m_gt.construct_vector_3_object(); } - - typedef typename Gt::Construct_point_2 Construct_point_2; - Construct_point_2 construct_point_2_object() const - { return m_gt.construct_point_2_object(); } - - typedef typename Gt::Construct_vector_2 Construct_vector_2; - Construct_vector_2 construct_vector_2_object() const - { return m_gt.construct_vector_2_object(); } - - typedef typename Gt::Construct_sphere_3 Construct_sphere_3; - Construct_sphere_3 construct_sphere_3_object() const - { return m_gt.construct_sphere_3_object(); } - - typedef typename Gt::Construct_line_3 Construct_line_3; - Construct_line_3 construct_line_3_object() const - { return m_gt.construct_line_3_object(); } - - typedef typename Gt::Construct_circle_2 Construct_circle_2; - Construct_circle_2 construct_circle_2_object() const - { return m_gt.construct_circle_2_object(); } - - typedef typename Gt::Construct_point_on_3 Construct_point_on_3; - Construct_point_on_3 construct_point_on_3_object() const - { return m_gt.construct_point_on_3_object(); } - - typedef typename Gt::Compute_x_2 Compute_x_2; - Compute_x_2 compute_x_2_object() const - { return m_gt.compute_x_2_object(); } - - typedef typename Gt::Compute_y_2 Compute_y_2; - Compute_y_2 compute_y_2_object() const - { return m_gt.compute_y_2_object(); } - - typedef typename Gt::Compute_x_3 Compute_x_3; - Compute_x_3 compute_x_3_object() const - { return m_gt.compute_x_3_object(); } - - typedef typename Gt::Compute_y_3 Compute_y_3; - Compute_y_3 compute_y_3_object() const - { return m_gt.compute_y_3_object(); } - - typedef typename Gt::Compute_z_3 Compute_z_3; - Compute_z_3 compute_z_3_object() const - { return m_gt.compute_z_3_object(); } - - typedef typename Gt::Compute_squared_length_3 Compute_squared_length_3; - Compute_squared_length_3 compute_squared_length_3_object() const - { return m_gt.compute_squared_length_3_object(); } - - typedef typename Gt::Compute_squared_length_2 Compute_squared_length_2; - Compute_squared_length_2 compute_squared_length_2_object() const - { return m_gt.compute_squared_length_2_object(); } - - typedef typename Gt::Construct_scaled_vector_3 Construct_scaled_vector_3; - Construct_scaled_vector_3 construct_scaled_vector_3_object() const - { return m_gt.construct_scaled_vector_3_object(); } - - typedef typename Gt::Construct_sum_of_vectors_3 Construct_sum_of_vectors_3; - Construct_sum_of_vectors_3 construct_sum_of_vectors_3_object() const - { return m_gt.construct_sum_of_vectors_3_object(); } - - typedef typename Gt::Construct_translated_point_3 Construct_translated_point_3; - Construct_translated_point_3 construct_translated_point_3_object() const - { return m_gt.construct_translated_point_3_object(); } - - typedef typename Gt::Compute_scalar_product_3 Compute_scalar_product_3; - Compute_scalar_product_3 compute_scalar_product_3_object() const - { return m_gt.compute_scalar_product_3_object(); } - - typedef typename Gt::Construct_cross_product_vector_3 Construct_cross_product_vector_3; - Construct_cross_product_vector_3 construct_cross_product_vector_3_object() const - { return m_gt.construct_cross_product_vector_3_object(); } - - typedef typename Gt::Construct_center_3 Construct_center_3; - Construct_center_3 construct_center_3_object() const - { return m_gt.construct_center_3_object(); } - - typedef typename Gt::Construct_center_2 Construct_center_2; - Construct_center_2 construct_center_2_object() const - { return m_gt.construct_center_2_object(); } - - typedef typename Gt::Compute_squared_radius_3 Compute_squared_radius_3; - Compute_squared_radius_3 compute_squared_radius_3_object() const - { return m_gt.compute_squared_radius_3_object(); } - - typedef typename Gt::Compute_squared_radius_2 Compute_squared_radius_2; - Compute_squared_radius_2 compute_squared_radius_2_object() const - { return m_gt.compute_squared_radius_2_object(); } - - typedef typename Gt::Collinear_2 Collinear_2; - Collinear_2 collinear_2_object() const - { return m_gt.collinear_2_object(); } - - typedef typename Gt::Intersect_3 Intersect_3; - Intersect_3 intersection_3_object() const - { return m_gt.intersection_3_object(); } - - private: - Gt m_gt; - }; - - #ifdef DOXYGEN_NS - } // namespace deprecated - #endif - -} // namespace Shape_detection -} // namespace CGAL - -// --< - -#endif // CGAL_SHAPE_DETECTION_SHAPE_DETECTION_TRAITS_DEPRECATED_H diff --git a/Shape_detection/include/CGAL/Shape_detection_3.h b/Shape_detection/include/CGAL/Shape_detection_3.h deleted file mode 100644 index f448c640d36..00000000000 --- a/Shape_detection/include/CGAL/Shape_detection_3.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2015 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Sven Oesau, Yannick Verdie, Clément Jamin, Pierre Alliez, Florent Lafarge, Simon Giraudot, Thien Hoang, Dmitry Anisimov -// - -#ifndef CGAL_SHAPE_DETECTION_3_DEPRECATED_H -#define CGAL_SHAPE_DETECTION_3_DEPRECATED_H - -#include - -#include - -// Deprecated --> -#include -#include - -#define CGAL_DEPRECATED_MESSAGE_DETAILS \ - "CGAL::Shape_detection_3 namespace has been replaced by the namespace "\ - "CGAL::Shape_detection." - -#include - -namespace CGAL { - namespace Shape_detection_3 = Shape_detection; -} -// --< - -#endif // CGAL_SHAPE_DETECTION_3_DEPRECATED_H diff --git a/Shape_detection/package_info/Shape_detection/dependencies b/Shape_detection/package_info/Shape_detection/dependencies index 0e1d2b20985..63e6337e4fb 100644 --- a/Shape_detection/package_info/Shape_detection/dependencies +++ b/Shape_detection/package_info/Shape_detection/dependencies @@ -6,8 +6,6 @@ Circulator Distance_2 Distance_3 Filtered_kernel -HalfedgeDS -Hash_map Homogeneous_kernel Installation Intersections_2 @@ -15,11 +13,9 @@ Intersections_3 Interval_support Kernel_23 Kernel_d -Modifier Modular_arithmetic Number_types Orthtree -Polyhedron Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools @@ -30,4 +26,3 @@ Shape_detection Solver_interface Spatial_searching Stream_support -Surface_mesh diff --git a/Shape_detection/package_info/Shape_detection/description.txt b/Shape_detection/package_info/Shape_detection/description.txt index 968caf8b6a7..3a879a7e775 100644 --- a/Shape_detection/package_info/Shape_detection/description.txt +++ b/Shape_detection/package_info/Shape_detection/description.txt @@ -3,6 +3,3 @@ Shape Detection This CGAL package implements the Efficient RANSAC (RANdom SAmple Consensus) approach for detecting arbitrary shapes in an unorganized point set with unoriented normals and the Region Growing approach for detecting shapes in a set of arbitrary items. -For the latter approach, CGAL provides three particular instances of the algorithm: -detecting lines in a 2D point set, detecting planes in a 3D point set, -and detecting planes on a polygon mesh. diff --git a/Shape_detection/package_info/Shape_detection/long_description.txt b/Shape_detection/package_info/Shape_detection/long_description.txt index b2523e76a4d..b9cf7d3c5bc 100644 --- a/Shape_detection/package_info/Shape_detection/long_description.txt +++ b/Shape_detection/package_info/Shape_detection/long_description.txt @@ -9,6 +9,7 @@ Additional shapes can be detected, given a custom shape class by the user. In addition to the RANSAC algorithm, the generic Region Growing algorithm is implemented. This algorithm can detect shapes in a set of arbitrary items. In particular, -CGAL provides three instances of the algorithm: detecting lines in a 2D point set, -detecting planes in a 3D point set, and detecting planes on a polygon mesh. +CGAL provides several instances of the algorithm: detecting lines and circles in a 2D point set, +detecting planes, spheres, and cylinders in a 3D point set, detecting planes on a polygon mesh, detecting lines +in a 2D/3D segment set, and detecting lines on a 2D/3D polyline. Other custom instances can be easily added by the user. diff --git a/Shape_detection/test/Shape_detection/CMakeLists.txt b/Shape_detection/test/Shape_detection/CMakeLists.txt index e625c9f8b83..ac4e28e2877 100644 --- a/Shape_detection/test/Shape_detection/CMakeLists.txt +++ b/Shape_detection/test/Shape_detection/CMakeLists.txt @@ -21,7 +21,9 @@ create_single_source_cgal_program("test_efficient_RANSAC_scene.cpp") find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater) include(CGAL_Eigen3_support) if(TARGET CGAL::Eigen3_support) + create_single_source_cgal_program("test_region_growing_basic.cpp") + create_single_source_cgal_program("test_region_growing_strict.cpp") create_single_source_cgal_program("test_region_growing_on_cube.cpp") create_single_source_cgal_program("test_region_growing_on_point_set_2.cpp") create_single_source_cgal_program("test_region_growing_on_point_set_3.cpp") @@ -34,6 +36,7 @@ if(TARGET CGAL::Eigen3_support) foreach( target test_region_growing_basic + test_region_growing_strict test_region_growing_on_cube test_region_growing_on_point_set_2 test_region_growing_on_point_set_3 diff --git a/Shape_detection/test/Shape_detection/README.md b/Shape_detection/test/Shape_detection/README.md deleted file mode 100644 index b6fbaf655bd..00000000000 --- a/Shape_detection/test/Shape_detection/README.md +++ /dev/null @@ -1,6 +0,0 @@ -README: - -Data: -To keep the size of this package small, the point_set_3.xyz file is simplified. -The full version, which is used in docs, can be found here: -https://github.com/... /data diff --git a/Shape_detection/test/Shape_detection/test_region_growing_basic.cpp b/Shape_detection/test/Shape_detection/test_region_growing_basic.cpp index 3e6ed93d3f3..d1c4c11a045 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_basic.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_basic.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace SD = CGAL::Shape_detection; using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; @@ -23,84 +23,68 @@ using Vector_2 = typename Kernel::Vector_2; using Point_with_normal = std::pair; using Input_range = std::vector; -using Point_map = CGAL::First_of_pair_property_map; -using Normal_map = CGAL::Second_of_pair_property_map; - -using Neighbor_query = SD::Point_set::Sphere_neighbor_query; -using Region_type = SD::Point_set::Least_squares_line_fit_region; -using Region_growing = SD::Region_growing; +using Deref_map = CGAL::Dereference_property_map; +using Point_map = CGAL::Compose_property_map>; +using Normal_map = CGAL::Compose_property_map>; +using Neighbor_query = SD::Point_set::Sphere_neighbor_query; +using Region_type = SD::Point_set::Least_squares_line_fit_region; +using Region_growing = SD::Region_growing; int main(int argc, char *argv[]) { - bool success = true; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_2.xyz")); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/buildings_outline.xyz")); CGAL::IO::set_ascii_mode(in); + assert(in); - if (!in) { - std::cout << - "Error: cannot read the file point_set_2.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - assert(false); - return EXIT_FAILURE; - } - - Input_range input_range; FT a, b, c, d, e, f; - + Input_range input_range; while (in >> a >> b >> c >> d >> e >> f) input_range.push_back(std::make_pair(Point_2(a, b), Vector_2(d, e))); - in.close(); - assert(input_range.size() == 3634); - if (input_range.size() != 3634) - success = false; + + Point_map point_map; + Normal_map normal_map; // Create parameter classes. - Neighbor_query neighbor_query( - input_range); - Region_type region_type( - input_range); + Neighbor_query neighbor_query(input_range); + Region_type region_type; // Run region growing. Region_growing region_growing( input_range, neighbor_query, region_type); - // Test data. - std::vector unassigned_points; - region_growing.unassigned_items(std::back_inserter(unassigned_points)); - + std::vector unassigned_points; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); assert(unassigned_points.size() == 3634); - if (unassigned_points.size() != 3634) - success = false; - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - assert(regions.size() != 0); - if (regions.size() == 0) - success = false; + const std::size_t num_regions = regions.size(); + assert(num_regions != 0); unassigned_points.clear(); - region_growing.unassigned_items(std::back_inserter(unassigned_points)); + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); + const std::size_t num_unassigned_points = unassigned_points.size(); + assert(num_unassigned_points != 3634); - assert(unassigned_points.size() != 3634); - if (unassigned_points.size() == 3634) - success = false; - - const std::size_t num_regions = regions.size(); regions.clear(); region_growing.detect(std::back_inserter(regions)); - assert(regions.size() == num_regions); - if (regions.size() != num_regions) - success = false; - std::cout << "basic_test_success: " << success << std::endl; - assert(success); + unassigned_points.clear(); + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); + assert(unassigned_points.size() == num_unassigned_points); - return (success) ? EXIT_SUCCESS : EXIT_FAILURE; + region_growing.clear(input_range); + + unassigned_points.clear(); + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); + assert(unassigned_points.size() == 3634); + + std::cout << "rg_basic, epick_test_success: " << true << std::endl; + return EXIT_SUCCESS; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp index e3ea45870ad..ceb277c521d 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_cube.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -29,102 +29,120 @@ bool test_region_growing_on_cube(int argc, char *argv[]) { using Polyhedron = CGAL::Polyhedron_3; using Face_range = typename CGAL::Iterator_range::face_iterator>; - using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; - using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; - using Region_growing = SD::Region_growing; + using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; + using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; + using Sorting = SD::Polygon_mesh::Least_squares_plane_fit_sorting; + using Region_growing = SD::Region_growing; - // Default parameter values for the data file cube.off. + // Default parameter values. const FT distance_threshold = FT(1) / FT(10); const FT angle_threshold = FT(25); const std::size_t min_region_size = 1; // Load data. - std::ifstream in(argc > 1 ? argv[1] : "data/cube.off"); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/cube-sd.off")); CGAL::IO::set_ascii_mode(in); - - if (!in) { - std::cout << - "Error: cannot read the file cube.off!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } + assert(in); Polyhedron polyhedron; in >> polyhedron; - in.close(); const Face_range face_range = faces(polyhedron); - assert(face_range.size() == 6); - if (face_range.size() != 6) - return false; - // Create parameter classes. - Neighbor_query neighbor_query(polyhedron); + for (const auto& face : face_range) { + const auto he = halfedge(face, polyhedron); + const auto vertices = vertices_around_face(he, polyhedron); + assert(vertices.size() == 4); + } - Region_type region_type( - polyhedron, - distance_threshold, angle_threshold, min_region_size); + using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; + const Vertex_to_point_map vertex_to_point_map( + get(CGAL::vertex_point, polyhedron)); - // Run region growing. - Region_growing region_growing( - face_range, neighbor_query, region_type); + for (std::size_t k = 0; k < 3; ++k) // Test stability. + { + // Create parameter classes. + Neighbor_query neighbor_query(polyhedron); + Region_type region_type( + polyhedron, + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size). + vertex_point_map(vertex_to_point_map)); - std::vector< std::vector > regions; - region_growing.detect(std::back_inserter(regions)); + // Sort indices. + Sorting sorting( + polyhedron, neighbor_query, + CGAL::parameters::vertex_point_map(vertex_to_point_map)); + sorting.sort(); - // Test data. - assert(regions.size() == 6); + // Run region growing. + Region_growing region_growing( + face_range, sorting.ordered(), neighbor_query, region_type); - if (regions.size() != 6) - return false; + std::vector regions; + region_growing.detect(std::back_inserter(regions)); + assert(regions.size() == face_range.size()); + for (const auto& region : regions) + assert(region_type.is_valid_region(region.second)); - for (const auto& region : regions) - if (!region_type.is_valid_region(region)) - return false; + std::vector unassigned_faces; + region_growing.unassigned_items(face_range, std::back_inserter(unassigned_faces)); + assert(unassigned_faces.size() == 0); - std::vector unassigned_faces; - region_growing.unassigned_items(std::back_inserter(unassigned_faces)); + const typename Region_growing::Region_map map = region_growing.region_map(); - assert(unassigned_faces.size() == 0); + for (std::size_t i = 0; i < regions.size(); i++) + for (auto& item : regions[i].second) { + if (i != get(map, item)) { + std::cout << "Region map incorrect" << std::endl; + assert(false); + } + } - if (unassigned_faces.size() != 0) - return false; + for (auto& item : unassigned_faces) { + if (std::size_t(-1) != get(map, item)) { + std::cout << "Region map for unassigned incorrect" << std::endl; + assert(false); + } + } + } return true; } int main(int argc, char *argv[]) { - // ------> - - bool cartesian_double_test_success = true; - if (!test_region_growing_on_cube< CGAL::Simple_cartesian >(argc, argv)) - cartesian_double_test_success = false; - - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; - assert(cartesian_double_test_success); + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; // ------> - bool exact_inexact_test_success = true; - if (!test_region_growing_on_cube(argc, argv)) - exact_inexact_test_success = false; - - std::cout << "exact_inexact_test_success: " << exact_inexact_test_success << std::endl; - assert(exact_inexact_test_success); + bool sc_test_success = true; + if (!test_region_growing_on_cube(argc, argv)) + sc_test_success = false; + std::cout << "rg_cube, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); // ------> - bool exact_exact_test_success = true; - if (!test_region_growing_on_cube(argc, argv)) - exact_exact_test_success = false; + bool epick_test_success = true; + if (!test_region_growing_on_cube(argc, argv)) + epick_test_success = false; + std::cout << "rg_cube, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); - std::cout << "exact_exact_test_success: " << exact_exact_test_success << std::endl; - assert(exact_exact_test_success); + // ------> - const bool success = cartesian_double_test_success && exact_inexact_test_success && exact_exact_test_success; + bool epeck_test_success = true; + if (!test_region_growing_on_cube(argc, argv)) + epeck_test_success = false; + std::cout << "rg_cube, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; return (success) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_degenerated_mesh.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_degenerated_mesh.cpp index 155db88d445..8e8431c0fe2 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_degenerated_mesh.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_degenerated_mesh.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -30,103 +30,85 @@ bool test_region_growing_on_degenerated_mesh(int argc, char *argv[]) { using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; - using Region_growing = SD::Region_growing; + using Region_growing = SD::Region_growing; - // Default parameter values for the data file degenerated.off. + // Default parameter values. const FT distance_threshold = FT(1); const FT angle_threshold = FT(45); const std::size_t min_region_size = 5; // Load data. - std::ifstream in(argc > 1 ? argv[1] : "data/degenerated.off"); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/degenerated-sd.off")); CGAL::IO::set_ascii_mode(in); - - if (!in) { - std::cout << - "Error: cannot read the file degenerated.off!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } + assert(in); Surface_mesh surface_mesh; in >> surface_mesh; - in.close(); const Face_range face_range = faces(surface_mesh); - assert(face_range.size() == 13477); - if (face_range.size() != 13477) - return false; - - // Create parameter classes. - Neighbor_query neighbor_query(surface_mesh); using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; const Vertex_to_point_map vertex_to_point_map( get(CGAL::vertex_point, surface_mesh)); + // Create parameter classes. + Neighbor_query neighbor_query(surface_mesh); + Region_type region_type( surface_mesh, - distance_threshold, angle_threshold, min_region_size, - vertex_to_point_map); + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size). + vertex_point_map(vertex_to_point_map)); // Run region growing. Region_growing region_growing( face_range, neighbor_query, region_type); - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - // Test data. - assert(regions.size() >= 265 && regions.size() <= 269); - if (regions.size() < 265 || regions.size() > 269) - return false; - + assert(regions.size() == 298); for (const auto& region : regions) - if (!region_type.is_valid_region(region)) - return false; - - std::vector unassigned_faces; - region_growing.unassigned_items(std::back_inserter(unassigned_faces)); - - assert(unassigned_faces.size() >= 501 && unassigned_faces.size() <= 521); - if (unassigned_faces.size() < 501 || unassigned_faces.size() > 521) - return false; + assert(region_type.is_valid_region(region.second)); + std::vector unassigned_faces; + region_growing.unassigned_items(face_range, std::back_inserter(unassigned_faces)); + assert(unassigned_faces.size() == 496); return true; } int main(int argc, char *argv[]) { - // ------> - - bool cartesian_double_test_success = true; - if (!test_region_growing_on_degenerated_mesh< CGAL::Simple_cartesian >(argc, argv)) - cartesian_double_test_success = false; - - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; - assert(cartesian_double_test_success); + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; // ------> - bool exact_inexact_test_success = true; - if (!test_region_growing_on_degenerated_mesh(argc, argv)) - exact_inexact_test_success = false; - - std::cout << "exact_inexact_test_success: " << exact_inexact_test_success << std::endl; - assert(exact_inexact_test_success); + bool sc_test_success = true; + if (!test_region_growing_on_degenerated_mesh(argc, argv)) + sc_test_success = false; + std::cout << "rg_degmesh, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); // ------> - bool exact_exact_test_success = true; - if (!test_region_growing_on_degenerated_mesh(argc, argv)) - exact_exact_test_success = false; + bool epick_test_success = true; + if (!test_region_growing_on_degenerated_mesh(argc, argv)) + epick_test_success = false; + std::cout << "rg_degmesh, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); - std::cout << "exact_exact_test_success: " << exact_exact_test_success << std::endl; - assert(exact_exact_test_success); + // ------> - const bool success = cartesian_double_test_success && exact_inexact_test_success && exact_exact_test_success; + bool epeck_test_success = true; + if (!test_region_growing_on_degenerated_mesh(argc, argv)) + epeck_test_success = false; + std::cout << "rg_degmesh, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; return (success) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2.cpp index 23408f19ba1..ac293d67494 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -29,108 +29,94 @@ bool test_region_growing_on_point_set_2(int argc, char *argv[]) { using Point_with_normal = std::pair; using Input_range = std::vector; - using Point_map = CGAL::First_of_pair_property_map; - using Normal_map = CGAL::Second_of_pair_property_map; + using Item = typename Input_range::const_iterator; + using Deref_map = CGAL::Dereference_property_map; + using Point_map = CGAL::Compose_property_map>; + using Normal_map = CGAL::Compose_property_map>; - using Neighbor_query = SD::Point_set::Sphere_neighbor_query; - using Region_type = SD::Point_set::Least_squares_line_fit_region; - using Region_growing = SD::Region_growing; + using Neighbor_query = SD::Point_set::Sphere_neighbor_query; + using Region_type = SD::Point_set::Least_squares_line_fit_region; + using Region_growing = SD::Region_growing; - // Default parameter values for the data file point_set_2.xyz. + // Default parameter values. const FT sphere_radius = FT(5); const FT distance_threshold = FT(45) / FT(10); const FT angle_threshold = FT(45); const std::size_t min_region_size = 5; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_2.xyz")); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/buildings_outline.xyz")); CGAL::IO::set_ascii_mode(in); + assert(in); - if (!in) { - std::cout << - "Error: cannot read the file point_set_2.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } - - Input_range input_range; FT a, b, c, d, e, f; - - while (in >> a >> b >> c >> d >> e >> f) - input_range.push_back(std::make_pair(Point_2(a, b), Vector_2(d, e))); - + Input_range input_range; + while (in >> a >> b >> c >> d >> e >> f) { + input_range.push_back( + std::make_pair(Point_2(a, b), Vector_2(d, e))); + } in.close(); - assert(input_range.size() == 3634); - if (input_range.size() != 3634) - return false; // Create parameter classes. Neighbor_query neighbor_query( input_range, - sphere_radius); + CGAL::parameters::sphere_radius(sphere_radius)); Region_type region_type( - input_range, - distance_threshold, angle_threshold, min_region_size); + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size)); // Run region growing. Region_growing region_growing( input_range, neighbor_query, region_type); - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - // Test data. - assert(regions.size() >= 63 && regions.size() <= 67); - if (regions.size() < 63 || regions.size() > 67) - return false; - + assert(regions.size() == 72); for (const auto& region : regions) - if (!region_type.is_valid_region(region)) - return false; - - std::vector unassigned_points; - region_growing.unassigned_items(std::back_inserter(unassigned_points)); - - assert(unassigned_points.size() >= 77 && unassigned_points.size() <= 97); - if (unassigned_points.size() < 77 || unassigned_points.size() > 97) - return false; + assert(region_type.is_valid_region(region.second)); + std::vector unassigned_points; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); + assert(unassigned_points.size() == 86); return true; } int main(int argc, char *argv[]) { - // ------> - - bool cartesian_double_test_success = true; - if (!test_region_growing_on_point_set_2< CGAL::Simple_cartesian >(argc, argv)) - cartesian_double_test_success = false; - - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; - assert(cartesian_double_test_success); + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; // ------> - bool exact_inexact_test_success = true; - if (!test_region_growing_on_point_set_2(argc, argv)) - exact_inexact_test_success = false; - - std::cout << "exact_inexact_test_success: " << exact_inexact_test_success << std::endl; - assert(exact_inexact_test_success); + bool sc_test_success = true; + if (!test_region_growing_on_point_set_2(argc, argv)) + sc_test_success = false; + std::cout << "rg_points2, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); // ------> - bool exact_exact_test_success = true; - if (!test_region_growing_on_point_set_2(argc, argv)) - exact_exact_test_success = false; + bool epick_test_success = true; + if (!test_region_growing_on_point_set_2(argc, argv)) + epick_test_success = false; + std::cout << "rg_points2, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); - std::cout << "exact_exact_test_success: " << exact_exact_test_success << std::endl; - assert(exact_exact_test_success); + // ------> - const bool success = cartesian_double_test_success && exact_inexact_test_success && exact_exact_test_success; + bool epeck_test_success = true; + if (!test_region_growing_on_point_set_2(argc, argv)) + epeck_test_success = false; + std::cout << "rg_points2, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; return (success) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp index a1c4741ea83..acf0640a56e 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_2_with_sorting.cpp @@ -14,11 +14,9 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; - -// Type declarations. using Kernel = CGAL::Simple_cartesian; using FT = typename Kernel::FT; @@ -27,85 +25,100 @@ using Vector_2 = typename Kernel::Vector_2; using Point_with_normal = std::pair; using Input_range = std::vector; -using Point_map = CGAL::First_of_pair_property_map; -using Normal_map = CGAL::Second_of_pair_property_map; +using Item = Input_range::const_iterator; -using Neighbor_query = SD::Point_set::Sphere_neighbor_query; -using Line_region = SD::Point_set::Least_squares_line_fit_region; -using Line_sorting = SD::Point_set::Least_squares_line_fit_sorting; -using Circle_region = SD::Point_set::Least_squares_circle_fit_region; -using Circle_sorting = SD::Point_set::Least_squares_circle_fit_sorting; +using Deref_map = CGAL::Dereference_property_map; +using Point_map = CGAL::Compose_property_map>; +using Normal_map = CGAL::Compose_property_map>; -template -bool test (int argc, char** argv, const std::size_t minr, const std::size_t maxr) -{ - using Region_growing = SD::Region_growing; +using Neighbor_query = SD::Point_set::Sphere_neighbor_query; +using Line_region = SD::Point_set::Least_squares_line_fit_region; +using Line_sorting = SD::Point_set::Least_squares_line_fit_sorting; +using Circle_region = SD::Point_set::Least_squares_circle_fit_region; +using Circle_sorting = SD::Point_set::Least_squares_circle_fit_sorting; + +template +bool test(int argc, char** argv, const std::string name, const std::size_t minr, const std::size_t maxr) { + using Region_growing = SD::Region_growing; + + // Default parameter values. + const std::size_t k = 12; + const FT max_distance = FT(45) / FT(10); + const FT max_angle = FT(45); + const std::size_t min_region_size = 5; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_2.xyz")); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/buildings_outline.xyz")); CGAL::IO::set_ascii_mode(in); + assert(in); - if (!in) { - std::cout << - "Error: cannot read the file point_set_2.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - assert(false); - return EXIT_FAILURE; - } - - Input_range input_range; FT a, b, c, d, e, f; - - while (in >> a >> b >> c >> d >> e >> f) + Input_range input_range; + while (in >> a >> b >> c >> d >> e >> f) { input_range.push_back( std::make_pair(Point_2(a, b), Vector_2(d, e))); + } in.close(); - - // Default parameter values for the data file point_set_2.xyz. - const FT sphere_radius = FT(5); - const FT distance_threshold = FT(45) / FT(10); - const FT angle_threshold = FT(45); - const std::size_t min_region_size = 5; + assert(input_range.size() == 3634); // Create parameter classes. Neighbor_query neighbor_query( input_range, - sphere_radius); + CGAL::parameters::k_neighbors(k)); Region_type region_type( - input_range, - distance_threshold, angle_threshold, min_region_size); + CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size)); // Sort indices. Sorting sorting( input_range, neighbor_query); sorting.sort(); - // Create an instance of the region growing class. + // Run region growing. Region_growing region_growing( - input_range, neighbor_query, region_type, - sorting.seed_map()); + input_range, sorting.ordered(), neighbor_query, region_type); - // Run the algorithm. - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - region_growing.release_memory(); + std::cout << "- num regions " + name + ": " << regions.size() << std::endl; assert(regions.size() >= minr && regions.size() <= maxr); - const bool cartesian_double_test_success = (regions.size() >= minr && regions.size() <= maxr); - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; + bool success = true; - const bool success = cartesian_double_test_success; + const typename Region_growing::Region_map &map = region_growing.region_map(); + + for (std::size_t i = 0; i < regions.size(); i++) + for (auto& item : regions[i].second) { + if (i != get(map, item)) { + std::cout << "Region map incorrect" << std::endl; + assert(success = false); + } + } + + std::vector unassigned; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned)); + + for (auto& item : unassigned) { + if (std::size_t(-1) != get(map, item)) { + std::cout << "Region map for unassigned incorrect" << std::endl; + assert(success = false); + } + } + + std::cout << "rg_" + name + "_sortpoints2, sc_test_success: " << success << std::endl; return success; } int main(int argc, char *argv[]) { return (( - test(argc, argv, 62, 66) && - test(argc, argv, 196, 200) + test(argc, argv, "lines", 62, 66) && // test lines + test(argc, argv, "circles", 62, 66) // test circles ) ? EXIT_SUCCESS : EXIT_FAILURE ); } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3.cpp index 4806868fc47..35a37e66a10 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3.cpp @@ -15,112 +15,99 @@ #include #include +#include #include -#include +#include namespace SD = CGAL::Shape_detection; template bool test_region_growing_on_point_set_3(int argc, char *argv[]) { - using FT = typename Kernel::FT; - using Point_3 = typename Kernel::Point_3; + using FT = typename Kernel::FT; + using Point_3 = typename Kernel::Point_3; using Input_range = CGAL::Point_set_3; - using Point_map = typename Input_range::Point_map; - using Normal_map = typename Input_range::Vector_map; - using Neighbor_query = SD::Point_set::K_neighbor_query; - using Region_type = SD::Point_set::Least_squares_plane_fit_region; - using Region_growing = SD::Region_growing; + using Neighbor_query = SD::Point_set::Sphere_neighbor_query_for_point_set; + using Region_type = SD::Point_set::Least_squares_plane_fit_region_for_point_set; + using Region_growing = SD::Region_growing; - // Default parameter values for the data file point_set_3.xyz. - const std::size_t k = 12; + // Default parameter values. + const FT sphere_radius = FT(5) / FT(100); const FT distance_threshold = FT(2); const FT angle_threshold = FT(20); const std::size_t min_region_size = 50; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_3.xyz")); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/building.xyz")); CGAL::IO::set_ascii_mode(in); - - if (!in) { - std::cout << - "Error: cannot read the file point_set_3.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } + assert(in); const bool with_normal_map = true; Input_range input_range(with_normal_map); - in >> input_range; in.close(); - assert(input_range.size() == 8075); - if (input_range.size() != 8075) - return false; // Create parameter classes. - Neighbor_query neighbor_query( - input_range, - k, - input_range.point_map()); + Neighbor_query neighbor_query = SD::Point_set::make_sphere_neighbor_query( + input_range, CGAL::parameters:: + sphere_radius(sphere_radius)); - Region_type region_type( - input_range, - distance_threshold, angle_threshold, min_region_size, - input_range.point_map(), input_range.normal_map()); + Region_type region_type = SD::Point_set::make_least_squares_plane_fit_region(input_range, + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size)); // Run region growing. Region_growing region_growing( input_range, neighbor_query, region_type); - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - // Test data. - assert(regions.size() >= 6 && regions.size() <= 8); - if (regions.size() < 6 || regions.size() > 8) - return false; - + assert(regions.size() == 10); for (const auto& region : regions) - if (!region_type.is_valid_region(region)) - return false; - - std::vector unassigned_points; - region_growing.unassigned_items(std::back_inserter(unassigned_points)); - - assert(unassigned_points.size() >= 528 && unassigned_points.size() <= 548); - if (unassigned_points.size() < 528 || unassigned_points.size() > 548) - return false; + assert(region_type.is_valid_region(region.second)); + std::vector unassigned_points; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned_points)); + assert(unassigned_points.size() == 246); return true; } int main(int argc, char *argv[]) { - // ------> - - bool cartesian_double_test_success = true; - if (!test_region_growing_on_point_set_3< CGAL::Simple_cartesian >(argc, argv)) - cartesian_double_test_success = false; - - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; - assert(cartesian_double_test_success); + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; // ------> - bool exact_inexact_test_success = true; - if (!test_region_growing_on_point_set_3(argc, argv)) - exact_inexact_test_success = false; + bool sc_test_success = true; + if (!test_region_growing_on_point_set_3(argc, argv)) + sc_test_success = false; + std::cout << "rg_points3, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); - std::cout << "exact_inexact_test_success: " << exact_inexact_test_success << std::endl; - assert(exact_inexact_test_success); + // ------> - const bool success = cartesian_double_test_success && exact_inexact_test_success; + bool epick_test_success = true; + if (!test_region_growing_on_point_set_3(argc, argv)) + epick_test_success = false; + std::cout << "rg_points3, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); + + // ------> + + bool epeck_test_success = true; // turn it off in case it is slow + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; + if (!test_region_growing_on_point_set_3(argc, argv)) + epeck_test_success = false; + std::cout << "rg_points3, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; return (success) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp index a1d8dd931d5..a110f376a22 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_point_set_3_with_sorting.cpp @@ -16,167 +16,169 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; - -// Type declarations. using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; -using FT = typename Kernel::FT; -using Point_3 = typename Kernel::Point_3; +using FT = typename Kernel::FT; +using Point_3 = typename Kernel::Point_3; using Input_range = CGAL::Point_set_3; using Point_map = typename Input_range::Point_map; using Normal_map = typename Input_range::Vector_map; -using Neighbor_query = SD::Point_set::K_neighbor_query; +using Neighbor_query = SD::Point_set::K_neighbor_query; -using Plane_region = SD::Point_set::Least_squares_plane_fit_region; -using Plane_sorting = SD::Point_set::Least_squares_plane_fit_sorting; -using Sphere_region = SD::Point_set::Least_squares_sphere_fit_region; -using Sphere_sorting = SD::Point_set::Least_squares_sphere_fit_sorting; -using Cylinder_region = SD::Point_set::Least_squares_cylinder_fit_region; -using Cylinder_sorting = SD::Point_set::Least_squares_cylinder_fit_sorting; +using Plane_region = SD::Point_set::Least_squares_plane_fit_region; +using Plane_sorting = SD::Point_set::Least_squares_plane_fit_sorting; +using Sphere_region = SD::Point_set::Least_squares_sphere_fit_region; +using Sphere_sorting = SD::Point_set::Least_squares_sphere_fit_sorting; +using Cylinder_region = SD::Point_set::Least_squares_cylinder_fit_region; +using Cylinder_sorting = SD::Point_set::Least_squares_cylinder_fit_sorting; -template -bool test (int argc, char** argv, const SortingCode& sc, const RegionCode& reg, const AssertionCode& assertion) -{ - using Region_growing = SD::Region_growing; +template< +typename Region_type, +typename Sorting, +typename Lambda_region, +typename Lambda_assertion> +bool test( + int argc, char** argv, const std::string &name, const std::string &inputfile, + const Lambda_region& lambda_region, + const Lambda_assertion& lambda_assertion) { + + using Region_growing = SD::Region_growing; + + // Default parameter values. + const std::size_t k = 12; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("points_3/point_set_3.xyz")); + std::ifstream in(argc > 1 ? argv[1] : inputfile); CGAL::IO::set_ascii_mode(in); - - if (!in) { - std::cout << - "Error: cannot read the file point_set_3.xyz!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } + assert(in); const bool with_normal_map = true; Input_range input_range(with_normal_map); - in >> input_range; in.close(); - const std::size_t k = 12; - // Create parameter classes. Neighbor_query neighbor_query( - input_range, - k, - input_range.point_map()); - - Region_type region_type = reg(input_range); + input_range, CGAL::parameters:: + k_neighbors(k).point_map(input_range.point_map())); // Sort indices. - Sorting sorting = sc(input_range, neighbor_query); + Sorting sorting( + input_range, neighbor_query, CGAL::parameters::point_map(input_range.point_map()).normal_map(input_range.normal_map())); sorting.sort(); - // Create an instance of the region growing class. + // Run region growing. + Region_type region_type = lambda_region(input_range); Region_growing region_growing( - input_range, neighbor_query, region_type, - sorting.seed_map()); + input_range, sorting.ordered(), neighbor_query, region_type); - // Run the algorithm. - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); + bool result = lambda_assertion(regions); + assert(result); - region_growing.release_memory(); + typename Region_growing::Region_map map = region_growing.region_map(); + + for (std::size_t i = 0; i < regions.size(); i++) + for (auto &item : regions[i].second) { + if (i != get(map, item)) { + std::cout << "Region map incorrect" << std::endl; + assert(result = false); + } + } + + std::vector unassigned; + region_growing.unassigned_items(input_range, std::back_inserter(unassigned)); + + for (auto& item : unassigned) { + if (std::size_t(-1) != get(map, item)) { + std::cout << "Region map for unassigned incorrect" << std::endl; + assert(result = false); + } + } + + std::cout << "rg_" + name + "_sortpoints3, epick_test_success: " << result << std::endl; - bool result = assertion(regions); - assert (result); - std::cout << "exact_inexact_test_success: " << result << std::endl; return result; } int main(int argc, char *argv[]) { + bool success = true; - bool success = - test - (argc, argv, - [](const auto& input_range, auto& neighbor_query) -> Plane_sorting - { - return Plane_sorting (input_range, neighbor_query, - input_range.point_map()); - }, - [](const auto& input_range) -> Plane_region - { - // Default parameter values for the data file point_set_3.xyz. - const FT distance_threshold = FT(2); - const FT angle_threshold = FT(20); - const std::size_t min_region_size = 50; - return Plane_region - (input_range, - distance_threshold, angle_threshold, min_region_size, - input_range.point_map(), input_range.normal_map()); - }, - [](const auto& r) -> bool { - std::cout << "- num regions planes: " << r.size() << std::endl; - return (r.size() >= 6 && r.size() <= 8); - }); - if (!success) - return EXIT_FAILURE; + // Test planes. + success = test(argc, argv, "planes", CGAL::data_file_path("points_3/building.xyz"), + [](const auto& input_range) -> Plane_region { - success = - test - (argc, argv, - [](const auto& input_range, auto& neighbor_query) -> Sphere_sorting - { - return Sphere_sorting (input_range, neighbor_query, - input_range.point_map()); - }, - [](const auto& input_range) -> Sphere_region - { - const double tolerance = 0.01; - const double max_angle = 10.; + const FT max_distance = FT(2); + const FT max_angle = FT(20); const std::size_t min_region_size = 50; - // No constraint on radius - const double min_radius = 0.; - const double max_radius = std::numeric_limits::infinity(); - return Sphere_region - (input_range, tolerance, max_angle, min_region_size, - min_radius, max_radius, - input_range.point_map(), input_range.normal_map()); - }, - [](const auto& r) -> bool { - std::cout << "- num regions spheres: " << r.size() << std::endl; - return (r.size() > 10 && r.size() < 90); - }); - if (!success) - return EXIT_FAILURE; + return Plane_region(CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size). + point_map(input_range.point_map()). + normal_map(input_range.normal_map())); + }, + [](const auto& region) -> bool { + std::cout << "- num regions planes: " << region.size() << std::endl; + return (region.size() == 7); + } + ); - success = - test - (argc, argv, - [](const auto& input_range, auto& neighbor_query) -> Cylinder_sorting - { - return Cylinder_sorting (input_range, neighbor_query, - input_range.point_map(), input_range.normal_map()); - }, - [](const auto& input_range) -> Cylinder_region - { - const double tolerance = 0.05; - const double max_angle = 5.; + if (!success) { + return EXIT_FAILURE; + } + + // Test spheres. + success = test(argc, argv, "spheres", CGAL::data_file_path("points_3/spheres.ply"), + [](const auto& input_range) -> Sphere_region { + + const FT max_distance = FT(1) / FT(100); + const FT max_angle = FT(10); + const std::size_t min_region_size = 50; + return Sphere_region(CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size). + point_map(input_range.point_map()). + normal_map(input_range.normal_map())); + }, + [](const auto& region) -> bool { + std::cout << "- num regions spheres: " << region.size() << std::endl; + return (region.size() == 10); + } + ); + + if (!success) { + return EXIT_FAILURE; + } + + // Test cylinders. + success = test(argc, argv, "cylinders", CGAL::data_file_path("points_3/cylinder_no_noise.ply"), + [](const auto& input_range) -> Cylinder_region { + + const FT max_distance = FT(1) / FT(20); + const FT max_angle = FT(5); const std::size_t min_region_size = 200; - // No constraint on radius - const double min_radius = 0.; - const double max_radius = std::numeric_limits::infinity(); - return Cylinder_region - (input_range, tolerance, max_angle, min_region_size, - min_radius, max_radius, - input_range.point_map(), input_range.normal_map()); - }, - [](const auto& r) -> bool { - std::cout << "- num regions cylinders: " << r.size() << std::endl; - return (r.size() > 2 && r.size() < 30); - }); - if (!success) - return EXIT_FAILURE; + return Cylinder_region(CGAL::parameters:: + maximum_distance(max_distance). + maximum_angle(max_angle). + minimum_region_size(min_region_size). + point_map(input_range.point_map()). + normal_map(input_range.normal_map())); + }, + [](const auto& region) -> bool { + std::cout << "- num regions cylinders: " << region.size() << std::endl; + return (region.size() == 1); + } + ); + if (!success) { + return EXIT_FAILURE; + } return EXIT_SUCCESS; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh.cpp index cbaa2b21645..afed5232286 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh.cpp @@ -12,9 +12,10 @@ #include #include +#include #include -#include +#include namespace SD = CGAL::Shape_detection; @@ -24,99 +25,89 @@ bool test_region_growing_on_polygon_mesh(int argc, char *argv[]) { using FT = typename Kernel::FT; using Point_3 = typename Kernel::Point_3; - using Surface_mesh = CGAL::Surface_mesh; - using Face_range = typename Surface_mesh::Face_range; + using Polygon_mesh = CGAL::Surface_mesh; + using Face_range = typename Polygon_mesh::Face_range; - using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; - using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; - using Region_growing = SD::Region_growing; + using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; + using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; + using Region_growing = SD::Region_growing; - // Default parameter values for the data file polygon_mesh.off. + // Default parameter values. const FT distance_threshold = FT(1); const FT angle_threshold = FT(45); const std::size_t min_region_size = 5; // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/polygon_mesh.off")); + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/building.off")); CGAL::IO::set_ascii_mode(in); + assert(in); - if (!in) { - std::cout << - "Error: cannot read the file polygon_mesh.off!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - return false; - } - - Surface_mesh surface_mesh; - in >> surface_mesh; - + Polygon_mesh mesh; + in >> mesh; in.close(); - const Face_range face_range = faces(surface_mesh); - + const Face_range face_range = faces(mesh); assert(face_range.size() == 32245); - if (face_range.size() != 32245) - return false; - - // Create parameter classes. - Neighbor_query neighbor_query(surface_mesh); using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; const Vertex_to_point_map vertex_to_point_map( - get(CGAL::vertex_point, surface_mesh)); + get(CGAL::vertex_point, mesh)); + // Create parameter classes. + Neighbor_query neighbor_query(mesh); Region_type region_type( - surface_mesh, - distance_threshold, angle_threshold, min_region_size, - vertex_to_point_map); + mesh, + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size). + vertex_point_map(vertex_to_point_map)); // Run region growing. Region_growing region_growing( face_range, neighbor_query, region_type); - std::vector< std::vector > regions; + std::vector regions; region_growing.detect(std::back_inserter(regions)); - - // Test data. - assert(regions.size() >= 324 && regions.size() <= 328); - if (regions.size() < 324 || regions.size() > 328) - return false; - + assert(regions.size() == 416); for (const auto& region : regions) - if (!region_type.is_valid_region(region)) - return false; - - std::vector unassigned_faces; - region_growing.unassigned_items(std::back_inserter(unassigned_faces)); - - assert(unassigned_faces.size() >= 904 && unassigned_faces.size() <= 924); - if (unassigned_faces.size() < 904 || unassigned_faces.size() > 924) - return false; + assert(region_type.is_valid_region(region.second)); + std::vector unassigned_faces; + region_growing.unassigned_items(face_range, std::back_inserter(unassigned_faces)); + assert(unassigned_faces.size() == 1006); return true; } int main(int argc, char *argv[]) { - // ------> - - bool cartesian_double_test_success = true; - if (!test_region_growing_on_polygon_mesh< CGAL::Simple_cartesian >(argc, argv)) - cartesian_double_test_success = false; - - std::cout << "cartesian_double_test_success: " << cartesian_double_test_success << std::endl; - assert(cartesian_double_test_success); + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; // ------> - bool exact_inexact_test_success = true; - if (!test_region_growing_on_polygon_mesh(argc, argv)) - exact_inexact_test_success = false; + bool sc_test_success = true; + if (!test_region_growing_on_polygon_mesh(argc, argv)) + sc_test_success = false; + std::cout << "rg_pmesh, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); - std::cout << "exact_inexact_test_success: " << exact_inexact_test_success << std::endl; - assert(exact_inexact_test_success); + // ------> - const bool success = cartesian_double_test_success && exact_inexact_test_success; + bool epick_test_success = true; + if (!test_region_growing_on_polygon_mesh(argc, argv)) + epick_test_success = false; + std::cout << "rg_pmesh, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); + + // ------> + + bool epeck_test_success = true; + if (!test_region_growing_on_polygon_mesh(argc, argv)) + epeck_test_success = false; + std::cout << "rg_pmesh, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; return (success) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp index d2a8f47c65c..9c348f335ff 100644 --- a/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp +++ b/Shape_detection/test/Shape_detection/test_region_growing_on_polygon_mesh_with_sorting.cpp @@ -14,11 +14,9 @@ #include #include -#include +#include namespace SD = CGAL::Shape_detection; - -// Type declarations. using Kernel = CGAL::Exact_predicates_exact_constructions_kernel; using FT = typename Kernel::FT; @@ -30,68 +28,59 @@ using Face_range = typename Polygon_mesh::Face_range; using Neighbor_query = SD::Polygon_mesh::One_ring_neighbor_query; using Region_type = SD::Polygon_mesh::Least_squares_plane_fit_region; using Sorting = SD::Polygon_mesh::Least_squares_plane_fit_sorting; -using Region_growing = SD::Region_growing; +using Region_growing = SD::Region_growing; int main(int argc, char *argv[]) { - // Load data. - std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/polygon_mesh.off")); - CGAL::IO::set_ascii_mode(in); - - if (!in) { - std::cout << - "Error: cannot read the file polygon_mesh.off!" << std::endl; - std::cout << - "You can either create a symlink to the data folder or provide this file by hand." - << std::endl << std::endl; - assert(false); - return EXIT_FAILURE; - } - - Polygon_mesh polygon_mesh; - in >> polygon_mesh; - - in.close(); - const Face_range face_range = faces(polygon_mesh); - - // Default parameter values for the data file polygon_mesh.off. + // Default parameter values. const FT distance_threshold = FT(1); const FT angle_threshold = FT(45); const std::size_t min_region_size = 5; - // Create parameter classes. - Neighbor_query neighbor_query(polygon_mesh); + // Load data. + std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("meshes/building.off")); + CGAL::IO::set_ascii_mode(in); + assert(in); + + Polygon_mesh polygon_mesh; + in >> polygon_mesh; + in.close(); + const Face_range face_range = faces(polygon_mesh); + assert(face_range.size() == 32245); using Vertex_to_point_map = typename Region_type::Vertex_to_point_map; const Vertex_to_point_map vertex_to_point_map( get(CGAL::vertex_point, polygon_mesh)); - Region_type region_type( - polygon_mesh, - distance_threshold, angle_threshold, min_region_size, - vertex_to_point_map); - // Sort indices. - Sorting sorting( - polygon_mesh, neighbor_query, - vertex_to_point_map); - sorting.sort(); + for (std::size_t k = 0; k < 3; ++k) // test stability + { + // Create parameter classes. + Neighbor_query neighbor_query(polygon_mesh); + Region_type region_type( + polygon_mesh, + CGAL::parameters:: + maximum_distance(distance_threshold). + maximum_angle(angle_threshold). + minimum_region_size(min_region_size). + vertex_point_map(vertex_to_point_map)); - // Create an instance of the region growing class. - Region_growing region_growing( - face_range, neighbor_query, region_type, - sorting.seed_map()); + // Sort indices. + Sorting sorting( + polygon_mesh, neighbor_query, + CGAL::parameters::vertex_point_map(vertex_to_point_map)); + sorting.sort(); - // Run the algorithm. - std::vector< std::vector > regions; - region_growing.detect(std::back_inserter(regions)); + // Run region growing. + Region_growing region_growing( + face_range, sorting.ordered(), neighbor_query, region_type); - region_growing.release_memory(); - assert(regions.size() >= 324 && regions.size() <= 328); + std::vector regions; + region_growing.detect(std::back_inserter(regions)); + region_growing.clear(face_range); + assert(regions.size() == 365); + } - const bool exact_exact_test_success = (regions.size() >= 324 && regions.size() <= 328); - std::cout << "exact_exact_test_success: " << exact_exact_test_success << std::endl; - - const bool success = exact_exact_test_success; - return (success) ? EXIT_SUCCESS : EXIT_FAILURE; + std::cout << "rg_sortfaces3, epeck_test_success: " << true << std::endl; + return EXIT_SUCCESS; } diff --git a/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp b/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp new file mode 100644 index 00000000000..82ed06f3ca4 --- /dev/null +++ b/Shape_detection/test/Shape_detection/test_region_growing_strict.cpp @@ -0,0 +1,509 @@ +// STL includes. +#include +#include +#include +#include +#include +#include +#include + +// CGAL includes. +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +template +bool test_lines_points_with_normals() { + + using Point_2 = typename Kernel::Point_2; + using Vector_2 = typename Kernel::Vector_2; + using Point_with_normal = std::pair; + using Item = typename std::vector< Point_with_normal >::const_iterator; + using Input_range = std::vector< Point_with_normal >; + const Input_range points_with_normals = { + std::make_pair(Point_2(0.1, 0.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.5, 0.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.9, 0.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.1, 2.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.5, 2.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.9, 2.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.1, 4.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.5, 4.0), Vector_2(0.0, 1.0)), + std::make_pair(Point_2(0.9, 4.0), Vector_2(0.0, 1.0)) + }; + + assert(points_with_normals.size() == 9); + std::vector< std::pair< typename Kernel::Line_2, std::vector > > regions; + + using Deref_map = CGAL::Dereference_property_map; + using Point_map = CGAL::Compose_property_map >; + using Normal_map = CGAL::Compose_property_map >; + + using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query; + using Region_type = CGAL::Shape_detection::Point_set::Least_squares_line_fit_region; + using Sorting_type = CGAL::Shape_detection::Point_set::Least_squares_line_fit_sorting; + using Region_growing = CGAL::Shape_detection::Region_growing; + + // Create parameter classes. + Neighbor_query neighbor_query(points_with_normals); + Region_type region_type; + Sorting_type sorting(points_with_normals, neighbor_query); + sorting.sort(); + + // Run region growing. + Region_growing region_growing( + points_with_normals, sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + + assert(regions.size() == 3); + assert(regions[0].second.size() == 3); + assert(regions[1].second.size() == 3); + assert(regions[2].second.size() == 3); + return true; +} + +template +bool test_lines_segment_set_2() { + + using Point_2 = typename Kernel::Point_2; + using Segment_2 = typename Kernel::Segment_2; + + using Segment_range = std::vector; + using Item = typename Segment_range::const_iterator; + + using Segment_map = CGAL::Dereference_property_map; + + using Region_type = CGAL::Shape_detection:: + Segment_set::Least_squares_line_fit_region; + + + const Segment_range segments = { + Segment_2(Point_2(0.1, 0.0), Point_2(0.5, 0.0)), + Segment_2(Point_2(0.5, 0.0), Point_2(0.9, 0.0)), + Segment_2(Point_2(0.9, 0.0), Point_2(0.9, 0.5)), + Segment_2(Point_2(0.9, 0.5), Point_2(0.9, 0.9)) + }; + assert(segments.size() == 4); + + struct Neighbor_query { + + std::map > m_neighbors; + Neighbor_query(const Segment_range& segments) { + m_neighbors[segments.begin()] = { segments.begin() + 1 }; + m_neighbors[segments.begin() + 1] = { segments.begin(), segments.begin() + 2 }; + m_neighbors[segments.begin() + 2] = { segments.begin() + 1, segments.begin() + 3 }; + m_neighbors[segments.begin() + 3] = { segments.begin() + 2 }; + } + + void operator()( + const Item query, std::vector& neighbors) const { + neighbors.clear(); + const auto& data = m_neighbors.at(query); + std::copy(data.begin(), data.end(), std::back_inserter(neighbors)); + } + }; + using Region_growing = CGAL::Shape_detection:: + Region_growing; + + Neighbor_query neighbor_query(segments); + Region_type region_type; + + std::vector< std::pair< typename Region_type::Primitive, std::vector > > regions; + Region_growing region_growing( + segments, neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + assert(regions.size() == 2); + assert(regions[0].second.size() == 2); + assert(regions[1].second.size() == 2); + return true; +} + +template +bool test_lines_segment_set_2_sorting() { + + using Point_2 = typename Kernel::Point_2; + using Segment_2 = typename Kernel::Segment_2; + + using Segment_range = std::vector; + using Item = typename Segment_range::const_iterator; + + using Segment_map = CGAL::Dereference_property_map; + + using Region_type = CGAL::Shape_detection:: + Segment_set::Least_squares_line_fit_region; + + const Segment_range segments = { + Segment_2(Point_2(0.1, 0.0), Point_2(0.5, 0.0)), + Segment_2(Point_2(0.5, 0.0), Point_2(0.9, 0.0)), + Segment_2(Point_2(0.9, 0.0), Point_2(0.9, 0.5)), + Segment_2(Point_2(0.9, 0.5), Point_2(0.9, 0.9)) + }; + assert(segments.size() == 4); + + struct Neighbor_query { + + std::map > m_neighbors; + Neighbor_query(const Segment_range& segments) { + m_neighbors[segments.begin()] = { segments.begin() + 1 }; + m_neighbors[segments.begin() + 1] = { segments.begin(), segments.begin() + 2 }; + m_neighbors[segments.begin() + 2] = { segments.begin() + 1, segments.begin() + 3 }; + m_neighbors[segments.begin() + 3] = { segments.begin() + 2 }; + } + + void operator()( + const Item query, std::vector& neighbors) const { + neighbors.clear(); + const auto& data = m_neighbors.at(query); + std::copy(data.begin(), data.end(), std::back_inserter(neighbors)); + } + }; + + using Region_growing = CGAL::Shape_detection:: + Region_growing; + + using Sorting = CGAL::Shape_detection::Segment_set::Least_squares_line_fit_sorting; + + Neighbor_query neighbor_query(segments); + + Sorting sorting( + segments, neighbor_query); + sorting.sort(); + + Region_type region_type; + + std::vector regions; + Region_growing region_growing( + segments, sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + assert(regions.size() == 2); + assert(regions[0].second.size() == 2); + assert(regions[1].second.size() == 2); + return true; +} + +template +bool test_lines_segment_set_3() { + + using Point_3 = typename Kernel::Point_3; + using Surface_mesh = CGAL::Surface_mesh; + + using Plane_region = CGAL::Shape_detection:: + Polygon_mesh::Least_squares_plane_fit_region; + + using One_ring_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; + + using Plane_sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; + + using RG_planes = CGAL::Shape_detection:: + Region_growing; + + using Polyline_graph = CGAL::Shape_detection:: + Polygon_mesh::Polyline_graph; + using Segment_map = typename Polyline_graph::Segment_map; + + using Region_type = CGAL::Shape_detection:: + Segment_set::Least_squares_line_fit_region; + using Sorting = CGAL::Shape_detection:: + Segment_set::Least_squares_line_fit_sorting; + using RG_lines = CGAL::Shape_detection:: + Region_growing; + + std::ifstream in(CGAL::data_file_path("meshes/am.off")); + CGAL::IO::set_ascii_mode(in); + assert(in); + + Surface_mesh surface_mesh; + in >> surface_mesh; + in.close(); + + const auto face_range = faces(surface_mesh); + + One_ring_query one_ring_query(surface_mesh); + + Plane_region plane_type( + surface_mesh); + + // Sort face indices. + Plane_sorting plane_sorting( + surface_mesh, one_ring_query); + plane_sorting.sort(); + + // Create an instance of the region growing class. + RG_planes rg_planes( + face_range, plane_sorting.ordered(), one_ring_query, plane_type); + + assert(surface_mesh.number_of_faces() == 7320); + std::vector regions; + rg_planes.detect(std::back_inserter(regions)); + assert(regions.size() == 9); + + assert(face_range.size() == 7320); + + Polyline_graph pgraph(surface_mesh, rg_planes.region_map()); + const auto& segment_range = pgraph.segment_range(); + + Region_type region_type(CGAL::parameters::segment_map(pgraph.segment_map())); + Sorting sorting( + segment_range, pgraph, CGAL::parameters::segment_map(pgraph.segment_map())); + sorting.sort(); + + std::vector regions2; + RG_lines region_growing( + segment_range, sorting.ordered(), pgraph, region_type); + region_growing.detect(std::back_inserter(regions2)); + assert(regions2.size() == 21); + return true; +} + +template +bool test_region_growing_lines() { + assert(test_lines_points_with_normals()); + assert(test_lines_segment_set_2()); + assert(test_lines_segment_set_2_sorting()); + assert(test_lines_segment_set_3()); + + return true; +} + +template +bool test_planes_points_with_normals() { + + using Point_3 = typename Kernel::Point_3; + using Vector_3 = typename Kernel::Vector_3; + using Point_with_normal = std::pair; + using Input_range = std::vector; + using Item = typename Input_range::const_iterator; + + const Input_range points_with_normals = { + std::make_pair(Point_3(0.1, 0.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 0.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 0.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.1, 1.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 1.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 1.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.1, 2.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 2.0, 0.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 2.0, 0.0), Vector_3(0.0, 0.0, 1.0)) + }; + + assert(points_with_normals.size() == 9); + std::vector< std::pair< typename Kernel::Plane_3, std::vector > > regions; + + using Deref_map = CGAL::Dereference_property_map; + using Point_map = CGAL::Compose_property_map >; + using Normal_map = CGAL::Compose_property_map >; + + using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query; + using Region_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region; + using Sorting_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting; + using Region_growing = CGAL::Shape_detection::Region_growing; + + // Create parameter classes. + Neighbor_query neighbor_query(points_with_normals); + Region_type region_type; + Sorting_type sorting(points_with_normals, neighbor_query); + sorting.sort(); + + // Run region growing. + Region_growing region_growing( + points_with_normals, sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + + assert(regions.size() == 1); + assert(regions[0].second.size() == 9); + return true; +} + +template +bool test_planes_point_set() { + + using Point_3 = typename Kernel::Point_3; + using Vector_3 = typename Kernel::Vector_3; + using Point_set = CGAL::Point_set_3; + + std::vector< std::pair > points_with_normals = { + std::make_pair(Point_3(0.1, 0.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 0.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 0.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.1, 1.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 1.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 1.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.1, 2.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.5, 2.0, 1.0), Vector_3(0.0, 0.0, 1.0)), + std::make_pair(Point_3(0.9, 2.0, 1.0), Vector_3(0.0, 0.0, 1.0)) + }; + assert(points_with_normals.size() == 9); + + Point_set point_set(true); + for (const auto& pwn : points_with_normals) + point_set.insert(pwn.first, pwn.second); + assert(point_set.size() == points_with_normals.size()); + + points_with_normals.clear(); + assert(points_with_normals.size() == 0); + + std::vector< std::pair< typename Kernel::Plane_3, std::vector > > regions; + + using Region_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region_for_point_set; + using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set; + using Sorting = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_sorting_for_point_set; + using Region_growing = CGAL::Shape_detection::Region_growing; + + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query(point_set); + + Sorting sorting = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_sorting(point_set, neighbor_query); + sorting.sort(); + + Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_region(point_set); + Region_growing region_growing(point_set, sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + + assert(regions.size() == 1); + assert(regions[0].second.size() == 9); + return true; +} + +template +bool test_planes_polyhedron() { + using Point_3 = typename Kernel::Point_3; + using Polygon_mesh = CGAL::Polyhedron_3; + using Item = typename boost::graph_traits::face_descriptor; + using Neighbor_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; + using Region_type = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; + using Sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; + using Region_growing = CGAL::Shape_detection::Region_growing; + + Polygon_mesh polygon_mesh; + const Point_3 p1(0, 0, 0); + const Point_3 p2(1, 0, 0); + const Point_3 p3(0, 1, 0); + const Point_3 p4(0, 0, 1); + const auto handle = polygon_mesh.make_tetrahedron(p1, p2, p3, p4); + assert(polygon_mesh.is_tetrahedron(handle)); + + assert(polygon_mesh.size_of_facets() == 4); + std::vector< std::pair< typename Kernel::Plane_3, std::vector > > regions; + + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query(polygon_mesh); + + Region_type region_type(polygon_mesh); + + // Sort face indices. + Sorting sorting(polygon_mesh, neighbor_query); + sorting.sort(); + + // Create an instance of the region growing class. + Region_growing region_growing(faces(polygon_mesh), sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + + assert(regions.size() == polygon_mesh.size_of_facets()); + return true; +} + +template +bool test_planes_surface_mesh() { + + using Point_3 = typename Kernel::Point_3; + using Polygon_mesh = CGAL::Surface_mesh; + using Item = typename boost::graph_traits::face_descriptor; + using Neighbor_query = CGAL::Shape_detection::Polygon_mesh::One_ring_neighbor_query; + using Region_type = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_region; + using Sorting = CGAL::Shape_detection::Polygon_mesh::Least_squares_plane_fit_sorting; + using Region_growing = CGAL::Shape_detection::Region_growing; + + std::ifstream in(CGAL::data_file_path("meshes/am.off")); + CGAL::IO::set_ascii_mode(in); + assert(in); + + Polygon_mesh polygon_mesh; + in >> polygon_mesh; + in.close(); + + assert(polygon_mesh.number_of_faces() == 7320); + std::vector< std::pair< typename Kernel::Plane_3, std::vector > > regions; + + // Create instances of the classes Neighbor_query and Region_type. + Neighbor_query neighbor_query(polygon_mesh); + + Region_type region_type(polygon_mesh); + + // Sort face indices. + Sorting sorting(polygon_mesh, neighbor_query); + sorting.sort(); + + // Create an instance of the region growing class. + Region_growing region_growing(faces(polygon_mesh), sorting.ordered(), neighbor_query, region_type); + region_growing.detect(std::back_inserter(regions)); + + assert(regions.size() == 9); + return true; +} + +template +bool test_region_growing_planes() { + assert(test_planes_points_with_normals()); + assert(test_planes_point_set()); + assert(test_planes_polyhedron()); + assert(test_planes_surface_mesh()); + return true; +} + +template +bool test_region_growing_strict() { + + assert(test_region_growing_lines()); + assert(test_region_growing_planes()); + return true; +} + +int main() { + using SC = CGAL::Simple_cartesian; + using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel; + using EPECK = CGAL::Exact_predicates_exact_constructions_kernel; + + // ------> + + bool sc_test_success = true; + if (!test_region_growing_strict()) + sc_test_success = false; + std::cout << "rg_strict, sc_test_success: " << sc_test_success << std::endl; + assert(sc_test_success); + + // ------> + + bool epick_test_success = true; + if (!test_region_growing_strict()) + epick_test_success = false; + std::cout << "rg_strict, epick_test_success: " << epick_test_success << std::endl; + assert(epick_test_success); + + // ------> + + bool epeck_test_success = true; + if (!test_region_growing_strict()) + epeck_test_success = false; + std::cout << "rg_strict, epeck_test_success: " << epeck_test_success << std::endl; + assert(epeck_test_success); + + const bool success = sc_test_success && epick_test_success && epeck_test_success; + return (success) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/Shape_detection/test/Shape_detection/test_validity_sampled_data.cpp b/Shape_detection/test/Shape_detection/test_validity_sampled_data.cpp index fc1ecd42bc1..58424b53aa8 100644 --- a/Shape_detection/test/Shape_detection/test_validity_sampled_data.cpp +++ b/Shape_detection/test/Shape_detection/test_validity_sampled_data.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #ifdef CGAL_TEST_RANSAC_PROTOTYPE #include @@ -29,12 +29,17 @@ using Vector_3 = Kernel::Vector_3; using Pwn = std::pair; using Point_set = std::vector; +using Item = Point_set::const_iterator; + +using Deref_map = CGAL::Dereference_property_map; using Point_map = CGAL::First_of_pair_property_map; using Normal_map = CGAL::Second_of_pair_property_map; +using RG_Point_map = CGAL::Compose_property_map; +using RG_Normal_map = CGAL::Compose_property_map; -using RG_query = SD::Point_set::Sphere_neighbor_query; -using RG_region = SD::Point_set::Least_squares_plane_fit_region; -using Region_growing = SD::Region_growing; +using RG_query = SD::Point_set::Sphere_neighbor_query; +using RG_region = SD::Point_set::Least_squares_plane_fit_region; +using Region_growing = SD::Region_growing; using RANSAC_traits = SD::Efficient_RANSAC_traits; using RANSAC = SD::Efficient_RANSAC; @@ -45,7 +50,7 @@ void test_copied_point_cloud (const Point_set& points, std::size_t nb); int main (int argc, char** argv) { Point_set points; - const std::string ifilename = (argc > 1) ? argv[1] : CGAL::data_file_path("points_3/point_set_3.xyz"); + const std::string ifilename = (argc > 1) ? argv[1] : CGAL::data_file_path("points_3/building.xyz"); std::ifstream ifile(ifilename); if (!ifile || @@ -100,7 +105,7 @@ void test_copied_point_cloud (const Point_set& original_points, std::size_t nb) bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), Point_map()), - CGAL::make_transform_iterator_from_property_map (points.end(), Point_map())); + CGAL::make_transform_iterator_from_property_map(points.end(), Point_map())); typename RANSAC::Parameters parameters; parameters.probability = 0.01; @@ -111,13 +116,19 @@ void test_copied_point_cloud (const Point_set& original_points, std::size_t nb) CGAL::Real_timer t; t.start(); - RG_query rg_query (points, parameters.cluster_epsilon); - RG_region rg_region (points, parameters.epsilon, parameters.normal_threshold, parameters.min_points); + RG_query rg_query ( + points, + CGAL::parameters::sphere_radius(parameters.cluster_epsilon)); + RG_region rg_region ( + CGAL::parameters:: + maximum_distance(parameters.epsilon). + cosine_of_maxium_angle(parameters.normal_threshold). + minimum_region_size(parameters.min_points)); Region_growing region_growing (points, rg_query, rg_region); std::size_t nb_detected = 0; std::size_t nb_unassigned = 0; region_growing.detect (boost::make_function_output_iterator ([&](const auto&) { ++ nb_detected; })); - region_growing.unassigned_items (boost::make_function_output_iterator ([&](const auto&) { ++ nb_unassigned; })); + region_growing.unassigned_items(points, boost::make_function_output_iterator ([&](const auto&) { ++ nb_unassigned; })); t.stop(); std::cerr << "Region Growing = " << nb_detected << " planes (" << 1000 * t.time() << "ms)" << std::endl; @@ -165,13 +176,13 @@ void test_copied_point_cloud (const Point_set& original_points, std::size_t nb) << detected_ransac.front() << ";" << detected_ransac.back() << "], time[" << times_ransac.front() << ";" << times_ransac.back() << "])" << std::endl; - // RANSAC should at least detect 75% of shapes + // RANSAC should detect at least 75% of shapes. assert (detected_ransac[detected_ransac.size() / 2] > std::size_t(0.75 * ground_truth)); #ifdef CGAL_TEST_RANSAC_PROTOTYPE { CGAL::Real_timer timer; - double timeout = 120.; // 2 minute timeout + double timeout = 120.; // 2 minutes timeout timer.start(); std::size_t nb_runs = 500; std::vector detected_ransac; @@ -196,7 +207,7 @@ void test_copied_point_cloud (const Point_set& original_points, std::size_t nb) proto_points.push_back(Pt); } - //manually set bounding box! + // Manually set bounding box! Vec3f cbbMin, cbbMax; cbbMin[0] = static_cast(bbox.xmin()); cbbMin[1] = static_cast(bbox.ymin()); diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Weighted_Minkowski_distance.h b/Spatial_searching/doc/Spatial_searching/CGAL/Weighted_Minkowski_distance.h index e1575fb05f3..80dd8677699 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Weighted_Minkowski_distance.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Weighted_Minkowski_distance.h @@ -10,6 +10,9 @@ defined by \f$ l_{\infty}(w)(r,q)=max \{w_i |r_i-q_i| \mid 1 \leq i \leq d\}\f$. For the purpose of the distance computations it is more efficient to compute the transformed distance \f$ {\sigma_{i=1}^{i=d} \, w_i(r_i-q_i)^p}\f$ instead of the actual distance. +\note As this distance involves the computation of a power it is not +done exact but with floating point arithmetic. + \tparam Traits must be a model of the concept `SearchTraits`, for example `Search_traits_2`. diff --git a/Spatial_searching/include/CGAL/Weighted_Minkowski_distance.h b/Spatial_searching/include/CGAL/Weighted_Minkowski_distance.h index f38f5b8cf37..fcc19d99841 100644 --- a/Spatial_searching/include/CGAL/Weighted_Minkowski_distance.h +++ b/Spatial_searching/include/CGAL/Weighted_Minkowski_distance.h @@ -18,15 +18,16 @@ #include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include - namespace CGAL { namespace internal { template @@ -56,10 +57,22 @@ namespace CGAL { private: typedef typename SearchTraits::Cartesian_const_iterator_d Coord_iterator; - FT power; + double power; + Weight_vector the_weights; + + FT pow(FT ft) const + { + return FT(std::pow(to_double(ft), power)); + } + + FT pow(FT ft, FT p) const + { + return FT(std::pow(to_double(ft), to_double(p))); + } + public: @@ -82,9 +95,9 @@ namespace CGAL { InputIterator begin, InputIterator CGAL_assertion_code(end), const SearchTraits& traits_=SearchTraits()) - : traits(traits_),power(pow) + : traits(traits_),power(to_double(pow)) { - CGAL_assertion(power >= FT(0)); + CGAL_assertion(is_positive(power)); Weight_vector_traits::resize(the_weights, dim); for (int i = 0; i < dim; ++i){ the_weights[i] = *begin; @@ -110,7 +123,7 @@ namespace CGAL { Coord_iterator qit = construct_it(q), qe = construct_it(q,1), pit = construct_it(p); - if (power == FT(0)) { + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) if (the_weights[i] * CGAL::abs((*qit) - (*pit)) > distance) distance = the_weights[i] * CGAL::abs((*qit)-(*pit)); @@ -118,7 +131,7 @@ namespace CGAL { else for (unsigned int i = 0; qit != qe; ++qit, ++i) distance += - the_weights[i] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[i] * pow(CGAL::abs((*qit)-(*pit))); return distance; } @@ -133,7 +146,7 @@ namespace CGAL { Coord_iterator qit = construct_it(q), qe = construct_it(q,1), pit = construct_it(p); - if (power == FT(0)) { + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) if (the_weights[i] * CGAL::abs((*qit) - (*pit)) > distance) distance = the_weights[i] * CGAL::abs((*qit)-(*pit)); @@ -141,7 +154,7 @@ namespace CGAL { else for (unsigned int i = 0; qit != qe; ++qit, ++i) distance += - the_weights[i] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[i] * pow(CGAL::abs((*qit)-(*pit))); return distance; } @@ -154,7 +167,7 @@ namespace CGAL { traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), pit = construct_it(p); - if (power == FT(0)) { + if (is_zero(power)) { if (the_weights[0] * CGAL::abs((*qit) - (*pit)) > distance) distance = the_weights[0] * CGAL::abs((*qit)-(*pit)); qit++;pit++; @@ -163,10 +176,10 @@ namespace CGAL { } else{ distance += - the_weights[0] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[0] * pow(CGAL::abs((*qit)-(*pit))); qit++;pit++; distance += - the_weights[1] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[1] * pow(CGAL::abs((*qit)-(*pit))); } return distance; } @@ -180,7 +193,7 @@ namespace CGAL { traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), pit = construct_it(p); - if (power == FT(0)) { + if (is_zero(power)) { if (the_weights[0] * CGAL::abs((*qit) - (*pit)) > distance) distance = the_weights[0] * CGAL::abs((*qit)-(*pit)); qit++;pit++; @@ -192,13 +205,13 @@ namespace CGAL { } else{ distance += - the_weights[0] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[0] * pow(CGAL::abs((*qit)-(*pit))); qit++;pit++; distance += - the_weights[1] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[1] * pow(CGAL::abs((*qit)-(*pit))); qit++;pit++; distance += - the_weights[2] * std::pow(CGAL::abs((*qit)-(*pit)),power); + the_weights[2] * pow(CGAL::abs((*qit)-(*pit))); } return distance; } @@ -212,7 +225,7 @@ namespace CGAL { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it= traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), qe = construct_it(q,1); - if (power == FT(0)) + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if (the_weights[i]*(r.min_coord(i) - @@ -230,10 +243,10 @@ namespace CGAL { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if ((*qit) < r.min_coord(i)) distance += the_weights[i] * - std::pow(r.min_coord(i)-(*qit),power); + pow(r.min_coord(i)-(*qit)); if ((*qit) > r.max_coord(i)) distance += the_weights[i] * - std::pow((*qit)-r.max_coord(i),power); + pow((*qit)-r.max_coord(i)); } }; return distance; @@ -247,7 +260,7 @@ namespace CGAL { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it= traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), qe = construct_it(q,1); - if (power == FT(0)) + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if (the_weights[i]*(r.min_coord(i) - @@ -270,12 +283,12 @@ namespace CGAL { if ((*qit) < r.min_coord(i)){ dists[i] = r.min_coord(i)-(*qit); distance += the_weights[i] * - std::pow(dists[i],power); + pow(dists[i]); } if ((*qit) > r.max_coord(i)){ dists[i] = (*qit)-r.max_coord(i); distance += the_weights[i] * - std::pow(dists[i],power); + pow(dists[i]); } } }; @@ -290,7 +303,7 @@ namespace CGAL { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it= traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), qe = construct_it(q,1); - if (power == FT(0)) + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if ((*qit) >= (r.min_coord(i) + @@ -311,9 +324,9 @@ namespace CGAL { { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - distance += the_weights[i] * std::pow(r.max_coord(i)-(*qit),power); + distance += the_weights[i] * pow(r.max_coord(i)-(*qit)); else - distance += the_weights[i] * std::pow((*qit)-r.min_coord(i),power); + distance += the_weights[i] * pow((*qit)-r.min_coord(i)); } }; return distance; @@ -327,7 +340,7 @@ namespace CGAL { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it= traits.construct_cartesian_const_iterator_d_object(); Coord_iterator qit = construct_it(q), qe = construct_it(q,1); - if (power == FT(0)) + if (is_zero(power)) { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if ((*qit) >= (r.min_coord(i) + @@ -353,11 +366,11 @@ namespace CGAL { for (unsigned int i = 0; qit != qe; ++qit, ++i) { if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)){ dists[i] = r.max_coord(i)-(*qit); - distance += the_weights[i] * std::pow(dists[i],power); + distance += the_weights[i] * pow(dists[i]); } else{ dists[i] = (*qit)-r.min_coord(i); - distance += the_weights[i] * std::pow(dists[i],power); + distance += the_weights[i] * pow(dists[i]); } } }; @@ -370,7 +383,7 @@ namespace CGAL { int cutting_dimension) const { FT new_dist; - if (power == FT(0)) + if (is_zero(power)) { if (the_weights[cutting_dimension]*CGAL::abs(new_off) > dist) @@ -381,7 +394,7 @@ namespace CGAL { else { new_dist = dist + the_weights[cutting_dimension] * - (std::pow(CGAL::abs(new_off),power)-std::pow(CGAL::abs(old_off),power)); + (pow(CGAL::abs(new_off))-pow(CGAL::abs(old_off))); } return new_dist; } @@ -390,8 +403,8 @@ namespace CGAL { FT transformed_distance(FT d) const { - if (power <= FT(0)) return d; - else return std::pow(d,power); + if (! is_positive(power)) return d; + else return pow(d); } @@ -399,8 +412,8 @@ namespace CGAL { FT inverse_of_transformed_distance(FT d) const { - if (power <= FT(0)) return d; - else return std::pow(d,1/power); + if (! is_positive(power)) return d; + else return pow(d,1/power); } diff --git a/Surface_mesh/doc/Surface_mesh/PackageDescription.txt b/Surface_mesh/doc/Surface_mesh/PackageDescription.txt index f0991aafdca..974c86b9f54 100644 --- a/Surface_mesh/doc/Surface_mesh/PackageDescription.txt +++ b/Surface_mesh/doc/Surface_mesh/PackageDescription.txt @@ -31,7 +31,7 @@ \cgalPkgDescriptionBegin{Surface Mesh,PkgSurfaceMesh} \cgalPkgPicture{Surface_mesh_teaser.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Mario Botsch, Daniel Sieger, Philipp Moeller, and Andreas Fabri} +\cgalPkgAuthors{Mario Botsch, Daniel Sieger, Philipp Moeller, and Andreas Fabri} \cgalPkgDesc{The surface mesh class provided by this package is an implementation of the halfedge data structure allowing to represent polyhedral surfaces. It is an alternative to the packages \ref PkgHalfedgeDS and \ref PkgPolyhedron. diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 290eb6ba0a6..ea1f3f048f9 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -511,13 +511,14 @@ private: //------------------------------------------------------ iterator types class Index_iterator : public boost::iterator_facade< Index_iterator, Index_, - std::random_access_iterator_tag + std::random_access_iterator_tag, + Index_ > { typedef boost::iterator_facade< Index_iterator, Index_, - std::random_access_iterator_tag - > Facade; + std::random_access_iterator_tag, + Index_> Facade; public: Index_iterator() : hnd_(), mesh_(nullptr) {} Index_iterator(const Index_& h, const Surface_mesh* m) @@ -595,7 +596,7 @@ private: //------------------------------------------------------ iterator types return this->hnd_ == other.hnd_; } - Index_& dereference() const { return const_cast(hnd_); } + Index_ dereference() const { return hnd_; } Index_ hnd_; const Surface_mesh* mesh_; diff --git a/Surface_mesh_approximation/doc/Surface_mesh_approximation/PackageDescription.txt b/Surface_mesh_approximation/doc/Surface_mesh_approximation/PackageDescription.txt index 99e6602b09a..e4f9503b14b 100644 --- a/Surface_mesh_approximation/doc/Surface_mesh_approximation/PackageDescription.txt +++ b/Surface_mesh_approximation/doc/Surface_mesh_approximation/PackageDescription.txt @@ -9,7 +9,7 @@ \cgalPkgPicture{sma-pkg-small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Pierre Alliez, David Cohen-Steiner, Lingjie Zhu} +\cgalPkgAuthors{Pierre Alliez, David Cohen-Steiner, and Lingjie Zhu} \cgalPkgDesc{This package implements the Variational Shape Approximation method to approximate an input surface triangle mesh by a simpler surface triangle mesh. The algorithm proceeds by iterative clustering of triangles, the clustering process being seeded randomly, incrementally or hierarchically. While the default function runs an automated version of the algorithm, interactive control is possible via a class interface. The API is flexible and can be extended to user-defined proxies and error metrics.} \cgalPkgManuals{Chapter_Triangulated_Surface_Mesh_Approximation,PkgTSMARef} diff --git a/Surface_mesh_deformation/doc/Surface_mesh_deformation/PackageDescription.txt b/Surface_mesh_deformation/doc/Surface_mesh_deformation/PackageDescription.txt index 0052d2f8e84..fc3fadcbef5 100644 --- a/Surface_mesh_deformation/doc/Surface_mesh_deformation/PackageDescription.txt +++ b/Surface_mesh_deformation/doc/Surface_mesh_deformation/PackageDescription.txt @@ -7,7 +7,7 @@ \cgalPkgDescriptionBegin{Triangulated Surface Mesh Deformation,PkgSurfaceMeshDeformation} \cgalPkgPicture{deform-ico.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Sébastien Loriot, Olga Sorkine-Hornung, Yin Xu and Ilker %O. Yaz} +\cgalPkgAuthors{Sébastien Loriot, Olga Sorkine-Hornung, Yin Xu, and Ilker %O. Yaz} \cgalPkgDesc{This package offers surface mesh deformation algorithms which provide new positions to the vertices of a surface mesh under positional constraints of some of its vertices, without requiring any additional structure other than the surface mesh itself.} \cgalPkgManuals{Chapter_SurfaceMeshDeformation,PkgSurfaceMeshDeformationRef} diff --git a/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/PackageDescription.txt b/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/PackageDescription.txt index fed84152440..358ac04ed5a 100644 --- a/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/PackageDescription.txt +++ b/Surface_mesh_segmentation/doc/Surface_mesh_segmentation/PackageDescription.txt @@ -11,7 +11,7 @@ \cgalPkgPicture{segmentation_ico.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Ilker %O. Yaz and Sébastien Loriot} +\cgalPkgAuthors{Ilker %O. Yaz and Sébastien Loriot} \cgalPkgDesc{This package provides a method to generate a segmentation of a triangulated surface mesh. The algorithm first computes the Shape Diameter Function (SDF) for all facets and applies a diff --git a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/PackageDescription.txt b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/PackageDescription.txt index 1f434655345..b16cceb370e 100644 --- a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/PackageDescription.txt +++ b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/PackageDescription.txt @@ -16,7 +16,7 @@ \cgalPkgDescriptionBegin{Triangulated Surface Mesh Shortest Paths,PkgSurfaceMeshShortestPath} \cgalPkgPicture{shortestpathspackage-ico.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Stephen Kiazyk, Sébastien Loriot, Éric Colin de Verdière} +\cgalPkgAuthors{Stephen Kiazyk, Sébastien Loriot, and Éric Colin de Verdière} \cgalPkgDesc{The package provides methods for computing geodesic shortest path on triangulated surface meshes. The algorithm used is based on a paper by Xin and Wang \cgalCite{XinWang2009improvingchenandhan} . The input of this package can be any model of the `FaceListGraph` concept. } \cgalPkgManuals{Chapter_Surface_mesh_shortest_path,PkgSurfaceMeshShortestPathRef} \cgalPkgSummaryEnd diff --git a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt index 1d97e670f9d..dcbee682d4e 100644 --- a/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt +++ b/Surface_mesh_simplification/doc/Surface_mesh_simplification/PackageDescription.txt @@ -6,7 +6,7 @@ \cgalPkgDescriptionBegin{Triangulated Surface Mesh Simplification,PkgSurfaceMeshSimplification} \cgalPkgPicture{SMS-detail.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Fernando Cacciola, Mael Rouxel-Labbé, Baskın Şenbaşlar, and Julian Komaromy} +\cgalPkgAuthors{Fernando Cacciola, Mael Rouxel-Labbé, Baskın Şenbaşlar, and Julian Komaromy} \cgalPkgDesc{This package provides an algorithm to simplify a triangulated surface mesh by edge collapsing. Users can define cost, constraints, and placement strategies to decide when and how should edges be collapsed. A few strategies are offered by default, such as the Turk/Lindstrom diff --git a/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_bounded_normal_change.cpp b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_bounded_normal_change.cpp index 88eb9b986e7..bc89a3b77aa 100644 --- a/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_bounded_normal_change.cpp +++ b/Surface_mesh_simplification/examples/Surface_mesh_simplification/edge_collapse_bounded_normal_change.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) // This is a stop predicate (defines when the algorithm terminates). // In this example, the simplification stops when the number of undirected edges // left in the surface mesh drops below the specified number - const std::size_t stop_n = (argc > 2) ? std::stoi(argv[2]) : num_halfedges(surface_mesh)/2 - 1; + const std::size_t stop_n = (argc > 2) ? std::stoi(argv[2]) : num_edges(surface_mesh)/2 - 1; SMS::Edge_count_stop_predicate stop(stop_n); typedef SMS::LindstromTurk_placement Placement; diff --git a/Surface_mesh_skeletonization/doc/Surface_mesh_skeletonization/PackageDescription.txt b/Surface_mesh_skeletonization/doc/Surface_mesh_skeletonization/PackageDescription.txt index fa4c5ae7fdb..b6c97efc05c 100644 --- a/Surface_mesh_skeletonization/doc/Surface_mesh_skeletonization/PackageDescription.txt +++ b/Surface_mesh_skeletonization/doc/Surface_mesh_skeletonization/PackageDescription.txt @@ -7,7 +7,7 @@ \cgalPkgDescriptionBegin{Triangulated Surface Mesh Skeletonization,PkgSurfaceMeshSkeletonization} \cgalPkgPicture{mcfskel-small.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Xiang Gao, Sébastien Loriot and Andrea Tagliasacchi} +\cgalPkgAuthors{Xiang Gao, Sébastien Loriot, and Andrea Tagliasacchi} \cgalPkgDesc{This package provides a (1D) curve skeleton extraction algorithm for a triangulated polygonal mesh without borders based on the mean curvature flow. The particularity of this skeleton is that it captures the topology of the input. For each skeleton vertex one can obtain its location and its corresponding vertices from the input mesh. diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt index 97f1f3bad7e..40828383894 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt @@ -20,7 +20,7 @@ \cgalPkgDescriptionBegin{Surface Mesh Topology,PkgSurfaceMeshTopology} \cgalPkgPicture{surface-mesh-topology-logo.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{Guillaume Damiand, Francis Lazarus} +\cgalPkgAuthors{Guillaume Damiand and Francis Lazarus} \cgalPkgDesc{This package provides a toolbox for manipulating curves on a combinatorial surface from the topological point of view. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other.} \cgalPkgManuals{Chapter_Surface_Mesh_Topology,PkgSurfaceMeshTopologyRef} \cgalPkgSummaryEnd diff --git a/TDS_3/doc/TDS_3/PackageDescription.txt b/TDS_3/doc/TDS_3/PackageDescription.txt index 19d3dfb5fcc..06523934036 100644 --- a/TDS_3/doc/TDS_3/PackageDescription.txt +++ b/TDS_3/doc/TDS_3/PackageDescription.txt @@ -14,7 +14,7 @@ \cgalPkgDescriptionBegin{3D Triangulation Data Structure,PkgTDS3} \cgalPkgPicture{tds3_small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Clément Jamin, Sylvain Pion and Monique Teillaud} +\cgalPkgAuthors{Clément Jamin, Sylvain Pion, and Monique Teillaud} \cgalPkgDesc{This package provides a data structure to store a three-dimensional triangulation that has the topology of a three-dimensional sphere. The package acts as a container for the vertices and cells of the triangulation and provides basic combinatorial operations on the triangulation.} \cgalPkgManuals{Chapter_3D_Triangulation_Data_Structure,PkgTDS3Ref} \cgalPkgSummaryEnd diff --git a/Testsuite/include/CGAL/Testsuite/Triangulation_23/test_move_semantic.h b/Testsuite/include/CGAL/Testsuite/Triangulation_23/test_move_semantic.h index 3254fb6571f..ed489b44bcf 100644 --- a/Testsuite/include/CGAL/Testsuite/Triangulation_23/test_move_semantic.h +++ b/Testsuite/include/CGAL/Testsuite/Triangulation_23/test_move_semantic.h @@ -11,6 +11,8 @@ // Author(s) : Laurent Rineau // +#ifndef CGAL_TEST_T23_MOVE_SEMANTIC_C +#define CGAL_TEST_T23_MOVE_SEMANTIC_C #include @@ -67,3 +69,5 @@ namespace CGAL { } } } + +#endif // CGAL_TEST_T23_MOVE_SEMANTIC_C diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 764ed582390..085ecc8c1e8 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -14,7 +14,7 @@ \cgalPkgPicture{bimba_back_small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur} +\cgalPkgAuthors{Jane Tournois, Noura Faraj, Jean-Marc Thiery, and Tamy Boubekeur} \cgalPkgDesc{ The package provides a function for remeshing tetrahedral meshes, targeting high quality meshes with respect to dihedral angles. diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 5814fc4fd28..be81a7809a4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1313,7 +1313,7 @@ void dump_surface_off(const Tr& tr, const char* filename) } //write facets - std::size_t nbf_print = 0; + CGAL_assertion_code(std::size_t nbf_print = 0); for (Finite_facets_iterator fit = tr.finite_facets_begin(); fit != tr.finite_facets_end(); ++fit) { @@ -1324,7 +1324,7 @@ void dump_surface_off(const Tr& tr, const char* filename) ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " << vertices.left.at(c->vertex((i + 2) % 4)) << " " << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; - ++nbf_print; + CGAL_assertion_code(++nbf_print); } } CGAL_assertion(nbf == nbf_print); @@ -1581,7 +1581,7 @@ void dump_facets_in_complex(const C3t3& c3t3, const char* filename) } //write facets - std::size_t nbf_print = 0; + CGAL_assertion_code(std::size_t nbf_print = 0); for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); fit != c3t3.facets_in_complex_end(); ++fit) { @@ -1590,7 +1590,7 @@ void dump_facets_in_complex(const C3t3& c3t3, const char* filename) ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " << vertices.left.at(c->vertex((i + 2) % 4)) << " " << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; - ++nbf_print; + CGAL_assertion_code(++nbf_print); } CGAL_assertion(nbf == nbf_print); diff --git a/Three/doc/Three/PackageDescription.txt b/Three/doc/Three/PackageDescription.txt index e8173a1e95e..f04d3ec8473 100644 --- a/Three/doc/Three/PackageDescription.txt +++ b/Three/doc/Three/PackageDescription.txt @@ -6,7 +6,7 @@ \cgalPkgDescriptionBegin{Three,PkgThree} \cgalPkgPicture{pkg-small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Laurent Rineau, Sebastien Loriot, Andreas Fabri, Maxime Gimeno} +\cgalPkgAuthors{Laurent Rineau, Sebastien Loriot, Andreas Fabri, and Maxime Gimeno} \cgalPkgDesc{This package provides base classes for building a plugin. } \cgalPkgManuals{Chapter_Three,PkgThreeRef} \cgalPkgSummaryEnd diff --git a/Triangulation_3/doc/Triangulation_3/PackageDescription.txt b/Triangulation_3/doc/Triangulation_3/PackageDescription.txt index 856c75270ee..6e12268a179 100644 --- a/Triangulation_3/doc/Triangulation_3/PackageDescription.txt +++ b/Triangulation_3/doc/Triangulation_3/PackageDescription.txt @@ -28,7 +28,7 @@ \cgalPkgDescriptionBegin{3D Triangulations,PkgTriangulation3} \cgalPkgPicture{twotets.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Clément Jamin, Sylvain Pion and Monique Teillaud} +\cgalPkgAuthors{Clément Jamin, Sylvain Pion, and Monique Teillaud} \cgalPkgDesc{This package allows to build and handle triangulations for point sets in three dimensions. Any \cgal triangulation covers the convex hull of its vertices. Triangulations are build incrementally and can be modified by insertion, displacements or removal of vertices. They offer point location facilities. The package provides plain triangulation (whose faces depends on the insertion order of the vertices) and Delaunay triangulations. Regular triangulations are also provided for sets of weighted points. Delaunay and regular triangulations offer nearest neighbor queries and primitives to build the dual Voronoi and power diagrams. Optionally, the main Delaunay and regular triangulation algorithms (insert, remove) support multi-core shared-memory architectures to take advantage of available parallelism.} \cgalPkgManuals{Chapter_3D_Triangulations,PkgTriangulation3Ref} \cgalPkgSummaryEnd diff --git a/Triangulation_3/test/Triangulation_3/CMakeLists.txt b/Triangulation_3/test/Triangulation_3/CMakeLists.txt index c87f341eb25..b0c09e90f59 100644 --- a/Triangulation_3/test/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/test/Triangulation_3/CMakeLists.txt @@ -22,9 +22,9 @@ create_single_source_cgal_program("test_regular_traits_3.cpp") create_single_source_cgal_program("test_RT_cell_base_with_weighted_circumcenter_3.cpp") create_single_source_cgal_program("test_robust_weighted_circumcenter.cpp") create_single_source_cgal_program("test_simplex_3.cpp") -create_single_source_cgal_program( "test_simplex_iterator_3.cpp" ) -create_single_source_cgal_program( "test_segment_cell_traverser_3.cpp" ) -create_single_source_cgal_program( "test_segment_simplex_traverser_3.cpp" ) +create_single_source_cgal_program("test_simplex_iterator_3.cpp" ) +create_single_source_cgal_program("test_segment_cell_traverser_3.cpp" ) +create_single_source_cgal_program("test_segment_simplex_traverser_3.cpp" ) create_single_source_cgal_program("test_static_filters.cpp") create_single_source_cgal_program("test_triangulation_3.cpp") create_single_source_cgal_program("test_io_triangulation_3.cpp") diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index 315e4b61a13..78b8822f598 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -14,6 +14,19 @@ #ifndef CGAL_TEST_CLS_DELAUNAY_C #define CGAL_TEST_CLS_DELAUNAY_C +#include "_test_cls_iterator.h" +#include "_test_cls_circulator.h" +#include "_test_remove_cluster.h" + +#include +#include + +#include +#include + +#include +#include + #include #include #include @@ -21,18 +34,6 @@ #include #include -#include -#include - -#include "_test_cls_iterator.h" -#include "_test_cls_circulator.h" -#include "_test_remove_cluster.h" - -#include -#include -#include -#include - // Accessory set of functions to differentiate between // Delaunay::nearest_vertex[_in_cell] and // Regular::nearest_power_vertex[_in_cell]. @@ -93,22 +94,6 @@ nearest_vertex_in_cell(const T&t, const P&p, const typename T::Cell_handle c) return nearest_vertex_in_cell(t, p, c, typename T::Weighted_tag()); } -// Template meta programming if. -template < typename Cond, typename Then, typename Else > -struct If; - -template < typename Then, typename Else > -struct If -{ - typedef Then type; -}; - -template < typename Then, typename Else > -struct If -{ - typedef Else type; -}; - template < typename T, typename P > void test_conflicts(T& T3_13, const P *q) { @@ -221,6 +206,10 @@ _test_cls_delaunay_3(const Triangulation &) CGAL_USE_TYPE(Cell); CGAL_USE_TYPE(Vertex_iterator); CGAL_USE_TYPE(Cell_iterator); + + CGAL_USE_TYPE(typename Cls::Periodic_tag); + CGAL_USE_TYPE(typename Cls::Weighted_tag); + // +++ We define now some points for building triangulations +++++// // list of Points for T1_0 , T1_1, T1_2 : @@ -947,7 +936,7 @@ _test_cls_delaunay_3(const Triangulation &) Vertex_handle tmv1 = TM_0.insert(Point(0,0,0)); Vertex_handle tmv2 = TM_0.insert(Point(0,1,0)); - TM_0.move_if_no_collision(tmv1, Point(0, 2, 1)); + TM_0.move_if_no_collision(tmv1, Point(0, 2, 1)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); assert(TM_0.dimension() == 1); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h index ea40d75963e..798c40e2b5f 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h @@ -10,49 +10,62 @@ // // Author(s) : Monique Teillaud (Monique.Teillaud@sophia.inria.fr) -// This stuff is not used (obsolete) at the moment. +#include + +#include #include #include #include #include -#include -#include template void _test_cls_regular_3(const Triangulation &) { - typedef Triangulation Cls; + typedef Triangulation Cls; - static_assert(std::is_nothrow_move_constructible::value, - "move cstr is missing"); - static_assert(std::is_nothrow_move_assignable::value, - "move assignment is missing"); + typedef typename Cls::Bare_point Point; + typedef typename Cls::Weighted_point Weighted_point; + + typedef typename Cls::Vertex_handle Vertex_handle; + typedef typename Cls::Cell_handle Cell_handle; + typedef typename Cls::Facet Facet; + typedef typename Cls::Edge Edge; + + typedef std::list list_point; + typedef typename Cls::Finite_cells_iterator Finite_cells_iterator; typedef typename Triangulation::Geom_traits Gt; CGAL_USE_TYPE(Gt); - // We assume the traits class has been tested already - // actually, any traits is good if it has been tested + CGAL_USE_TYPE(typename Cls::Periodic_tag); + CGAL_USE_TYPE(typename Cls::Weighted_tag); - typedef typename Cls::Bare_point Bare_point; - typedef typename Cls::Weighted_point Weighted_point; + int n, m; + int count = 0; - typedef std::list list_point; - - // temporary version - - int n,m; - int count = 0 ; + // For dimension 0, we need to check that the point of highest weight is the + // one that finally ends up in the vertex. + std::cout << " test dimension 0 " << std::endl; + Cls T0; + T0.insert(Weighted_point( Point (0,0,0), 0) ); + T0.insert(Weighted_point( Point (0,0,0), 1) ); + T0.insert(Weighted_point( Point (0,0,0), -1) ); + assert(T0.dimension() == 0); + assert(T0.number_of_vertices() == 1); + assert(T0.finite_vertices_begin()->point().weight() == 1); std::cout << " test dimension 1 " << std::endl; Cls T1; std::cout << " number of inserted points : " ; + Weighted_point p[5]; for ( m=0; m<5; m++) { if ( (m%2)== 0 ) - T1.insert( Weighted_point( Bare_point( 2*m,0,0 ), 2 ) ); - else T1.insert( Weighted_point( Bare_point( -2*m+1,0,0 ), 2 ) ); + p[m] = Weighted_point( Point( 2*m,0,0 ), 2 ); + else + p[m] = Weighted_point( Point( -2*m+1,0,0 ), 2 ); + T1.insert( p[m] ); count++; if (count <10) std::cout << count << '\b' ; @@ -65,47 +78,123 @@ _test_cls_regular_3(const Triangulation &) } assert( T1.is_valid() ); std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + << T1.number_of_vertices() << std::endl; std::cout << " number of inserted points : " ; + Weighted_point q[5]; for ( m=0; m<5; m++) { if ( (m%2)== 0 ) - T1.insert( Weighted_point( Bare_point( 2*m+1,0,0 ), 5 ) ); - else T1.insert( Weighted_point( Bare_point( -2*m+1,0,0 ), 5 ) ); + q[m] = Weighted_point( Point( 2*m+1,0,0 ), 5 ); + else + q[m] = Weighted_point( Point( -2*m+1,0,0 ), 5 ); + T1.insert( q[m] ); count++; if (count <10) std::cout << count << '\b' ; else if (count < 100) - std::cout << count << '\b' << '\b' ; + std::cout << count << '\b' << '\b' ; else - std::cout << count << '\b' << '\b' << '\b' ; + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } assert( T1.is_valid() ); std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + << T1.number_of_vertices() << std::endl; std::cout << " number of inserted points : " ; + Weighted_point r[10]; for ( m=0; m<10; m++) { if ( (m%2)== 0 ) - T1.insert( Weighted_point( Bare_point( m,0,0 ), 1 ) ); - else T1.insert( Weighted_point( Bare_point( -m,0,0 ), 1 ) ); + r[m] = Weighted_point( Point( m,0,0 ), 1 ); + else + r[m] = Weighted_point( Point( -m,0,0 ), 1 ); + T1.insert( r[m] ); count++; if (count <10) std::cout << count << '\b' ; else if (count < 100) - std::cout << count << '\b' << '\b' ; + std::cout << count << '\b' << '\b' ; else - std::cout << count << '\b' << '\b' << '\b' ; + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } assert( T1.is_valid() ); std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + << T1.number_of_vertices() << std::endl; assert( T1.dimension()==1 ); + // The following is distilled from a bug report by Wulue Zhao + // (zhao.88@osu.edu), a student of Tamal Dey. + Point pt0(0,0,0); + Point pt1( 1,0,0), pt2(2,0,0), pt3(3,0,0); + Point pt4(-1,0,0), pt5(-2,0,0), pt6(-3,0,0); + + Weighted_point wp0(pt0,10.0); + Weighted_point wp1(pt1,0.0), wp2(pt2,0.0), wp3(pt3,0.0); + Weighted_point wp4(pt4,0.0), wp5(pt5,0.0), wp6(pt6,0.0); + + Cls T11; + + T11.insert(wp0); + T11.insert(wp1); + T11.insert(wp2); + T11.insert(wp3); + T11.insert(wp4); + T11.insert(wp5); + T11.insert(wp6); + + assert(T11.is_valid()); + + // And another distilled bug report from the same guy. + { + Point p1(-0.07, 0.04, 0.04); + Point p2(0.09, 0.04, 0.04); + Point p3(0.09, -0.05, 0.04); + Point p4(0.05, -0.05, 0.04); + Point p5(0.05, 0.0, 0.04); + Point p6(-0.07, 0.0, 0.04); + Point p7(-0.07, 0.04, -0.04); + Point p8(0.09, 0.04, -0.04); + Point p9(0.09, -0.05, -0.04); + Point p10(0.05, -0.05, -0.04); + Point p11(0.05, 0.0, -0.04); + Point p12(-0.07, 0.0, -0.04); + + Weighted_point wp1(p1,0); + Weighted_point wp2(p2,0); + Weighted_point wp3(p3,0); + Weighted_point wp4(p4,0); + Weighted_point wp5(p5,0); + Weighted_point wp6(p6,0); + Weighted_point wp7(p7,0); + Weighted_point wp8(p8,0); + Weighted_point wp9(p9,0); + Weighted_point wp10(p10,0); + Weighted_point wp11(p11,0); + Weighted_point wp12(p12,0); + Weighted_point wp13(p3,0.3); // wp13 has the same coordinates with wp3 + + Cls T111; + + T111.insert(wp1); + T111.insert(wp2); + T111.insert(wp3); + T111.insert(wp13); // it doesnot work inserting wp13 here + T111.insert(wp4); + T111.insert(wp5); + T111.insert(wp6); + T111.insert(wp7); + T111.insert(wp8); + T111.insert(wp9); + T111.insert(wp10); + T111.insert(wp11); + T111.insert(wp12); + + assert(T111.is_valid()); + } + std::cout << " test dimension 2 " << std::endl; std::cout << " number of inserted points : " ; Cls T2; @@ -113,61 +202,66 @@ _test_cls_regular_3(const Triangulation &) count = 0 ; int px=1, py=1; int qx=-1, qy=2; + Weighted_point s[400]; for (m=0; m<10; m++) for (n=0; n<10; n++) { - T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), 1 ) ); + s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), 1 ); + T2.insert( s[m+20*n] ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=10; m<20; m++) for (n=0; n<10; n++) { - T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), -1 ) ); + s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), -1 ); + T2.insert( s[m+20*n] ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=0; m<10; m++) for (n=10; n<20; n++) { - T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), -2 ) ); + s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), -2 ); + T2.insert( s[m+20*n] ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=10; m<20; m++) for (n=10; n<20; n++) { - T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), 5 ) ); + s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), 5 ); + T2.insert( s[m+20*n] ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } std::cout << std::endl << " number of vertices : " - << T2.number_of_vertices() << std::endl; + << T2.number_of_vertices() << std::endl; assert( T2.dimension()==2 ); assert( T2.is_valid() ); @@ -178,16 +272,18 @@ _test_cls_regular_3(const Triangulation &) list_point lp; int a, b, d; for (a=0;a!=10;a++) - for (b=0;b!=10;b++) - for (d=0;d!=10;d++) - lp.push_back(Weighted_point( Bare_point(a*b-d*a + (a-b)*10 +a , - a-b+d +5*b, - a*a-d*d+b), - a*b-a*d) ); + // for (b=0;b!=10;b++) + for (b=0;b!=5;b++) + // for (d=0;d!=10;d++) + for (d=0;d!=5;d++) + lp.push_back(Weighted_point( Point(a*b-d*a + (a-b)*10 +a , + a-b+d +5*b, + a*a-d*d+b), + a*b-a*d) ); typename list_point::iterator it; count = 0 ; std::cout << " number of inserted points : " ; - for (it=lp.begin(); it!=lp.end();it++){ + for (it=lp.begin(); it!=lp.end(); ++it){ count++; T.insert(*it); if (count <10) @@ -199,15 +295,136 @@ _test_cls_regular_3(const Triangulation &) if (count < 1000) std::cout << count << '\b' << '\b' << '\b' ; else - std::cout << count << std::endl; + std::cout << count << std::endl; std::cout.flush(); } + std::cout << std::endl; std::cout << " number of vertices : " - << T.number_of_vertices() << std::endl; + << T.number_of_vertices() << std::endl; assert(T.is_valid()); assert(T.dimension()==3); + T.clear(); + std::cout << " test iterator range insert" << std::endl; + T.insert (lp.begin(), lp.end()); + + std::cout << " number of vertices : " + << T.number_of_vertices() << std::endl; + assert(T.is_valid()); + assert(T.dimension()==3); + + + //test nearest_power_vertex + std::cout << " test nearest_power_vertex " << std::endl; + Point pp1(0.0, 0.0, 0.0); + Point pp2(1.0, 0.0, 0.0); + Point pp3(0.0, 1.0, 0.0); + Point pp4(0.0, 0.0, 1.0); + Point pp5(1.0, 1.0, 0.0); + Point pp6(0.0, 1.0, 1.0); + Point pp7(1.0, 0.0, 1.0); + Point pp8(1.0, 1.0, 1.0); + Point pp9(0.5, 0.5, 0.5); + + Weighted_point wpp1(pp1, 1.0); + Weighted_point wpp2(pp2, 2.0); + Weighted_point wpp3(pp3, 1.0); + Weighted_point wpp4(pp4, 4.0); + Weighted_point wpp5(pp5, 1.0); + Weighted_point wpp6(pp6, 1.0); + Weighted_point wpp7(pp7, 1.0); + Weighted_point wpp8(pp8, 8.0); + Weighted_point wpp9(pp9, -8.0); + + Cls T3; + + T3.insert(wpp1); + Vertex_handle v2 = T3.insert(wpp2); + assert( T3.nearest_power_vertex(Point(0.5,0.5,0.5)) == v2); + + T3.insert(wpp3); + Vertex_handle v4 = T3.insert(wpp4); + assert( T3.nearest_power_vertex(Point(0.5,0.5,0.5)) == v4); + + T3.insert(wpp5); + T3.insert(wpp6); + T3.insert(wpp7); + + Vertex_handle v8 = T3.insert(wpp8); + Point query(0.5,0.5,0.5); + assert(T3.nearest_power_vertex(query) == v8); + assert(T3.nearest_power_vertex_in_cell(query ,v8->cell()) == v8); + + Vertex_handle v9 = T3.insert(wpp9); + assert(v9 == Vertex_handle()); // hidden point + + // test dual + std::cout << " test dual member functions" << std::endl; + Finite_cells_iterator fcit = T3.finite_cells_begin(); + for( ; fcit != T3.finite_cells_end(); ++fcit) { + Point cc = T3.dual(fcit); + Vertex_handle ncc = T3.nearest_power_vertex(cc); + assert(fcit->has_vertex(ncc)); + } + + // test Gabriel + std::cout << " test is_Gabriel " << std::endl; + Point q0(0.,0.,0.); + Point q1(2.,0.,0.); + Point q2(0.,2.,0.); + Point q3(0.,0.,2.); + + Weighted_point wq0(q0,0.); + Weighted_point wq1(q1,0.); + Weighted_point wq2(q2,0.); + Weighted_point wq3(q3,0.); + Weighted_point wq01(q0,2.); + + Cls T4; + Vertex_handle v0 = T4.insert(wq0); + Vertex_handle v1 = T4.insert(wq1); + v2 = T4.insert(wq2); + Vertex_handle v3 = T4.insert(wq3); + Cell_handle c; + int i,j,k,l; + assert(T4.is_facet(v0,v1,v2,c,j,k,l)); + i = 6 - (j+k+l); + Facet f = std::make_pair(c,i); + assert(T4.is_Gabriel(c,i)); + assert(T4.is_Gabriel(f)); + assert(T4.is_facet(v1,v2,v3,c,j,k,l)); + i = 6 - (j+k+l); + assert(!T4.is_Gabriel(c,i)); + assert(T4.is_edge(v0,v1,c,i,j)); + assert(T4.is_Gabriel(c,i,j)); + Edge e = make_triple(c,i,j); + assert(T4.is_Gabriel(e)); + assert(T4.is_edge(v2,v3,c,i,j)); + assert(T4.is_Gabriel(c,i,j)); + + Vertex_handle v01 = T4.insert(wq01); + (void) v01; // kill warning + assert(T4.is_edge(v2,v3,c,i,j)); + assert(!T4.is_Gabriel(c,i,j)); + + Weighted_point wwq0(q0,0.); + Weighted_point wwq1(q1,0.); + Weighted_point wwq2(q2,0.); + Weighted_point wwq3(q3,5.); + Cls T5; + v0 = T5.insert(wwq0); + v1 = T5.insert(wwq1); + v2 = T5.insert(wwq2); + v3 = T5.insert(wwq3); + assert(T5.nearest_power_vertex(v3->point().point()) == v3); + assert(T5.nearest_power_vertex(v0->point().point()) == v3); + assert(T5.is_Gabriel(v3)); + assert(!T5.is_Gabriel(v0)); + + static_assert(std::is_nothrow_move_constructible::value, "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, "move assignment is missing"); + namespace test_tr_23 = CGAL::Testsuite::Triangulation_23; test_tr_23::test_move_semantic(T); } diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index c8775dabbe2..21c8ee2d996 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -10,6 +10,14 @@ // // Author(s) : Francois Rebufat +#include "_test_cls_iterator.h" +#include "_test_cls_circulator.h" +#include +#include + +#include +#include + #include #include #include @@ -17,14 +25,6 @@ #include #include -#include "_test_cls_iterator.h" -#include "_test_cls_circulator.h" - -#include -#include -#include -#include - template bool check_all_are_finite(Triangulation* tr, const Container& cont) { @@ -120,6 +120,9 @@ _test_cls_triangulation_3(const Triangulation &) CGAL_USE_TYPE(Vertex_iterator); CGAL_USE_TYPE(Cell_iterator); + CGAL_USE_TYPE(typename Cls::Periodic_tag); + CGAL_USE_TYPE(typename Cls::Weighted_tag); + // +++ We define now some points for building triangulations +++++// // list of Points for T1_0 , T1_1, T1_2 : diff --git a/Triangulation_3/test/Triangulation_3/test_regular_3.cpp b/Triangulation_3/test/Triangulation_3/test_regular_3.cpp index 4aa9fa0654d..b8a9d8170ad 100644 --- a/Triangulation_3/test/Triangulation_3/test_regular_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_regular_3.cpp @@ -1,455 +1,51 @@ -// Copyright (c) 1998 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Monique Teillaud (Monique.Teillaud@sophia.inria.fr) -// : Mariette Yvinec (Mariette.Yvinec@sophia.inria.fr) - #include -#include -#include -#include + +bool del = true; #include #include #include -bool del=true; - -typedef CGAL::Exact_predicates_inexact_constructions_kernel traits; +#include +#include +#include +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC; // Explicit instantiation of the whole class : -template class CGAL::Regular_triangulation_3; +template class CGAL::Regular_triangulation_3; -template -void test_RT() +template +void test_kernel() { - typedef RT Cls; + using Cls = CGAL::Regular_triangulation_3; - _test_cls_regular_3( Cls() ); - typedef typename RT::Bare_point Point; - typedef typename RT::Weighted_point Weighted_point; - - typedef typename Cls::Vertex_handle Vertex_handle; - typedef typename Cls::Cell_handle Cell_handle; - typedef typename Cls::Facet Facet; - typedef typename Cls::Edge Edge; - - typedef std::list list_point; - typedef typename Cls::Finite_cells_iterator Finite_cells_iterator; - - // temporary version - - int n, m; - int count = 0; - - // For dimension 0, we need to check that the point of highest weight is the - // one that finally ends up in the vertex. - std::cout << " test dimension 0 " << std::endl; - Cls T0; - T0.insert(Weighted_point( Point (0,0,0), 0) ); - T0.insert(Weighted_point( Point (0,0,0), 1) ); - T0.insert(Weighted_point( Point (0,0,0), -1) ); - assert(T0.dimension() == 0); - assert(T0.number_of_vertices() == 1); - assert(T0.finite_vertices_begin()->point().weight() == 1); - - std::cout << " test dimension 1 " << std::endl; - Cls T1; - std::cout << " number of inserted points : " ; - Weighted_point p[5]; - for ( m=0; m<5; m++) { - if ( (m%2)== 0 ) - p[m] = Weighted_point( Point( 2*m,0,0 ), 2 ); - else - p[m] = Weighted_point( Point( -2*m+1,0,0 ), 2 ); - T1.insert( p[m] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; - - std::cout << " number of inserted points : " ; - Weighted_point q[5]; - for ( m=0; m<5; m++) { - if ( (m%2)== 0 ) - q[m] = Weighted_point( Point( 2*m+1,0,0 ), 5 ); - else - q[m] = Weighted_point( Point( -2*m+1,0,0 ), 5 ); - T1.insert( q[m] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; - - std::cout << " number of inserted points : " ; - Weighted_point r[10]; - for ( m=0; m<10; m++) { - if ( (m%2)== 0 ) - r[m] = Weighted_point( Point( m,0,0 ), 1 ); - else - r[m] = Weighted_point( Point( -m,0,0 ), 1 ); - T1.insert( r[m] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; - assert( T1.dimension()==1 ); - - // The following is distilled from a bug report by Wulue Zhao - // (zhao.88@osu.edu), a student of Tamal Dey. - Point pt0(0,0,0); - Point pt1( 1,0,0), pt2(2,0,0), pt3(3,0,0); - Point pt4(-1,0,0), pt5(-2,0,0), pt6(-3,0,0); - - Weighted_point wp0(pt0,10.0); - Weighted_point wp1(pt1,0.0), wp2(pt2,0.0), wp3(pt3,0.0); - Weighted_point wp4(pt4,0.0), wp5(pt5,0.0), wp6(pt6,0.0); - - Cls T11; - - T11.insert(wp0); - T11.insert(wp1); - T11.insert(wp2); - T11.insert(wp3); - T11.insert(wp4); - T11.insert(wp5); - T11.insert(wp6); - - assert(T11.is_valid()); - - // And another distilled bug report from the same guy. - { - Point p1(-0.07, 0.04, 0.04); - Point p2(0.09, 0.04, 0.04); - Point p3(0.09, -0.05, 0.04); - Point p4(0.05, -0.05, 0.04); - Point p5(0.05, 0.0, 0.04); - Point p6(-0.07, 0.0, 0.04); - Point p7(-0.07, 0.04, -0.04); - Point p8(0.09, 0.04, -0.04); - Point p9(0.09, -0.05, -0.04); - Point p10(0.05, -0.05, -0.04); - Point p11(0.05, 0.0, -0.04); - Point p12(-0.07, 0.0, -0.04); - - Weighted_point wp1(p1,0); - Weighted_point wp2(p2,0); - Weighted_point wp3(p3,0); - Weighted_point wp4(p4,0); - Weighted_point wp5(p5,0); - Weighted_point wp6(p6,0); - Weighted_point wp7(p7,0); - Weighted_point wp8(p8,0); - Weighted_point wp9(p9,0); - Weighted_point wp10(p10,0); - Weighted_point wp11(p11,0); - Weighted_point wp12(p12,0); - Weighted_point wp13(p3,0.3); // wp13 has the same coordinates with wp3 - - Cls T111; - - T111.insert(wp1); - T111.insert(wp2); - T111.insert(wp3); - T111.insert(wp13); // it doesn't work inserting wp13 here - T111.insert(wp4); - T111.insert(wp5); - T111.insert(wp6); - T111.insert(wp7); - T111.insert(wp8); - T111.insert(wp9); - T111.insert(wp10); - T111.insert(wp11); - T111.insert(wp12); - - assert(T111.is_valid()); - } - - std::cout << " test dimension 2 " << std::endl; - std::cout << " number of inserted points : " ; - Cls T2; - - count = 0 ; - int px=1, py=1; - int qx=-1, qy=2; - Weighted_point s[400]; - for (m=0; m<10; m++) - for (n=0; n<10; n++) { - s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), 1 ); - T2.insert( s[m+20*n] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - for (m=10; m<20; m++) - for (n=0; n<10; n++) { - s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), -1 ); - T2.insert( s[m+20*n] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - for (m=0; m<10; m++) - for (n=10; n<20; n++) { - s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), -2 ); - T2.insert( s[m+20*n] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - for (m=10; m<20; m++) - for (n=10; n<20; n++) { - s[m+20*n] = Weighted_point( Point(m*px+n*qx, m*py+n*qy, 0), 5 ); - T2.insert( s[m+20*n] ); - count++; - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); - } - - std::cout << std::endl << " number of vertices : " - << T2.number_of_vertices() << std::endl; - assert( T2.dimension()==2 ); - assert( T2.is_valid() ); - - // dimension 3 - std::cout << " test dimension 3" << std::endl; - Cls T; - - list_point lp; - int a, b, d; - for (a=0;a!=10;a++) - // for (b=0;b!=10;b++) - for (b=0;b!=5;b++) - // for (d=0;d!=10;d++) - for (d=0;d!=5;d++) - lp.push_back(Weighted_point( Point(a*b-d*a + (a-b)*10 +a , - a-b+d +5*b, - a*a-d*d+b), - a*b-a*d) ); - typename list_point::iterator it; - count = 0 ; - std::cout << " number of inserted points : " ; - for (it=lp.begin(); it!=lp.end(); ++it){ - count++; - T.insert(*it); - if (count <10) - std::cout << count << '\b' ; - else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - if (count < 1000) - std::cout << count << '\b' << '\b' << '\b' ; - else - std::cout << count << std::endl; - std::cout.flush(); - } - std::cout << std::endl; - - std::cout << " number of vertices : " - << T.number_of_vertices() << std::endl; - assert(T.is_valid()); - assert(T.dimension()==3); - - T.clear(); - std::cout << " test iterator range insert" << std::endl; - T.insert (lp.begin(), lp.end()); - - std::cout << " number of vertices : " - << T.number_of_vertices() << std::endl; - assert(T.is_valid()); - assert(T.dimension()==3); - - - //test nearest_power_vertex - std::cout << " test nearest_power_vertex " << std::endl; - Point pp1(0.0, 0.0, 0.0); - Point pp2(1.0, 0.0, 0.0); - Point pp3(0.0, 1.0, 0.0); - Point pp4(0.0, 0.0, 1.0); - Point pp5(1.0, 1.0, 0.0); - Point pp6(0.0, 1.0, 1.0); - Point pp7(1.0, 0.0, 1.0); - Point pp8(1.0, 1.0, 1.0); - Point pp9(0.5, 0.5, 0.5); - - Weighted_point wpp1(pp1, 1.0); - Weighted_point wpp2(pp2, 2.0); - Weighted_point wpp3(pp3, 1.0); - Weighted_point wpp4(pp4, 4.0); - Weighted_point wpp5(pp5, 1.0); - Weighted_point wpp6(pp6, 1.0); - Weighted_point wpp7(pp7, 1.0); - Weighted_point wpp8(pp8, 8.0); - Weighted_point wpp9(pp9, -8.0); - - Cls T3; - - T3.insert(wpp1); - Vertex_handle v2 = T3.insert(wpp2); - assert( T3.nearest_power_vertex(Point(0.5,0.5,0.5)) == v2); - - T3.insert(wpp3); - Vertex_handle v4 = T3.insert(wpp4); - assert( T3.nearest_power_vertex(Point(0.5,0.5,0.5)) == v4); - - T3.insert(wpp5); - T3.insert(wpp6); - T3.insert(wpp7); - - Vertex_handle v8 = T3.insert(wpp8); - Point query(0.5,0.5,0.5); - assert(T3.nearest_power_vertex(query) == v8); - assert(T3.nearest_power_vertex_in_cell(query ,v8->cell()) == v8); - - Vertex_handle v9 = T3.insert(wpp9); - assert(v9 == Vertex_handle()); // hidden point - - // test dual - std::cout << " test dual member functions" << std::endl; - Finite_cells_iterator fcit = T3.finite_cells_begin(); - for( ; fcit != T3.finite_cells_end(); ++fcit) { - Point cc = T3.dual(fcit); - Vertex_handle ncc = T3.nearest_power_vertex(cc); - assert(fcit->has_vertex(ncc)); - } - - // test Gabriel - std::cout << " test is_Gabriel " << std::endl; - Point q0(0.,0.,0.); - Point q1(2.,0.,0.); - Point q2(0.,2.,0.); - Point q3(0.,0.,2.); - - Weighted_point wq0(q0,0.); - Weighted_point wq1(q1,0.); - Weighted_point wq2(q2,0.); - Weighted_point wq3(q3,0.); - Weighted_point wq01(q0,2.); - - Cls T4; - Vertex_handle v0 = T4.insert(wq0); - Vertex_handle v1 = T4.insert(wq1); - v2 = T4.insert(wq2); - Vertex_handle v3 = T4.insert(wq3); - Cell_handle c; - int i,j,k,l; - assert(T4.is_facet(v0,v1,v2,c,j,k,l)); - i = 6 - (j+k+l); - Facet f = std::make_pair(c,i); - assert(T4.is_Gabriel(c,i)); - assert(T4.is_Gabriel(f)); - assert(T4.is_facet(v1,v2,v3,c,j,k,l)); - i = 6 - (j+k+l); - assert(!T4.is_Gabriel(c,i)); - assert(T4.is_edge(v0,v1,c,i,j)); - assert(T4.is_Gabriel(c,i,j)); - Edge e = make_triple(c,i,j); - assert(T4.is_Gabriel(e)); - assert(T4.is_edge(v2,v3,c,i,j)); - assert(T4.is_Gabriel(c,i,j)); - - Vertex_handle v01 = T4.insert(wq01); - (void) v01; // kill warning - assert(T4.is_edge(v2,v3,c,i,j)); - assert(!T4.is_Gabriel(c,i,j)); - - Weighted_point wwq0(q0,0.); - Weighted_point wwq1(q1,0.); - Weighted_point wwq2(q2,0.); - Weighted_point wwq3(q3,5.); - Cls T5; - v0 = T5.insert(wwq0); - v1 = T5.insert(wwq1); - v2 = T5.insert(wwq2); - v3 = T5.insert(wwq3); - assert(T5.nearest_power_vertex(v3->point().point()) == v3); - assert(T5.nearest_power_vertex(v0->point().point()) == v3); - assert(T5.is_Gabriel(v3)); - assert(!T5.is_Gabriel(v0)); -} - -int main() -{ - test_RT >(); + _test_cls_regular_3(Cls()); #ifdef CGAL_LINKED_WITH_TBB typedef CGAL::Spatial_lock_grid_3< CGAL::Tag_priority_blocking> Lock_ds; typedef CGAL::Triangulation_data_structure_3< - CGAL::Regular_triangulation_vertex_base_3, - CGAL::Regular_triangulation_cell_base_3, - CGAL::Parallel_tag > Tds_parallel; + CGAL::Regular_triangulation_vertex_base_3, + CGAL::Regular_triangulation_cell_base_3, + CGAL::Parallel_tag > Tds_parallel; typedef CGAL::Regular_triangulation_3< - traits, Tds_parallel, Lock_ds> RT_parallel; + K, Tds_parallel, Lock_ds> RT_parallel; // The following test won't do things in parallel since it doesn't provide a lock data structure - test_RT(); + _test_cls_regular_3(RT_parallel()); // This test performs parallel operations - _test_cls_parallel_triangulation_3( RT_parallel() ); + _test_cls_parallel_triangulation_3(RT_parallel()); #endif - - std::cout << " quit " << std::endl; - return 0; +} + +int main() +{ + test_kernel(); + test_kernel(); + + std::cout << "Done!" << std::endl; + return EXIT_SUCCESS; } diff --git a/Triangulation_3/test/Triangulation_3/test_regular_as_delaunay_3.cpp b/Triangulation_3/test/Triangulation_3/test_regular_as_delaunay_3.cpp index c607bae4119..b7ab0c7c7cb 100644 --- a/Triangulation_3/test/Triangulation_3/test_regular_as_delaunay_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_regular_as_delaunay_3.cpp @@ -1,33 +1,37 @@ -// Copyright (c) 2004 INRIA Sophia-Antipolis (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Sylvain Pion - #include +bool del = true; -bool del=true; +#include +#include -#include "include/CGAL/_test_types.h" -#include "include/CGAL/_test_cls_delaunay_3.h" +template +void test_kernel() +{ + using Cls = CGAL::Regular_triangulation_3; + _test_cls_delaunay_3(Cls()); + +#ifdef CGAL_LINKED_WITH_TBB + typedef CGAL::Spatial_lock_grid_3< + CGAL::Tag_priority_blocking> Lock_ds; + typedef CGAL::Triangulation_data_structure_3< + CGAL::Regular_triangulation_vertex_base_3, + CGAL::Regular_triangulation_cell_base_3, + CGAL::Parallel_tag > Tds_parallel; + typedef CGAL::Regular_triangulation_3< + K, Tds_parallel, Lock_ds> RT_parallel; + + // The following test won't do things in parallel since it doesn't provide a lock data structure + _test_cls_delaunay_3(RT_parallel()); +#endif +} int main() { - typedef CGAL::Regular_triangulation_3 Cls; + test_kernel(); + test_kernel(); - _test_cls_delaunay_3( Cls() ); - - return 0; + std::cout << "Done!" << std::endl; + return EXIT_SUCCESS; } - -// MipsPro prefers this after the other instantiations... -// Explicit instantiation of the whole class : -template class CGAL::Regular_triangulation_3; diff --git a/Visibility_2/doc/Visibility_2/PackageDescription.txt b/Visibility_2/doc/Visibility_2/PackageDescription.txt index 24d45e71b50..4f1919adc56 100644 --- a/Visibility_2/doc/Visibility_2/PackageDescription.txt +++ b/Visibility_2/doc/Visibility_2/PackageDescription.txt @@ -11,7 +11,7 @@ \cgalPkgDescriptionBegin{2D Visibility Computation,PkgVisibility2} \cgalPkgPicture{visibility-teaser-thumbnail.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Michael Hemmer, Kan Huang, Francisc Bungiu, Ning Xu} +\cgalPkgAuthors{Michael Hemmer, Kan Huang, Francisc Bungiu, and Ning Xu} \cgalPkgDesc{This package provides several variants to compute the visibility area of a point within polygonal regions in two dimensions.} \cgalPkgManuals{Chapter_2D_Visibility_Computation,PkgVisibility2Ref} diff --git a/Weights/doc/Weights/PackageDescription.txt b/Weights/doc/Weights/PackageDescription.txt index a2cd0632d19..b59f3e06d68 100644 --- a/Weights/doc/Weights/PackageDescription.txt +++ b/Weights/doc/Weights/PackageDescription.txt @@ -513,7 +513,7 @@ a model of `AnalyticWeightTraits_3` for 3D points \cgalPkgPicture{weights_logo_120x120.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Dmitry Anisimov} +\cgalPkgAuthor{Dmitry Anisimov} \cgalPkgDesc{Many geometric algorithms rely on weighted constructions. This package provides a simple and unified interface to different types of weights. In particular, it includes numerous weights with a simple analytic expression, generalized barycentric