From b6da83066d0adef89924267800ffbdebc3d5be75 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sun, 4 Aug 2024 00:50:25 +0000 Subject: [PATCH] build based on b1ecb26 --- previews/PR135/404.html | 8 +- previews/PR135/api.html | 62 +++++++------- ...jisc.BOOG5oTW.png => afsyzdr.BOOG5oTW.png} | Bin ...saah.C3SxJ3x-.png => aithltv.C3SxJ3x-.png} | Bin ...{api.md.D8UtvlcW.js => api.md.BkdCNSpp.js} | 52 +++++------ ...UtvlcW.lean.js => api.md.BkdCNSpp.lean.js} | 2 +- .../{app.BPnMWvu-.js => app.okziLJoA.js} | 2 +- ...herl.BEFUMtlf.png => bhjiovt.BEFUMtlf.png} | Bin previews/PR135/assets/briiybs.Cy4gx45x.png | Bin 0 -> 73994 bytes ....DwdSQiwl.js => call_notes.md.CzI2sRnh.js} | 2 +- ...lean.js => call_notes.md.CzI2sRnh.lean.js} | 2 +- previews/PR135/assets/cezjmfi.BcI7dJNv.png | Bin 0 -> 206800 bytes .../chunks/@localSearchIndexroot.BBdiXmf3.js | 1 - .../chunks/@localSearchIndexroot.DOIebHWk.js | 1 + .../chunks/VPLocalSearchBox.CqCoAOXo.js | 7 -- .../chunks/VPLocalSearchBox.DLn4sKrv.js | 7 ++ .../PR135/assets/chunks/framework.CONf0Rze.js | 17 ++++ .../PR135/assets/chunks/framework.k41oUgTf.js | 17 ---- .../{theme.BCxq1kHm.js => theme.D6VlRy8Q.js} | 4 +- ...jvje.CG4dr3Lx.png => ejkzyqr.CG4dr3Lx.png} | Bin previews/PR135/assets/erkqkyr.Danh069g.png | Bin 0 -> 191571 bytes ...ents_accurate_accumulators.md.BEvtokUD.js} | 2 +- ...accurate_accumulators.md.BEvtokUD.lean.js} | 2 +- ... => experiments_predicates.md.Cb_olK_t.js} | 2 +- ...xperiments_predicates.md.Cb_olK_t.lean.js} | 2 +- ...pH0.js => explanations_crs.md.BcB0kXKu.js} | 2 +- ...s => explanations_crs.md.BcB0kXKu.lean.js} | 2 +- ... => explanations_paradigms.md.BQbTsKKW.js} | 2 +- ...xplanations_paradigms.md.BQbTsKKW.lean.js} | 2 +- ...explanations_peculiarities.md.D7wlShpB.js} | 2 +- ...nations_peculiarities.md.D7wlShpB.lean.js} | 2 +- ...explanations_winding_order.md.BzkvsLOj.js} | 2 +- ...nations_winding_order.md.BzkvsLOj.lean.js} | 2 +- previews/PR135/assets/fntoqls.y5I2w7nz.png | Bin 0 -> 63270 bytes previews/PR135/assets/fpctjru.CnVzN9w3.png | Bin 209977 -> 0 bytes ...ffhi.Dig-DWOQ.png => fsdxqux.Dig-DWOQ.png} | Bin ...uryx.CgiryX2p.png => ftxvlaw.CgiryX2p.png} | Bin ...jwqj.0OJvb21A.png => gobvpyq.0OJvb21A.png} | Bin previews/PR135/assets/goeuznk.8ErH1nVM.png | Bin 63008 -> 0 bytes previews/PR135/assets/hkyjgno.Cga6urUX.png | Bin 59648 -> 0 bytes ...pvpf.CLtpJ5Wb.png => hsawanf.CLtpJ5Wb.png} | Bin ...ztgb.Dz86q2IX.png => iijrfjx.Dz86q2IX.png} | Bin ...ex.md.y8l83Kxy.js => index.md.Dm7lK_c9.js} | 2 +- ...3Kxy.lean.js => index.md.Dm7lK_c9.lean.js} | 2 +- ...fhrN8RE.js => introduction.md.EstDN9hf.js} | 2 +- ...an.js => introduction.md.EstDN9hf.lean.js} | 2 +- ...fcxo.BD0hVfse.png => jphsfis.BD0hVfse.png} | Bin ...mqvz.CULn5saZ.png => kbchokg.CULn5saZ.png} | Bin ...ymdf.DwqDxlAG.png => kgneegt.DwqDxlAG.png} | Bin previews/PR135/assets/leqplng.DT95HOc4.png | Bin 0 -> 228635 bytes ...jhao.Bglvb-jp.png => limmhqq.Bglvb-jp.png} | Bin ...grqm.3sfpQl2i.png => ltowmlk.3sfpQl2i.png} | Bin ...jvuj.Dab1-ETk.png => mqcmtly.Dab1-ETk.png} | Bin ...qznt.DC3TvBOO.png => nlfztmc.DC3TvBOO.png} | Bin ...gynm.DHcwB147.png => nmofpgl.DHcwB147.png} | Bin ...cmhd._0R9BbFk.png => noqiyfz._0R9BbFk.png} | Bin previews/PR135/assets/nyoicmp.ClueNz2m.png | Bin 63644 -> 0 bytes ...crog.lu4jwpi-.png => ovfjlyd.lu4jwpi-.png} | Bin previews/PR135/assets/oylwyba.CuwrHkOd.png | Bin 0 -> 59413 bytes ...bkgt.DaovVbE6.png => piejhcv.DaovVbE6.png} | Bin ...ledz.-VpeHhXX.png => prhmudq.-VpeHhXX.png} | Bin ...nnad.CZy9YIUA.png => prtwaxi.CZy9YIUA.png} | Bin ...xllp.DiwGEg2f.png => pthvojo.DiwGEg2f.png} | Bin ...crtt.Cb0_DiYE.png => pzrdbdt.Cb0_DiYE.png} | Bin previews/PR135/assets/qfveqll.DPlfA76p.png | Bin 0 -> 63261 bytes ...wrae.DeeQUply.png => rezvvce.DeeQUply.png} | Bin ...Y.js => source_GeometryOps.md.BnVY2YxC.js} | 10 ++- ...=> source_GeometryOps.md.BnVY2YxC.lean.js} | 2 +- ...s => source_methods_angles.md.BGpTF9uY.js} | 6 +- ...source_methods_angles.md.BGpTF9uY.lean.js} | 2 +- ....js => source_methods_area.md.CXVG-VeW.js} | 6 +- ...> source_methods_area.md.CXVG-VeW.lean.js} | 2 +- ...source_methods_barycentric.md.DiCxsA-F.js} | 2 +- ...e_methods_barycentric.md.DiCxsA-F.lean.js} | 2 +- ...s => source_methods_buffer.md.CxkGeu_t.js} | 2 +- ...source_methods_buffer.md.CxkGeu_t.lean.js} | 2 +- ...=> source_methods_centroid.md.CICsk7_Q.js} | 6 +- ...ource_methods_centroid.md.CICsk7_Q.lean.js | 1 + ...ource_methods_centroid.md.D456D2F_.lean.js | 1 - ...lipping_clipping_processor.md.5X_cs7CX.js} | 16 ++-- ...ng_clipping_processor.md.5X_cs7CX.lean.js} | 2 +- ..._methods_clipping_coverage.md.8uUWzwQ-.js} | 4 +- ...ods_clipping_coverage.md.8uUWzwQ-.lean.js} | 2 +- ...ource_methods_clipping_cut.md.DC5HX6wc.js} | 4 +- ..._methods_clipping_cut.md.DC5HX6wc.lean.js} | 2 +- ...ethods_clipping_difference.md.BlomfT6l.js} | 8 +- ...s_clipping_difference.md.BlomfT6l.lean.js} | 2 +- ...hods_clipping_intersection.md.fOblypzx.js} | 16 ++-- ...clipping_intersection.md.fOblypzx.lean.js} | 2 +- ...ethods_clipping_predicates.md.DUY6Mg1n.js} | 2 +- ...s_clipping_predicates.md.DUY6Mg1n.lean.js} | 2 +- ...rce_methods_clipping_union.md.BUlTcf5A.js} | 8 +- ...ethods_clipping_union.md.BUlTcf5A.lean.js} | 2 +- .../source_methods_convex_hull.md.C926w3uT.js | 57 ++++++++++++ ...ce_methods_convex_hull.md.C926w3uT.lean.js | 1 + ...=> source_methods_distance.md.BNGMDaam.js} | 2 +- ...urce_methods_distance.md.BNGMDaam.lean.js} | 2 +- ...s => source_methods_equals.md.CInRsM-y.js} | 12 +-- ...source_methods_equals.md.CInRsM-y.lean.js} | 2 +- ...ds_geom_relations_contains.md.CT7VUSG_.js} | 2 +- ...om_relations_contains.md.CT7VUSG_.lean.js} | 2 +- ...s_geom_relations_coveredby.md.t8U8nVnZ.js} | 6 +- ...m_relations_coveredby.md.t8U8nVnZ.lean.js} | 2 +- ...hods_geom_relations_covers.md.DG_3zZRD.js} | 2 +- ...geom_relations_covers.md.DG_3zZRD.lean.js} | 2 +- ...ods_geom_relations_crosses.md.5YXBFQwW.js} | 2 +- ...eom_relations_crosses.md.5YXBFQwW.lean.js} | 2 +- ...ds_geom_relations_disjoint.md.Cp4OC057.js} | 4 +- ...om_relations_disjoint.md.Cp4OC057.lean.js} | 2 +- ...tions_geom_geom_processors.md.B09zbe43.js} | 20 ++--- ..._geom_geom_processors.md.B09zbe43.lean.js} | 2 +- ..._geom_relations_intersects.md.DH-bN_kE.js} | 2 +- ..._relations_intersects.md.DH-bN_kE.lean.js} | 2 +- ...ds_geom_relations_overlaps.md.DaCX808s.js} | 8 +- ...om_relations_overlaps.md.DaCX808s.lean.js} | 2 +- ...ods_geom_relations_touches.md.z4ceia7e.js} | 16 ++-- ...eom_relations_touches.md.z4ceia7e.lean.js} | 2 +- ...hods_geom_relations_within.md.DNx_0bB6.js} | 6 +- ...geom_relations_within.md.DNx_0bB6.lean.js} | 2 +- ...source_methods_orientation.md.C6hml0DY.js} | 2 +- ...e_methods_orientation.md.C6hml0DY.lean.js} | 2 +- ... source_methods_polygonize.md.BjnTo1d_.js} | 6 +- ...ce_methods_polygonize.md.BjnTo1d_.lean.js} | 2 +- ...source_not_implemented_yet.md.DttPeX-2.js} | 2 +- ...e_not_implemented_yet.md.DttPeX-2.lean.js} | 2 +- ...cN.js => source_primitives.md.4UCUXvfy.js} | 22 ++--- ... => source_primitives.md.4UCUXvfy.lean.js} | 2 +- ...ons_correction_closed_ring.md.CohSwGqX.js} | 2 +- ...orrection_closed_ring.md.CohSwGqX.lean.js} | 2 +- ...ection_geometry_correction.md.gAjUHu5U.js} | 4 +- ...n_geometry_correction.md.gAjUHu5U.lean.js} | 2 +- ...tion_intersecting_polygons.md.Dp-0YCkQ.js} | 3 +- ...intersecting_polygons.md.Dp-0YCkQ.lean.js} | 2 +- ...rce_transformations_extent.md.aqCZuaCr.js} | 2 +- ...ransformations_extent.md.aqCZuaCr.lean.js} | 2 +- ...ource_transformations_flip.md.D247Ejcp.js} | 2 +- ..._transformations_flip.md.D247Ejcp.lean.js} | 2 +- ...e_transformations_reproject.md.oTc7A1Wp.js | 1 - ...e_transformations_reproject.md.plsPtFYv.js | 1 + ...sformations_reproject.md.plsPtFYv.lean.js} | 2 +- ...transformations_segmentize.md.DnUWdzb5.js} | 2 +- ...formations_segmentize.md.DnUWdzb5.lean.js} | 2 +- ...ansformations_simplify.md.Bc-qtAXt.lean.js | 1 - ...e_transformations_simplify.md.k2EFW9YY.js} | 19 ++-- ...ansformations_simplify.md.k2EFW9YY.lean.js | 1 + ..._transformations_transform.md.Bz0uRhiV.js} | 4 +- ...sformations_transform.md.Bz0uRhiV.lean.js} | 2 +- ...rce_transformations_tuples.md.BlsK6oDR.js} | 2 +- ...ransformations_tuples.md.BlsK6oDR.lean.js} | 2 +- ...YfpLUKR.js => source_types.md.D4PahPU_.js} | 2 +- ...an.js => source_types.md.D4PahPU_.lean.js} | 2 +- ...PaVoqLr.js => source_utils.md.CZ0t5hCA.js} | 2 +- ...an.js => source_utils.md.CZ0t5hCA.lean.js} | 2 +- ...{style.DLw2TsOP.css => style.D6YisBrO.css} | 2 +- ...utorials_creating_geometry.md.CQNXRFYE.js} | 6 +- ...ials_creating_geometry.md.CQNXRFYE.lean.js | 1 + ...ials_creating_geometry.md.D-ZnfJ-b.lean.js | 1 - .../tutorials_geodesic_paths.md.B5A7YX9J.js | 11 +++ ...torials_geodesic_paths.md.B5A7YX9J.lean.js | 1 + ...=> tutorials_spatial_joins.md.BU34-gKB.js} | 2 +- ...torials_spatial_joins.md.BU34-gKB.lean.js} | 2 +- previews/PR135/assets/tzjojwg.DvOK4aMR.png | Bin 0 -> 79050 bytes ...jmam.DuBHk1fh.png => ugotupt.DuBHk1fh.png} | Bin previews/PR135/assets/uywhdfm.CbsJ8bL8.png | Bin 78984 -> 0 bytes previews/PR135/assets/weygerj.mCtKcWOr.png | Bin 0 -> 83901 bytes previews/PR135/assets/wkykfav.OhZZIiD6.png | Bin 232894 -> 0 bytes ...aytr.B9NpLJr_.png => xheurnn.B9NpLJr_.png} | Bin previews/PR135/assets/xqlfxjv.AayN5YeI.png | Bin 0 -> 63300 bytes ...mngr.B94PsR1K.png => yygelii.B94PsR1K.png} | Bin ...bfnb.3UVIT8DR.png => zghchbn.3UVIT8DR.png} | Bin ...surm.Cx40vhB3.png => ztkdutf.Cx40vhB3.png} | Bin previews/PR135/call_notes.html | 16 ++-- .../experiments/accurate_accumulators.html | 16 ++-- previews/PR135/experiments/predicates.html | 18 ++-- previews/PR135/explanations/crs.html | 16 ++-- previews/PR135/explanations/paradigms.html | 16 ++-- .../PR135/explanations/peculiarities.html | 16 ++-- .../PR135/explanations/winding_order.html | 16 ++-- previews/PR135/hashmap.json | 2 +- previews/PR135/index.html | 16 ++-- previews/PR135/introduction.html | 16 ++-- previews/PR135/source/GeometryOps.html | 24 +++--- previews/PR135/source/methods/angles.html | 22 ++--- previews/PR135/source/methods/area.html | 22 ++--- .../PR135/source/methods/barycentric.html | 18 ++-- previews/PR135/source/methods/buffer.html | 16 ++-- previews/PR135/source/methods/centroid.html | 20 ++--- .../methods/clipping/clipping_processor.html | 30 +++---- .../source/methods/clipping/coverage.html | 18 ++-- .../PR135/source/methods/clipping/cut.html | 20 ++--- .../source/methods/clipping/difference.html | 22 ++--- .../source/methods/clipping/intersection.html | 30 +++---- .../source/methods/clipping/predicates.html | 16 ++-- .../PR135/source/methods/clipping/union.html | 24 +++--- .../PR135/source/methods/convex_hull.html | 81 ++++++++++++++++++ previews/PR135/source/methods/distance.html | 22 ++--- previews/PR135/source/methods/equals.html | 24 +++--- .../methods/geom_relations/contains.html | 18 ++-- .../methods/geom_relations/coveredby.html | 22 ++--- .../source/methods/geom_relations/covers.html | 18 ++-- .../methods/geom_relations/crosses.html | 16 ++-- .../methods/geom_relations/disjoint.html | 20 ++--- .../geom_relations/geom_geom_processors.html | 34 ++++---- .../methods/geom_relations/intersects.html | 18 ++-- .../methods/geom_relations/overlaps.html | 22 ++--- .../methods/geom_relations/touches.html | 32 +++---- .../source/methods/geom_relations/within.html | 20 ++--- .../PR135/source/methods/orientation.html | 16 ++-- previews/PR135/source/methods/polygonize.html | 20 ++--- .../PR135/source/not_implemented_yet.html | 16 ++-- previews/PR135/source/primitives.html | 36 ++++---- .../correction/closed_ring.html | 16 ++-- .../correction/geometry_correction.html | 18 ++-- .../correction/intersecting_polygons.html | 17 ++-- .../PR135/source/transformations/extent.html | 16 ++-- .../PR135/source/transformations/flip.html | 16 ++-- .../source/transformations/reproject.html | 22 ++--- .../source/transformations/segmentize.html | 20 ++--- .../source/transformations/simplify.html | 41 ++++----- .../source/transformations/transform.html | 18 ++-- .../PR135/source/transformations/tuples.html | 16 ++-- previews/PR135/source/types.html | 16 ++-- previews/PR135/source/utils.html | 16 ++-- .../PR135/tutorials/creating_geometry.html | 40 ++++----- previews/PR135/tutorials/geodesic_paths.html | 35 ++++++++ previews/PR135/tutorials/spatial_joins.html | 22 ++--- 226 files changed, 1008 insertions(+), 818 deletions(-) rename previews/PR135/assets/{uugjisc.BOOG5oTW.png => afsyzdr.BOOG5oTW.png} (100%) rename previews/PR135/assets/{rlpsaah.C3SxJ3x-.png => aithltv.C3SxJ3x-.png} (100%) rename previews/PR135/assets/{api.md.D8UtvlcW.js => api.md.BkdCNSpp.js} (84%) rename previews/PR135/assets/{api.md.D8UtvlcW.lean.js => api.md.BkdCNSpp.lean.js} (91%) rename previews/PR135/assets/{app.BPnMWvu-.js => app.okziLJoA.js} (90%) rename previews/PR135/assets/{zbzherl.BEFUMtlf.png => bhjiovt.BEFUMtlf.png} (100%) create mode 100644 previews/PR135/assets/briiybs.Cy4gx45x.png rename previews/PR135/assets/{call_notes.md.DwdSQiwl.js => call_notes.md.CzI2sRnh.js} (96%) rename previews/PR135/assets/{call_notes.md.DwdSQiwl.lean.js => call_notes.md.CzI2sRnh.lean.js} (67%) create mode 100644 previews/PR135/assets/cezjmfi.BcI7dJNv.png delete mode 100644 previews/PR135/assets/chunks/@localSearchIndexroot.BBdiXmf3.js create mode 100644 previews/PR135/assets/chunks/@localSearchIndexroot.DOIebHWk.js delete mode 100644 previews/PR135/assets/chunks/VPLocalSearchBox.CqCoAOXo.js create mode 100644 previews/PR135/assets/chunks/VPLocalSearchBox.DLn4sKrv.js create mode 100644 previews/PR135/assets/chunks/framework.CONf0Rze.js delete mode 100644 previews/PR135/assets/chunks/framework.k41oUgTf.js rename previews/PR135/assets/chunks/{theme.BCxq1kHm.js => theme.D6VlRy8Q.js} (76%) rename previews/PR135/assets/{xgnjvje.CG4dr3Lx.png => ejkzyqr.CG4dr3Lx.png} (100%) create mode 100644 previews/PR135/assets/erkqkyr.Danh069g.png rename previews/PR135/assets/{experiments_accurate_accumulators.md.OMJKLp4S.js => experiments_accurate_accumulators.md.BEvtokUD.js} (98%) rename previews/PR135/assets/{experiments_accurate_accumulators.md.OMJKLp4S.lean.js => experiments_accurate_accumulators.md.BEvtokUD.lean.js} (73%) rename previews/PR135/assets/{experiments_predicates.md.DZFjCVCq.js => experiments_predicates.md.Cb_olK_t.js} (99%) rename previews/PR135/assets/{experiments_predicates.md.DZFjCVCq.lean.js => experiments_predicates.md.Cb_olK_t.lean.js} (61%) rename previews/PR135/assets/{explanations_crs.md.D0_U8pH0.js => explanations_crs.md.BcB0kXKu.js} (83%) rename previews/PR135/assets/{explanations_crs.md.D0_U8pH0.lean.js => explanations_crs.md.BcB0kXKu.lean.js} (83%) rename previews/PR135/assets/{explanations_paradigms.md.Dg8b3Bxh.js => explanations_paradigms.md.BQbTsKKW.js} (97%) rename previews/PR135/assets/{explanations_paradigms.md.Dg8b3Bxh.lean.js => explanations_paradigms.md.BQbTsKKW.lean.js} (70%) rename previews/PR135/assets/{explanations_peculiarities.md.CdVD731s.js => explanations_peculiarities.md.D7wlShpB.js} (96%) rename previews/PR135/assets/{explanations_peculiarities.md.CdVD731s.lean.js => explanations_peculiarities.md.D7wlShpB.lean.js} (71%) rename previews/PR135/assets/{explanations_winding_order.md.P7cnQ8tJ.js => explanations_winding_order.md.BzkvsLOj.js} (84%) rename previews/PR135/assets/{explanations_winding_order.md.P7cnQ8tJ.lean.js => explanations_winding_order.md.BzkvsLOj.lean.js} (84%) create mode 100644 previews/PR135/assets/fntoqls.y5I2w7nz.png delete mode 100644 previews/PR135/assets/fpctjru.CnVzN9w3.png rename previews/PR135/assets/{ouhffhi.Dig-DWOQ.png => fsdxqux.Dig-DWOQ.png} (100%) rename previews/PR135/assets/{dtturyx.CgiryX2p.png => ftxvlaw.CgiryX2p.png} (100%) rename previews/PR135/assets/{wvwjwqj.0OJvb21A.png => gobvpyq.0OJvb21A.png} (100%) delete mode 100644 previews/PR135/assets/goeuznk.8ErH1nVM.png delete mode 100644 previews/PR135/assets/hkyjgno.Cga6urUX.png rename previews/PR135/assets/{gwypvpf.CLtpJ5Wb.png => hsawanf.CLtpJ5Wb.png} (100%) rename previews/PR135/assets/{tkuztgb.Dz86q2IX.png => iijrfjx.Dz86q2IX.png} (100%) rename previews/PR135/assets/{index.md.y8l83Kxy.js => index.md.Dm7lK_c9.js} (96%) rename previews/PR135/assets/{index.md.y8l83Kxy.lean.js => index.md.Dm7lK_c9.lean.js} (92%) rename previews/PR135/assets/{introduction.md.ofhrN8RE.js => introduction.md.EstDN9hf.js} (95%) rename previews/PR135/assets/{introduction.md.ofhrN8RE.lean.js => introduction.md.EstDN9hf.lean.js} (68%) rename previews/PR135/assets/{lxyfcxo.BD0hVfse.png => jphsfis.BD0hVfse.png} (100%) rename previews/PR135/assets/{batmqvz.CULn5saZ.png => kbchokg.CULn5saZ.png} (100%) rename previews/PR135/assets/{xpzymdf.DwqDxlAG.png => kgneegt.DwqDxlAG.png} (100%) create mode 100644 previews/PR135/assets/leqplng.DT95HOc4.png rename previews/PR135/assets/{rsijhao.Bglvb-jp.png => limmhqq.Bglvb-jp.png} (100%) rename previews/PR135/assets/{kbdgrqm.3sfpQl2i.png => ltowmlk.3sfpQl2i.png} (100%) rename previews/PR135/assets/{yrwjvuj.Dab1-ETk.png => mqcmtly.Dab1-ETk.png} (100%) rename previews/PR135/assets/{awrqznt.DC3TvBOO.png => nlfztmc.DC3TvBOO.png} (100%) rename previews/PR135/assets/{zmwgynm.DHcwB147.png => nmofpgl.DHcwB147.png} (100%) rename previews/PR135/assets/{oxrcmhd._0R9BbFk.png => noqiyfz._0R9BbFk.png} (100%) delete mode 100644 previews/PR135/assets/nyoicmp.ClueNz2m.png rename previews/PR135/assets/{nfdcrog.lu4jwpi-.png => ovfjlyd.lu4jwpi-.png} (100%) create mode 100644 previews/PR135/assets/oylwyba.CuwrHkOd.png rename previews/PR135/assets/{ickbkgt.DaovVbE6.png => piejhcv.DaovVbE6.png} (100%) rename previews/PR135/assets/{mubledz.-VpeHhXX.png => prhmudq.-VpeHhXX.png} (100%) rename previews/PR135/assets/{uwqnnad.CZy9YIUA.png => prtwaxi.CZy9YIUA.png} (100%) rename previews/PR135/assets/{psixllp.DiwGEg2f.png => pthvojo.DiwGEg2f.png} (100%) rename previews/PR135/assets/{atqcrtt.Cb0_DiYE.png => pzrdbdt.Cb0_DiYE.png} (100%) create mode 100644 previews/PR135/assets/qfveqll.DPlfA76p.png rename previews/PR135/assets/{gxjwrae.DeeQUply.png => rezvvce.DeeQUply.png} (100%) rename previews/PR135/assets/{source_GeometryOps.md.BxznbMxY.js => source_GeometryOps.md.BnVY2YxC.js} (95%) rename previews/PR135/assets/{source_GeometryOps.md.BxznbMxY.lean.js => source_GeometryOps.md.BnVY2YxC.lean.js} (70%) rename previews/PR135/assets/{source_methods_angles.md.D0iJTZWo.js => source_methods_angles.md.BGpTF9uY.js} (99%) rename previews/PR135/assets/{source_methods_angles.md.D0iJTZWo.lean.js => source_methods_angles.md.BGpTF9uY.lean.js} (74%) rename previews/PR135/assets/{source_methods_area.md.7qdFk2Vq.js => source_methods_area.md.CXVG-VeW.js} (92%) rename previews/PR135/assets/{source_methods_area.md.7qdFk2Vq.lean.js => source_methods_area.md.CXVG-VeW.lean.js} (65%) rename previews/PR135/assets/{source_methods_barycentric.md.DUTwwa2T.js => source_methods_barycentric.md.DiCxsA-F.js} (99%) rename previews/PR135/assets/{source_methods_barycentric.md.DUTwwa2T.lean.js => source_methods_barycentric.md.DiCxsA-F.lean.js} (98%) rename previews/PR135/assets/{source_methods_buffer.md.CTloyyO4.js => source_methods_buffer.md.CxkGeu_t.js} (98%) rename previews/PR135/assets/{source_methods_buffer.md.CTloyyO4.lean.js => source_methods_buffer.md.CxkGeu_t.lean.js} (70%) rename previews/PR135/assets/{source_methods_centroid.md.D456D2F_.js => source_methods_centroid.md.CICsk7_Q.js} (99%) create mode 100644 previews/PR135/assets/source_methods_centroid.md.CICsk7_Q.lean.js delete mode 100644 previews/PR135/assets/source_methods_centroid.md.D456D2F_.lean.js rename previews/PR135/assets/{source_methods_clipping_clipping_processor.md.DWDSGXct.js => source_methods_clipping_clipping_processor.md.5X_cs7CX.js} (96%) rename previews/PR135/assets/{source_methods_clipping_clipping_processor.md.DWDSGXct.lean.js => source_methods_clipping_clipping_processor.md.5X_cs7CX.lean.js} (75%) rename previews/PR135/assets/{source_methods_clipping_coverage.md.B5mnmfCT.js => source_methods_clipping_coverage.md.8uUWzwQ-.js} (99%) rename previews/PR135/assets/{source_methods_clipping_coverage.md.B5mnmfCT.lean.js => source_methods_clipping_coverage.md.8uUWzwQ-.lean.js} (50%) rename previews/PR135/assets/{source_methods_clipping_cut.md.DyYI9STF.js => source_methods_clipping_cut.md.DC5HX6wc.js} (99%) rename previews/PR135/assets/{source_methods_clipping_cut.md.DyYI9STF.lean.js => source_methods_clipping_cut.md.DC5HX6wc.lean.js} (75%) rename previews/PR135/assets/{source_methods_clipping_difference.md.CmRUkDo6.js => source_methods_clipping_difference.md.BlomfT6l.js} (98%) rename previews/PR135/assets/{source_methods_clipping_difference.md.CmRUkDo6.lean.js => source_methods_clipping_difference.md.BlomfT6l.lean.js} (73%) rename previews/PR135/assets/{source_methods_clipping_intersection.md.CVEaF8-J.js => source_methods_clipping_intersection.md.fOblypzx.js} (99%) rename previews/PR135/assets/{source_methods_clipping_intersection.md.CVEaF8-J.lean.js => source_methods_clipping_intersection.md.fOblypzx.lean.js} (73%) rename previews/PR135/assets/{source_methods_clipping_predicates.md.DvipA0zH.js => source_methods_clipping_predicates.md.DUY6Mg1n.js} (99%) rename previews/PR135/assets/{source_methods_clipping_predicates.md.DvipA0zH.lean.js => source_methods_clipping_predicates.md.DUY6Mg1n.lean.js} (75%) rename previews/PR135/assets/{source_methods_clipping_union.md.DCiyvI5u.js => source_methods_clipping_union.md.BUlTcf5A.js} (98%) rename previews/PR135/assets/{source_methods_clipping_union.md.DCiyvI5u.lean.js => source_methods_clipping_union.md.BUlTcf5A.lean.js} (72%) create mode 100644 previews/PR135/assets/source_methods_convex_hull.md.C926w3uT.js create mode 100644 previews/PR135/assets/source_methods_convex_hull.md.C926w3uT.lean.js rename previews/PR135/assets/{source_methods_distance.md.CGbMIn6Z.js => source_methods_distance.md.BNGMDaam.js} (99%) rename previews/PR135/assets/{source_methods_distance.md.CGbMIn6Z.lean.js => source_methods_distance.md.BNGMDaam.lean.js} (67%) rename previews/PR135/assets/{source_methods_equals.md.cKbLrMmC.js => source_methods_equals.md.CInRsM-y.js} (98%) rename previews/PR135/assets/{source_methods_equals.md.cKbLrMmC.lean.js => source_methods_equals.md.CInRsM-y.lean.js} (51%) rename previews/PR135/assets/{source_methods_geom_relations_contains.md.DzU4Cn9q.js => source_methods_geom_relations_contains.md.CT7VUSG_.js} (92%) rename previews/PR135/assets/{source_methods_geom_relations_contains.md.DzU4Cn9q.lean.js => source_methods_geom_relations_contains.md.CT7VUSG_.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_coveredby.md.BAWIQHTY.js => source_methods_geom_relations_coveredby.md.t8U8nVnZ.js} (99%) rename previews/PR135/assets/{source_methods_geom_relations_coveredby.md.BAWIQHTY.lean.js => source_methods_geom_relations_coveredby.md.t8U8nVnZ.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_covers.md.BWa6PpTv.js => source_methods_geom_relations_covers.md.DG_3zZRD.js} (90%) rename previews/PR135/assets/{source_methods_geom_relations_covers.md.BWa6PpTv.lean.js => source_methods_geom_relations_covers.md.DG_3zZRD.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_crosses.md.CrWCei4a.js => source_methods_geom_relations_crosses.md.5YXBFQwW.js} (99%) rename previews/PR135/assets/{source_methods_geom_relations_crosses.md.CrWCei4a.lean.js => source_methods_geom_relations_crosses.md.5YXBFQwW.lean.js} (73%) rename previews/PR135/assets/{source_methods_geom_relations_disjoint.md.CH3IJNyL.js => source_methods_geom_relations_disjoint.md.Cp4OC057.js} (99%) rename previews/PR135/assets/{source_methods_geom_relations_disjoint.md.CH3IJNyL.lean.js => source_methods_geom_relations_disjoint.md.Cp4OC057.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_geom_geom_processors.md.DeClVOfg.js => source_methods_geom_relations_geom_geom_processors.md.B09zbe43.js} (97%) rename previews/PR135/assets/{source_methods_geom_relations_geom_geom_processors.md.DeClVOfg.lean.js => source_methods_geom_relations_geom_geom_processors.md.B09zbe43.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_intersects.md.C0hjmSuR.js => source_methods_geom_relations_intersects.md.DH-bN_kE.js} (98%) rename previews/PR135/assets/{source_methods_geom_relations_intersects.md.C0hjmSuR.lean.js => source_methods_geom_relations_intersects.md.DH-bN_kE.lean.js} (77%) rename previews/PR135/assets/{source_methods_geom_relations_overlaps.md.BK3Hcl18.js => source_methods_geom_relations_overlaps.md.DaCX808s.js} (96%) rename previews/PR135/assets/{source_methods_geom_relations_overlaps.md.BK3Hcl18.lean.js => source_methods_geom_relations_overlaps.md.DaCX808s.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_touches.md.oH9OwOqC.js => source_methods_geom_relations_touches.md.z4ceia7e.js} (97%) rename previews/PR135/assets/{source_methods_geom_relations_touches.md.oH9OwOqC.lean.js => source_methods_geom_relations_touches.md.z4ceia7e.lean.js} (76%) rename previews/PR135/assets/{source_methods_geom_relations_within.md.yOtMwkyH.js => source_methods_geom_relations_within.md.DNx_0bB6.js} (96%) rename previews/PR135/assets/{source_methods_geom_relations_within.md.yOtMwkyH.lean.js => source_methods_geom_relations_within.md.DNx_0bB6.lean.js} (52%) rename previews/PR135/assets/{source_methods_orientation.md.CxJbsDsq.js => source_methods_orientation.md.C6hml0DY.js} (99%) rename previews/PR135/assets/{source_methods_orientation.md.CxJbsDsq.lean.js => source_methods_orientation.md.C6hml0DY.lean.js} (71%) rename previews/PR135/assets/{source_methods_polygonize.md.Bf-4bMgE.js => source_methods_polygonize.md.BjnTo1d_.js} (99%) rename previews/PR135/assets/{source_methods_polygonize.md.Bf-4bMgE.lean.js => source_methods_polygonize.md.BjnTo1d_.lean.js} (72%) rename previews/PR135/assets/{source_not_implemented_yet.md.9VgY15CW.js => source_not_implemented_yet.md.DttPeX-2.js} (94%) rename previews/PR135/assets/{source_not_implemented_yet.md.9VgY15CW.lean.js => source_not_implemented_yet.md.DttPeX-2.lean.js} (71%) rename previews/PR135/assets/{source_primitives.md.B8mDJecN.js => source_primitives.md.4UCUXvfy.js} (97%) rename previews/PR135/assets/{source_primitives.md.B8mDJecN.lean.js => source_primitives.md.4UCUXvfy.lean.js} (70%) rename previews/PR135/assets/{source_transformations_correction_closed_ring.md.D6ZEKMv-.js => source_transformations_correction_closed_ring.md.CohSwGqX.js} (99%) rename previews/PR135/assets/{source_transformations_correction_closed_ring.md.D6ZEKMv-.lean.js => source_transformations_correction_closed_ring.md.CohSwGqX.lean.js} (97%) rename previews/PR135/assets/{source_transformations_correction_geometry_correction.md.BEDLeelw.js => source_transformations_correction_geometry_correction.md.gAjUHu5U.js} (82%) rename previews/PR135/assets/{source_transformations_correction_geometry_correction.md.BEDLeelw.lean.js => source_transformations_correction_geometry_correction.md.gAjUHu5U.lean.js} (76%) rename previews/PR135/assets/{source_transformations_correction_intersecting_polygons.md.Df5YX__2.js => source_transformations_correction_intersecting_polygons.md.Dp-0YCkQ.js} (95%) rename previews/PR135/assets/{source_transformations_correction_intersecting_polygons.md.Df5YX__2.lean.js => source_transformations_correction_intersecting_polygons.md.Dp-0YCkQ.lean.js} (76%) rename previews/PR135/assets/{source_transformations_extent.md.Dg5_Nny1.js => source_transformations_extent.md.aqCZuaCr.js} (95%) rename previews/PR135/assets/{source_transformations_extent.md.Dg5_Nny1.lean.js => source_transformations_extent.md.aqCZuaCr.lean.js} (72%) rename previews/PR135/assets/{source_transformations_flip.md.B6-KSgw2.js => source_transformations_flip.md.D247Ejcp.js} (97%) rename previews/PR135/assets/{source_transformations_flip.md.B6-KSgw2.lean.js => source_transformations_flip.md.D247Ejcp.lean.js} (72%) delete mode 100644 previews/PR135/assets/source_transformations_reproject.md.oTc7A1Wp.js create mode 100644 previews/PR135/assets/source_transformations_reproject.md.plsPtFYv.js rename previews/PR135/assets/{source_transformations_reproject.md.oTc7A1Wp.lean.js => source_transformations_reproject.md.plsPtFYv.lean.js} (73%) rename previews/PR135/assets/{source_transformations_segmentize.md.2rQJGEWB.js => source_transformations_segmentize.md.DnUWdzb5.js} (99%) rename previews/PR135/assets/{source_transformations_segmentize.md.2rQJGEWB.lean.js => source_transformations_segmentize.md.DnUWdzb5.lean.js} (57%) delete mode 100644 previews/PR135/assets/source_transformations_simplify.md.Bc-qtAXt.lean.js rename previews/PR135/assets/{source_transformations_simplify.md.Bc-qtAXt.js => source_transformations_simplify.md.k2EFW9YY.js} (98%) create mode 100644 previews/PR135/assets/source_transformations_simplify.md.k2EFW9YY.lean.js rename previews/PR135/assets/{source_transformations_transform.md.iKlEQxrg.js => source_transformations_transform.md.Bz0uRhiV.js} (98%) rename previews/PR135/assets/{source_transformations_transform.md.iKlEQxrg.lean.js => source_transformations_transform.md.Bz0uRhiV.lean.js} (73%) rename previews/PR135/assets/{source_transformations_tuples.md.DP26qgdc.js => source_transformations_tuples.md.BlsK6oDR.js} (96%) rename previews/PR135/assets/{source_transformations_tuples.md.DP26qgdc.lean.js => source_transformations_tuples.md.BlsK6oDR.lean.js} (72%) rename previews/PR135/assets/{source_types.md.BYfpLUKR.js => source_types.md.D4PahPU_.js} (99%) rename previews/PR135/assets/{source_types.md.BYfpLUKR.lean.js => source_types.md.D4PahPU_.lean.js} (68%) rename previews/PR135/assets/{source_utils.md.CPaVoqLr.js => source_utils.md.CZ0t5hCA.js} (99%) rename previews/PR135/assets/{source_utils.md.CPaVoqLr.lean.js => source_utils.md.CZ0t5hCA.lean.js} (69%) rename previews/PR135/assets/{style.DLw2TsOP.css => style.D6YisBrO.css} (99%) rename previews/PR135/assets/{tutorials_creating_geometry.md.D-ZnfJ-b.js => tutorials_creating_geometry.md.CQNXRFYE.js} (97%) create mode 100644 previews/PR135/assets/tutorials_creating_geometry.md.CQNXRFYE.lean.js delete mode 100644 previews/PR135/assets/tutorials_creating_geometry.md.D-ZnfJ-b.lean.js create mode 100644 previews/PR135/assets/tutorials_geodesic_paths.md.B5A7YX9J.js create mode 100644 previews/PR135/assets/tutorials_geodesic_paths.md.B5A7YX9J.lean.js rename previews/PR135/assets/{tutorials_spatial_joins.md.C715FNUG.js => tutorials_spatial_joins.md.BU34-gKB.js} (99%) rename previews/PR135/assets/{tutorials_spatial_joins.md.C715FNUG.lean.js => tutorials_spatial_joins.md.BU34-gKB.lean.js} (89%) create mode 100644 previews/PR135/assets/tzjojwg.DvOK4aMR.png rename previews/PR135/assets/{nnfjmam.DuBHk1fh.png => ugotupt.DuBHk1fh.png} (100%) delete mode 100644 previews/PR135/assets/uywhdfm.CbsJ8bL8.png create mode 100644 previews/PR135/assets/weygerj.mCtKcWOr.png delete mode 100644 previews/PR135/assets/wkykfav.OhZZIiD6.png rename previews/PR135/assets/{zxxaytr.B9NpLJr_.png => xheurnn.B9NpLJr_.png} (100%) create mode 100644 previews/PR135/assets/xqlfxjv.AayN5YeI.png rename previews/PR135/assets/{tmmmngr.B94PsR1K.png => yygelii.B94PsR1K.png} (100%) rename previews/PR135/assets/{ukybfnb.3UVIT8DR.png => zghchbn.3UVIT8DR.png} (100%) rename previews/PR135/assets/{khdsurm.Cx40vhB3.png => ztkdutf.Cx40vhB3.png} (100%) create mode 100644 previews/PR135/source/methods/convex_hull.html create mode 100644 previews/PR135/tutorials/geodesic_paths.html diff --git a/previews/PR135/404.html b/previews/PR135/404.html index 798e3189e..1e7f79a52 100644 --- a/previews/PR135/404.html +++ b/previews/PR135/404.html @@ -5,10 +5,10 @@ 404 | GeometryOps.jl - - + + - + @@ -16,7 +16,7 @@
- + \ No newline at end of file diff --git a/previews/PR135/api.html b/previews/PR135/api.html index a28a79c9a..7fb6d0aac 100644 --- a/previews/PR135/api.html +++ b/previews/PR135/api.html @@ -5,20 +5,20 @@ Full GeometryOps API documentation | GeometryOps.jl - - + + - + - - - + + + -
Skip to content

Full GeometryOps API documentation

Warning

This page is still very much WIP!

Documentation for GeometryOps's full API (only for reference!).

apply and associated functions

# GeometryOps.applyFunction.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
+    
Skip to content

Full GeometryOps API documentation

Warning

This page is still very much WIP!

Documentation for GeometryOps's full API (only for reference!).

apply and associated functions

# GeometryOps.applyFunction.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
 import GeometryOps as GO
 geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]),
                    GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])])
@@ -27,7 +27,7 @@
     (GI.y(p), GI.x(p))
 end

source


# GeometryOps.applyreduceFunction.
julia
applyreduce(f, op, target::Union{TraitTarget, GI.AbstractTrait}, obj; threaded)

Apply function f to all objects with the target trait, and reduce the result with an op like +.

The order and grouping of application of op is not guaranteed.

If threaded==true threads will be used over arrays and iterables, feature collections and nested geometries.

source


# GeometryOps.reprojectFunction.
julia
reproject(geometry; source_crs, target_crs, transform, always_xy, time)
 reproject(geometry, source_crs, target_crs; always_xy, time)
-reproject(geometry, transform; always_xy, time)

Reproject any GeoInterface.jl compatible geometry from source_crs to target_crs.

The returned object will be constructed from GeoInterface.WrapperGeometry geometries, wrapping views of a Vector{Proj.Point{D}}, where D is the dimension.

Tip

The Proj.jl package must be loaded for this method to work, since it is implemented in a package extension.

Arguments

  • geometry: Any GeoInterface.jl compatible geometries.

  • source_crs: the source coordinate referece system, as a GeoFormatTypes.jl object or a string.

  • target_crs: the target coordinate referece system, as a GeoFormatTypes.jl object or a string.

If these a passed as keywords, transform will take priority. Without it target_crs is always needed, and source_crs is needed if it is not retreivable from the geometry with GeoInterface.crs(geometry).

Keywords

  • always_xy: force x, y coordinate order, true by default. false will expect and return points in the crs coordinate order.

  • time: the time for the coordinates. Inf by default.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.transformFunction.
julia
transform(f, obj)

Apply a function f to all the points in obj.

Points will be passed to f as an SVector to allow using CoordinateTransformations.jl and Rotations.jl without hassle.

SVector is also a valid GeoInterface.jl point, so will work in all GeoInterface.jl methods.

Example

julia
julia> import GeoInterface as GI
+reproject(geometry, transform; always_xy, time)

Reproject any GeoInterface.jl compatible geometry from source_crs to target_crs.

The returned object will be constructed from GeoInterface.WrapperGeometry geometries, wrapping views of a Vector{Proj.Point{D}}, where D is the dimension.

Tip

The Proj.jl package must be loaded for this method to work, since it is implemented in a package extension.

Arguments

  • geometry: Any GeoInterface.jl compatible geometries.

  • source_crs: the source coordinate reference system, as a GeoFormatTypes.jl object or a string.

  • target_crs: the target coordinate reference system, as a GeoFormatTypes.jl object or a string.

If these a passed as keywords, transform will take priority. Without it target_crs is always needed, and source_crs is needed if it is not retrievable from the geometry with GeoInterface.crs(geometry).

Keywords

  • always_xy: force x, y coordinate order, true by default. false will expect and return points in the crs coordinate order.

  • time: the time for the coordinates. Inf by default.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.transformFunction.
julia
transform(f, obj)

Apply a function f to all the points in obj.

Points will be passed to f as an SVector to allow using CoordinateTransformations.jl and Rotations.jl without hassle.

SVector is also a valid GeoInterface.jl point, so will work in all GeoInterface.jl methods.

Example

julia
julia> import GeoInterface as GI
 
 julia> import GeometryOps as GO
 
@@ -40,7 +40,7 @@
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea
 rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo
 re.SVector{2, Float64}[[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA
-rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actuall multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
+rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actually multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
 
 julia> GO.transform(p -> one(RotMatrix{2}) * p, geom)
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.LinearR
@@ -89,7 +89,7 @@
 true

source

julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source

julia
overlaps(
     ::GI.MultiPointTrait, points1,
     ::GI.MultiPointTrait, points2,
-)::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source

julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are colinear but each have one endpoint outside of the other line, return true. Else false.

source

julia
overlaps(
+)::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source

julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are collinear but each have one endpoint outside of the other line, return true. Else false.

source

julia
overlaps(
     ::Union{GI.LineStringTrait, GI.LinearRing}, line1,
     ::Union{GI.LineStringTrait, GI.LinearRing}, line2,
 )::Bool

If the curves overlap, meaning that at least one edge of each curve overlaps, return true. Else false.

source

julia
overlaps(
@@ -104,7 +104,7 @@
 )::Bool

Return true if polygon overlaps with at least one of the polygons within the multipolygon. Else false.

source

julia
overlaps(
     ::GI.MultiPolygonTrait, polys1,
     ::GI.MultiPolygonTrait, polys2,
-)::Bool

Return true if at least one pair of polygons from multipolygons overlap. Else false.

source


# GeometryOps.touchesFunction.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometies interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+)::Bool

Return true if at least one pair of polygons from multipolygons overlap. Else false.

source


# GeometryOps.touchesFunction.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometry's interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 
 l1 = GI.Line([(0.0, 0.0), (1.0, 0.0)])
 l2 = GI.Line([(1.0, 1.0), (1.0, -1.0)])
@@ -127,13 +127,13 @@
 true

source

julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source

julia
equals(trait_a, geom_a, trait_b, geom_b)

Two geometries which are not of the same type cannot be equal so they always return false.

source

julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source

julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source

julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source

julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source

julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by defintion.

source

julia
equals(
+)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by definition.

source

julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::GI.LinearRingTrait, l2,
-)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
+)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
     ::GI.LinearRingTrait, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
+)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
     ::GI.LinearRingTrait, l1,
     ::GI.LinearRingTrait, l2,
 )::Bool

Two linear rings are equal if they share the same set of points going along the curve. Note that rings are closed by definition, so they can have, but don't need, a repeated last point to be equal.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source

julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.centroidFunction.
julia
centroid(geom, [T=Float64])::Tuple{T, T}

Returns the centroid of a given line segment, linear ring, polygon, or mutlipolygon.

source


# GeometryOps.distanceFunction.
julia
distance(point, geom, ::Type{T} = Float64)::T

Calculates the ditance from the geometry g1 to the point. The distance will always be positive or zero.

The method will differ based on the type of the geometry provided: - The distance from a point to a point is just the Euclidean distance between the points. - The distance from a point to a line is the minimum distance from the point to the closest point on the given line. - The distance from a point to a linestring is the minimum distance from the point to the closest segment of the linestring. - The distance from a point to a linear ring is the minimum distance from the point to the closest segment of the linear ring. - The distance from a point to a polygon is zero if the point is within the polygon and otherwise is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The distance from a point to a multigeometry or a geometry collection is the minimum distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_distanceFunction.
julia
signed_distance(point, geom, ::Type{T} = Float64)::T

Calculates the signed distance from the geometry geom to the given point. Points within geom have a negative signed distance, and points outside of geom have a positive signed distance. - The signed distance from a point to a point, line, linestring, or linear ring is equal to the distance between the two. - The signed distance from a point to a polygon is negative if the point is within the polygon and is positive otherwise. The value of the distance is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The signed distance from a point to a multigeometry or a geometry collection is the minimum signed distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.areaFunction.
julia
area(geom, [T = Float64])::T

Returns the area of a geometry or collection of geometries. This is computed slightly differently for different geometries:

- The area of a point/multipoint is always zero.
@@ -141,7 +141,7 @@
 - The area of a polygon is the absolute value of the signed area.
 - The area multi-polygon is the sum of the areas of all of the sub-polygons.
 - The area of a geometry collection, feature collection of array/iterable 
-    is the sum of the areas of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_areaFunction.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slighly differently for different geometries:

- The signed area of a point is always zero.
+    is the sum of the areas of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_areaFunction.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slightly differently for different geometries:

- The signed area of a point is always zero.
 - The signed area of a curve is always zero.
 - The signed area of a polygon is computed with the shoelace formula and is
 positive if the polygon coordinates wind clockwise and negative if
@@ -150,11 +150,11 @@
 meaning as each sub-polygon could have a different winding order.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.anglesFunction.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
 - The angles of a single line segment is an empty vector.
 - The angles of a linestring or linearring is a vector of angles formed by the curve.
-- The angles of a polygin is a vector of vectors of angles formed by each ring.
+- The angles of a polygon is a vector of vectors of angles formed by each ring.
 - The angles of a multi-geometry collection is a vector of the angles of each of the
-    sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.embed_extentFunction.
julia
embed_extent(obj)

Recursively wrap the object with a GeoInterface.jl geometry, calculating and adding an Extents.Extent to all objects.

This can improve performance when extents need to be checked multiple times, such when needing to check if many points are in geometries, and using their extents as a quick filter for obviously exterior points.

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

source


Barycentric coordinates

# GeometryOps.barycentric_coordinatesFunction.
julia
barycentric_coordinates(method = MeanValue(), polygon, point)

Returns the barycentric coordinates of point in polygon using the barycentric coordinate method method.

source


# GeometryOps.barycentric_coordinates!Function.
julia
barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, polygon, point)

Loads the barycentric coordinates of point in polygon into λs using the barycentric coordinate method method.

λs must be of the length of the polygon plus its holes.

Tip

Use this method to avoid excess allocations when you need to calculate barycentric coordinates for many points.

source


# GeometryOps.barycentric_interpolateFunction.
julia
barycentric_interpolate(method = MeanValue(), polygon, values::AbstractVector{V}, point)

Returns the interpolated value at point within polygon using the barycentric coordinate method method. values are the per-point values for the polygon which are to be interpolated.

Returns an object of type V.

Warning

Barycentric interpolation is currently defined only for 2-dimensional polygons. If you pass a 3-D polygon in, the Z coordinate will be used as per-vertex value to be interpolated (the M coordinate in GIS parlance).

source


Other methods

# GeometryOps.AbstractBarycentricCoordinateMethodType.
julia
abstract type AbstractBarycentricCoordinateMethod

Abstract supertype for barycentric coordinate methods. The subtypes may serve as dispatch types, or may cache some information about the target polygon.

API

The following methods must be implemented for all subtypes:

  • barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, point::Point{2, T2})

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, values::Vector{V}, point::Point{2, T2})::V

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, interiors::Vector{<: Vector{<: Point{2, T1}}} values::Vector{V}, point::Point{2, T2})::V

The rest of the methods will be implemented in terms of these, and have efficient dispatches for broadcasting.

source


# GeometryOps.ClosedRingType.
julia
ClosedRing() <: GeometryCorrection

This correction ensures that a polygon's exterior and interior rings are closed.

It can be called on any geometry correction as usual.

See also GeometryCorrection.

source


# GeometryOps.DiffIntersectingPolygonsType.
julia
DiffIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygons included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be made nonintersecting through the difference operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area. See also GeometryCorrection, UnionIntersectingPolygons.

source


# GeometryOps.DouglasPeuckerType.
julia
DouglasPeucker <: SimplifyAlg
+    sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.embed_extentFunction.
julia
embed_extent(obj)

Recursively wrap the object with a GeoInterface.jl geometry, calculating and adding an Extents.Extent to all objects.

This can improve performance when extents need to be checked multiple times, such when needing to check if many points are in geometries, and using their extents as a quick filter for obviously exterior points.

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

source


Barycentric coordinates

# GeometryOps.barycentric_coordinatesFunction.
julia
barycentric_coordinates(method = MeanValue(), polygon, point)

Returns the barycentric coordinates of point in polygon using the barycentric coordinate method method.

source


# GeometryOps.barycentric_coordinates!Function.
julia
barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, polygon, point)

Loads the barycentric coordinates of point in polygon into λs using the barycentric coordinate method method.

λs must be of the length of the polygon plus its holes.

Tip

Use this method to avoid excess allocations when you need to calculate barycentric coordinates for many points.

source


# GeometryOps.barycentric_interpolateFunction.
julia
barycentric_interpolate(method = MeanValue(), polygon, values::AbstractVector{V}, point)

Returns the interpolated value at point within polygon using the barycentric coordinate method method. values are the per-point values for the polygon which are to be interpolated.

Returns an object of type V.

Warning

Barycentric interpolation is currently defined only for 2-dimensional polygons. If you pass a 3-D polygon in, the Z coordinate will be used as per-vertex value to be interpolated (the M coordinate in GIS parlance).

source


Other methods

# GeometryOps.AbstractBarycentricCoordinateMethodType.
julia
abstract type AbstractBarycentricCoordinateMethod

Abstract supertype for barycentric coordinate methods. The subtypes may serve as dispatch types, or may cache some information about the target polygon.

API

The following methods must be implemented for all subtypes:

  • barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, point::Point{2, T2})

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, values::Vector{V}, point::Point{2, T2})::V

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, interiors::Vector{<: Vector{<: Point{2, T1}}} values::Vector{V}, point::Point{2, T2})::V

The rest of the methods will be implemented in terms of these, and have efficient dispatches for broadcasting.

source


# GeometryOps.ClosedRingType.
julia
ClosedRing() <: GeometryCorrection

This correction ensures that a polygon's exterior and interior rings are closed.

It can be called on any geometry correction as usual.

See also GeometryCorrection.

source


# GeometryOps.DiffIntersectingPolygonsType.
julia
DiffIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygons included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be made nonintersecting through the difference operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area. See also GeometryCorrection, UnionIntersectingPolygons.

source


# GeometryOps.DouglasPeuckerType.
julia
DouglasPeucker <: SimplifyAlg
 
-DouglasPeucker(; number, ratio, tol)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Note: user input tol is squared to avoid uneccesary computation in algorithm.

source


# GeometryOps.GEOSType.
julia
GEOS(; params...)

A struct which instructs the method it's passed to as an algorithm to use the appropriate GEOS function via LibGEOS.jl for the operation.

Dispatch is generally carried out using the names of the keyword arguments. For example, segmentize will only accept a GEOS struct with only a max_distance keyword, and no other.

It's generally a lot slower than the native Julia implementations, since it must convert to the LibGEOS implementation and back - so be warned!

source


# GeometryOps.GeodesicSegmentsType.
julia
GeodesicSegments(; max_distance::Real, equatorial_radius::Real=6378137, flattening::Real=1/298.257223563)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance. This method calculates the distance between points on the geodesic, and assumes input in lat/long coordinates.

Warning

Any input geometries must be in lon/lat coordinates! If not, the method may fail or error.

Arguments

  • max_distance::Real: The maximum distance, in meters, between vertices in the geometry.

  • equatorial_radius::Real=6378137: The equatorial radius of the Earth, in meters. Passed to Proj.geod_geodesic.

  • flattening::Real=1/298.257223563: The flattening of the Earth, which is the ratio of the difference between the equatorial and polar radii to the equatorial radius. Passed to Proj.geod_geodesic.

One can also omit the equatorial_radius and flattening keyword arguments, and pass a geodesic object directly to the eponymous keyword.

This method uses the Proj/GeographicLib API for geodesic calculations.

source


# GeometryOps.GeometryCorrectionType.
julia
abstract type GeometryCorrection

This abstract type represents a geometry correction.

Interface

Any GeometryCorrection must implement two functions: * application_level(::GeometryCorrection)::AbstractGeometryTrait: This function should return the GeoInterface trait that the correction is intended to be applied to, like PointTrait or LineStringTrait or PolygonTrait. * (::GeometryCorrection)(::AbstractGeometryTrait, geometry)::(some_geometry): This function should apply the correction to the given geometry, and return a new geometry.

source


# GeometryOps.LineOrientationType.
julia
Enum LineOrientation

Enum for the orientation of a line with respect to a curve. A line can be line_cross (crossing over the curve), line_hinge (crossing the endpoint of the curve), line_over (colinear with the curve), or line_out (not interacting with the curve).

source


# GeometryOps.LinearSegmentsType.
julia
LinearSegments(; max_distance::Real)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance.

Here, max_distance is a purely nondimensional quantity and will apply in the input space. This is to say, that if the polygon is provided in lat/lon coordinates then the max_distance will be in degrees of arc. If the polygon is provided in meters, then the max_distance will be in meters.

source


# GeometryOps.MeanValueType.
julia
MeanValue() <: AbstractBarycentricCoordinateMethod

This method calculates barycentric coordinates using the mean value method.

References

source


# GeometryOps.PointOrientationType.
julia
Enum PointOrientation

Enum for the orientation of a point with respect to a curve. A point can be point_in the curve, point_on the curve, or point_out of the curve.

source


# GeometryOps.RadialDistanceType.
julia
RadialDistance <: SimplifyAlg

Simplifies geometries by removing points less than tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance between points.

Note: user input tol is squared to avoid uneccesary computation in algorithm.

source


# GeometryOps.SimplifyAlgType.
julia
abstract type SimplifyAlg

Abstract type for simplification algorithms.

API

For now, the algorithm must hold the number, ratio and tol properties.

Simplification algorithm types can hook into the interface by implementing the _simplify(trait, alg, geom) methods for whichever traits are necessary.

source


# GeometryOps.TraitTargetType.
julia
TraitTarget{T}

This struct holds a trait parameter or a union of trait parameters.

It is primarily used for dispatch into methods which select trait levels, like apply, or as a parameter to target.

Constructors

julia
TraitTarget(GI.PointTrait())
+DouglasPeucker(; number, ratio, tol)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Note: user input tol is squared to avoid unnecessary computation in algorithm.

source


# GeometryOps.GEOSType.
julia
GEOS(; params...)

A struct which instructs the method it's passed to as an algorithm to use the appropriate GEOS function via LibGEOS.jl for the operation.

Dispatch is generally carried out using the names of the keyword arguments. For example, segmentize will only accept a GEOS struct with only a max_distance keyword, and no other.

It's generally a lot slower than the native Julia implementations, since it must convert to the LibGEOS implementation and back - so be warned!

source


# GeometryOps.GeodesicSegmentsType.
julia
GeodesicSegments(; max_distance::Real, equatorial_radius::Real=6378137, flattening::Real=1/298.257223563)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance. This method calculates the distance between points on the geodesic, and assumes input in lat/long coordinates.

Warning

Any input geometries must be in lon/lat coordinates! If not, the method may fail or error.

Arguments

  • max_distance::Real: The maximum distance, in meters, between vertices in the geometry.

  • equatorial_radius::Real=6378137: The equatorial radius of the Earth, in meters. Passed to Proj.geod_geodesic.

  • flattening::Real=1/298.257223563: The flattening of the Earth, which is the ratio of the difference between the equatorial and polar radii to the equatorial radius. Passed to Proj.geod_geodesic.

One can also omit the equatorial_radius and flattening keyword arguments, and pass a geodesic object directly to the eponymous keyword.

This method uses the Proj/GeographicLib API for geodesic calculations.

source


# GeometryOps.GeometryCorrectionType.
julia
abstract type GeometryCorrection

This abstract type represents a geometry correction.

Interface

Any GeometryCorrection must implement two functions: * application_level(::GeometryCorrection)::AbstractGeometryTrait: This function should return the GeoInterface trait that the correction is intended to be applied to, like PointTrait or LineStringTrait or PolygonTrait. * (::GeometryCorrection)(::AbstractGeometryTrait, geometry)::(some_geometry): This function should apply the correction to the given geometry, and return a new geometry.

source


# GeometryOps.LineOrientationType.
julia
Enum LineOrientation

Enum for the orientation of a line with respect to a curve. A line can be line_cross (crossing over the curve), line_hinge (crossing the endpoint of the curve), line_over (collinear with the curve), or line_out (not interacting with the curve).

source


# GeometryOps.LinearSegmentsType.
julia
LinearSegments(; max_distance::Real)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance.

Here, max_distance is a purely nondimensional quantity and will apply in the input space. This is to say, that if the polygon is provided in lat/lon coordinates then the max_distance will be in degrees of arc. If the polygon is provided in meters, then the max_distance will be in meters.

source


# GeometryOps.MeanValueType.
julia
MeanValue() <: AbstractBarycentricCoordinateMethod

This method calculates barycentric coordinates using the mean value method.

References

source


# GeometryOps.MonotoneChainMethodType.
julia
MonotoneChainMethod()

This is an algorithm for the convex_hull function.

Uses DelaunayTriangulation.jl to compute the convex hull. This is a pure Julia algorithm which provides an optimal Delaunay triangulation.

See also convex_hull

source


# GeometryOps.PointOrientationType.
julia
Enum PointOrientation

Enum for the orientation of a point with respect to a curve. A point can be point_in the curve, point_on the curve, or point_out of the curve.

source


# GeometryOps.RadialDistanceType.
julia
RadialDistance <: SimplifyAlg

Simplifies geometries by removing points less than tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance between points.

Note: user input tol is squared to avoid unnecessary computation in algorithm.

source


# GeometryOps.SimplifyAlgType.
julia
abstract type SimplifyAlg

Abstract type for simplification algorithms.

API

For now, the algorithm must hold the number, ratio and tol properties.

Simplification algorithm types can hook into the interface by implementing the _simplify(trait, alg, geom) methods for whichever traits are necessary.

source


# GeometryOps.TraitTargetType.
julia
TraitTarget{T}

This struct holds a trait parameter or a union of trait parameters.

It is primarily used for dispatch into methods which select trait levels, like apply, or as a parameter to target.

Constructors

julia
TraitTarget(GI.PointTrait())
 TraitTarget(GI.LineStringTrait(), GI.LinearRingTrait()) # and other traits as you may like
 TraitTarget(TraitTarget(...))
 # There are also type based constructors available, but that's not advised.
@@ -162,10 +162,10 @@
 TraitTarget(Union{GI.LineStringTrait, GI.LinearRingTrait})
 # etc.

source


# GeometryOps.UnionIntersectingPolygonsType.
julia
UnionIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygon's included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be combined through the union operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area.

See also GeometryCorrection.

source


# GeometryOps.VisvalingamWhyattType.
julia
VisvalingamWhyatt <: SimplifyAlg
 
-VisvalingamWhyatt(; kw...)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum area of a triangle made with a point and its neighboring points.

Note: user input tol is doubled to avoid uneccesary computation in algorithm.

source


# GeometryOps._detMethod.
julia
_det(s1::Point2{T1}, s2::Point2{T2}) where {T1 <: Real, T2 <: Real}

Returns the determinant of the matrix formed by hcat'ing two points s1 and s2.

Specifically, this is:

julia
s1[1] * s2[2] - s1[2] * s2[1]

source


# GeometryOps._equals_curvesMethod.
julia
_equals_curves(c1, c2, closed_type1, closed_type2)::Bool

Two curves are equal if they share the same set of point, representing the same geometry. Both curves must must be composed of the same set of points, however, they do not have to wind in the same direction, or start on the same point to be equivalent. Inputs: c1 first geometry c2 second geometry closed_type1::Bool true if c1 is closed by definition (polygon, linear ring) closed_type2::Bool true if c2 is closed by definition (polygon, linear ring)

source


# GeometryOps.anglesMethod.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
+VisvalingamWhyatt(; kw...)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum area of a triangle made with a point and its neighboring points.

Note: user input tol is doubled to avoid unnecessary computation in algorithm.

source


# GeometryOps._detMethod.
julia
_det(s1::Point2{T1}, s2::Point2{T2}) where {T1 <: Real, T2 <: Real}

Returns the determinant of the matrix formed by hcat'ing two points s1 and s2.

Specifically, this is:

julia
s1[1] * s2[2] - s1[2] * s2[1]

source


# GeometryOps._equals_curvesMethod.
julia
_equals_curves(c1, c2, closed_type1, closed_type2)::Bool

Two curves are equal if they share the same set of point, representing the same geometry. Both curves must must be composed of the same set of points, however, they do not have to wind in the same direction, or start on the same point to be equivalent. Inputs: c1 first geometry c2 second geometry closed_type1::Bool true if c1 is closed by definition (polygon, linear ring) closed_type2::Bool true if c2 is closed by definition (polygon, linear ring)

source


# GeometryOps.anglesMethod.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
 - The angles of a single line segment is an empty vector.
 - The angles of a linestring or linearring is a vector of angles formed by the curve.
-- The angles of a polygin is a vector of vectors of angles formed by each ring.
+- The angles of a polygon is a vector of vectors of angles formed by each ring.
 - The angles of a multi-geometry collection is a vector of the angles of each of the
     sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.applyMethod.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
 import GeometryOps as GO
@@ -185,7 +185,7 @@
 
 GO.contains(line, point)
 # output
-true

source


# GeometryOps.coverageMethod.
julia
coverage(geom, xmin, xmax, ymin, ymax, [T = Float64])::T

Returns the area of intersection between given geometry and grid cell defined by its minimum and maximum x and y-values. This is computed differently for different geometries:

  • The signed area of a point is always zero.

  • The signed area of a curve is always zero.

  • The signed area of a polygon is calculated by tracing along its edges and switching to the cell edges if needed.

  • The coverage of a geometry collection, multi-geometry, feature collection of array/iterable is the sum of the coverages of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.coveredbyMethod.
julia
coveredby(g1, g2)::Bool

Return true if the first geometry is completely covered by the second geometry. The interior and boundary of the primary geometry (g1) must not intersect the exterior of the secondary geometry (g2).

Furthermore, coveredby returns the exact opposite result of covers. They are equivalent with the order of the arguments swapped.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+true

source


# GeometryOps.convex_hullFunction.
julia
convex_hull([method], geometries)

Compute the convex hull of the points in geometries. Returns a GI.Polygon representing the convex hull.

Note that the polygon returned is wound counterclockwise as in the Simple Features standard by default. If you choose GEOS, the winding order will be inverted.

Warning

This interface only computes the 2-dimensional convex hull!

For higher dimensional hulls, use the relevant package (Qhull.jl, Quickhull.jl, or similar).

source


# GeometryOps.coverageMethod.
julia
coverage(geom, xmin, xmax, ymin, ymax, [T = Float64])::T

Returns the area of intersection between given geometry and grid cell defined by its minimum and maximum x and y-values. This is computed differently for different geometries:

  • The signed area of a point is always zero.

  • The signed area of a curve is always zero.

  • The signed area of a polygon is calculated by tracing along its edges and switching to the cell edges if needed.

  • The coverage of a geometry collection, multi-geometry, feature collection of array/iterable is the sum of the coverages of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.coveredbyMethod.
julia
coveredby(g1, g2)::Bool

Return true if the first geometry is completely covered by the second geometry. The interior and boundary of the primary geometry (g1) must not intersect the exterior of the secondary geometry (g2).

Furthermore, coveredby returns the exact opposite result of covers. They are equivalent with the order of the arguments swapped.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 p1 = GI.Point(0.0, 0.0)
 p2 = GI.Point(1.0, 1.0)
 l1 = GI.Line([p1, p2])
@@ -237,13 +237,13 @@
 )::Bool

Two linear rings are equal if they share the same set of points going along the curve. Note that rings are closed by definition, so they can have, but don't need, a repeated last point to be equal.

source


# GeometryOps.equalsMethod.
julia
equals(
     ::GI.LinearRingTrait, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source


# GeometryOps.equalsMethod.
julia
equals(
+)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source


# GeometryOps.equalsMethod.
julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::GI.LinearRingTrait, l2,
-)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(
+)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by defintion.

source


# GeometryOps.equalsMethod.
julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source


# GeometryOps.flattenMethod.
julia
flatten(target::Type{<:GI.AbstractTrait}, obj)
+)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by definition.

source


# GeometryOps.equalsMethod.
julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source


# GeometryOps.flattenMethod.
julia
flatten(target::Type{<:GI.AbstractTrait}, obj)
 flatten(f, target::Type{<:GI.AbstractTrait}, obj)

Lazily flatten any AbstractArray, iterator, FeatureCollectionTrait, FeatureTrait or AbstractGeometryTrait object obj, so that objects with the target trait are returned by the iterator.

If f is passed in it will be applied to the target geometries.

source


# GeometryOps.flipMethod.
julia
flip(obj)

Swap all of the x and y coordinates in obj, otherwise keeping the original structure (but not necessarily the original type).

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.intersectionMethod.
julia
intersection(geom_a, geom_b, [T::Type]; target::Type, fix_multipoly = UnionIntersectingPolygons())

Return the intersection between two geometries as a list of geometries. Return an empty list if none are found. The type of the list will be constrained as much as possible given the input geometries. Furthermore, the user can provide a target type as a keyword argument and a list of target geometries found in the intersection will be returned. The user can also provide a float type that they would like the points of returned geometries to be. If the user is taking a intersection involving one or more multipolygons, and the multipolygon might be comprised of polygons that intersect, if fix_multipoly is set to an IntersectingPolygons correction (the default is UnionIntersectingPolygons()), then the needed multipolygons will be fixed to be valid before performing the intersection to ensure a correct answer. Only set fix_multipoly to nothing if you know that the multipolygons are valid, as it will avoid unneeded computation.

Example

julia
import GeoInterface as GI, GeometryOps as GO
 
 line1 = GI.Line([(124.584961,-12.768946), (126.738281,-17.224758)])
@@ -295,7 +295,7 @@
 
 GO.overlaps(poly1, poly2)
 # output
-true

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are colinear but each have one endpoint outside of the other line, return true. Else false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
+true

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are collinear but each have one endpoint outside of the other line, return true. Else false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
     ::GI.MultiPointTrait, points1,
     ::GI.MultiPointTrait, points2,
 )::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
@@ -323,14 +323,14 @@
 polygonize(xs, ys, A::AbstractMatrix{Bool}; kw...)
 polygonize(f, xs, ys, A::AbstractMatrix; kw...)

Polygonize an AbstractMatrix of values, currently to a single class of polygons.

Returns a MultiPolygon for Bool values and f return values, and a FeatureCollection of Features holding MultiPolygon for all other values.

Function f should return either true or false or a transformation of values into simpler groups, especially useful for floating point arrays.

If xs and ys are ranges, they are used as the pixel/cell center points. If they are Vector of Tuple they are used as the lower and upper bounds of each pixel/cell.

Keywords

  • minpoints: ignore polygons with less than minpoints points.

  • values: the values to turn into polygons. By default these are union(A), If function f is passed these refer to the return values of f, by default union(map(f, A). If values Bool, false is ignored and a single MultiPolygon is returned rather than a FeatureCollection.

Example

julia
using GeometryOps
 A = rand(100, 100)
-multipolygon = polygonize(>(0.5), A);

source


# GeometryOps.rebuildMethod.
julia
rebuild(geom, child_geoms)

Rebuild a geometry from child geometries.

By default geometries will be rebuilt as a GeoInterface.Wrappers geometry, but rebuild can have methods added to it to dispatch on geometries from other packages and specify how to rebuild them.

(Maybe it should go into GeoInterface.jl)

source


# GeometryOps.reconstructMethod.
julia
reconstruct(geom, components)

Reconstruct geom from an iterable of component objects that match its structure.

All objects in components must have the same GeoInterface.trait.

Ususally used in combination with flatten.

source


# GeometryOps.segmentizeMethod.
julia
segmentize([method = LinearSegments()], geom; max_distance::Real, threaded)

Segmentize a geometry by adding extra vertices to the geometry so that no segment is longer than a given distance. This is useful for plotting geometries with a limited number of vertices, or for ensuring that a geometry is not too "coarse" for a given application.

Arguments

  • method::SegmentizeMethod = LinearSegments(): The method to use for segmentizing the geometry. At the moment, only LinearSegments and GeodesicSegments are available.

  • geom: The geometry to segmentize. Must be a LineString, LinearRing, or greater in complexity.

  • max_distance::Real: The maximum distance, in the input space, between vertices in the geometry. Only used if you don't explicitly pass a method.

Returns a geometry of similar type to the input geometry, but resampled.

source


# GeometryOps.signed_areaMethod.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slighly differently for different geometries:

- The signed area of a point is always zero.
+multipolygon = polygonize(>(0.5), A);

source


# GeometryOps.rebuildMethod.
julia
rebuild(geom, child_geoms)

Rebuild a geometry from child geometries.

By default geometries will be rebuilt as a GeoInterface.Wrappers geometry, but rebuild can have methods added to it to dispatch on geometries from other packages and specify how to rebuild them.

(Maybe it should go into GeoInterface.jl)

source


# GeometryOps.reconstructMethod.
julia
reconstruct(geom, components)

Reconstruct geom from an iterable of component objects that match its structure.

All objects in components must have the same GeoInterface.trait.

Usually used in combination with flatten.

source


# GeometryOps.segmentizeMethod.
julia
segmentize([method = LinearSegments()], geom; max_distance::Real, threaded)

Segmentize a geometry by adding extra vertices to the geometry so that no segment is longer than a given distance. This is useful for plotting geometries with a limited number of vertices, or for ensuring that a geometry is not too "coarse" for a given application.

Arguments

  • method::SegmentizeMethod = LinearSegments(): The method to use for segmentizing the geometry. At the moment, only LinearSegments and GeodesicSegments are available.

  • geom: The geometry to segmentize. Must be a LineString, LinearRing, or greater in complexity.

  • max_distance::Real: The maximum distance, in the input space, between vertices in the geometry. Only used if you don't explicitly pass a method.

Returns a geometry of similar type to the input geometry, but resampled.

source


# GeometryOps.signed_areaMethod.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slightly differently for different geometries:

- The signed area of a point is always zero.
 - The signed area of a curve is always zero.
 - The signed area of a polygon is computed with the shoelace formula and is
 positive if the polygon coordinates wind clockwise and negative if
 counterclockwise.
 - You cannot compute the signed area of a multipolygon as it doesn't have a
 meaning as each sub-polygon could have a different winding order.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_distanceMethod.
julia
signed_distance(point, geom, ::Type{T} = Float64)::T

Calculates the signed distance from the geometry geom to the given point. Points within geom have a negative signed distance, and points outside of geom have a positive signed distance. - The signed distance from a point to a point, line, linestring, or linear ring is equal to the distance between the two. - The signed distance from a point to a polygon is negative if the point is within the polygon and is positive otherwise. The value of the distance is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The signed distance from a point to a multigeometry or a geometry collection is the minimum signed distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.simplifyMethod.
julia
simplify(obj; kw...)
-simplify(::SimplifyAlg, obj; kw...)

Simplify a geometry, feature, feature collection, or nested vectors or a table of these.

RadialDistance, DouglasPeucker, or VisvalingamWhyatt algorithms are available, listed in order of increasing quality but decreaseing performance.

PoinTrait and MultiPointTrait are returned unchanged.

The default behaviour is simplify(DouglasPeucker(; kw...), obj). Pass in other SimplifyAlg to use other algorithms.

Keywords

  • prefilter_alg: SimplifyAlg algorithm used to pre-filter object before using primary filtering algorithm.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Keywords for DouglasPeucker are allowed when no algorithm is specified:

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Example

Simplify a polygon to have six points:

julia
import GeoInterface as GI
+simplify(::SimplifyAlg, obj; kw...)

Simplify a geometry, feature, feature collection, or nested vectors or a table of these.

RadialDistance, DouglasPeucker, or VisvalingamWhyatt algorithms are available, listed in order of increasing quality but decreasing performance.

PoinTrait and MultiPointTrait are returned unchanged.

The default behaviour is simplify(DouglasPeucker(; kw...), obj). Pass in other SimplifyAlg to use other algorithms.

Keywords

  • prefilter_alg: SimplifyAlg algorithm used to pre-filter object before using primary filtering algorithm.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Keywords for DouglasPeucker are allowed when no algorithm is specified:

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Example

Simplify a polygon to have six points:

julia
import GeoInterface as GI
 import GeometryOps as GO
 
 poly = GI.Polygon([[
@@ -359,7 +359,7 @@
 GI.npoint(simple)
 
 # output
-6

source


# GeometryOps.t_valueMethod.
julia
t_value(sᵢ, sᵢ₊₁, rᵢ, rᵢ₊₁)

Returns the "T-value" as described in Hormann's presentation [1] on how to calculate the mean-value coordinate.

Here, sᵢ is the vector from vertex vᵢ to the point, and rᵢ is the norm (length) of sᵢ. s must be Point and r must be real numbers.

t=det(s,s)rr+ss

+6

source


# GeometryOps.t_valueMethod.
julia
t_value(sᵢ, sᵢ₊₁, rᵢ, rᵢ₊₁)

Returns the "T-value" as described in Hormann's presentation [1] on how to calculate the mean-value coordinate.

Here, sᵢ is the vector from vertex vᵢ to the point, and rᵢ is the norm (length) of sᵢ. s must be Point and r must be real numbers.

t=det(s,s)rr+ss

 
 [source](https://github.com/JuliaGeo/GeometryOps.jl/blob/v0.1.10/src/methods/barycentric.jl#L289-L305)
 
@@ -372,7 +372,7 @@
 
 
 ```julia
-to_edges()

Convert any geometry or collection of geometries into a flat vector of Tuple{Tuple{Float64,Float64},Tuple{Float64,Float64}} edges.

source


# GeometryOps.touchesMethod.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometies interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+to_edges()

Convert any geometry or collection of geometries into a flat vector of Tuple{Tuple{Float64,Float64},Tuple{Float64,Float64}} edges.

source


# GeometryOps.touchesMethod.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometry's interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 
 l1 = GI.Line([(0.0, 0.0), (1.0, 0.0)])
 l2 = GI.Line([(1.0, 1.0), (1.0, -1.0)])
@@ -392,7 +392,7 @@
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea
 rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo
 re.SVector{2, Float64}[[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA
-rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actuall multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
+rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actually multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
 
 julia> GO.transform(p -> one(RotMatrix{2}) * p, geom)
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.LinearR
@@ -416,7 +416,7 @@
 
 # output
 true

source



  1. K. Hormann and N. Sukumar. Generalized Barycentric Coordinates in Computer Graphics and Computational Mechanics. Taylor & Fancis, CRC Press, 2017. ↩︎

- + \ No newline at end of file diff --git a/previews/PR135/assets/uugjisc.BOOG5oTW.png b/previews/PR135/assets/afsyzdr.BOOG5oTW.png similarity index 100% rename from previews/PR135/assets/uugjisc.BOOG5oTW.png rename to previews/PR135/assets/afsyzdr.BOOG5oTW.png diff --git a/previews/PR135/assets/rlpsaah.C3SxJ3x-.png b/previews/PR135/assets/aithltv.C3SxJ3x-.png similarity index 100% rename from previews/PR135/assets/rlpsaah.C3SxJ3x-.png rename to previews/PR135/assets/aithltv.C3SxJ3x-.png diff --git a/previews/PR135/assets/api.md.D8UtvlcW.js b/previews/PR135/assets/api.md.BkdCNSpp.js similarity index 84% rename from previews/PR135/assets/api.md.D8UtvlcW.js rename to previews/PR135/assets/api.md.BkdCNSpp.js index 8df9bb16a..3c39cf685 100644 --- a/previews/PR135/assets/api.md.D8UtvlcW.js +++ b/previews/PR135/assets/api.md.BkdCNSpp.js @@ -1,4 +1,4 @@ -import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js";const q=JSON.parse('{"title":"Full GeometryOps API documentation","description":"","frontmatter":{},"headers":[],"relativePath":"api.md","filePath":"api.md","lastUpdated":null}'),l={name:"api.md"},h=i(`

Full GeometryOps API documentation

Warning

This page is still very much WIP!

Documentation for GeometryOps's full API (only for reference!).

apply and associated functions

# GeometryOps.applyFunction.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
+import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.CONf0Rze.js";const q=JSON.parse('{"title":"Full GeometryOps API documentation","description":"","frontmatter":{},"headers":[],"relativePath":"api.md","filePath":"api.md","lastUpdated":null}'),l={name:"api.md"},h=i(`

Full GeometryOps API documentation

Warning

This page is still very much WIP!

Documentation for GeometryOps's full API (only for reference!).

apply and associated functions

# GeometryOps.applyFunction.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
 import GeometryOps as GO
 geom = GI.Polygon([GI.LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]),
                    GI.LinearRing([(3, 4), (5, 6), (6, 7), (3, 4)])])
@@ -7,7 +7,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
     (GI.y(p), GI.x(p))
 end

source


# GeometryOps.applyreduceFunction.
julia
applyreduce(f, op, target::Union{TraitTarget, GI.AbstractTrait}, obj; threaded)

Apply function f to all objects with the target trait, and reduce the result with an op like +.

The order and grouping of application of op is not guaranteed.

If threaded==true threads will be used over arrays and iterables, feature collections and nested geometries.

source


# GeometryOps.reprojectFunction.
julia
reproject(geometry; source_crs, target_crs, transform, always_xy, time)
 reproject(geometry, source_crs, target_crs; always_xy, time)
-reproject(geometry, transform; always_xy, time)

Reproject any GeoInterface.jl compatible geometry from source_crs to target_crs.

The returned object will be constructed from GeoInterface.WrapperGeometry geometries, wrapping views of a Vector{Proj.Point{D}}, where D is the dimension.

Tip

The Proj.jl package must be loaded for this method to work, since it is implemented in a package extension.

Arguments

  • geometry: Any GeoInterface.jl compatible geometries.

  • source_crs: the source coordinate referece system, as a GeoFormatTypes.jl object or a string.

  • target_crs: the target coordinate referece system, as a GeoFormatTypes.jl object or a string.

If these a passed as keywords, transform will take priority. Without it target_crs is always needed, and source_crs is needed if it is not retreivable from the geometry with GeoInterface.crs(geometry).

Keywords

  • always_xy: force x, y coordinate order, true by default. false will expect and return points in the crs coordinate order.

  • time: the time for the coordinates. Inf by default.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.transformFunction.
julia
transform(f, obj)

Apply a function f to all the points in obj.

Points will be passed to f as an SVector to allow using CoordinateTransformations.jl and Rotations.jl without hassle.

SVector is also a valid GeoInterface.jl point, so will work in all GeoInterface.jl methods.

Example

julia
julia> import GeoInterface as GI
+reproject(geometry, transform; always_xy, time)

Reproject any GeoInterface.jl compatible geometry from source_crs to target_crs.

The returned object will be constructed from GeoInterface.WrapperGeometry geometries, wrapping views of a Vector{Proj.Point{D}}, where D is the dimension.

Tip

The Proj.jl package must be loaded for this method to work, since it is implemented in a package extension.

Arguments

  • geometry: Any GeoInterface.jl compatible geometries.

  • source_crs: the source coordinate reference system, as a GeoFormatTypes.jl object or a string.

  • target_crs: the target coordinate reference system, as a GeoFormatTypes.jl object or a string.

If these a passed as keywords, transform will take priority. Without it target_crs is always needed, and source_crs is needed if it is not retrievable from the geometry with GeoInterface.crs(geometry).

Keywords

  • always_xy: force x, y coordinate order, true by default. false will expect and return points in the crs coordinate order.

  • time: the time for the coordinates. Inf by default.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.transformFunction.
julia
transform(f, obj)

Apply a function f to all the points in obj.

Points will be passed to f as an SVector to allow using CoordinateTransformations.jl and Rotations.jl without hassle.

SVector is also a valid GeoInterface.jl point, so will work in all GeoInterface.jl methods.

Example

julia
julia> import GeoInterface as GI
 
 julia> import GeometryOps as GO
 
@@ -20,7 +20,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea
 rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo
 re.SVector{2, Float64}[[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA
-rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actuall multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
+rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actually multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
 
 julia> GO.transform(p -> one(RotMatrix{2}) * p, geom)
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.LinearR
@@ -69,7 +69,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 true

source

julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source

julia
overlaps(
     ::GI.MultiPointTrait, points1,
     ::GI.MultiPointTrait, points2,
-)::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source

julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are colinear but each have one endpoint outside of the other line, return true. Else false.

source

julia
overlaps(
+)::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source

julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are collinear but each have one endpoint outside of the other line, return true. Else false.

source

julia
overlaps(
     ::Union{GI.LineStringTrait, GI.LinearRing}, line1,
     ::Union{GI.LineStringTrait, GI.LinearRing}, line2,
 )::Bool

If the curves overlap, meaning that at least one edge of each curve overlaps, return true. Else false.

source

julia
overlaps(
@@ -84,7 +84,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 )::Bool

Return true if polygon overlaps with at least one of the polygons within the multipolygon. Else false.

source

julia
overlaps(
     ::GI.MultiPolygonTrait, polys1,
     ::GI.MultiPolygonTrait, polys2,
-)::Bool

Return true if at least one pair of polygons from multipolygons overlap. Else false.

source


# GeometryOps.touchesFunction.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometies interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+)::Bool

Return true if at least one pair of polygons from multipolygons overlap. Else false.

source


# GeometryOps.touchesFunction.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometry's interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 
 l1 = GI.Line([(0.0, 0.0), (1.0, 0.0)])
 l2 = GI.Line([(1.0, 1.0), (1.0, -1.0)])
@@ -107,13 +107,13 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 true

source

julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source

julia
equals(trait_a, geom_a, trait_b, geom_b)

Two geometries which are not of the same type cannot be equal so they always return false.

source

julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source

julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source

julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source

julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source

julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by defintion.

source

julia
equals(
+)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by definition.

source

julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::GI.LinearRingTrait, l2,
-)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
+)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
     ::GI.LinearRingTrait, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
+)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source

julia
equals(
     ::GI.LinearRingTrait, l1,
     ::GI.LinearRingTrait, l2,
 )::Bool

Two linear rings are equal if they share the same set of points going along the curve. Note that rings are closed by definition, so they can have, but don't need, a repeated last point to be equal.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source

julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source

julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.centroidFunction.
julia
centroid(geom, [T=Float64])::Tuple{T, T}

Returns the centroid of a given line segment, linear ring, polygon, or mutlipolygon.

source


# GeometryOps.distanceFunction.
julia
distance(point, geom, ::Type{T} = Float64)::T

Calculates the ditance from the geometry g1 to the point. The distance will always be positive or zero.

The method will differ based on the type of the geometry provided: - The distance from a point to a point is just the Euclidean distance between the points. - The distance from a point to a line is the minimum distance from the point to the closest point on the given line. - The distance from a point to a linestring is the minimum distance from the point to the closest segment of the linestring. - The distance from a point to a linear ring is the minimum distance from the point to the closest segment of the linear ring. - The distance from a point to a polygon is zero if the point is within the polygon and otherwise is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The distance from a point to a multigeometry or a geometry collection is the minimum distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_distanceFunction.
julia
signed_distance(point, geom, ::Type{T} = Float64)::T

Calculates the signed distance from the geometry geom to the given point. Points within geom have a negative signed distance, and points outside of geom have a positive signed distance. - The signed distance from a point to a point, line, linestring, or linear ring is equal to the distance between the two. - The signed distance from a point to a polygon is negative if the point is within the polygon and is positive otherwise. The value of the distance is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The signed distance from a point to a multigeometry or a geometry collection is the minimum signed distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.areaFunction.
julia
area(geom, [T = Float64])::T

Returns the area of a geometry or collection of geometries. This is computed slightly differently for different geometries:

- The area of a point/multipoint is always zero.
@@ -121,7 +121,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 - The area of a polygon is the absolute value of the signed area.
 - The area multi-polygon is the sum of the areas of all of the sub-polygons.
 - The area of a geometry collection, feature collection of array/iterable 
-    is the sum of the areas of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_areaFunction.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slighly differently for different geometries:

- The signed area of a point is always zero.
+    is the sum of the areas of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_areaFunction.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slightly differently for different geometries:

- The signed area of a point is always zero.
 - The signed area of a curve is always zero.
 - The signed area of a polygon is computed with the shoelace formula and is
 positive if the polygon coordinates wind clockwise and negative if
@@ -130,11 +130,11 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 meaning as each sub-polygon could have a different winding order.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.anglesFunction.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
 - The angles of a single line segment is an empty vector.
 - The angles of a linestring or linearring is a vector of angles formed by the curve.
-- The angles of a polygin is a vector of vectors of angles formed by each ring.
+- The angles of a polygon is a vector of vectors of angles formed by each ring.
 - The angles of a multi-geometry collection is a vector of the angles of each of the
-    sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.embed_extentFunction.
julia
embed_extent(obj)

Recursively wrap the object with a GeoInterface.jl geometry, calculating and adding an Extents.Extent to all objects.

This can improve performance when extents need to be checked multiple times, such when needing to check if many points are in geometries, and using their extents as a quick filter for obviously exterior points.

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

source


Barycentric coordinates

# GeometryOps.barycentric_coordinatesFunction.
julia
barycentric_coordinates(method = MeanValue(), polygon, point)

Returns the barycentric coordinates of point in polygon using the barycentric coordinate method method.

source


# GeometryOps.barycentric_coordinates!Function.
julia
barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, polygon, point)

Loads the barycentric coordinates of point in polygon into λs using the barycentric coordinate method method.

λs must be of the length of the polygon plus its holes.

Tip

Use this method to avoid excess allocations when you need to calculate barycentric coordinates for many points.

source


# GeometryOps.barycentric_interpolateFunction.
julia
barycentric_interpolate(method = MeanValue(), polygon, values::AbstractVector{V}, point)

Returns the interpolated value at point within polygon using the barycentric coordinate method method. values are the per-point values for the polygon which are to be interpolated.

Returns an object of type V.

Warning

Barycentric interpolation is currently defined only for 2-dimensional polygons. If you pass a 3-D polygon in, the Z coordinate will be used as per-vertex value to be interpolated (the M coordinate in GIS parlance).

source


Other methods

# GeometryOps.AbstractBarycentricCoordinateMethodType.
julia
abstract type AbstractBarycentricCoordinateMethod

Abstract supertype for barycentric coordinate methods. The subtypes may serve as dispatch types, or may cache some information about the target polygon.

API

The following methods must be implemented for all subtypes:

  • barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, point::Point{2, T2})

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, values::Vector{V}, point::Point{2, T2})::V

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, interiors::Vector{<: Vector{<: Point{2, T1}}} values::Vector{V}, point::Point{2, T2})::V

The rest of the methods will be implemented in terms of these, and have efficient dispatches for broadcasting.

source


# GeometryOps.ClosedRingType.
julia
ClosedRing() <: GeometryCorrection

This correction ensures that a polygon's exterior and interior rings are closed.

It can be called on any geometry correction as usual.

See also GeometryCorrection.

source


# GeometryOps.DiffIntersectingPolygonsType.
julia
DiffIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygons included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be made nonintersecting through the difference operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area. See also GeometryCorrection, UnionIntersectingPolygons.

source


# GeometryOps.DouglasPeuckerType.
julia
DouglasPeucker <: SimplifyAlg
+    sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.embed_extentFunction.
julia
embed_extent(obj)

Recursively wrap the object with a GeoInterface.jl geometry, calculating and adding an Extents.Extent to all objects.

This can improve performance when extents need to be checked multiple times, such when needing to check if many points are in geometries, and using their extents as a quick filter for obviously exterior points.

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

source


Barycentric coordinates

# GeometryOps.barycentric_coordinatesFunction.
julia
barycentric_coordinates(method = MeanValue(), polygon, point)

Returns the barycentric coordinates of point in polygon using the barycentric coordinate method method.

source


# GeometryOps.barycentric_coordinates!Function.
julia
barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, polygon, point)

Loads the barycentric coordinates of point in polygon into λs using the barycentric coordinate method method.

λs must be of the length of the polygon plus its holes.

Tip

Use this method to avoid excess allocations when you need to calculate barycentric coordinates for many points.

source


# GeometryOps.barycentric_interpolateFunction.
julia
barycentric_interpolate(method = MeanValue(), polygon, values::AbstractVector{V}, point)

Returns the interpolated value at point within polygon using the barycentric coordinate method method. values are the per-point values for the polygon which are to be interpolated.

Returns an object of type V.

Warning

Barycentric interpolation is currently defined only for 2-dimensional polygons. If you pass a 3-D polygon in, the Z coordinate will be used as per-vertex value to be interpolated (the M coordinate in GIS parlance).

source


Other methods

# GeometryOps.AbstractBarycentricCoordinateMethodType.
julia
abstract type AbstractBarycentricCoordinateMethod

Abstract supertype for barycentric coordinate methods. The subtypes may serve as dispatch types, or may cache some information about the target polygon.

API

The following methods must be implemented for all subtypes:

  • barycentric_coordinates!(λs::Vector{<: Real}, method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, point::Point{2, T2})

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, values::Vector{V}, point::Point{2, T2})::V

  • barycentric_interpolate(method::AbstractBarycentricCoordinateMethod, exterior::Vector{<: Point{2, T1}}, interiors::Vector{<: Vector{<: Point{2, T1}}} values::Vector{V}, point::Point{2, T2})::V

The rest of the methods will be implemented in terms of these, and have efficient dispatches for broadcasting.

source


# GeometryOps.ClosedRingType.
julia
ClosedRing() <: GeometryCorrection

This correction ensures that a polygon's exterior and interior rings are closed.

It can be called on any geometry correction as usual.

See also GeometryCorrection.

source


# GeometryOps.DiffIntersectingPolygonsType.
julia
DiffIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygons included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be made nonintersecting through the difference operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area. See also GeometryCorrection, UnionIntersectingPolygons.

source


# GeometryOps.DouglasPeuckerType.
julia
DouglasPeucker <: SimplifyAlg
 
-DouglasPeucker(; number, ratio, tol)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Note: user input tol is squared to avoid uneccesary computation in algorithm.

source


# GeometryOps.GEOSType.
julia
GEOS(; params...)

A struct which instructs the method it's passed to as an algorithm to use the appropriate GEOS function via LibGEOS.jl for the operation.

Dispatch is generally carried out using the names of the keyword arguments. For example, segmentize will only accept a GEOS struct with only a max_distance keyword, and no other.

It's generally a lot slower than the native Julia implementations, since it must convert to the LibGEOS implementation and back - so be warned!

source


# GeometryOps.GeodesicSegmentsType.
julia
GeodesicSegments(; max_distance::Real, equatorial_radius::Real=6378137, flattening::Real=1/298.257223563)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance. This method calculates the distance between points on the geodesic, and assumes input in lat/long coordinates.

Warning

Any input geometries must be in lon/lat coordinates! If not, the method may fail or error.

Arguments

  • max_distance::Real: The maximum distance, in meters, between vertices in the geometry.

  • equatorial_radius::Real=6378137: The equatorial radius of the Earth, in meters. Passed to Proj.geod_geodesic.

  • flattening::Real=1/298.257223563: The flattening of the Earth, which is the ratio of the difference between the equatorial and polar radii to the equatorial radius. Passed to Proj.geod_geodesic.

One can also omit the equatorial_radius and flattening keyword arguments, and pass a geodesic object directly to the eponymous keyword.

This method uses the Proj/GeographicLib API for geodesic calculations.

source


# GeometryOps.GeometryCorrectionType.
julia
abstract type GeometryCorrection

This abstract type represents a geometry correction.

Interface

Any GeometryCorrection must implement two functions: * application_level(::GeometryCorrection)::AbstractGeometryTrait: This function should return the GeoInterface trait that the correction is intended to be applied to, like PointTrait or LineStringTrait or PolygonTrait. * (::GeometryCorrection)(::AbstractGeometryTrait, geometry)::(some_geometry): This function should apply the correction to the given geometry, and return a new geometry.

source


# GeometryOps.LineOrientationType.
julia
Enum LineOrientation

Enum for the orientation of a line with respect to a curve. A line can be line_cross (crossing over the curve), line_hinge (crossing the endpoint of the curve), line_over (colinear with the curve), or line_out (not interacting with the curve).

source


# GeometryOps.LinearSegmentsType.
julia
LinearSegments(; max_distance::Real)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance.

Here, max_distance is a purely nondimensional quantity and will apply in the input space. This is to say, that if the polygon is provided in lat/lon coordinates then the max_distance will be in degrees of arc. If the polygon is provided in meters, then the max_distance will be in meters.

source


# GeometryOps.MeanValueType.
julia
MeanValue() <: AbstractBarycentricCoordinateMethod

This method calculates barycentric coordinates using the mean value method.

References

source


# GeometryOps.PointOrientationType.
julia
Enum PointOrientation

Enum for the orientation of a point with respect to a curve. A point can be point_in the curve, point_on the curve, or point_out of the curve.

source


# GeometryOps.RadialDistanceType.
julia
RadialDistance <: SimplifyAlg

Simplifies geometries by removing points less than tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance between points.

Note: user input tol is squared to avoid uneccesary computation in algorithm.

source


# GeometryOps.SimplifyAlgType.
julia
abstract type SimplifyAlg

Abstract type for simplification algorithms.

API

For now, the algorithm must hold the number, ratio and tol properties.

Simplification algorithm types can hook into the interface by implementing the _simplify(trait, alg, geom) methods for whichever traits are necessary.

source


# GeometryOps.TraitTargetType.
julia
TraitTarget{T}

This struct holds a trait parameter or a union of trait parameters.

It is primarily used for dispatch into methods which select trait levels, like apply, or as a parameter to target.

Constructors

julia
TraitTarget(GI.PointTrait())
+DouglasPeucker(; number, ratio, tol)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Note: user input tol is squared to avoid unnecessary computation in algorithm.

source


# GeometryOps.GEOSType.
julia
GEOS(; params...)

A struct which instructs the method it's passed to as an algorithm to use the appropriate GEOS function via LibGEOS.jl for the operation.

Dispatch is generally carried out using the names of the keyword arguments. For example, segmentize will only accept a GEOS struct with only a max_distance keyword, and no other.

It's generally a lot slower than the native Julia implementations, since it must convert to the LibGEOS implementation and back - so be warned!

source


# GeometryOps.GeodesicSegmentsType.
julia
GeodesicSegments(; max_distance::Real, equatorial_radius::Real=6378137, flattening::Real=1/298.257223563)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance. This method calculates the distance between points on the geodesic, and assumes input in lat/long coordinates.

Warning

Any input geometries must be in lon/lat coordinates! If not, the method may fail or error.

Arguments

  • max_distance::Real: The maximum distance, in meters, between vertices in the geometry.

  • equatorial_radius::Real=6378137: The equatorial radius of the Earth, in meters. Passed to Proj.geod_geodesic.

  • flattening::Real=1/298.257223563: The flattening of the Earth, which is the ratio of the difference between the equatorial and polar radii to the equatorial radius. Passed to Proj.geod_geodesic.

One can also omit the equatorial_radius and flattening keyword arguments, and pass a geodesic object directly to the eponymous keyword.

This method uses the Proj/GeographicLib API for geodesic calculations.

source


# GeometryOps.GeometryCorrectionType.
julia
abstract type GeometryCorrection

This abstract type represents a geometry correction.

Interface

Any GeometryCorrection must implement two functions: * application_level(::GeometryCorrection)::AbstractGeometryTrait: This function should return the GeoInterface trait that the correction is intended to be applied to, like PointTrait or LineStringTrait or PolygonTrait. * (::GeometryCorrection)(::AbstractGeometryTrait, geometry)::(some_geometry): This function should apply the correction to the given geometry, and return a new geometry.

source


# GeometryOps.LineOrientationType.
julia
Enum LineOrientation

Enum for the orientation of a line with respect to a curve. A line can be line_cross (crossing over the curve), line_hinge (crossing the endpoint of the curve), line_over (collinear with the curve), or line_out (not interacting with the curve).

source


# GeometryOps.LinearSegmentsType.
julia
LinearSegments(; max_distance::Real)

A method for segmentizing geometries by adding extra vertices to the geometry so that no segment is longer than a given distance.

Here, max_distance is a purely nondimensional quantity and will apply in the input space. This is to say, that if the polygon is provided in lat/lon coordinates then the max_distance will be in degrees of arc. If the polygon is provided in meters, then the max_distance will be in meters.

source


# GeometryOps.MeanValueType.
julia
MeanValue() <: AbstractBarycentricCoordinateMethod

This method calculates barycentric coordinates using the mean value method.

References

source


# GeometryOps.MonotoneChainMethodType.
julia
MonotoneChainMethod()

This is an algorithm for the convex_hull function.

Uses DelaunayTriangulation.jl to compute the convex hull. This is a pure Julia algorithm which provides an optimal Delaunay triangulation.

See also convex_hull

source


# GeometryOps.PointOrientationType.
julia
Enum PointOrientation

Enum for the orientation of a point with respect to a curve. A point can be point_in the curve, point_on the curve, or point_out of the curve.

source


# GeometryOps.RadialDistanceType.
julia
RadialDistance <: SimplifyAlg

Simplifies geometries by removing points less than tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance between points.

Note: user input tol is squared to avoid unnecessary computation in algorithm.

source


# GeometryOps.SimplifyAlgType.
julia
abstract type SimplifyAlg

Abstract type for simplification algorithms.

API

For now, the algorithm must hold the number, ratio and tol properties.

Simplification algorithm types can hook into the interface by implementing the _simplify(trait, alg, geom) methods for whichever traits are necessary.

source


# GeometryOps.TraitTargetType.
julia
TraitTarget{T}

This struct holds a trait parameter or a union of trait parameters.

It is primarily used for dispatch into methods which select trait levels, like apply, or as a parameter to target.

Constructors

julia
TraitTarget(GI.PointTrait())
 TraitTarget(GI.LineStringTrait(), GI.LinearRingTrait()) # and other traits as you may like
 TraitTarget(TraitTarget(...))
 # There are also type based constructors available, but that's not advised.
@@ -142,10 +142,10 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 TraitTarget(Union{GI.LineStringTrait, GI.LinearRingTrait})
 # etc.

source


# GeometryOps.UnionIntersectingPolygonsType.
julia
UnionIntersectingPolygons() <: GeometryCorrection

This correction ensures that the polygon's included in a multipolygon aren't intersecting. If any polygon's are intersecting, they will be combined through the union operation to create a unique set of disjoint (other than potentially connections by a single point) polygons covering the same area.

See also GeometryCorrection.

source


# GeometryOps.VisvalingamWhyattType.
julia
VisvalingamWhyatt <: SimplifyAlg
 
-VisvalingamWhyatt(; kw...)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum area of a triangle made with a point and its neighboring points.

Note: user input tol is doubled to avoid uneccesary computation in algorithm.

source


# GeometryOps._detMethod.
julia
_det(s1::Point2{T1}, s2::Point2{T2}) where {T1 <: Real, T2 <: Real}

Returns the determinant of the matrix formed by hcat'ing two points s1 and s2.

Specifically, this is:

julia
s1[1] * s2[2] - s1[2] * s2[1]

source


# GeometryOps._equals_curvesMethod.
julia
_equals_curves(c1, c2, closed_type1, closed_type2)::Bool

Two curves are equal if they share the same set of point, representing the same geometry. Both curves must must be composed of the same set of points, however, they do not have to wind in the same direction, or start on the same point to be equivalent. Inputs: c1 first geometry c2 second geometry closed_type1::Bool true if c1 is closed by definition (polygon, linear ring) closed_type2::Bool true if c2 is closed by definition (polygon, linear ring)

source


# GeometryOps.anglesMethod.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
+VisvalingamWhyatt(; kw...)

Simplifies geometries by removing points below tol distance from the line between its neighboring points.

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum area of a triangle made with a point and its neighboring points.

Note: user input tol is doubled to avoid unnecessary computation in algorithm.

source


# GeometryOps._detMethod.
julia
_det(s1::Point2{T1}, s2::Point2{T2}) where {T1 <: Real, T2 <: Real}

Returns the determinant of the matrix formed by hcat'ing two points s1 and s2.

Specifically, this is:

julia
s1[1] * s2[2] - s1[2] * s2[1]

source


# GeometryOps._equals_curvesMethod.
julia
_equals_curves(c1, c2, closed_type1, closed_type2)::Bool

Two curves are equal if they share the same set of point, representing the same geometry. Both curves must must be composed of the same set of points, however, they do not have to wind in the same direction, or start on the same point to be equivalent. Inputs: c1 first geometry c2 second geometry closed_type1::Bool true if c1 is closed by definition (polygon, linear ring) closed_type2::Bool true if c2 is closed by definition (polygon, linear ring)

source


# GeometryOps.anglesMethod.
julia
angles(geom, ::Type{T} = Float64)

Returns the angles of a geometry or collection of geometries. This is computed differently for different geometries:

- The angles of a point is an empty vector.
 - The angles of a single line segment is an empty vector.
 - The angles of a linestring or linearring is a vector of angles formed by the curve.
-- The angles of a polygin is a vector of vectors of angles formed by each ring.
+- The angles of a polygon is a vector of vectors of angles formed by each ring.
 - The angles of a multi-geometry collection is a vector of the angles of each of the
     sub-geometries as defined above.

Result will be a Vector, or nested set of vectors, of type T where an optional argument with a default value of Float64.

source


# GeometryOps.applyMethod.
julia
apply(f, target::Union{TraitTarget, GI.AbstractTrait}, obj; kw...)

Reconstruct a geometry, feature, feature collection, or nested vectors of either using the function f on the target trait.

f(target_geom) => x where x also has the target trait, or a trait that can be substituted. For example, swapping PolgonTrait to MultiPointTrait will fail if the outer object has MultiPolygonTrait, but should work if it has FeatureTrait.

Objects "shallower" than the target trait are always completely rebuilt, like a Vector of FeatureCollectionTrait of FeatureTrait when the target has PolygonTrait and is held in the features. These will always be GeoInterface geometries/feature/feature collections. But "deeper" objects may remain unchanged or be whatever GeoInterface compatible objects f returns.

The result is a functionally similar geometry with values depending on f.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Example

Flipped point the order in any feature or geometry, or iterables of either:

julia
import GeoInterface as GI
 import GeometryOps as GO
@@ -165,7 +165,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 
 GO.contains(line, point)
 # output
-true

source


# GeometryOps.coverageMethod.
julia
coverage(geom, xmin, xmax, ymin, ymax, [T = Float64])::T

Returns the area of intersection between given geometry and grid cell defined by its minimum and maximum x and y-values. This is computed differently for different geometries:

  • The signed area of a point is always zero.

  • The signed area of a curve is always zero.

  • The signed area of a polygon is calculated by tracing along its edges and switching to the cell edges if needed.

  • The coverage of a geometry collection, multi-geometry, feature collection of array/iterable is the sum of the coverages of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.coveredbyMethod.
julia
coveredby(g1, g2)::Bool

Return true if the first geometry is completely covered by the second geometry. The interior and boundary of the primary geometry (g1) must not intersect the exterior of the secondary geometry (g2).

Furthermore, coveredby returns the exact opposite result of covers. They are equivalent with the order of the arguments swapped.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+true

source


# GeometryOps.convex_hullFunction.
julia
convex_hull([method], geometries)

Compute the convex hull of the points in geometries. Returns a GI.Polygon representing the convex hull.

Note that the polygon returned is wound counterclockwise as in the Simple Features standard by default. If you choose GEOS, the winding order will be inverted.

Warning

This interface only computes the 2-dimensional convex hull!

For higher dimensional hulls, use the relevant package (Qhull.jl, Quickhull.jl, or similar).

source


# GeometryOps.coverageMethod.
julia
coverage(geom, xmin, xmax, ymin, ymax, [T = Float64])::T

Returns the area of intersection between given geometry and grid cell defined by its minimum and maximum x and y-values. This is computed differently for different geometries:

  • The signed area of a point is always zero.

  • The signed area of a curve is always zero.

  • The signed area of a polygon is calculated by tracing along its edges and switching to the cell edges if needed.

  • The coverage of a geometry collection, multi-geometry, feature collection of array/iterable is the sum of the coverages of all of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.coveredbyMethod.
julia
coveredby(g1, g2)::Bool

Return true if the first geometry is completely covered by the second geometry. The interior and boundary of the primary geometry (g1) must not intersect the exterior of the secondary geometry (g2).

Furthermore, coveredby returns the exact opposite result of covers. They are equivalent with the order of the arguments swapped.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 p1 = GI.Point(0.0, 0.0)
 p2 = GI.Point(1.0, 1.0)
 l1 = GI.Line([p1, p2])
@@ -217,13 +217,13 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 )::Bool

Two linear rings are equal if they share the same set of points going along the curve. Note that rings are closed by definition, so they can have, but don't need, a repeated last point to be equal.

source


# GeometryOps.equalsMethod.
julia
equals(
     ::GI.LinearRingTrait, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source


# GeometryOps.equalsMethod.
julia
equals(
+)::Bool

A linear ring and a line/linestring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.MultiPointTrait, mp2)::Bool

Two multipoints are equal if they share the same set of points.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPointTrait, mp1, ::GI.PointTrait, p2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two multipolygons are equal if they share the same set of polygons.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.MultiPolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.MultiPointTrait, mp2)::Bool

A point and a multipoint are equal if the multipoint is composed of a single point that is equivalent to the given point.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PointTrait, p1, ::GI.PointTrait, p2)::Bool

Two points are the same if they have the same x and y (and z if 3D) coordinates.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.MultiPolygonTrait, geom_b)::Bool

A polygon and a multipolygon are equal if the multipolygon is composed of a single polygon that is equivalent to the given polygon.

source


# GeometryOps.equalsMethod.
julia
equals(::GI.PolygonTrait, geom_a, ::GI.PolygonTrait, geom_b)::Bool

Two polygons are equal if they share the same exterior edge and holes.

source


# GeometryOps.equalsMethod.
julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::GI.LinearRingTrait, l2,
-)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by defintion, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(
+)::Bool

A line/linestring and a linear ring are equal if they share the same set of points going along the curve. Note that lines aren't closed by definition, but rings are, so the line must have a repeated last point to be equal

source


# GeometryOps.equalsMethod.
julia
equals(
     ::Union{GI.LineTrait, GI.LineStringTrait}, l1,
     ::Union{GI.LineTrait, GI.LineStringTrait}, l2,
-)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by defintion.

source


# GeometryOps.equalsMethod.
julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source


# GeometryOps.flattenMethod.
julia
flatten(target::Type{<:GI.AbstractTrait}, obj)
+)::Bool

Two lines/linestrings are equal if they share the same set of points going along the curve. Note that lines/linestrings aren't closed by definition.

source


# GeometryOps.equalsMethod.
julia
equals(::T, geom_a, ::T, geom_b)::Bool

Two geometries of the same type, which don't have a equals function to dispatch off of should throw an error.

source


# GeometryOps.flattenMethod.
julia
flatten(target::Type{<:GI.AbstractTrait}, obj)
 flatten(f, target::Type{<:GI.AbstractTrait}, obj)

Lazily flatten any AbstractArray, iterator, FeatureCollectionTrait, FeatureTrait or AbstractGeometryTrait object obj, so that objects with the target trait are returned by the iterator.

If f is passed in it will be applied to the target geometries.

source


# GeometryOps.flipMethod.
julia
flip(obj)

Swap all of the x and y coordinates in obj, otherwise keeping the original structure (but not necessarily the original type).

Keywords

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

source


# GeometryOps.intersectionMethod.
julia
intersection(geom_a, geom_b, [T::Type]; target::Type, fix_multipoly = UnionIntersectingPolygons())

Return the intersection between two geometries as a list of geometries. Return an empty list if none are found. The type of the list will be constrained as much as possible given the input geometries. Furthermore, the user can provide a target type as a keyword argument and a list of target geometries found in the intersection will be returned. The user can also provide a float type that they would like the points of returned geometries to be. If the user is taking a intersection involving one or more multipolygons, and the multipolygon might be comprised of polygons that intersect, if fix_multipoly is set to an IntersectingPolygons correction (the default is UnionIntersectingPolygons()), then the needed multipolygons will be fixed to be valid before performing the intersection to ensure a correct answer. Only set fix_multipoly to nothing if you know that the multipolygons are valid, as it will avoid unneeded computation.

Example

julia
import GeoInterface as GI, GeometryOps as GO
 
 line1 = GI.Line([(124.584961,-12.768946), (126.738281,-17.224758)])
@@ -259,7 +259,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 GO.intersects(line1, line2)
 
 # output
-true

source


`,174),p={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},r=s("a",{id:"GeometryOps.isclockwise-Tuple{Any}",href:"#GeometryOps.isclockwise-Tuple{Any}"},"#",-1),k=s("b",null,[s("u",null,"GeometryOps.isclockwise")],-1),o=s("i",null,"Method",-1),d=i('
julia
isclockwise(line::Union{LineString, Vector{Position}})::Bool

Take a ring and return true if the line goes clockwise, or false if the line goes counter-clockwise. "Going clockwise" means, mathematically,

',2),g={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},y={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.827ex"},xmlns:"http://www.w3.org/2000/svg",width:"33.539ex",height:"6.785ex",role:"img",focusable:"false",viewBox:"0 -1749.5 14824.1 2999","aria-hidden":"true"},E=i('',1),c=[E],u=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("munderover",null,[s("mo",{"data-mjx-texclass":"OP"},"∑"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"2")]),s("mi",null,"n")]),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"y"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",{"data-mjx-texclass":"CLOSE"},")")]),s("mo",null,">"),s("mn",null,"0")])],-1),m=i(`

Example

julia
julia> import GeoInterface as GI, GeometryOps as GO
+true

source


`,178),p={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},r=s("a",{id:"GeometryOps.isclockwise-Tuple{Any}",href:"#GeometryOps.isclockwise-Tuple{Any}"},"#",-1),k=s("b",null,[s("u",null,"GeometryOps.isclockwise")],-1),o=s("i",null,"Method",-1),d=i('
julia
isclockwise(line::Union{LineString, Vector{Position}})::Bool

Take a ring and return true if the line goes clockwise, or false if the line goes counter-clockwise. "Going clockwise" means, mathematically,

',2),g={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},y={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.827ex"},xmlns:"http://www.w3.org/2000/svg",width:"33.539ex",height:"6.785ex",role:"img",focusable:"false",viewBox:"0 -1749.5 14824.1 2999","aria-hidden":"true"},E=i('',1),c=[E],u=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("munderover",null,[s("mo",{"data-mjx-texclass":"OP"},"∑"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"2")]),s("mi",null,"n")]),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"y"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",{"data-mjx-texclass":"CLOSE"},")")]),s("mo",null,">"),s("mn",null,"0")])],-1),m=i(`

Example

julia
julia> import GeoInterface as GI, GeometryOps as GO
 julia> ring = GI.LinearRing([(0, 0), (1, 1), (1, 0), (0, 0)]);
 julia> GO.isclockwise(ring)
 # output
@@ -275,7 +275,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 
 GO.overlaps(poly1, poly2)
 # output
-true

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are colinear but each have one endpoint outside of the other line, return true. Else false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
+true

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.AbstractTrait, geom1, ::GI.AbstractTrait, geom2)::Bool

For any non-specified pair, all have non-matching dimensions, return false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(::GI.LineTrait, line1, ::GI.LineTrait, line)::Bool

If the lines overlap, meaning that they are collinear but each have one endpoint outside of the other line, return true. Else false.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
     ::GI.MultiPointTrait, points1,
     ::GI.MultiPointTrait, points2,
 )::Bool

If the multipoints overlap, meaning some, but not all, of the points within the multipoints are shared, return true.

source


# GeometryOps.overlapsMethod.
julia
overlaps(
@@ -303,14 +303,14 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 polygonize(xs, ys, A::AbstractMatrix{Bool}; kw...)
 polygonize(f, xs, ys, A::AbstractMatrix; kw...)

Polygonize an AbstractMatrix of values, currently to a single class of polygons.

Returns a MultiPolygon for Bool values and f return values, and a FeatureCollection of Features holding MultiPolygon for all other values.

Function f should return either true or false or a transformation of values into simpler groups, especially useful for floating point arrays.

If xs and ys are ranges, they are used as the pixel/cell center points. If they are Vector of Tuple they are used as the lower and upper bounds of each pixel/cell.

Keywords

  • minpoints: ignore polygons with less than minpoints points.

  • values: the values to turn into polygons. By default these are union(A), If function f is passed these refer to the return values of f, by default union(map(f, A). If values Bool, false is ignored and a single MultiPolygon is returned rather than a FeatureCollection.

Example

julia
using GeometryOps
 A = rand(100, 100)
-multipolygon = polygonize(>(0.5), A);

source


# GeometryOps.rebuildMethod.
julia
rebuild(geom, child_geoms)

Rebuild a geometry from child geometries.

By default geometries will be rebuilt as a GeoInterface.Wrappers geometry, but rebuild can have methods added to it to dispatch on geometries from other packages and specify how to rebuild them.

(Maybe it should go into GeoInterface.jl)

source


# GeometryOps.reconstructMethod.
julia
reconstruct(geom, components)

Reconstruct geom from an iterable of component objects that match its structure.

All objects in components must have the same GeoInterface.trait.

Ususally used in combination with flatten.

source


# GeometryOps.segmentizeMethod.
julia
segmentize([method = LinearSegments()], geom; max_distance::Real, threaded)

Segmentize a geometry by adding extra vertices to the geometry so that no segment is longer than a given distance. This is useful for plotting geometries with a limited number of vertices, or for ensuring that a geometry is not too "coarse" for a given application.

Arguments

  • method::SegmentizeMethod = LinearSegments(): The method to use for segmentizing the geometry. At the moment, only LinearSegments and GeodesicSegments are available.

  • geom: The geometry to segmentize. Must be a LineString, LinearRing, or greater in complexity.

  • max_distance::Real: The maximum distance, in the input space, between vertices in the geometry. Only used if you don't explicitly pass a method.

Returns a geometry of similar type to the input geometry, but resampled.

source


# GeometryOps.signed_areaMethod.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slighly differently for different geometries:

- The signed area of a point is always zero.
+multipolygon = polygonize(>(0.5), A);

source


# GeometryOps.rebuildMethod.
julia
rebuild(geom, child_geoms)

Rebuild a geometry from child geometries.

By default geometries will be rebuilt as a GeoInterface.Wrappers geometry, but rebuild can have methods added to it to dispatch on geometries from other packages and specify how to rebuild them.

(Maybe it should go into GeoInterface.jl)

source


# GeometryOps.reconstructMethod.
julia
reconstruct(geom, components)

Reconstruct geom from an iterable of component objects that match its structure.

All objects in components must have the same GeoInterface.trait.

Usually used in combination with flatten.

source


# GeometryOps.segmentizeMethod.
julia
segmentize([method = LinearSegments()], geom; max_distance::Real, threaded)

Segmentize a geometry by adding extra vertices to the geometry so that no segment is longer than a given distance. This is useful for plotting geometries with a limited number of vertices, or for ensuring that a geometry is not too "coarse" for a given application.

Arguments

  • method::SegmentizeMethod = LinearSegments(): The method to use for segmentizing the geometry. At the moment, only LinearSegments and GeodesicSegments are available.

  • geom: The geometry to segmentize. Must be a LineString, LinearRing, or greater in complexity.

  • max_distance::Real: The maximum distance, in the input space, between vertices in the geometry. Only used if you don't explicitly pass a method.

Returns a geometry of similar type to the input geometry, but resampled.

source


# GeometryOps.signed_areaMethod.
julia
signed_area(geom, [T = Float64])::T

Returns the signed area of a single geometry, based on winding order. This is computed slightly differently for different geometries:

- The signed area of a point is always zero.
 - The signed area of a curve is always zero.
 - The signed area of a polygon is computed with the shoelace formula and is
 positive if the polygon coordinates wind clockwise and negative if
 counterclockwise.
 - You cannot compute the signed area of a multipolygon as it doesn't have a
 meaning as each sub-polygon could have a different winding order.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.signed_distanceMethod.
julia
signed_distance(point, geom, ::Type{T} = Float64)::T

Calculates the signed distance from the geometry geom to the given point. Points within geom have a negative signed distance, and points outside of geom have a positive signed distance. - The signed distance from a point to a point, line, linestring, or linear ring is equal to the distance between the two. - The signed distance from a point to a polygon is negative if the point is within the polygon and is positive otherwise. The value of the distance is the minimum distance from the point to an edge of the polygon. This includes edges created by holes. - The signed distance from a point to a multigeometry or a geometry collection is the minimum signed distance between the point and any of the sub-geometries.

Result will be of type T, where T is an optional argument with a default value of Float64.

source


# GeometryOps.simplifyMethod.
julia
simplify(obj; kw...)
-simplify(::SimplifyAlg, obj; kw...)

Simplify a geometry, feature, feature collection, or nested vectors or a table of these.

RadialDistance, DouglasPeucker, or VisvalingamWhyatt algorithms are available, listed in order of increasing quality but decreaseing performance.

PoinTrait and MultiPointTrait are returned unchanged.

The default behaviour is simplify(DouglasPeucker(; kw...), obj). Pass in other SimplifyAlg to use other algorithms.

Keywords

  • prefilter_alg: SimplifyAlg algorithm used to pre-filter object before using primary filtering algorithm.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Keywords for DouglasPeucker are allowed when no algorithm is specified:

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Example

Simplify a polygon to have six points:

julia
import GeoInterface as GI
+simplify(::SimplifyAlg, obj; kw...)

Simplify a geometry, feature, feature collection, or nested vectors or a table of these.

RadialDistance, DouglasPeucker, or VisvalingamWhyatt algorithms are available, listed in order of increasing quality but decreasing performance.

PoinTrait and MultiPointTrait are returned unchanged.

The default behaviour is simplify(DouglasPeucker(; kw...), obj). Pass in other SimplifyAlg to use other algorithms.

Keywords

  • prefilter_alg: SimplifyAlg algorithm used to pre-filter object before using primary filtering algorithm.

  • threaded: true or false. Whether to use multithreading. Defaults to false.

  • crs: The CRS to attach to geometries. Defaults to nothing.

  • calc_extent: true or false. Whether to calculate the extent. Defaults to false.

Keywords for DouglasPeucker are allowed when no algorithm is specified:

Keywords

  • ratio: the fraction of points that should remain after simplify. Useful as it will generalise for large collections of objects.

  • number: the number of points that should remain after simplify. Less useful for large collections of mixed size objects.

  • tol: the minimum distance a point will be from the line joining its neighboring points.

Example

Simplify a polygon to have six points:

julia
import GeoInterface as GI
 import GeometryOps as GO
 
 poly = GI.Polygon([[
@@ -339,7 +339,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 GI.npoint(simple)
 
 # output
-6

source


`,37),b={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},C=s("a",{id:"GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}",href:"#GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}"},"#",-1),T=s("b",null,[s("u",null,"GeometryOps.t_value")],-1),f=s("i",null,"Method",-1),v=i('
julia
t_value(sᵢ, sᵢ₊₁, rᵢ, rᵢ₊₁)

Returns the "T-value" as described in Hormann's presentation [1] on how to calculate the mean-value coordinate.

Here, sᵢ is the vector from vertex vᵢ to the point, and rᵢ is the norm (length) of sᵢ. s must be Point and r must be real numbers.

',3),A={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},G={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.059ex"},xmlns:"http://www.w3.org/2000/svg",width:"27.746ex",height:"5.362ex",role:"img",focusable:"false",viewBox:"0 -1460 12263.9 2370","aria-hidden":"true"},B=i('',1),O=[B],D=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mi",null,"t"),s("mi",null,"ᵢ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",{"data-mjx-auto-op":"false"},"det")]),s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,","),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",{"data-mjx-texclass":"CLOSE"},")")])]),s("mrow",null,[s("mi",null,"r"),s("mi",null,"ᵢ"),s("mo",null,"∗"),s("mi",null,"r"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",null,"+"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,"⋅"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")])])])])],-1),j=i(`

+6

source


`,37),b={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},C=s("a",{id:"GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}",href:"#GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}"},"#",-1),f=s("b",null,[s("u",null,"GeometryOps.t_value")],-1),T=s("i",null,"Method",-1),v=i('
julia
t_value(sᵢ, sᵢ₊₁, rᵢ, rᵢ₊₁)

Returns the "T-value" as described in Hormann's presentation [1] on how to calculate the mean-value coordinate.

Here, sᵢ is the vector from vertex vᵢ to the point, and rᵢ is the norm (length) of sᵢ. s must be Point and r must be real numbers.

',3),G={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},A={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.059ex"},xmlns:"http://www.w3.org/2000/svg",width:"27.746ex",height:"5.362ex",role:"img",focusable:"false",viewBox:"0 -1460 12263.9 2370","aria-hidden":"true"},B=i('',1),O=[B],D=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mi",null,"t"),s("mi",null,"ᵢ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",{"data-mjx-auto-op":"false"},"det")]),s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,","),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",{"data-mjx-texclass":"CLOSE"},")")])]),s("mrow",null,[s("mi",null,"r"),s("mi",null,"ᵢ"),s("mo",null,"∗"),s("mi",null,"r"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",null,"+"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,"⋅"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")])])])])],-1),j=i(`

 
 [source](https://github.com/JuliaGeo/GeometryOps.jl/blob/v0.1.10/src/methods/barycentric.jl#L289-L305)
 
@@ -352,7 +352,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 
 
 \`\`\`julia
-to_edges()

Convert any geometry or collection of geometries into a flat vector of Tuple{Tuple{Float64,Float64},Tuple{Float64,Float64}} edges.

source

`,3),x=i(`
# GeometryOps.touchesMethod.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometies interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
+to_edges()

Convert any geometry or collection of geometries into a flat vector of Tuple{Tuple{Float64,Float64},Tuple{Float64,Float64}} edges.

source

`,3),x=i(`
# GeometryOps.touchesMethod.
julia
touches(geom1, geom2)::Bool

Return true if the first geometry touches the second geometry. In other words, the two interiors cannot interact, but one of the geometries must have a boundary point that interacts with either the other geometry's interior or boundary.

Examples

julia
import GeometryOps as GO, GeoInterface as GI
 
 l1 = GI.Line([(0.0, 0.0), (1.0, 0.0)])
 l2 = GI.Line([(1.0, 1.0), (1.0, -1.0)])
@@ -372,7 +372,7 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.Linea
 rRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}[GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticArraysCo
 re.SVector{2, Float64}[[4.5, 3.5], [6.5, 5.5], [8.5, 7.5], [4.5, 3.5]], nothing, nothing), GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Float64}}, Nothing, Nothing}(StaticA
-rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actuall multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
+rraysCore.SVector{2, Float64}[[6.5, 5.5], [8.5, 7.5], [9.5, 8.5], [6.5, 5.5]], nothing, nothing)], nothing, nothing)

With Rotations.jl you need to actually multiply the Rotation by the SVector point, which is easy using an anonymous function.

julia
julia> using Rotations
 
 julia> GO.transform(p -> one(RotMatrix{2}) * p, geom)
 GeoInterface.Wrappers.Polygon{false, false, Vector{GeoInterface.Wrappers.LinearRing{false, false, Vector{StaticArraysCore.SVector{2, Int64}}, Nothing, Nothing}}, Nothing, Nothing}(GeoInterface.Wrappers.LinearR
@@ -395,4 +395,4 @@ import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js
 GO.within(point, line)
 
 # output
-true

source



  1. K. Hormann and N. Sukumar. Generalized Barycentric Coordinates in Computer Graphics and Computational Mechanics. Taylor & Fancis, CRC Press, 2017. ↩︎

`,17);function w(Q,_,I,L,P,M){return t(),e("div",null,[h,s("div",p,[r,a(" "),k,a(" — "),o,a(". "),d,s("mjx-container",g,[(t(),e("svg",y,c)),u]),m]),F,s("div",b,[C,a(" "),T,a(" — "),f,a(". "),v,s("mjx-container",A,[(t(),e("svg",G,O)),D]),j]),x])}const S=n(l,[["render",w]]);export{q as __pageData,S as default}; +true

source



  1. K. Hormann and N. Sukumar. Generalized Barycentric Coordinates in Computer Graphics and Computational Mechanics. Taylor & Fancis, CRC Press, 2017. ↩︎

`,17);function w(Q,_,I,L,P,M){return t(),e("div",null,[h,s("div",p,[r,a(" "),k,a(" — "),o,a(". "),d,s("mjx-container",g,[(t(),e("svg",y,c)),u]),m]),F,s("div",b,[C,a(" "),f,a(" — "),T,a(". "),v,s("mjx-container",G,[(t(),e("svg",A,O)),D]),j]),x])}const S=n(l,[["render",w]]);export{q as __pageData,S as default}; diff --git a/previews/PR135/assets/api.md.D8UtvlcW.lean.js b/previews/PR135/assets/api.md.BkdCNSpp.lean.js similarity index 91% rename from previews/PR135/assets/api.md.D8UtvlcW.lean.js rename to previews/PR135/assets/api.md.BkdCNSpp.lean.js index 3ecf51118..11e83afee 100644 --- a/previews/PR135/assets/api.md.D8UtvlcW.lean.js +++ b/previews/PR135/assets/api.md.BkdCNSpp.lean.js @@ -1 +1 @@ -import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.k41oUgTf.js";const q=JSON.parse('{"title":"Full GeometryOps API documentation","description":"","frontmatter":{},"headers":[],"relativePath":"api.md","filePath":"api.md","lastUpdated":null}'),l={name:"api.md"},h=i("",174),p={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},r=s("a",{id:"GeometryOps.isclockwise-Tuple{Any}",href:"#GeometryOps.isclockwise-Tuple{Any}"},"#",-1),k=s("b",null,[s("u",null,"GeometryOps.isclockwise")],-1),o=s("i",null,"Method",-1),d=i("",2),g={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},y={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.827ex"},xmlns:"http://www.w3.org/2000/svg",width:"33.539ex",height:"6.785ex",role:"img",focusable:"false",viewBox:"0 -1749.5 14824.1 2999","aria-hidden":"true"},E=i("",1),c=[E],u=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("munderover",null,[s("mo",{"data-mjx-texclass":"OP"},"∑"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"2")]),s("mi",null,"n")]),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"y"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",{"data-mjx-texclass":"CLOSE"},")")]),s("mo",null,">"),s("mn",null,"0")])],-1),m=i("",3),F=i("",37),b={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},C=s("a",{id:"GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}",href:"#GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}"},"#",-1),T=s("b",null,[s("u",null,"GeometryOps.t_value")],-1),f=s("i",null,"Method",-1),v=i("",3),A={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},G={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.059ex"},xmlns:"http://www.w3.org/2000/svg",width:"27.746ex",height:"5.362ex",role:"img",focusable:"false",viewBox:"0 -1460 12263.9 2370","aria-hidden":"true"},B=i("",1),O=[B],D=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mi",null,"t"),s("mi",null,"ᵢ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",{"data-mjx-auto-op":"false"},"det")]),s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,","),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",{"data-mjx-texclass":"CLOSE"},")")])]),s("mrow",null,[s("mi",null,"r"),s("mi",null,"ᵢ"),s("mo",null,"∗"),s("mi",null,"r"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",null,"+"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,"⋅"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")])])])])],-1),j=i("",3),x=i("",17);function w(Q,_,I,L,P,M){return t(),e("div",null,[h,s("div",p,[r,a(" "),k,a(" — "),o,a(". "),d,s("mjx-container",g,[(t(),e("svg",y,c)),u]),m]),F,s("div",b,[C,a(" "),T,a(" — "),f,a(". "),v,s("mjx-container",A,[(t(),e("svg",G,O)),D]),j]),x])}const S=n(l,[["render",w]]);export{q as __pageData,S as default}; +import{_ as n,c as e,j as s,a,a7 as i,o as t}from"./chunks/framework.CONf0Rze.js";const q=JSON.parse('{"title":"Full GeometryOps API documentation","description":"","frontmatter":{},"headers":[],"relativePath":"api.md","filePath":"api.md","lastUpdated":null}'),l={name:"api.md"},h=i("",178),p={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},r=s("a",{id:"GeometryOps.isclockwise-Tuple{Any}",href:"#GeometryOps.isclockwise-Tuple{Any}"},"#",-1),k=s("b",null,[s("u",null,"GeometryOps.isclockwise")],-1),o=s("i",null,"Method",-1),d=i("",2),g={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},y={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.827ex"},xmlns:"http://www.w3.org/2000/svg",width:"33.539ex",height:"6.785ex",role:"img",focusable:"false",viewBox:"0 -1749.5 14824.1 2999","aria-hidden":"true"},E=i("",1),c=[E],u=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("munderover",null,[s("mo",{"data-mjx-texclass":"OP"},"∑"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"="),s("mn",null,"2")]),s("mi",null,"n")]),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"x"),s("mi",null,"i")]),s("mo",null,"−"),s("msub",null,[s("mi",null,"x"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",null,"⋅"),s("mo",{stretchy:"false"},"("),s("msub",null,[s("mi",null,"y"),s("mi",null,"i")]),s("mo",null,"+"),s("msub",null,[s("mi",null,"y"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",null,"i"),s("mo",null,"−"),s("mn",null,"1")])]),s("mo",{stretchy:"false"},")"),s("mo",{"data-mjx-texclass":"CLOSE"},")")]),s("mo",null,">"),s("mn",null,"0")])],-1),m=i("",3),F=i("",37),b={style:{"border-width":"1px","border-style":"solid","border-color":"black",padding:"1em","border-radius":"25px"}},C=s("a",{id:"GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}",href:"#GeometryOps.t_value-Union{Tuple{T2}, Tuple{T1}, Tuple{N}, Tuple{Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, Union{Tuple{Vararg{T1, N}}, StaticArraysCore.StaticArray{Tuple{N}, T1, 1}}, T2, T2}} where {N, T1<:Real, T2<:Real}"},"#",-1),f=s("b",null,[s("u",null,"GeometryOps.t_value")],-1),T=s("i",null,"Method",-1),v=i("",3),G={class:"MathJax",jax:"SVG",display:"true",style:{direction:"ltr",display:"block","text-align":"center",margin:"1em 0",position:"relative"}},A={style:{overflow:"visible","min-height":"1px","min-width":"1px","vertical-align":"-2.059ex"},xmlns:"http://www.w3.org/2000/svg",width:"27.746ex",height:"5.362ex",role:"img",focusable:"false",viewBox:"0 -1460 12263.9 2370","aria-hidden":"true"},B=i("",1),O=[B],D=s("mjx-assistive-mml",{unselectable:"on",display:"block",style:{top:"0px",left:"0px",clip:"rect(1px, 1px, 1px, 1px)","-webkit-touch-callout":"none","-webkit-user-select":"none","-khtml-user-select":"none","-moz-user-select":"none","-ms-user-select":"none","user-select":"none",position:"absolute",padding:"1px 0px 0px 0px",border:"0px",display:"block",overflow:"hidden",width:"100%"}},[s("math",{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block"},[s("mi",null,"t"),s("mi",null,"ᵢ"),s("mo",null,"="),s("mfrac",null,[s("mrow",null,[s("mrow",{"data-mjx-texclass":"ORD"},[s("mi",{"data-mjx-auto-op":"false"},"det")]),s("mrow",{"data-mjx-texclass":"INNER"},[s("mo",{"data-mjx-texclass":"OPEN"},"("),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,","),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",{"data-mjx-texclass":"CLOSE"},")")])]),s("mrow",null,[s("mi",null,"r"),s("mi",null,"ᵢ"),s("mo",null,"∗"),s("mi",null,"r"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")]),s("mo",null,"+"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mo",null,"⋅"),s("mi",null,"s"),s("mi",null,"ᵢ"),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₊")]),s("mrow",{"data-mjx-texclass":"ORD"},[s("mo",{"data-mjx-pseudoscript":"true"},"₁")])])])])],-1),j=i("",3),x=i("",17);function w(Q,_,I,L,P,M){return t(),e("div",null,[h,s("div",p,[r,a(" "),k,a(" — "),o,a(". "),d,s("mjx-container",g,[(t(),e("svg",y,c)),u]),m]),F,s("div",b,[C,a(" "),f,a(" — "),T,a(". "),v,s("mjx-container",G,[(t(),e("svg",A,O)),D]),j]),x])}const S=n(l,[["render",w]]);export{q as __pageData,S as default}; diff --git a/previews/PR135/assets/app.BPnMWvu-.js b/previews/PR135/assets/app.okziLJoA.js similarity index 90% rename from previews/PR135/assets/app.BPnMWvu-.js rename to previews/PR135/assets/app.okziLJoA.js index 59373d7b8..9f514c9f8 100644 --- a/previews/PR135/assets/app.BPnMWvu-.js +++ b/previews/PR135/assets/app.okziLJoA.js @@ -1 +1 @@ -import{U as o,a8 as p,a9 as u,aa as l,ab as c,ac as f,ad as d,ae as m,af as h,ag as g,ah as A,d as P,u as v,y,x as w,ai as C,aj as R,ak as b,a6 as E}from"./chunks/framework.k41oUgTf.js";import{R as S}from"./chunks/theme.BCxq1kHm.js";function i(e){if(e.extends){const a=i(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=i(S),T=P({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=v();return y(()=>{w(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),R(),b(),s.setup&&s.setup(),()=>E(s.Layout)}});async function _(){globalThis.__VITEPRESS__=!0;const e=x(),a=j();a.provide(u,e);const t=l(e.route);return a.provide(c,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function j(){return h(T)}function x(){let e=o,a;return g(t=>{let n=A(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=import(n)),o&&(e=!1),r},s.NotFound)}o&&_().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{_ as createApp}; +import{U as o,a8 as p,a9 as u,aa as l,ab as c,ac as f,ad as d,ae as m,af as h,ag as g,ah as A,d as P,u as v,y,x as w,ai as C,aj as R,ak as b,a6 as E}from"./chunks/framework.CONf0Rze.js";import{R as S}from"./chunks/theme.D6VlRy8Q.js";function i(e){if(e.extends){const a=i(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=i(S),T=P({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=v();return y(()=>{w(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),R(),b(),s.setup&&s.setup(),()=>E(s.Layout)}});async function _(){globalThis.__VITEPRESS__=!0;const e=x(),a=j();a.provide(u,e);const t=l(e.route);return a.provide(c,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function j(){return h(T)}function x(){let e=o,a;return g(t=>{let n=A(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=import(n)),o&&(e=!1),r},s.NotFound)}o&&_().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{_ as createApp}; diff --git a/previews/PR135/assets/zbzherl.BEFUMtlf.png b/previews/PR135/assets/bhjiovt.BEFUMtlf.png similarity index 100% rename from previews/PR135/assets/zbzherl.BEFUMtlf.png rename to previews/PR135/assets/bhjiovt.BEFUMtlf.png diff --git a/previews/PR135/assets/briiybs.Cy4gx45x.png b/previews/PR135/assets/briiybs.Cy4gx45x.png new file mode 100644 index 0000000000000000000000000000000000000000..74d2b4aec55c84d6d9c7e9c7e0f28760425000fa GIT binary patch literal 73994 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